| 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 | { "" }, |
| 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 *strncmp(); |
| 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/mem"; |
| 110 | if(kflg) |
| 111 | coref = "/usr/sys/core"; |
| 112 | if ((mem = open(coref, 0)) < 0) { |
| 113 | fprintf(stderr, "No mem\n"); |
| 114 | exit(1); |
| 115 | } |
| 116 | swmem = open(coref, 0); |
| 117 | /* |
| 118 | * read mem to find swap dev. |
| 119 | */ |
| 120 | lseek(mem, (long)nl[1].n_value, 0); |
| 121 | read(mem, (char *)&nl[1].n_value, sizeof(nl[1].n_value)); |
| 122 | /* |
| 123 | * Find base of swap |
| 124 | */ |
| 125 | lseek(mem, (long)nl[2].n_value, 0); |
| 126 | read(mem, (char *)&swplo, sizeof(swplo)); |
| 127 | /* |
| 128 | * Locate proc table |
| 129 | */ |
| 130 | lseek(mem, (long)nl[0].n_value, 0); |
| 131 | getdev(); |
| 132 | uid = getuid(); |
| 133 | if (lflg) |
| 134 | printf(" F S UID PID PPID CPU PRI NICE ADDR SZ WCHAN TTY TIME CMD\n"); else |
| 135 | if (chkpid==0) printf(" PID TTY TIME CMD\n"); |
| 136 | for (i=0; i<NPROC; i++) { |
| 137 | read(mem, (char *)&mproc, sizeof mproc); |
| 138 | if (mproc.p_stat==0) |
| 139 | continue; |
| 140 | if (mproc.p_pgrp==0 && xflg==0 && mproc.p_uid==0) |
| 141 | continue; |
| 142 | puid = mproc.p_uid; |
| 143 | if ((uid != puid && aflg==0) || |
| 144 | (chkpid!=0 && chkpid!=mproc.p_pid)) |
| 145 | continue; |
| 146 | if(prcom(puid)) { |
| 147 | printf("\n"); |
| 148 | retcode=0; |
| 149 | } |
| 150 | } |
| 151 | exit(retcode); |
| 152 | } |
| 153 | |
| 154 | getdev() |
| 155 | { |
| 156 | #include <sys/stat.h> |
| 157 | register FILE *df; |
| 158 | struct stat sbuf; |
| 159 | struct direct dbuf; |
| 160 | |
| 161 | if ((df = fopen("/dev", "r")) == NULL) { |
| 162 | fprintf(stderr, "Can't open /dev\n"); |
| 163 | exit(1); |
| 164 | } |
| 165 | ndev = 0; |
| 166 | while (fread((char *)&dbuf, sizeof(dbuf), 1, df) == 1) { |
| 167 | if(dbuf.d_ino == 0) |
| 168 | continue; |
| 169 | if(stat(dbuf.d_name, &sbuf) < 0) |
| 170 | continue; |
| 171 | if ((sbuf.st_mode&S_IFMT) != S_IFCHR) |
| 172 | continue; |
| 173 | strcpy(devl[ndev].dname, dbuf.d_name); |
| 174 | devl[ndev].dev = sbuf.st_rdev; |
| 175 | ndev++; |
| 176 | } |
| 177 | fclose(df); |
| 178 | if ((swap = open("/dev/swap", 0)) < 0) { |
| 179 | fprintf(stderr, "Can't open /dev/swap\n"); |
| 180 | exit(1); |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | long |
| 185 | round(a, b) |
| 186 | long a, b; |
| 187 | { |
| 188 | long w = ((a+b-1)/b)*b; |
| 189 | |
| 190 | return(w); |
| 191 | } |
| 192 | |
| 193 | struct map { |
| 194 | long b1, e1; long f1; |
| 195 | long b2, e2; long f2; |
| 196 | }; |
| 197 | struct map datmap; |
| 198 | int file; |
| 199 | prcom(puid) |
| 200 | { |
| 201 | char abuf[512]; |
| 202 | long addr; |
| 203 | register int *ip; |
| 204 | register char *cp, *cp1; |
| 205 | long tm; |
| 206 | int c, nbad; |
| 207 | register char *tp; |
| 208 | long txtsiz, datsiz, stksiz; |
| 209 | int septxt; |
| 210 | int lw=(lflg?35:80); |
| 211 | char **ap; |
| 212 | |
| 213 | if (mproc.p_flag&SLOAD) { |
| 214 | addr = ctob((long)mproc.p_addr); |
| 215 | file = swmem; |
| 216 | } else { |
| 217 | addr = (mproc.p_addr+swplo)<<9; |
| 218 | file = swap; |
| 219 | } |
| 220 | lseek(file, addr, 0); |
| 221 | if (read(file, (char *)&u, sizeof(u)) != sizeof(u)) |
| 222 | return(0); |
| 223 | |
| 224 | /* set up address maps for user pcs */ |
| 225 | txtsiz = ctob(u.u_tsize); |
| 226 | datsiz = ctob(u.u_dsize); |
| 227 | stksiz = ctob(u.u_ssize); |
| 228 | septxt = u.u_sep; |
| 229 | datmap.b1 = (septxt ? 0 : round(txtsiz,TXTRNDSIZ)); |
| 230 | datmap.e1 = datmap.b1+datsiz; |
| 231 | datmap.f1 = ctob(USIZE)+addr; |
| 232 | datmap.b2 = stackbas(stksiz); |
| 233 | datmap.e2 = stacktop(stksiz); |
| 234 | datmap.f2 = ctob(USIZE)+(datmap.e1-datmap.b1)+addr; |
| 235 | |
| 236 | tp = gettty(); |
| 237 | if (tptr && strncmp(tptr, tp, 2)) |
| 238 | return(0); |
| 239 | if (lflg) { |
| 240 | printf("%2o %c%4d", mproc.p_flag, |
| 241 | "0SWRIZT"[mproc.p_stat], puid); |
| 242 | } |
| 243 | printf("%6u", mproc.p_pid); |
| 244 | if (lflg) { |
| 245 | printf("%6u%4d%4d%5d%6o%4d", mproc.p_ppid, mproc.p_cpu&0377, |
| 246 | mproc.p_pri, |
| 247 | mproc.p_nice, |
| 248 | mproc.p_addr, (mproc.p_size+7)>>3); |
| 249 | if (mproc.p_wchan) |
| 250 | printf("%7o", mproc.p_wchan); |
| 251 | else |
| 252 | printf(" "); |
| 253 | } |
| 254 | printf(" %-2.2s", tp); |
| 255 | if (mproc.p_stat==SZOMB) { |
| 256 | printf(" <defunct>"); |
| 257 | return(1); |
| 258 | } |
| 259 | tm = (u.u_utime + u.u_stime + 30)/60; |
| 260 | printf(" %2ld:", tm/60); |
| 261 | tm %= 60; |
| 262 | printf(tm<10?"0%ld":"%ld", tm); |
| 263 | if (vflg && lflg==0) { /* 0 == old tflg (print long times) */ |
| 264 | tm = (u.u_cstime + 30)/60; |
| 265 | printf(" %2ld:", tm/60); |
| 266 | tm %= 60; |
| 267 | printf(tm<10?"0%ld":"%ld", tm); |
| 268 | tm = (u.u_cutime + 30)/60; |
| 269 | printf(" %2ld:", tm/60); |
| 270 | tm %= 60; |
| 271 | printf(tm<10?"0%ld":"%ld", tm); |
| 272 | } |
| 273 | if (mproc.p_pid == 0) { |
| 274 | printf(" swapper"); |
| 275 | return(1); |
| 276 | } |
| 277 | addr += ctob((long)mproc.p_size) - 512; |
| 278 | |
| 279 | /* look for sh special */ |
| 280 | lseek(file, addr+512-sizeof(char **), 0); |
| 281 | if (read(file, (char *)&ap, sizeof(char *)) != sizeof(char *)) |
| 282 | return(1); |
| 283 | if (ap) { |
| 284 | char b[82]; |
| 285 | char *bp = b; |
| 286 | while((cp=getptr(ap++)) && cp && (bp<b+lw) ) { |
| 287 | nbad = 0; |
| 288 | while((c=getbyte(cp++)) && (bp<b+lw)) { |
| 289 | if (c<' ' || c>'~') { |
| 290 | if (nbad++>3) |
| 291 | break; |
| 292 | continue; |
| 293 | } |
| 294 | *bp++ = c; |
| 295 | } |
| 296 | *bp++ = ' '; |
| 297 | } |
| 298 | *bp++ = 0; |
| 299 | printf(lflg?" %.30s":" %.60s", b); |
| 300 | return(1); |
| 301 | } |
| 302 | |
| 303 | lseek(file, addr, 0); |
| 304 | if (read(file, abuf, sizeof(abuf)) != sizeof(abuf)) |
| 305 | return(1); |
| 306 | for (ip = (int *)&abuf[512]-2; ip > (int *)abuf; ) { |
| 307 | if (*--ip == -1 || *ip==0) { |
| 308 | cp = (char *)(ip+1); |
| 309 | if (*cp==0) |
| 310 | cp++; |
| 311 | nbad = 0; |
| 312 | for (cp1 = cp; cp1 < &abuf[512]; cp1++) { |
| 313 | c = *cp1&0177; |
| 314 | if (c==0) |
| 315 | *cp1 = ' '; |
| 316 | else if (c < ' ' || c > 0176) { |
| 317 | if (++nbad >= 5) { |
| 318 | *cp1++ = ' '; |
| 319 | break; |
| 320 | } |
| 321 | *cp1 = '?'; |
| 322 | } else if (c=='=') { |
| 323 | *cp1 = 0; |
| 324 | while (cp1>cp && *--cp1!=' ') |
| 325 | *cp1 = 0; |
| 326 | break; |
| 327 | } |
| 328 | } |
| 329 | while (*--cp1==' ') |
| 330 | *cp1 = 0; |
| 331 | printf(lflg?" %.30s":" %.60s", cp); |
| 332 | return(1); |
| 333 | } |
| 334 | } |
| 335 | return(1); |
| 336 | } |
| 337 | |
| 338 | char * |
| 339 | gettty() |
| 340 | { |
| 341 | register i; |
| 342 | register char *p; |
| 343 | |
| 344 | if (u.u_ttyp==0) |
| 345 | return("?"); |
| 346 | for (i=0; i<ndev; i++) { |
| 347 | if (devl[i].dev == u.u_ttyd) { |
| 348 | p = devl[i].dname; |
| 349 | if (p[0]=='t' && p[1]=='t' && p[2]=='y') |
| 350 | p += 3; |
| 351 | return(p); |
| 352 | } |
| 353 | } |
| 354 | return("?"); |
| 355 | } |
| 356 | |
| 357 | char * |
| 358 | getptr(adr) |
| 359 | char **adr; |
| 360 | { |
| 361 | char *ptr; |
| 362 | register char *p, *pa; |
| 363 | register i; |
| 364 | |
| 365 | ptr = 0; |
| 366 | pa = (char *)adr; |
| 367 | p = (char *)&ptr; |
| 368 | for (i=0; i<sizeof(ptr); i++) |
| 369 | *p++ = getbyte(pa++); |
| 370 | return(ptr); |
| 371 | } |
| 372 | |
| 373 | getbyte(adr) |
| 374 | char *adr; |
| 375 | { |
| 376 | register struct map *amap = &datmap; |
| 377 | char b; |
| 378 | long saddr; |
| 379 | |
| 380 | if(!within(adr, amap->b1, amap->e1)) { |
| 381 | if(within(adr, amap->b2, amap->e2)) { |
| 382 | saddr = (unsigned)adr + amap->f2 - amap->b2; |
| 383 | } else |
| 384 | return(0); |
| 385 | } else |
| 386 | saddr = (unsigned)adr + amap->f1 - amap->b1; |
| 387 | if(lseek(file, saddr, 0)==-1 |
| 388 | || read(file, &b, 1)<1) { |
| 389 | return(0); |
| 390 | } |
| 391 | return((unsigned)b); |
| 392 | } |
| 393 | |
| 394 | |
| 395 | within(adr,lbd,ubd) |
| 396 | char *adr; |
| 397 | long lbd, ubd; |
| 398 | { |
| 399 | return((unsigned)adr>=lbd && (unsigned)adr<ubd); |
| 400 | } |