1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 char copyright[] = 9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)w.c 5.15 (Berkeley) 02/06/90"; 15 #endif not lint 16 17 /* 18 * w - print system status (who and what) 19 * 20 * This program is similar to the systat command on Tenex/Tops 10/20 21 */ 22 #include <sys/param.h> 23 #include <nlist.h> 24 #include <stdio.h> 25 #include <ctype.h> 26 #include <utmp.h> 27 #include <sys/stat.h> 28 #include <sys/dir.h> 29 #include <sys/user.h> 30 #include <sys/proc.h> 31 #include <sys/ioctl.h> 32 #include <machine/pte.h> 33 #include <sys/vm.h> 34 #include <sys/tty.h> 35 #include <sys/kinfo.h> 36 #include <paths.h> 37 38 #define ARGWIDTH 33 /* # chars left on 80 col crt for args */ 39 40 struct pr { 41 short w_pid; /* proc.p_pid */ 42 char w_flag; /* proc.p_flag */ 43 short w_size; /* proc.p_size */ 44 long w_seekaddr; /* where to find args */ 45 long w_lastpg; /* disk address of stack */ 46 int w_igintr; /* INTR+3*QUIT, 0=die, 1=ign, 2=catch */ 47 time_t w_time; /* CPU time used by this process */ 48 time_t w_ctime; /* CPU time used by children */ 49 dev_t w_tty; /* tty device of process */ 50 int w_uid; /* uid of process */ 51 char w_comm[15]; /* user.u_comm, null terminated */ 52 char w_args[ARGWIDTH+1]; /* args if interesting process */ 53 } *pr; 54 int nproc; 55 56 struct nlist nl[] = { 57 { "_nproc" }, 58 #define X_NPROC 0 59 { "_boottime" }, 60 #define X_BOOTTIME 1 61 { "_proc" }, 62 #define X_PROC 2 63 { "_swapdev" }, 64 #define X_SWAPDEV 3 65 { "_Usrptmap" }, 66 #define X_USRPTMA 4 67 { "_usrpt" }, 68 #define X_USRPT 5 69 { "_nswap" }, 70 #define X_NSWAP 6 71 { "_dmmin" }, 72 #define X_DMMIN 7 73 { "_dmmax" }, 74 #define X_DMMAX 8 75 { "" }, 76 }; 77 78 FILE *ps; 79 FILE *ut; 80 FILE *bootfd; 81 int kmem; 82 int mem; 83 int swap; /* kmem, mem, and swap */ 84 int nswap; 85 int dmmin, dmmax; 86 dev_t tty; 87 int uid; 88 char doing[520]; /* process attached to terminal */ 89 time_t proctime; /* cpu time of process in doing */ 90 double avenrun[3]; 91 struct proc *aproc; 92 pid_t pgid; 93 pid_t tpgid; 94 95 #define DIV60(t) ((t+30)/60) /* x/60 rounded */ 96 #define TTYEQ (tty == pr[i].w_tty) 97 #define IGINT (1+3*1) /* ignoring both SIGINT & SIGQUIT */ 98 99 char *getargs(); 100 char *ctime(); 101 char *rindex(); 102 FILE *popen(); 103 struct tm *localtime(); 104 time_t findidle(); 105 106 int debug; /* true if -d flag: debugging output */ 107 int ttywidth = 80; /* width of tty */ 108 int header = 1; /* true if -h flag: don't print heading */ 109 int lflag = 1; /* true if -l flag: long style output */ 110 int prfrom = 1; /* true if not -f flag: print host from */ 111 int login; /* true if invoked as login shell */ 112 time_t idle; /* number of minutes user is idle */ 113 int nusers; /* number of users logged in now */ 114 char * sel_user; /* login of particular user selected */ 115 char firstchar; /* first char of name of prog invoked as */ 116 time_t jobtime; /* total cpu time visible */ 117 time_t now; /* the current time of day */ 118 struct timeval boottime; 119 time_t uptime; /* time of last reboot & elapsed time since */ 120 int np; /* number of processes currently active */ 121 struct utmp utmp; 122 union { 123 struct user U_up; 124 char pad[NBPG][UPAGES]; 125 } Up; 126 #define up Up.U_up 127 128 main(argc, argv) 129 char **argv; 130 { 131 int days, hrs, mins; 132 register int i, j; 133 char *cp; 134 register int curpid, empty; 135 struct winsize win; 136 137 login = (argv[0][0] == '-'); 138 cp = rindex(argv[0], '/'); 139 firstchar = login ? argv[0][1] : (cp==0) ? argv[0][0] : cp[1]; 140 cp = argv[0]; /* for Usage */ 141 142 while (argc > 1) { 143 if (argv[1][0] == '-') { 144 for (i=1; argv[1][i]; i++) { 145 switch(argv[1][i]) { 146 147 case 'd': 148 debug++; 149 break; 150 151 case 'f': 152 prfrom = !prfrom; 153 break; 154 155 case 'h': 156 header = 0; 157 break; 158 159 case 'l': 160 lflag++; 161 break; 162 163 case 's': 164 lflag = 0; 165 break; 166 167 case 'u': 168 case 'w': 169 firstchar = argv[1][i]; 170 break; 171 172 default: 173 fprintf(stderr, "w: Bad flag %s\n", 174 argv[1]); 175 exit(1); 176 } 177 } 178 } else { 179 if (!isalnum(argv[1][0]) || argc > 2) { 180 fprintf(stderr, 181 "Usage: %s [ -hlsfuw ] [ user ]\n", cp); 182 exit(1); 183 } else 184 sel_user = argv[1]; 185 } 186 argc--; argv++; 187 } 188 189 if ((kmem = open(_PATH_KMEM, 0)) < 0) { 190 fprintf(stderr, "w: no %s.\n", _PATH_KMEM); 191 exit(1); 192 } 193 nlist(_PATH_UNIX, nl); 194 if (nl[0].n_type==0) { 195 fprintf(stderr, "w: no %s namelist.\n", _PATH_UNIX); 196 exit(1); 197 } 198 199 if (firstchar == 'u') /* uptime(1) */ 200 nl[X_BOOTTIME+1].n_name = ""; 201 else { /* then read in procs, get window size */ 202 readpr(); 203 if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_col > 70) 204 ttywidth = win.ws_col; 205 } 206 207 ut = fopen(_PATH_UTMP, "r"); 208 time(&now); 209 if (header) { 210 /* Print time of day */ 211 prtat(&now); 212 213 /* 214 * Print how long system has been up. 215 * (Found by looking for "boottime" in kernel) 216 */ 217 lseek(kmem, (long)nl[X_BOOTTIME].n_value, 0); 218 read(kmem, &boottime, sizeof (boottime)); 219 220 uptime = now - boottime.tv_sec; 221 uptime += 30; 222 days = uptime / (60*60*24); 223 uptime %= (60*60*24); 224 hrs = uptime / (60*60); 225 uptime %= (60*60); 226 mins = uptime / 60; 227 228 printf(" up"); 229 if (days > 0) 230 printf(" %d day%s,", days, days>1?"s":""); 231 if (hrs > 0 && mins > 0) { 232 printf(" %2d:%02d,", hrs, mins); 233 } else { 234 if (hrs > 0) 235 printf(" %d hr%s,", hrs, hrs>1?"s":""); 236 if (mins > 0) 237 printf(" %d min%s,", mins, mins>1?"s":""); 238 } 239 240 /* Print number of users logged in to system */ 241 while (fread(&utmp, sizeof(utmp), 1, ut)) { 242 if (utmp.ut_name[0] != '\0') 243 nusers++; 244 } 245 rewind(ut); 246 printf(" %d user%s", nusers, nusers>1?"s":""); 247 248 /* 249 * Print 1, 5, and 15 minute load averages. 250 */ 251 printf(", load average:"); 252 (void)getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); 253 for (i = 0; i < (sizeof(avenrun)/sizeof(avenrun[0])); i++) { 254 if (i > 0) 255 printf(","); 256 printf(" %.2f", avenrun[i]); 257 } 258 printf("\n"); 259 if (firstchar == 'u') /* if this was uptime(1), finished */ 260 exit(0); 261 262 /* Headers for rest of output */ 263 if (lflag && prfrom) 264 printf("USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT\n"); 265 else if (lflag) 266 printf("USER TTY LOGIN@ IDLE JCPU PCPU WHAT\n"); 267 else if (prfrom) 268 printf("USER TTY FROM IDLE WHAT\n"); 269 else 270 printf("USER TTY IDLE WHAT\n"); 271 fflush(stdout); 272 } 273 274 275 for (;;) { /* for each entry in utmp */ 276 if (fread(&utmp, sizeof(utmp), 1, ut) == NULL) { 277 fclose(ut); 278 exit(0); 279 } 280 if (utmp.ut_name[0] == '\0') 281 continue; /* that tty is free */ 282 if (sel_user && strncmp(utmp.ut_name, sel_user, UT_NAMESIZE) != 0) 283 continue; /* we wanted only somebody else */ 284 285 gettty(); 286 jobtime = 0; 287 proctime = 0; 288 strcpy(doing, "-"); /* default act: normally never prints */ 289 empty = 1; 290 curpid = -1; 291 idle = findidle(); 292 for (i=0; i<np; i++) { /* for each process on this tty */ 293 if (!(TTYEQ)) 294 continue; 295 jobtime += pr[i].w_time + pr[i].w_ctime; 296 proctime += pr[i].w_time; 297 /* 298 * Meaning of debug fields following proc name is: 299 * & by itself: ignoring both SIGINT and QUIT. 300 * (==> this proc is not a candidate.) 301 * & <i> <q>: i is SIGINT status, q is quit. 302 * 0 == DFL, 1 == IGN, 2 == caught. 303 * *: proc pgrp == tty pgrp. 304 */ 305 if (debug) { 306 printf("\t\t%d\t%s", pr[i].w_pid, pr[i].w_args); 307 if ((j=pr[i].w_igintr) > 0) 308 if (j==IGINT) 309 printf(" &"); 310 else 311 printf(" & %d %d", j%3, j/3); 312 printf("\n"); 313 } 314 if (empty && pr[i].w_igintr!=IGINT) { 315 empty = 0; 316 curpid = -1; 317 } 318 if(pr[i].w_pid>curpid && (pr[i].w_igintr!=IGINT || empty)){ 319 curpid = pr[i].w_pid; 320 strcpy(doing, lflag ? pr[i].w_args : pr[i].w_comm); 321 #ifdef notdef 322 if (doing[0]==0 || doing[0]=='-' && doing[1]<=' ' || doing[0] == '?') { 323 strcat(doing, " ("); 324 strcat(doing, pr[i].w_comm); 325 strcat(doing, ")"); 326 } 327 #endif 328 } 329 } 330 putline(); 331 } 332 } 333 334 /* figure out the major/minor device # pair for this tty */ 335 gettty() 336 { 337 char ttybuf[20]; 338 struct stat statbuf; 339 340 ttybuf[0] = 0; 341 strcpy(ttybuf, _PATH_DEV); 342 strcat(ttybuf, utmp.ut_line); 343 stat(ttybuf, &statbuf); 344 tty = statbuf.st_rdev; 345 uid = statbuf.st_uid; 346 } 347 348 /* 349 * putline: print out the accumulated line of info about one user. 350 */ 351 putline() 352 { 353 register int tm; 354 int width = ttywidth - 1; 355 356 /* print login name of the user */ 357 printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, utmp.ut_name); 358 width -= UT_NAMESIZE + 1; 359 360 /* print tty user is on */ 361 if (lflag && !prfrom) { 362 /* long form: all (up to) UT_LINESIZE chars */ 363 printf("%-*.*s", UT_LINESIZE, UT_LINESIZE, utmp.ut_line); 364 width -= UT_LINESIZE; 365 } else { 366 /* short form: 2 chars, skipping 'tty' if there */ 367 if (utmp.ut_line[0]=='t' && utmp.ut_line[1]=='t' && utmp.ut_line[2]=='y') 368 printf("%-2.2s", &utmp.ut_line[3]); 369 else 370 printf("%-2.2s", utmp.ut_line); 371 width -= 2; 372 } 373 374 if (prfrom) { 375 if (*utmp.ut_host == '\0') 376 printf(" - "); 377 else 378 printf(" %-14.14s", utmp.ut_host); 379 width -= 15; 380 } 381 382 if (lflag) { 383 /* print when the user logged in */ 384 prtat(&utmp.ut_time); 385 width -= 8; 386 } 387 388 /* print idle time */ 389 if (idle >= 36 * 60) 390 printf(" %ddays ", (idle + 12 * 60) / (24 * 60)); 391 else 392 prttime(idle," "); 393 width -= 7; 394 395 if (lflag) { 396 /* print CPU time for all processes & children */ 397 prttime(jobtime," "); 398 width -= 7; 399 /* print cpu time for interesting process */ 400 prttime(proctime," "); 401 width -= 7; 402 } 403 404 /* what user is doing, either command tail or args */ 405 printf(" %-.*s\n", width-1, doing); 406 fflush(stdout); 407 } 408 409 /* find & return number of minutes current tty has been idle */ 410 time_t 411 findidle() 412 { 413 struct stat stbuf; 414 long lastaction, diff; 415 char ttyname[20]; 416 417 strcpy(ttyname, _PATH_DEV); 418 strncat(ttyname, utmp.ut_line, UT_LINESIZE); 419 stat(ttyname, &stbuf); 420 time(&now); 421 lastaction = stbuf.st_atime; 422 diff = now - lastaction; 423 diff = DIV60(diff); 424 if (diff < 0) diff = 0; 425 return(diff); 426 } 427 428 #define HR (60 * 60) 429 #define DAY (24 * HR) 430 #define MON (30 * DAY) 431 432 /* 433 * prttime prints a time in hours and minutes or minutes and seconds. 434 * The character string tail is printed at the end, obvious 435 * strings to pass are "", " ", or "am". 436 */ 437 prttime(tim, tail) 438 time_t tim; 439 char *tail; 440 { 441 442 if (tim >= 60) { 443 printf(" %2d:", tim/60); 444 tim %= 60; 445 printf("%02d", tim); 446 } else if (tim >= 0) 447 printf(" %2d", tim); 448 printf("%s", tail); 449 } 450 451 char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 452 char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 453 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 454 455 /* prtat prints a 12 hour time given a pointer to a time of day */ 456 prtat(time) 457 long *time; 458 { 459 struct tm *p; 460 register int hr, pm; 461 462 p = localtime(time); 463 hr = p->tm_hour; 464 pm = (hr > 11); 465 if (hr > 11) 466 hr -= 12; 467 if (hr == 0) 468 hr = 12; 469 if (now - *time <= 18 * HR) 470 prttime(hr * 60 + p->tm_min, pm ? "pm" : "am"); 471 else if (now - *time <= 7 * DAY) 472 printf(" %*s%d%s", hr < 10 ? 4 : 3, weekday[p->tm_wday], hr, 473 pm ? "pm" : "am"); 474 else 475 printf(" %2d%s%2d", p->tm_mday, month[p->tm_mon], p->tm_year); 476 } 477 478 /* 479 * readpr finds and reads in the array pr, containing the interesting 480 * parts of the proc and user tables for each live process. 481 * We only accept procs whos controlling tty has a pgrp equal to the 482 * pgrp of the proc. This accurately defines the notion of the current 483 * process(s), but because of time skew, we always read in the tty struct 484 * after reading the proc, even though the same tty struct may have been 485 * read earlier on. 486 */ 487 readpr() 488 { 489 int mf, addr, c; 490 int szpt, pfnum, i; 491 struct pte *Usrptma, *usrpt, *pte, apte; 492 struct dblock db; 493 struct kinfo_proc *kp; 494 register struct proc *p; 495 int nentries; 496 497 Usrptma = (struct pte *) nl[X_USRPTMA].n_value; 498 usrpt = (struct pte *) nl[X_USRPT].n_value; 499 if((mem = open(_PATH_MEM, 0)) < 0) { 500 fprintf(stderr, "w: no %s.\n", _PATH_MEM); 501 exit(1); 502 } 503 if ((swap = open(_PATH_DRUM, 0)) < 0) { 504 fprintf(stderr, "w: no %s\n", _PATH_DRUM); 505 exit(1); 506 } 507 /* 508 * read mem to find swap dev. 509 */ 510 lseek(kmem, (long)nl[X_SWAPDEV].n_value, 0); 511 read(kmem, &nl[X_SWAPDEV].n_value, sizeof(nl[X_SWAPDEV].n_value)); 512 /* 513 * Find base of and parameters of swap 514 */ 515 lseek(kmem, (long)nl[X_NSWAP].n_value, 0); 516 read(kmem, &nswap, sizeof(nswap)); 517 lseek(kmem, (long)nl[X_DMMIN].n_value, 0); 518 read(kmem, &dmmin, sizeof(dmmin)); 519 lseek(kmem, (long)nl[X_DMMAX].n_value, 0); 520 read(kmem, &dmmax, sizeof(dmmax)); 521 /* 522 * Read proc table. 523 */ 524 np = 0; 525 nentries = kvm_getkproc(&kp); 526 pr = (struct pr *)calloc(nentries, sizeof (struct pr)); 527 for (i=0; i < nentries; i++, kp++) { 528 p = &kp->kp_proc; 529 /* decide if it's an interesting process */ 530 if (p->p_stat==0 || p->p_stat==SZOMB 531 || p->p_stat==SSTOP) 532 continue; 533 /* find & read in the user structure */ 534 if ((p->p_flag & SLOAD) == 0) { 535 /* not in memory - get from swap device */ 536 addr = dtob(p->p_swaddr); 537 lseek(swap, (long)addr, 0); 538 if (read(swap, &up, sizeof(up)) != sizeof(up)) { 539 continue; 540 } 541 } else { 542 int p0br, cc; 543 #define INTPPG (NBPG / sizeof (int)) 544 struct pte pagetbl[NBPG / sizeof (struct pte)]; 545 /* loaded, get each page from memory separately */ 546 szpt = p->p_szpt; 547 p0br = (int)p->p_p0br; 548 pte = &Usrptma[btokmx(p->p_p0br) + szpt-1]; 549 lseek(kmem, (long)pte, 0); 550 if (read(kmem, &apte, sizeof(apte)) != sizeof(apte)) 551 continue; 552 lseek(mem, ctob(apte.pg_pfnum), 0); 553 if (read(mem,pagetbl,sizeof(pagetbl)) != sizeof(pagetbl)) 554 cont: 555 continue; 556 for(cc=0; cc<UPAGES; cc++) { /* get u area */ 557 int upage = pagetbl[NPTEPG-UPAGES+cc].pg_pfnum; 558 lseek(mem,ctob(upage),0); 559 if (read(mem,((int *)&up)+INTPPG*cc,NBPG) != NBPG) 560 goto cont; 561 } 562 szpt = up.u_pcb.pcb_szpt; 563 pr[np].w_seekaddr = ctob(apte.pg_pfnum); 564 } 565 vstodb(0, CLSIZE, &up.u_smap, &db, 1); 566 pr[np].w_lastpg = dtob(db.db_base); 567 if (kp->kp_eproc.kp_tdev == NODEV) 568 continue; 569 570 /* only include a process whose tty has a pgrp which matchs its own */ 571 if (kp->kp_eproc.kp_pgid != kp->kp_eproc.kp_tpgid) 572 continue; 573 574 /* save the interesting parts */ 575 pr[np].w_pid = p->p_pid; 576 pr[np].w_flag = p->p_flag; 577 pr[np].w_size = p->p_dsize + p->p_ssize; 578 pr[np].w_igintr = (((int)up.u_signal[2]==1) + 579 2*((int)up.u_signal[2]>1) + 3*((int)up.u_signal[3]==1)) + 580 6*((int)up.u_signal[3]>1); 581 pr[np].w_time = 582 up.u_ru.ru_utime.tv_sec + up.u_ru.ru_stime.tv_sec; 583 pr[np].w_ctime = 584 up.u_cru.ru_utime.tv_sec + up.u_cru.ru_stime.tv_sec; 585 pr[np].w_tty = kp->kp_eproc.kp_tdev; 586 pr[np].w_uid = p->p_uid; 587 strcpy(pr[np].w_comm, p->p_comm, MAXCOMLEN+1); 588 /* 589 * Get args if there's a chance we'll print it. 590 * Can't just save pointer: getargs returns static place. 591 * Can't use strncpy, it blank pads. 592 */ 593 pr[np].w_args[0] = 0; 594 strncat(pr[np].w_args,getargs(&pr[np]),ARGWIDTH); 595 if (pr[np].w_args[0]==0 || pr[np].w_args[0]=='-' && pr[np].w_args[1]<=' ' || pr[np].w_args[0] == '?') { 596 strcat(pr[np].w_args, " ("); 597 strcat(pr[np].w_args, pr[np].w_comm); 598 strcat(pr[np].w_args, ")"); 599 } 600 np++; 601 } 602 } 603 604 /* 605 * getargs: given a pointer to a proc structure, this looks at the swap area 606 * and tries to reconstruct the arguments. This is straight out of ps. 607 */ 608 char * 609 getargs(p) 610 struct pr *p; 611 { 612 int c, addr, nbad; 613 static int abuf[CLSIZE*NBPG/sizeof(int)]; 614 struct pte pagetbl[NPTEPG]; 615 register int *ip; 616 register char *cp, *cp1; 617 618 if ((p->w_flag & SLOAD) == 0) { 619 lseek(swap, p->w_lastpg, 0); 620 if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf)) 621 return(p->w_comm); 622 } else { 623 c = p->w_seekaddr; 624 lseek(mem,c,0); 625 if (read(mem,pagetbl,NBPG) != NBPG) 626 return(p->w_comm); 627 if (pagetbl[NPTEPG-CLSIZE-UPAGES].pg_fod==0 && pagetbl[NPTEPG-CLSIZE-UPAGES].pg_pfnum) { 628 lseek(mem,ctob(pagetbl[NPTEPG-CLSIZE-UPAGES].pg_pfnum),0); 629 if (read(mem,abuf,sizeof(abuf)) != sizeof(abuf)) 630 return(p->w_comm); 631 } else { 632 lseek(swap, p->w_lastpg, 0); 633 if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf)) 634 return(p->w_comm); 635 } 636 } 637 abuf[sizeof(abuf)/sizeof(abuf[0])-1] = 0; 638 for (ip = &abuf[sizeof(abuf)/sizeof(abuf[0])-2]; ip > abuf;) { 639 /* Look from top for -1 or 0 as terminator flag. */ 640 if (*--ip == -1 || *ip == 0) { 641 cp = (char *)(ip+1); 642 if (*cp==0) 643 cp++; 644 nbad = 0; /* up to 5 funny chars as ?'s */ 645 for (cp1 = cp; cp1 < (char *)&abuf[sizeof(abuf)/sizeof(abuf[0])]; cp1++) { 646 c = *cp1&0177; 647 if (c==0) /* nulls between args => spaces */ 648 *cp1 = ' '; 649 else if (c < ' ' || c > 0176) { 650 if (++nbad >= 5) { 651 *cp1++ = ' '; 652 break; 653 } 654 *cp1 = '?'; 655 } else if (c=='=') { /* Oops - found an 656 * environment var, back 657 * over & erase it. */ 658 *cp1 = 0; 659 while (cp1>cp && *--cp1!=' ') 660 *cp1 = 0; 661 break; 662 } 663 } 664 while (*--cp1==' ') /* strip trailing spaces */ 665 *cp1 = 0; 666 return(cp); 667 } 668 } 669 return (p->w_comm); 670 } 671 672 /* 673 * Given a base/size pair in virtual swap area, 674 * return a physical base/size pair which is the 675 * (largest) initial, physically contiguous block. 676 */ 677 vstodb(vsbase, vssize, dmp, dbp, rev) 678 register int vsbase; 679 int vssize; 680 struct dmap *dmp; 681 register struct dblock *dbp; 682 { 683 register int blk = dmmin; 684 register swblk_t *ip = dmp->dm_map; 685 686 vsbase = ctod(vsbase); 687 vssize = ctod(vssize); 688 if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 689 panic("vstodb"); 690 while (vsbase >= blk) { 691 vsbase -= blk; 692 if (blk < dmmax) 693 blk *= 2; 694 ip++; 695 } 696 if (*ip <= 0 || *ip + blk > nswap) 697 panic("vstodb *ip"); 698 dbp->db_size = MIN(vssize, blk - vsbase); 699 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase); 700 } 701 702 panic(cp) 703 char *cp; 704 { 705 706 /* printf("%s\n", cp); */ 707 } 708 709 #define PROCSLOP (5 * sizeof (struct kinfo_proc)) 710 kvm_getkproc(bp) 711 char **bp; 712 { 713 int ret; 714 int copysize; 715 int need; 716 char *buff; 717 718 if ((ret = syscall(63, KINFO_PROC_ALL, NULL, NULL, 0)) == -1) { 719 perror("ktable, error getting estimate"); 720 return (0); 721 } 722 copysize = ret + PROCSLOP; /* XXX PROCSLOP should be in header ? */ 723 buff = (char *)malloc(copysize); 724 if (buff == NULL) { 725 fprintf(stderr, "out of memory"); 726 exit (1); 727 } 728 if ((ret = syscall(63, KINFO_PROC_ALL, buff, ©size, 0)) == -1) { 729 perror("ktable"); 730 return (0); 731 } 732 *bp = buff; 733 734 return (copysize / sizeof (struct kinfo_proc)); 735 } 736