| 1 | /* |
| 2 | * ps - process status |
| 3 | * examine and print certain things about processes |
| 4 | */ |
| 5 | |
| 6 | #include <stdio.h> |
| 7 | #include <a.out.h> |
| 8 | #include <core.h> |
| 9 | #include <sys/param.h> |
| 10 | #include <sys/proc.h> |
| 11 | #include <sys/tty.h> |
| 12 | #include <sys/dir.h> |
| 13 | #include <sys/user.h> |
| 14 | |
| 15 | struct nlist nl[] = { |
| 16 | { "_proc" }, |
| 17 | { "_swapdev" }, |
| 18 | { "_swplo" }, |
| 19 | { 0 }, |
| 20 | }; |
| 21 | |
| 22 | struct proc mproc; |
| 23 | |
| 24 | struct user u; |
| 25 | int chkpid; |
| 26 | int retcode=1; |
| 27 | int lflg; |
| 28 | int vflg; |
| 29 | int kflg; |
| 30 | int xflg; |
| 31 | char *tptr; |
| 32 | long lseek(); |
| 33 | char *gettty(); |
| 34 | char *getptr(); |
| 35 | char *strcmpn(); |
| 36 | int aflg; |
| 37 | int mem; |
| 38 | int swmem; |
| 39 | int swap; |
| 40 | daddr_t swplo; |
| 41 | |
| 42 | int ndev; |
| 43 | struct devl { |
| 44 | char dname[DIRSIZ]; |
| 45 | dev_t dev; |
| 46 | } devl[256]; |
| 47 | |
| 48 | char *coref; |
| 49 | |
| 50 | main(argc, argv) |
| 51 | char **argv; |
| 52 | { |
| 53 | int i; |
| 54 | char *ap; |
| 55 | int uid, puid; |
| 56 | |
| 57 | if (argc>1) { |
| 58 | ap = argv[1]; |
| 59 | while (*ap) switch (*ap++) { |
| 60 | |
| 61 | case 'v': |
| 62 | vflg++; |
| 63 | break; |
| 64 | |
| 65 | case 'a': |
| 66 | aflg++; |
| 67 | break; |
| 68 | |
| 69 | case 't': |
| 70 | if(*ap) |
| 71 | tptr = ap; |
| 72 | aflg++; |
| 73 | if (*tptr == '?') |
| 74 | xflg++; |
| 75 | goto bbreak; |
| 76 | |
| 77 | case 'x': |
| 78 | xflg++; |
| 79 | break; |
| 80 | |
| 81 | case '-': |
| 82 | break; |
| 83 | |
| 84 | case 'l': |
| 85 | lflg++; |
| 86 | break; |
| 87 | |
| 88 | case 'k': |
| 89 | kflg++; |
| 90 | break; |
| 91 | |
| 92 | default: |
| 93 | chkpid = atoi(ap-1); |
| 94 | goto bbreak; |
| 95 | break; |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | bbreak: |
| 100 | if(chdir("/dev") < 0) { |
| 101 | fprintf(stderr, "Can't change to /dev\n"); |
| 102 | exit(1); |
| 103 | } |
| 104 | nlist(argc>2? argv[2]:"/unix", nl); |
| 105 | if (nl[0].n_type==0) { |
| 106 | fprintf(stderr, "No namelist\n"); |
| 107 | exit(1); |
| 108 | } |
| 109 | coref = "/dev/kmem"; |
| 110 | if(kflg) |
| 111 | coref = "/usr/sys/core"; |
| 112 | if ((mem = open(coref, 0)) < 0) { |
| 113 | fprintf(stderr, "No kmem\n"); |
| 114 | exit(1); |
| 115 | } |
| 116 | if ((swmem = open("/dev/mem", 0)) < 0) { |
| 117 | fprintf(stderr, "No mem\n"); |
| 118 | exit(1); |
| 119 | } |
| 120 | /* |
| 121 | * read mem to find swap dev. |
| 122 | */ |
| 123 | lseek(mem, (long)nl[1].n_value, 0); |
| 124 | read(mem, (char *)&nl[1].n_value, sizeof(nl[1].n_value)); |
| 125 | /* |
| 126 | * Find base of swap |
| 127 | */ |
| 128 | lseek(mem, (long)nl[2].n_value, 0); |
| 129 | read(mem, (char *)&swplo, sizeof(swplo)); |
| 130 | /* |
| 131 | * Locate proc table |
| 132 | */ |
| 133 | lseek(mem, (long)nl[0].n_value, 0); |
| 134 | getdev(); |
| 135 | uid = getuid(); |
| 136 | if (lflg) |
| 137 | printf(" F S UID PID PPID CPU PRI NICE ADDR SZ WCHAN TTY TIME CMD\n"); else |
| 138 | if (chkpid==0) printf(" PID TTY TIME CMD\n"); |
| 139 | for (i=0; i<NPROC; i++) { |
| 140 | read(mem, (char *)&mproc, sizeof mproc); |
| 141 | if (mproc.p_stat==0) |
| 142 | continue; |
| 143 | if (mproc.p_pgrp==0 && xflg==0 && mproc.p_uid==0) |
| 144 | continue; |
| 145 | puid = mproc.p_uid; |
| 146 | if ((uid != puid && aflg==0) || |
| 147 | (chkpid!=0 && chkpid!=mproc.p_pid)) |
| 148 | continue; |
| 149 | if(prcom(puid)) { |
| 150 | printf("\n"); |
| 151 | retcode=0; |
| 152 | } |
| 153 | } |
| 154 | exit(retcode); |
| 155 | } |
| 156 | |
| 157 | getdev() |
| 158 | { |
| 159 | #include <sys/stat.h> |
| 160 | register FILE *df; |
| 161 | struct stat sbuf; |
| 162 | struct direct dbuf; |
| 163 | |
| 164 | if ((df = fopen("/dev", "r")) == NULL) { |
| 165 | fprintf(stderr, "Can't open /dev\n"); |
| 166 | exit(1); |
| 167 | } |
| 168 | ndev = 0; |
| 169 | while (fread((char *)&dbuf, sizeof(dbuf), 1, df) == 1) { |
| 170 | if(dbuf.d_ino == 0) |
| 171 | continue; |
| 172 | if(stat(dbuf.d_name, &sbuf) < 0) |
| 173 | continue; |
| 174 | if ((sbuf.st_mode&S_IFMT) != S_IFCHR) |
| 175 | continue; |
| 176 | strcpy(devl[ndev].dname, dbuf.d_name); |
| 177 | devl[ndev].dev = sbuf.st_rdev; |
| 178 | ndev++; |
| 179 | } |
| 180 | fclose(df); |
| 181 | if ((swap = open("/dev/swap", 0)) < 0) { |
| 182 | fprintf(stderr, "Can't open /dev/swap\n"); |
| 183 | exit(1); |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | long |
| 188 | round(a, b) |
| 189 | long a, b; |
| 190 | { |
| 191 | long w = ((a+b-1)/b)*b; |
| 192 | |
| 193 | return(w); |
| 194 | } |
| 195 | |
| 196 | struct map { |
| 197 | long b1, e1; long f1; |
| 198 | long b2, e2; long f2; |
| 199 | }; |
| 200 | struct map datmap; |
| 201 | int file; |
| 202 | prcom(puid) |
| 203 | { |
| 204 | char abuf[512]; |
| 205 | long addr; |
| 206 | register int *ip; |
| 207 | register char *cp, *cp1; |
| 208 | long tm; |
| 209 | int c, nbad; |
| 210 | register char *tp; |
| 211 | long txtsiz, datsiz, stksiz; |
| 212 | int lw=(lflg?35:80); |
| 213 | char **ap; |
| 214 | |
| 215 | if (mproc.p_flag&SLOAD) { |
| 216 | addr = ctob((long)mproc.p_addr); |
| 217 | file = swmem; |
| 218 | } else { |
| 219 | addr = (mproc.p_addr+swplo)<<9; |
| 220 | file = swap; |
| 221 | } |
| 222 | lseek(file, addr, 0); |
| 223 | if (read(file, (char *)&u, sizeof(u)) != sizeof(u)) |
| 224 | return(0); |
| 225 | |
| 226 | /* set up address maps for user pcs */ |
| 227 | txtsiz = ctob(u.u_tsize); |
| 228 | datsiz = ctob(u.u_dsize); |
| 229 | stksiz = ctob(u.u_ssize); |
| 230 | datmap.b1 = round(txtsiz,TXTRNDSIZ); |
| 231 | datmap.e1 = datmap.b1+datsiz; |
| 232 | datmap.f1 = ctob(USIZE)+addr; |
| 233 | datmap.b2 = stackbas(stksiz); |
| 234 | datmap.e2 = stacktop(stksiz); |
| 235 | datmap.f2 = ctob(USIZE)+(datmap.e1-datmap.b1)+addr; |
| 236 | |
| 237 | tp = gettty(); |
| 238 | if (tptr && strcmpn(tptr, tp, 2)) |
| 239 | return(0); |
| 240 | if (lflg) { |
| 241 | printf("%2o %c%4d", mproc.p_flag, |
| 242 | "0SWRIZT"[mproc.p_stat], puid); |
| 243 | } |
| 244 | printf("%6u", mproc.p_pid); |
| 245 | if (lflg) { |
| 246 | printf("%6u%4d%4d%5d%6x%4d", mproc.p_ppid, mproc.p_cpu&0377, |
| 247 | mproc.p_pri, |
| 248 | mproc.p_nice, |
| 249 | mproc.p_addr, mproc.p_size); |
| 250 | if (mproc.p_wchan) |
| 251 | printf("%9x", mproc.p_wchan); |
| 252 | else |
| 253 | printf(" "); |
| 254 | } |
| 255 | printf(" %-2.2s", tp); |
| 256 | if (mproc.p_stat==SZOMB) { |
| 257 | printf(" <defunct>"); |
| 258 | return(1); |
| 259 | } |
| 260 | tm = (u.u_utime + u.u_stime + 30)/60; |
| 261 | printf(" %2ld:", tm/60); |
| 262 | tm %= 60; |
| 263 | printf(tm<10?"0%ld":"%ld", tm); |
| 264 | if (vflg && lflg==0) { /* 0 == old tflg (print long times) */ |
| 265 | tm = (u.u_cstime + 30)/60; |
| 266 | printf(" %2ld:", tm/60); |
| 267 | tm %= 60; |
| 268 | printf(tm<10?"0%ld":"%ld", tm); |
| 269 | tm = (u.u_cutime + 30)/60; |
| 270 | printf(" %2ld:", tm/60); |
| 271 | tm %= 60; |
| 272 | printf(tm<10?"0%ld":"%ld", tm); |
| 273 | } |
| 274 | if (mproc.p_pid == 0) { |
| 275 | printf(" swapper"); |
| 276 | return(1); |
| 277 | } |
| 278 | addr += ctob((long)mproc.p_size) - 512; |
| 279 | |
| 280 | /* look for sh special */ |
| 281 | lseek(file, addr+512-sizeof(char **), 0); |
| 282 | if (read(file, (char *)&ap, sizeof(char *)) != sizeof(char *)) |
| 283 | return(1); |
| 284 | if (ap) { |
| 285 | char b[82]; |
| 286 | char *bp = b; |
| 287 | while((cp=getptr(ap++)) && cp && (bp<b+lw) ) { |
| 288 | nbad = 0; |
| 289 | while((c=getbyte(cp++)) && (bp<b+lw)) { |
| 290 | if (c<' ' || c>'~') { |
| 291 | if (nbad++>3) |
| 292 | break; |
| 293 | continue; |
| 294 | } |
| 295 | *bp++ = c; |
| 296 | } |
| 297 | *bp++ = ' '; |
| 298 | } |
| 299 | *bp++ = 0; |
| 300 | printf(lflg?" %.30s":" %.60s", b); |
| 301 | return(1); |
| 302 | } |
| 303 | |
| 304 | lseek(file, addr, 0); |
| 305 | if (read(file, abuf, sizeof(abuf)) != sizeof(abuf)) |
| 306 | return(1); |
| 307 | for (ip = (int *)&abuf[512]-2; ip > (int *)abuf; ) { |
| 308 | if (*--ip == -1 || *ip==0) { |
| 309 | cp = (char *)(ip+1); |
| 310 | if (*cp==0) |
| 311 | cp++; |
| 312 | nbad = 0; |
| 313 | for (cp1 = cp; cp1 < &abuf[512]; cp1++) { |
| 314 | c = *cp1&0177; |
| 315 | if (c==0) |
| 316 | *cp1 = ' '; |
| 317 | else if (c < ' ' || c > 0176) { |
| 318 | if (++nbad >= 5) { |
| 319 | *cp1++ = ' '; |
| 320 | break; |
| 321 | } |
| 322 | *cp1 = '?'; |
| 323 | } else if (c=='=') { |
| 324 | *cp1 = 0; |
| 325 | while (cp1>cp && *--cp1!=' ') |
| 326 | *cp1 = 0; |
| 327 | break; |
| 328 | } |
| 329 | } |
| 330 | while (*--cp1==' ') |
| 331 | *cp1 = 0; |
| 332 | printf(lflg?" %.30s":" %.60s", cp); |
| 333 | return(1); |
| 334 | } |
| 335 | } |
| 336 | return(1); |
| 337 | } |
| 338 | |
| 339 | char * |
| 340 | gettty() |
| 341 | { |
| 342 | register i; |
| 343 | register char *p; |
| 344 | |
| 345 | if (u.u_ttyp==0) |
| 346 | return("?"); |
| 347 | for (i=0; i<ndev; i++) { |
| 348 | if (devl[i].dev == u.u_ttyd) { |
| 349 | p = devl[i].dname; |
| 350 | if (p[0]=='t' && p[1]=='t' && p[2]=='y') |
| 351 | p += 3; |
| 352 | return(p); |
| 353 | } |
| 354 | } |
| 355 | return("?"); |
| 356 | } |
| 357 | |
| 358 | char * |
| 359 | getptr(adr) |
| 360 | char **adr; |
| 361 | { |
| 362 | char *ptr; |
| 363 | register char *p, *pa; |
| 364 | register i; |
| 365 | |
| 366 | ptr = 0; |
| 367 | pa = (char *)adr; |
| 368 | p = (char *)&ptr; |
| 369 | for (i=0; i<sizeof(ptr); i++) |
| 370 | *p++ = getbyte(pa++); |
| 371 | return(ptr); |
| 372 | } |
| 373 | |
| 374 | getbyte(adr) |
| 375 | char *adr; |
| 376 | { |
| 377 | register struct map *amap = &datmap; |
| 378 | char b; |
| 379 | long saddr; |
| 380 | |
| 381 | if(!within(adr, amap->b1, amap->e1)) { |
| 382 | if(within(adr, amap->b2, amap->e2)) { |
| 383 | saddr = (unsigned)adr + amap->f2 - amap->b2; |
| 384 | } else |
| 385 | return(0); |
| 386 | } else |
| 387 | saddr = (unsigned)adr + amap->f1 - amap->b1; |
| 388 | if(lseek(file, saddr, 0)==-1 |
| 389 | || read(file, &b, 1)<1) { |
| 390 | return(0); |
| 391 | } |
| 392 | return((unsigned)b); |
| 393 | } |
| 394 | |
| 395 | |
| 396 | within(adr,lbd,ubd) |
| 397 | char *adr; |
| 398 | long lbd, ubd; |
| 399 | { |
| 400 | return((unsigned)adr>=lbd && (unsigned)adr<ubd); |
| 401 | } |