Welcome to The Fiwix Project
A UNIX-like kernel for the i386 architecture
1 /* 2 * fiwix/fs/procfs/data.c 3 * 4 * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved. 5 * Distributed under the terms of the Fiwix License. 6 */ 7 8 #include <fiwix/kernel.h> 9 #include <fiwix/system.h> 10 #include <fiwix/types.h> 11 #include <fiwix/process.h> 12 #include <fiwix/cmos.h> 13 #include <fiwix/dma.h> 14 #include <fiwix/ide.h> 15 #include <fiwix/fs.h> 16 #include <fiwix/filesystems.h> 17 #include <fiwix/devices.h> 18 #include <fiwix/locks.h> 19 #include <fiwix/mm.h> 20 #include <fiwix/mman.h> 21 #include <fiwix/fs_proc.h> 22 #include <fiwix/cpu.h> 23 #include <fiwix/pic.h> 24 #include <fiwix/sched.h> 25 #include <fiwix/timer.h> 26 #include <fiwix/utsname.h> 27 #include <fiwix/version.h> 28 #include <fiwix/errno.h> 29 #include <fiwix/stdio.h> 30 #include <fiwix/string.h> 31 32 #define FSHIFT16 16 33 #define FIXED16_1 (1 << FSHIFT16) 34 #define LOAD_INT(x) ((x) >> FSHIFT16) 35 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED16_1 - 1)) * 100) 36 37 static const char *pstate[] = { 38 "? (unused!)", 39 "R (running)", 40 "S (sleeping)", 41 "Z (zombie)", 42 "T (stopped)", 43 "D (idle)", 44 }; 45 46 /* 47 * procfs root directory related functions 48 * --------------------------------------- 49 */ 50 int data_proc_self(char *buffer, __pid_t pid) 51 { 52 return sprintk(buffer, "%s", current->pidstr); 53 } 54 55 int data_proc_cmdline(char *buffer, __pid_t pid) 56 { 57 return sprintk(buffer, "%s\n", cmdline); 58 } 59 60 int data_proc_cpuinfo(char *buffer, __pid_t pid) 61 { 62 int size; 63 64 size = sprintk(buffer, "processor : 0\n"); 65 size += sprintk(buffer + size, "cpu family : %d86\n", cpu_table.family <= 6 ? cpu_table.family : 6); 66 if(cpu_table.model >= 0) { 67 size += sprintk(buffer + size, "model : %d\n", cpu_table.model); 68 } else { 69 size += sprintk(buffer + size, "model : unknown\n"); 70 } 71 72 if(cpu_table.vendor_id) { 73 size += sprintk(buffer + size, "vendor_id : %s\n", cpu_table.vendor_id); 74 } 75 if(cpu_table.model_name) { 76 size += sprintk(buffer + size, "model name : %s\n", cpu_table.model_name); 77 } 78 if(cpu_table.stepping >= 0) { 79 size += sprintk(buffer + size, "stepping : %d\n", cpu_table.stepping); 80 } else { 81 size += sprintk(buffer + size, "stepping : unknown\n"); 82 } 83 84 size += sprintk(buffer + size, "cpu MHz : "); 85 if(cpu_table.hz) { 86 size += sprintk(buffer + size, "%d.%d\n", (cpu_table.hz / 1000000), ((cpu_table.hz % 1000000) / 100000)); 87 } else { 88 size += sprintk(buffer + size, "unknown\n"); 89 } 90 if(cpu_table.cache) { 91 size += sprintk(buffer + size, "cache size : %s\n", cpu_table.cache); 92 } 93 size += sprintk(buffer + size, "cpuid : %s\n", cpu_table.has_cpuid ? "yes" : "no"); 94 size += sprintk(buffer + size, "fpu : %s\n", cpu_table.has_fpu ? "yes" : "no"); 95 size += get_cpu_flags(buffer, size); 96 return size; 97 } 98 99 int data_proc_devices(char *buffer, __pid_t pid) 100 { 101 int n, size; 102 struct device *d; 103 104 size = sprintk(buffer, "Character devices:\n"); 105 for(n = 0; n < NR_CHRDEV; n++) { 106 d = chr_device_table[n]; 107 while(d) { 108 size += sprintk(buffer + size, "%3d %s\n", d->major, d->name); 109 d = d->next; 110 } 111 } 112 113 size += sprintk(buffer + size, "\nBlock devices:\n"); 114 for(n = 0; n < NR_BLKDEV; n++) { 115 d = blk_device_table[n]; 116 while(d) { 117 size += sprintk(buffer + size, "%3d %s\n", d->major, d->name); 118 d = d->next; 119 } 120 } 121 return size; 122 } 123 124 int data_proc_dma(char *buffer, __pid_t pid) 125 { 126 int n, size; 127 128 size = 0; 129 for(n = 0; n < DMA_CHANNELS; n++) { 130 if(dma_resources[n]) { 131 size += sprintk(buffer + size, "%2d: %s\n", n, dma_resources[n]); 132 } 133 } 134 return size; 135 } 136 137 int data_proc_filesystems(char *buffer, __pid_t pid) 138 { 139 int n, size; 140 int nodev; 141 142 size = 0; 143 for(n = 0; n < NR_FILESYSTEMS; n++) { 144 if(filesystems_table[n].name) { 145 nodev = 0; 146 if(filesystems_table[n].fsop->flags != FSOP_REQUIRES_DEV) { 147 nodev = 1; 148 } 149 size += sprintk(buffer + size, "%s %s\n", nodev ? "nodev" : " ", filesystems_table[n].name); 150 } 151 } 152 return size; 153 } 154 155 int data_proc_interrupts(char *buffer, __pid_t pid) 156 { 157 struct interrupt *irq; 158 int n, size; 159 160 size = 0; 161 for(n = 0; n < NR_IRQS; n++) { 162 if((irq = irq_table[n])) { 163 size += sprintk(buffer + size, "%3d: %9u %s", n, irq->ticks, irq->name); 164 while((irq = irq->next)) { 165 size += sprintk(buffer + size, ",%s", irq->name); 166 } 167 size += sprintk(buffer + size, "\n"); 168 } 169 } 170 size += sprintk(buffer + size, "SPU: %9u %s\n", kstat.sirqs, "Spurious interrupts"); 171 return size; 172 } 173 174 int data_proc_loadavg(char *buffer, __pid_t pid) 175 { 176 int a, b, c; 177 int size; 178 struct proc *p; 179 int nrun = 0; 180 int nprocs = 0; 181 182 a = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); 183 b = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); 184 c = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); 185 186 FOR_EACH_PROCESS(p) { 187 nprocs++; 188 if(p->state == PROC_RUNNING) { 189 nrun++; 190 } 191 p = p->next; 192 } 193 194 size = sprintk(buffer, "%d.%02d %d.%02d %d.%02d %d/%d %d\n", LOAD_INT(a), LOAD_FRAC(a), LOAD_INT(b), LOAD_FRAC(b), LOAD_INT(c), LOAD_FRAC(c), nrun, nprocs, lastpid); 195 return size; 196 } 197 198 int data_proc_locks(char *buffer, __pid_t pid) 199 { 200 int n, size; 201 struct flock_file *ff; 202 203 size = 0; 204 205 for(n = 0; n < NR_FLOCKS; n++) { 206 ff = &flock_file_table[n]; 207 if(ff->inode) { 208 size += sprintk(buffer + size, "%d: FLOCK ADVISORY %s ", n + 1, ff->type & LOCK_SH ? "READ " : "WRITE"); 209 size += sprintk(buffer + size, "%d %x:%d:%d 0 EOF\n", ff->proc->pid, MAJOR(ff->inode->dev), MINOR(ff->inode->dev), ff->inode->inode); 210 } 211 } 212 213 return size; 214 } 215 216 int data_proc_meminfo(char *buffer, __pid_t pid) 217 { 218 struct page *pg; 219 int n, size; 220 221 kstat.shared = 0; 222 for(n = 0; n < kstat.physical_pages; n++) { 223 pg = &page_table[n]; 224 if(pg->flags & PAGE_RESERVED) { 225 continue; 226 } 227 if(!pg->count) { 228 continue; 229 } 230 kstat.shared += pg->count - 1; 231 } 232 233 size = 0; 234 size += sprintk(buffer + size, " total: used: free: shared: buffers: cached:\n"); 235 size += sprintk(buffer + size, "Mem: %8u %8u %8u %8u %8u %8u\n", kstat.total_mem_pages << PAGE_SHIFT, (kstat.total_mem_pages << PAGE_SHIFT) - (kstat.free_pages << PAGE_SHIFT), kstat.free_pages << PAGE_SHIFT, kstat.shared * 1024, kstat.buffers * 1024, kstat.cached * 1024); 236 size += sprintk(buffer + size, "Swap: %8u %8u %8u\n", 0, 0, 0); 237 size += sprintk(buffer + size, "MemTotal: %9d kB\n", kstat.total_mem_pages << 2); 238 size += sprintk(buffer + size, "MemFree: %9d kB\n", kstat.free_pages << 2); 239 size += sprintk(buffer + size, "MemShared:%9d kB\n", kstat.shared); 240 size += sprintk(buffer + size, "Buffers: %9d kB\n", kstat.buffers); 241 size += sprintk(buffer + size, "Cached: %9d kB\n", kstat.cached); 242 size += sprintk(buffer + size, "SwapTotal:%9d kB\n", 0); 243 size += sprintk(buffer + size, "SwapFree: %9d kB\n", 0); 244 size += sprintk(buffer + size, "Dirty: %9d kB\n", kstat.dirty); 245 return size; 246 } 247 248 int data_proc_mounts(char *buffer, __pid_t pid) 249 { 250 int n, size; 251 char *flag; 252 253 size = 0; 254 for(n = 0; n < NR_MOUNT_POINTS; n++) { 255 if(mount_table[n].used) { 256 if(mount_table[n].fs->fsop->flags != FSOP_KERN_MOUNT) { 257 flag = "rw"; 258 if(mount_table[n].sb.flags & MS_RDONLY) { 259 flag = "ro"; 260 } 261 size += sprintk(buffer + size, "%s %s %s %s 0 0\n", mount_table[n].devname, mount_table[n].dirname, mount_table[n].fs->name, flag); 262 } 263 } 264 } 265 return size; 266 } 267 268 int data_proc_partitions(char *buffer, __pid_t pid) 269 { 270 int n, ctrl, drv, size; 271 int minor, major; 272 unsigned int blocks; 273 struct ide *ide; 274 struct ide_drv *drive; 275 276 size = 0; 277 size += sprintk(buffer + size, "major minor #blocks name\n\n"); 278 279 for(ctrl = 0; ctrl < NR_IDE_CTRLS; ctrl++) { 280 ide = &ide_table[ctrl]; 281 for(drv = 0; drv < NR_IDE_DRVS; drv++) { 282 drive = &ide->drive[drv]; 283 if(!drive->nr_sects) { 284 continue; 285 } 286 if(drive->flags & DEVICE_IS_DISK) { 287 major = (int)drive->major; 288 minor = (int)drive->minor_shift; 289 blocks = drive->nr_sects / 2; 290 size += sprintk(buffer + size, "%4d %4d %9d %s\n", major, 0, blocks, drive->dev_name); 291 for(n = 0; n < NR_PARTITIONS; n++) { 292 if(drive->part_table[n].type) { 293 blocks = drive->part_table[n].nr_sects / 2; 294 size += sprintk(buffer + size, "%4d %4d %9u %s%d\n", major, (n + 1) << minor, blocks, drive->dev_name, n + 1); 295 } 296 } 297 } 298 } 299 } 300 return size; 301 } 302 303 int data_proc_rtc(char *buffer, __pid_t pid) 304 { 305 int size; 306 short int sec, min, hour; 307 short int day, month, year, century; 308 309 sec = cmos_read_date(CMOS_SEC); 310 min = cmos_read_date(CMOS_MIN); 311 hour = cmos_read_date(CMOS_HOUR); 312 day = cmos_read_date(CMOS_DAY); 313 month = cmos_read_date(CMOS_MONTH); 314 year = cmos_read_date(CMOS_YEAR); 315 century = cmos_read_date(CMOS_CENTURY); 316 year += century * 100; 317 318 size = 0; 319 size += sprintk(buffer + size, "rtc_time\t: %02d:%02d:%02d\n", hour, min, sec); 320 size += sprintk(buffer + size, "rtc_date\t: %02d-%02d-%02d\n", year, month, day); 321 sec = cmos_read_date(CMOS_ASEC); 322 min = cmos_read_date(CMOS_AMIN); 323 hour = cmos_read_date(CMOS_AHOUR); 324 size += sprintk(buffer + size, "alarm\t\t: %02d:%02d:%02d\n", hour, min, sec); 325 size += sprintk(buffer + size, "DST_enable\t: %s\n", cmos_read(CMOS_STATB) & CMOS_STATB_DSE ? "yes" : "no"); 326 size += sprintk(buffer + size, "BCD\t\t: %s\n", cmos_read(CMOS_STATB) & CMOS_STATB_DM ? "no" : "yes"); 327 size += sprintk(buffer + size, "24hr\t\t: %s\n", cmos_read(CMOS_STATB) & CMOS_STATB_24H ? "yes" : "no"); 328 size += sprintk(buffer + size, "square_wave\t: %s\n", cmos_read(CMOS_STATB) & CMOS_STATB_SQWE ? "yes" : "no"); 329 size += sprintk(buffer + size, "alarm_IRQ\t: %s\n", cmos_read(CMOS_STATB) & CMOS_STATB_AIE ? "yes" : "no"); 330 size += sprintk(buffer + size, "update_IRQ\t: %s\n", cmos_read(CMOS_STATB) & CMOS_STATB_UIE ? "yes" : "no"); 331 size += sprintk(buffer + size, "periodic_IRQ\t: %s\n", cmos_read(CMOS_STATB) & CMOS_STATB_PIE ? "yes" : "no"); 332 size += sprintk(buffer + size, "periodic_freq\t: %s\n", (cmos_read(CMOS_STATA) & CMOS_STATA_IRQF) == 0x6 ? "1024" : "?"); 333 size += sprintk(buffer + size, "batt_status\t: %s\n", cmos_read(CMOS_STATD) & CMOS_STATD_VRT ? "okay" : "dead"); 334 return size; 335 } 336 337 int data_proc_stat(char *buffer, __pid_t pid) 338 { 339 int n, size; 340 unsigned int idle; 341 struct interrupt *irq; 342 343 idle = kstat.ticks - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system); 344 size = 0; 345 size += sprintk(buffer + size, "cpu %d %d %d %d\n", kstat.cpu_user, kstat.cpu_nice, kstat.cpu_system, idle); 346 size += sprintk(buffer + size, "disk 0 0 0 0\n"); 347 size += sprintk(buffer + size, "page 0 0\n"); 348 size += sprintk(buffer + size, "swap 0 0\n"); 349 size += sprintk(buffer + size, "intr %u", kstat.irqs); 350 for(n = 0; n < NR_IRQS; n++) { 351 irq = irq_table[n]; 352 if(irq) { 353 size += sprintk(buffer + size, " %u", irq->ticks); 354 } 355 } 356 size += sprintk(buffer + size, "\n"); 357 size += sprintk(buffer + size, "ctxt %u\n", kstat.ctxt); 358 size += sprintk(buffer + size, "btime %d\n", kstat.boot_time); 359 size += sprintk(buffer + size, "processes %d\n", kstat.processes); 360 return size; 361 } 362 363 int data_proc_uptime(char *buffer, __pid_t pid) 364 { 365 struct proc *p; 366 unsigned long int idle; 367 368 p = &proc_table[IDLE]; 369 idle = tv2ticks(&p->usage.ru_utime); 370 idle += tv2ticks(&p->usage.ru_stime); 371 return sprintk(buffer, "%u.%02u %u.%02u\n", kstat.uptime, kstat.ticks % HZ, idle / HZ, idle % HZ); 372 } 373 374 int data_proc_fullversion(char *buffer, __pid_t pid) 375 { 376 return sprintk(buffer, "Fiwix version %s %s\n", UTS_RELEASE, UTS_VERSION); 377 } 378 379 int data_proc_domainname(char *buffer, __pid_t pid) 380 { 381 return sprintk(buffer, "%s\n", sys_utsname.domainname); 382 } 383 384 int data_proc_filemax(char *buffer, __pid_t pid) 385 { 386 return sprintk(buffer, "%d\n", NR_OPENS); 387 } 388 389 int data_proc_filenr(char *buffer, __pid_t pid) 390 { 391 int n, nr; 392 393 nr = 0; 394 for(n = 1; n < NR_OPENS; n++) { 395 if(fd_table[n].count != 0) { 396 nr++; 397 } 398 } 399 return sprintk(buffer, "%d\n", nr); 400 } 401 402 int data_proc_hostname(char *buffer, __pid_t pid) 403 { 404 return sprintk(buffer, "%s\n", sys_utsname.nodename); 405 } 406 407 int data_proc_inodemax(char *buffer, __pid_t pid) 408 { 409 return sprintk(buffer, "%d\n", inode_table_size / sizeof(struct inode)); 410 } 411 412 int data_proc_inodenr(char *buffer, __pid_t pid) 413 { 414 return sprintk(buffer, "%d\n", (inode_table_size / sizeof(struct inode)) - kstat.free_inodes); 415 } 416 417 int data_proc_osrelease(char *buffer, __pid_t pid) 418 { 419 return sprintk(buffer, "%s\n", UTS_RELEASE); 420 } 421 422 int data_proc_ostype(char *buffer, __pid_t pid) 423 { 424 return sprintk(buffer, "%s\n", UTS_SYSNAME); 425 } 426 427 int data_proc_version(char *buffer, __pid_t pid) 428 { 429 return sprintk(buffer, "%s\n", UTS_VERSION); 430 } 431 432 433 /* 434 * PID directory related functions 435 * ------------------------------- 436 */ 437 int data_proc_pid_cmdline(char *buffer, __pid_t pid) 438 { 439 int n, size; 440 char *arg; 441 char **argv; 442 unsigned int addr, offset; 443 struct proc *p; 444 445 size = 0; 446 if((p = get_proc_by_pid(pid))) { 447 for(n = 0; n < p->argc && (p->argv + n); n++) { 448 argv = p->argv + n; 449 offset = (int)argv & ~PAGE_MASK; 450 addr = get_mapped_addr(p, (int)argv) & PAGE_MASK; 451 addr = P2V(addr); 452 argv = (char **)(addr + offset); 453 offset = (int)argv[0] & ~PAGE_MASK; 454 addr = get_mapped_addr(p, (int)argv[0]) & PAGE_MASK; 455 addr = P2V(addr); 456 arg = (char *)(addr + offset); 457 if(size + strlen(arg) < (PAGE_SIZE - 1)) { 458 size += sprintk(buffer + size, "%s", arg); 459 buffer[size++] = NULL; 460 } else { 461 break; 462 } 463 } 464 } 465 return size; 466 } 467 468 int data_proc_pid_cwd(char *buffer, __pid_t pid) 469 { 470 int size; 471 struct proc *p; 472 struct inode *i; 473 474 size = 0; 475 if((p = get_proc_by_pid(pid))) { 476 477 /* zombie processes don't have current working directory */ 478 if(!p->pwd) { 479 return -ENOENT; 480 } 481 482 i = p->pwd; 483 size = sprintk(buffer, "[%02d%02d]:%d", MAJOR(i->rdev), MINOR(i->rdev), i->inode); 484 } 485 return size; 486 } 487 488 int data_proc_pid_environ(char *buffer, __pid_t pid) 489 { 490 int n, size; 491 char *env; 492 char **envp; 493 unsigned int addr, offset; 494 struct proc *p; 495 496 size = 0; 497 if((p = get_proc_by_pid(pid))) { 498 for(n = 0; n < p->envc && (p->envp + n); n++) { 499 envp = p->envp + n; 500 offset = (int)envp & ~PAGE_MASK; 501 addr = get_mapped_addr(p, (int)envp) & PAGE_MASK; 502 addr = P2V(addr); 503 envp = (char **)(addr + offset); 504 offset = (int)envp[0] & ~PAGE_MASK; 505 addr = get_mapped_addr(p, (int)envp[0]) & PAGE_MASK; 506 addr = P2V(addr); 507 env = (char *)(addr + offset); 508 if(size + strlen(env) < (PAGE_SIZE - 1)) { 509 size += sprintk(buffer + size, "%s", env); 510 buffer[size++] = NULL; 511 } else { 512 break; 513 } 514 } 515 } 516 return size; 517 } 518 519 int data_proc_pid_exe(char *buffer, __pid_t pid) 520 { 521 int size; 522 struct proc *p; 523 struct inode *i; 524 525 size = 0; 526 if((p = get_proc_by_pid(pid))) { 527 528 /* kernel and zombie processes are programless */ 529 if(!p->vma || !p->vma->inode) { 530 return -ENOENT; 531 } 532 533 i = p->vma->inode; 534 size = sprintk(buffer, "[%02d%02d]:%d", MAJOR(i->rdev), MINOR(i->rdev), i->inode); 535 } 536 return size; 537 } 538 539 int data_proc_pid_maps(char *buffer, __pid_t pid) 540 { 541 unsigned int n; 542 int size, len; 543 __ino_t inode; 544 int major, minor; 545 char *section; 546 char r, w, x, f; 547 struct proc *p; 548 struct vma *vma; 549 550 size = 0; 551 if((p = get_proc_by_pid(pid))) { 552 if(!p->vma) { 553 return 0; 554 } 555 vma = p->vma; 556 for(n = 0; n < VMA_REGIONS && vma->start; n++, vma++) { 557 r = vma->prot & PROT_READ ? 'r' : '-'; 558 w = vma->prot & PROT_WRITE ? 'w' : '-'; 559 x = vma->prot & PROT_EXEC ? 'x' : '-'; 560 if(vma->flags & MAP_SHARED) { 561 f = 's'; 562 } else if(vma->flags & MAP_PRIVATE) { 563 f = 'p'; 564 } else { 565 f = '-'; 566 } 567 switch(vma->s_type) { 568 case P_TEXT: section = "text"; 569 break; 570 case P_DATA: section = "data"; 571 break; 572 case P_BSS: section = "bss"; 573 break; 574 case P_HEAP: section = "heap"; 575 break; 576 case P_STACK: section = "stack"; 577 break; 578 case P_MMAP: section = "mmap"; 579 break; 580 default: 581 section = NULL; 582 break; 583 } 584 inode = major = minor = 0; 585 if(vma->inode) { 586 inode = vma->inode->inode; 587 major = MAJOR(vma->inode->dev); 588 minor = MINOR(vma->inode->dev); 589 } 590 len = sprintk(buffer + size, "%08x-%08x %c%c%c%c %08x %02d:%02d %- 10u [%s]\n", vma->start, vma->end, r, w, x, f, vma->offset, major, minor, inode, section); 591 size += len; 592 } 593 } 594 return size; 595 } 596 597 int data_proc_pid_mountinfo(char *buffer, __pid_t pid) 598 { 599 int n, size; 600 char *flag, *devname; 601 602 size = 0; 603 for(n = 0; n < NR_MOUNT_POINTS; n++) { 604 if(mount_table[n].used) { 605 if(mount_table[n].fs->fsop->flags != FSOP_KERN_MOUNT) { 606 flag = "rw"; 607 if(mount_table[n].sb.flags & MS_RDONLY) { 608 flag = "ro"; 609 } 610 devname = mount_table[n].devname; 611 if(!strcmp(mount_table[n].devname, "/dev/root")) { 612 devname = _rootdevname; 613 } 614 size += sprintk(buffer + size, "%d 0 %d:%d %s %s %s - %s %s %s\n", n, MAJOR(mount_table[n].dev), MINOR(mount_table[n].dev), "/", mount_table[n].dirname, flag, mount_table[n].fs->name, devname, flag); 615 } 616 } 617 } 618 return size; 619 } 620 621 int data_proc_pid_root(char *buffer, __pid_t pid) 622 { 623 int size; 624 struct proc *p; 625 struct inode *i; 626 627 size = 0; 628 if((p = get_proc_by_pid(pid))) { 629 630 /* zombie processes don't have root directory */ 631 if(!p->root) { 632 return -ENOENT; 633 } 634 635 i = p->root; 636 size = sprintk(buffer, "[%02d%02d]:%d", MAJOR(i->rdev), MINOR(i->rdev), i->inode); 637 } 638 return size; 639 } 640 641 int data_proc_pid_stat(char *buffer, __pid_t pid) 642 { 643 int n, size, vma_start, vma_end; 644 unsigned int esp, eip; 645 int signum, mask; 646 __sigset_t sigignored, sigcaught; 647 struct proc *p; 648 struct sigcontext *sc; 649 struct vma *vma; 650 int text, data, stack, mmap; 651 652 size = text = data = stack = mmap = 0; 653 if((p = get_proc_by_pid(pid))) { 654 if(!p->vma) { 655 return 0; 656 } 657 vma_start = p->vma[0].start; 658 vma_end = p->vma[0].end; 659 660 vma = p->vma; 661 for(n = 0; n < VMA_REGIONS && vma->start; n++, vma++) { 662 switch(vma->s_type) { 663 case P_TEXT: 664 text += vma->end - vma->start; 665 break; 666 case P_HEAP: 667 data += vma->end - vma->start; 668 break; 669 case P_STACK: 670 stack += vma->end - vma->start; 671 break; 672 case P_MMAP: 673 mmap += vma->end - vma->start; 674 break; 675 } 676 } 677 678 sigignored = sigcaught = 0; 679 for(signum = 0, mask = 1; signum < NSIG; signum++, mask <<= 1) { 680 if(p->sigaction[signum].sa_handler == SIG_IGN) { 681 sigignored |= mask; 682 } 683 if(p->sigaction[signum].sa_handler == SIG_DFL) { 684 sigcaught |= mask; 685 } 686 } 687 688 esp = eip = 0; 689 if(p->sp) { 690 sc = (struct sigcontext *)p->sp; 691 esp = sc->oldesp; 692 eip = sc->eip; 693 } 694 size = sprintk(buffer, "%d (%s) %c %d %d %d %d %d %d %d %d %d %d %u %u %u %u %d %d %d %d %d %d %u %u %u %u %u %u %u %d %d %u %u %u\n", 695 p->pid, 696 p->argv0, 697 pstate[p->state][0], 698 p->ppid, p->pgid, p->sid, 699 p->ctty ? p->ctty->dev : 0, 700 p->ctty ? p->ctty->pgid : - 1, 701 0, /* flags */ 702 0, 0, 0, 0, /* minflt, cminflt, majflt, cmajflt */ 703 tv2ticks(&p->usage.ru_utime), 704 tv2ticks(&p->usage.ru_stime), 705 tv2ticks(&p->cusage.ru_utime), 706 tv2ticks(&p->cusage.ru_stime), 707 0, /* counter */ 708 0, /* priority */ 709 0, /* timeout */ 710 0, /* itrealvalue */ 711 p->start_time, 712 text + data + stack + mmap, 713 p->rss, 714 0x7FFFFFFF, /* rlim */ 715 vma_start, /* startcode */ 716 vma_end, /* endcode */ 717 KERNEL_BASE_ADDR - 1, /* startstack */ 718 esp, /* kstkesp */ 719 eip, /* kstkeip */ 720 p->sigpending, 721 p->sigblocked, 722 sigignored, 723 sigcaught, 724 p->sleep_address 725 ); 726 } 727 return size; 728 } 729 730 int data_proc_pid_statm(char *buffer, __pid_t pid) 731 { 732 int n, size; 733 struct proc *p; 734 struct vma *vma; 735 int text, data, stack, mmap; 736 737 size = text = data = stack = mmap = 0; 738 if((p = get_proc_by_pid(pid))) { 739 if(!p->vma) { 740 return 0; 741 } 742 vma = p->vma; 743 for(n = 0; n < VMA_REGIONS && vma->start; n++, vma++) { 744 switch(vma->s_type) { 745 case P_TEXT: 746 text += vma->end - vma->start; 747 break; 748 case P_HEAP: 749 data += vma->end - vma->start; 750 break; 751 case P_STACK: 752 stack += vma->end - vma->start; 753 break; 754 case P_MMAP: 755 mmap += vma->end - vma->start; 756 break; 757 } 758 } 759 760 size = sprintk(buffer, "%d", (text + data + stack + mmap) / PAGE_SIZE); 761 size += sprintk(buffer + size, " %d", p->rss); 762 size += sprintk(buffer + size, " 0"); /* shared mappings */ 763 size += sprintk(buffer + size, " %d", text / PAGE_SIZE); 764 size += sprintk(buffer + size, " 0"); 765 size += sprintk(buffer + size, " %d", (data + stack) / PAGE_SIZE); 766 size += sprintk(buffer + size, " 0\n"); 767 } 768 return size; 769 } 770 771 int data_proc_pid_status(char *buffer, __pid_t pid) 772 { 773 int n, size; 774 int signum, mask; 775 __sigset_t sigignored, sigcaught; 776 struct proc *p; 777 struct vma *vma; 778 int text, data, stack, mmap; 779 780 size = text = data = stack = mmap = 0; 781 if((p = get_proc_by_pid(pid))) { 782 if(!p->vma) { 783 return 0; 784 } 785 vma = p->vma; 786 for(n = 0; n < VMA_REGIONS && vma->start; n++, vma++) { 787 switch(vma->s_type) { 788 case P_TEXT: 789 text += vma->end - vma->start; 790 break; 791 case P_HEAP: 792 data += vma->end - vma->start; 793 break; 794 case P_STACK: 795 stack += vma->end - vma->start; 796 break; 797 case P_MMAP: 798 mmap += vma->end - vma->start; 799 break; 800 } 801 } 802 803 size = sprintk(buffer, "Name:\t%s\n", p->argv0); 804 size += sprintk(buffer + size, "State:\t%s\n", pstate[p->state]); 805 size += sprintk(buffer + size, "Pid:\t%d\n", p->pid); 806 size += sprintk(buffer + size, "PPid:\t%d\n", p->ppid); 807 size += sprintk(buffer + size, "Uid:\t%d\t%d\t%d\t-\n", p->uid, p->euid, p->suid); 808 size += sprintk(buffer + size, "Gid:\t%d\t%d\t%d\t-\n", p->gid, p->egid, p->sgid); 809 size += sprintk(buffer + size, "VmSize:\t%8d kB\n", (text + data + stack + mmap) / 1024); 810 size += sprintk(buffer + size, "VmLck:\t%8d kB\n", 0); 811 size += sprintk(buffer + size, "VmRSS:\t%8d kB\n", p->rss << 2); 812 size += sprintk(buffer + size, "VmData:\t%8d kB\n", data / 1024); 813 size += sprintk(buffer + size, "VmStk:\t%8d kB\n", stack / 1024); 814 size += sprintk(buffer + size, "VmExe:\t%8d kB\n", text / 1024); 815 size += sprintk(buffer + size, "VmLib:\t%8d kB\n", 0); 816 size += sprintk(buffer + size, "SigPnd:\t%08x\n", p->sigpending); 817 size += sprintk(buffer + size, "SigBlk:\t%08x\n", p->sigblocked); 818 sigignored = sigcaught = 0; 819 for(signum = 0, mask = 1; signum < NSIG; signum++, mask <<= 1) { 820 if(p->sigaction[signum].sa_handler == SIG_IGN) { 821 sigignored |= mask; 822 } 823 if(p->sigaction[signum].sa_handler == SIG_DFL) { 824 sigcaught |= mask; 825 } 826 } 827 size += sprintk(buffer + size, "SigIgn:\t%08x\n", sigignored); 828 size += sprintk(buffer + size, "SigCgt:\t%08x\n", sigcaught); 829 } 830 return size; 831 }