|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <string.h> ! 3: #include <sys/coherent.h> ! 4: #include <sys/coh_ps.h> ! 5: #include <fcntl.h> ! 6: #include <sys/types.h> ! 7: #include <sys/stat.h> ! 8: #include <dirent.h> ! 9: #include <pwd.h> ! 10: #include "ps.h" ! 11: ! 12: #define PROC_NUM 64 /* Number of processes */ ! 13: #define CON_SIZE 8 /* max # of bytes in contrl terminal filed */ ! 14: ! 15: extern char *malloc(); ! 16: void vGetData(); /* Read the data about all processes */ ! 17: void vCvtArgs(); /* Process command line */ ! 18: void vPrintPs(); /* Print data */ ! 19: void vPrintHeader(); /* Print ps header */ ! 20: void vPrintLine(); /* Print ps data */ ! 21: dev_t dvtGetTerminal();/* Get ps controlling terminal */ ! 22: int iState(); /* Is the process asleep, running, or zombie? */ ! 23: void ReadDevDir(); /* Read device directory */ ! 24: unsigned uOkToPrint(); /* Is the process one we want to display? */ ! 25: ! 26: stMonitor *pMonData = NULL; /* Pointer to an array of data for ps */ ! 27: int iRet; /* Number of bytes read */ ! 28: dev_t dvtPs; /* ps device */ ! 29: ! 30: #define MAXPROCESSES 40 /* # max number of precesses */ ! 31: ! 32: unsigned auProcessP[MAXPROCESSES]; /* List of process to print */ ! 33: int iNumProcessP = 0; /* Number of process to print */ ! 34: ! 35: static stDevices *pstDevFirst= NULL; /* List of character devices. */ ! 36: ! 37: /* Flags for input command options */ ! 38: int iaFlag, /* Display information from all terminals */ ! 39: idFlag, /* Status of loadable drivers */ ! 40: ifFlag, /* Blank fields have '-' */ ! 41: igFlag, /* Print group leader if l given */ ! 42: ilFlag, /* Long format */ ! 43: imFlag, /* Scheduling fields */ ! 44: inFlag, /* Suppress header line */ ! 45: ipFlag, /* Print only specified processes */ ! 46: irFlag, /* Print real size of processes */ ! 47: itFlag, /* Print elapsed CPU time */ ! 48: iwFlag, /* Wide format (print 132 columns) */ ! 49: ixFlag; /* Display processes without controlling terminals */ ! 50: ! 51: /* ! 52: * Print out process status. ! 53: */ ! 54: main(argc, argv) ! 55: int argc; ! 56: char *argv[]; ! 57: { ! 58: /* ! 59: * To preserve compatibility with older versions of COHERENT ps ! 60: * we will fake minus here. Be aware that it adds '-' not only to ! 61: * the command line options but to their arguments as well ;-( ! 62: * See 'p' case. ! 63: */ ! 64: fakeMinus(argc, argv); ! 65: /* ! 66: * Digest the command line. ! 67: * ! 68: * This routine will not return if there are errors in ! 69: * the command line. ! 70: */ ! 71: vCvtArgs(argc, argv); ! 72: ! 73: /* This function will not return if error occurs */ ! 74: vGetData(); ! 75: ! 76: /* Get dev_t value for device from which ps was fired */ ! 77: dvtPs = dvtGetTerminal(); ! 78: ! 79: /* We have our data and all flags are set. So, we can print it */ ! 80: vPrintPs(); ! 81: } ! 82: ! 83: /* ! 84: * Fetch all data for ps from the kernel. ! 85: */ ! 86: void vGetData() ! 87: { ! 88: int fd; /* File descriptor to /dev/ps*/ ! 89: int iCnt; /* number of attempt to read */ ! 90: ! 91: /* Open process device */ ! 92: if ((fd = open("/dev/ps", O_RDONLY)) < 0) { ! 93: fflush(stdout); ! 94: perror("ps: cannot open /dev/ps"); ! 95: exit(1); ! 96: } ! 97: ! 98: /* This is our main engine. At this point we do not know the ! 99: * total number of processes. So, we start from our gess PROC_NUM. ! 100: * If we get close enough, do realloc and try again. ! 101: */ ! 102: for (iCnt = 0, iRet = 0; iCnt - iRet <= sizeof(stMonitor); ) { ! 103: iCnt += sizeof(stMonitor) * PROC_NUM; ! 104: if (pMonData != NULL) ! 105: free(pMonData); ! 106: if ((pMonData = (stMonitor *) malloc(iCnt)) == NULL) { ! 107: fflush(stdout); ! 108: perror("ps"); ! 109: exit(1); ! 110: } ! 111: if ((iRet = read(fd, (char *) pMonData, iCnt)) < 0) { ! 112: fflush(stdout); ! 113: perror("ps"); ! 114: exit(1); ! 115: } ! 116: } ! 117: ! 118: close(fd); ! 119: fflush(stdout); ! 120: ! 121: } /* main() */ ! 122: ! 123: /* ! 124: * Digest the command line. ! 125: */ ! 126: void ! 127: vCvtArgs(argc, argv) ! 128: int argc; ! 129: char *argv[]; ! 130: { ! 131: char *opstring = "ac:defgk:lmnp:rtwx"; ! 132: extern char *optarg; ! 133: int c; ! 134: char *token; ! 135: ! 136: while ((c = getopt(argc, argv, opstring)) != EOF) ! 137: switch (c) { ! 138: case 'a': ! 139: case 'e': ! 140: iaFlag = 1; ! 141: break; ! 142: case 'c': /* We will just ignore it */ ! 143: break; ! 144: case 'd': ! 145: idFlag = 1; ! 146: break; ! 147: case 'f': ! 148: ifFlag = 1; ! 149: break; ! 150: case 'g': ! 151: igFlag = 1; ! 152: break; ! 153: case 'k': /* We will just ignore it */ ! 154: break; ! 155: case 'l': ! 156: ilFlag = 1; ! 157: break; ! 158: case 'm': ! 159: imFlag = 1; ! 160: break; ! 161: case 'n': ! 162: inFlag = 1; ! 163: break; ! 164: case 'p': ! 165: ipFlag = iaFlag = 1; ! 166: ! 167: /* Take out the '-' that fakeMinus puts in */ ! 168: while (*optarg == '-') ! 169: optarg++; ! 170: ! 171: token = strtok(optarg, ","); ! 172: while((token != NULL) && (iNumProcessP < MAXPROCESSES)) ! 173: { ! 174: auProcessP[iNumProcessP++] = atoi(token); ! 175: token = strtok(NULL, ","); ! 176: } ! 177: if (iNumProcessP == 0) ! 178: ipFlag = 0; ! 179: break; ! 180: case 'r': ! 181: irFlag = 1; ! 182: break; ! 183: case 't': ! 184: itFlag = 1; ! 185: break; ! 186: case 'w': ! 187: iwFlag = 1; ! 188: break; ! 189: case 'x': ! 190: ixFlag = 1; ! 191: break; ! 192: default: ! 193: usage(c); ! 194: } ! 195: if (ilFlag && igFlag) ! 196: igFlag = 1; ! 197: else ! 198: igFlag = 0; ! 199: } /* cvt_args() */ ! 200: ! 201: void vPrintPs() ! 202: { ! 203: register stMonitor *pMonTmp; ! 204: ! 205: /* Read device directory only once */ ! 206: ReadDevDir(); /* We may not return from ReadDevDir */ ! 207: ! 208: /* Print the header line */ ! 209: vPrintHeader(); ! 210: ! 211: for (pMonTmp = pMonData + iRet / sizeof(stMonitor) - 1; ! 212: pMonTmp >= pMonData; pMonTmp--) { ! 213: if (uOkToPrint(pMonTmp->p_pid)) ! 214: vPrintLine(pMonTmp); ! 215: } ! 216: } ! 217: ! 218: void vPrintHeader() ! 219: { ! 220: /* If header suppressed */ ! 221: if (inFlag) ! 222: return; ! 223: /* Now we can print */ ! 224: printf("%-8s%5s", "TTY", "PID"); ! 225: if (igFlag) ! 226: printf(" %5s", "GROUP"); ! 227: if (ilFlag) ! 228: printf(" %5s%9s%5s%5s%2s%9s", ! 229: "PPID", "UID", "K", "F", "S", "EVENT"); ! 230: #if 0 ! 231: if (imFlag) ! 232: printf(" %8s %8s %8s %8s", "CVAL", "SVAL", "IVAL", "RVAL"); ! 233: #endif ! 234: if (itFlag) ! 235: printf(" UTIME STIME"); ! 236: puts(" COMMAND"); ! 237: } ! 238: ! 239: /* ! 240: * Print next line. ! 241: */ ! 242: void vPrintLine(pMonLine) ! 243: stMonitor *pMonLine; ! 244: { ! 245: char *cpFindTerminal(); ! 246: char *cpTty; ! 247: ! 248: /* Check controling terminal */ ! 249: if (major(pMonLine->p_ttdev) == 0) { ! 250: if (minor(pMonLine->p_ttdev) == 0) ! 251: cpTty = "null"; ! 252: } else { ! 253: if (major(pMonLine->p_ttdev) == 0x0FF) { ! 254: if (minor(pMonLine->p_ttdev) == 255) { ! 255: cpTty = "-------"; ! 256: } ! 257: } else { ! 258: if ((cpTty=cpFindTerminal(pMonLine->p_ttdev)) == NULL) ! 259: cpTty = "?"; ! 260: } ! 261: } ! 262: ! 263: /* Do we have to skip this line? */ ! 264: if (!iaFlag && (dvtPs != pMonLine->p_ttdev)) { ! 265: if (!ixFlag || strcmp("-------", cpTty)) ! 266: return; ! 267: } else ! 268: if (!ixFlag && !strcmp("-------", cpTty)) ! 269: return; ! 270: printf("%-8s%5u", cpTty, pMonLine->p_pid); ! 271: ! 272: if (igFlag) ! 273: printf(" %5d", pMonLine->p_rgid); ! 274: ! 275: if (ilFlag) { ! 276: int c; ! 277: struct passwd *pstPasswd; ! 278: ! 279: if ((pstPasswd = getpwuid(pMonLine->p_uid)) == NULL) { ! 280: fflush(stdout); ! 281: perror("\nps: cannot get user name"); ! 282: exit(1); ! 283: } ! 284: printf("%6d%9s", pMonLine->p_ppid, pstPasswd->pw_name); ! 285: if (irFlag) ! 286: printf("%5d", pMonLine->rsize); ! 287: else ! 288: printf("%5d", pMonLine->size); ! 289: printf("%5o", pMonLine->p_flags); ! 290: c = iState(pMonLine); ! 291: printf(" %c", c); ! 292: if (c == 'S') { ! 293: if (pMonLine->u_sleep[0] != '\0') ! 294: printf("%9s", pMonLine->u_sleep); ! 295: else ! 296: printf("%9x", pMonLine->p_event); ! 297: } else ! 298: if (ifFlag) ! 299: printf(" -"); ! 300: else ! 301: printf(" "); ! 302: ! 303: } ! 304: ! 305: /* Scheduling fields */ ! 306: #if 0 ! 307: if (imFlag) ! 308: printf(" %8x %8x %8x %8x", pMonLine->p_cval, ! 309: pMonLine->p_sval, ! 310: pMonLine->p_ival, ! 311: pMonLine->p_rval); ! 312: #endif ! 313: if (itFlag) { ! 314: ptime(pMonLine->p_utime); ! 315: ptime(pMonLine->p_stime); ! 316: } ! 317: ! 318: printf(" %.*s\n", U_COMM_LEN, pMonLine->u_comm); ! 319: } ! 320: ! 321: /* ! 322: * Given a time in HZ, print it out. ! 323: */ ! 324: ptime(l) ! 325: long l; ! 326: { ! 327: register unsigned m; ! 328: ! 329: if ((l=(l+HZ/2)/HZ) == 0) { ! 330: if (ifFlag) ! 331: printf(" -"); ! 332: else ! 333: printf(" "); ! 334: return; ! 335: } ! 336: if ((m=l/60) >= 100) { ! 337: printf("%6d", m); ! 338: return; ! 339: } ! 340: printf(" %2d:%02d", m, (unsigned)l%60); ! 341: } ! 342: ! 343: /* ! 344: * Find status of a proces. If sleep, reason why. ! 345: */ ! 346: int iState(pMon) ! 347: stMonitor *pMon; ! 348: { ! 349: ! 350: if (ASLEEP(pMon)) { ! 351: if (pMon->rrun) ! 352: return 'S'; ! 353: if ((pMon->p_flags & PFSTOP) != 0) ! 354: return 'T'; ! 355: if (pMon->p_state == PSSLEEP) ! 356: return 'W'; ! 357: else ! 358: return 'w'; ! 359: } ! 360: ! 361: if (pMon->p_state == PSRUN) ! 362: return 'R'; ! 363: if (pMon->p_state == PSDEAD) ! 364: return 'Z'; ! 365: return '?'; ! 366: } ! 367: ! 368: /* ! 369: * Find a device. Return device name or NULL if device was not found. ! 370: */ ! 371: char *cpFindTerminal(dev) ! 372: dev_t dev; ! 373: { ! 374: register stDevices *pstDev; ! 375: ! 376: /* Find a proper device */ ! 377: for (pstDev = pstDevFirst; pstDev != NULL; pstDev = pstDev->next) { ! 378: if (dev == pstDev->dev) { ! 379: return pstDev->pDevName; ! 380: } ! 381: } ! 382: /* Device not found */ ! 383: return NULL; ! 384: } ! 385: ! 386: /* ! 387: * Read device directory and store data in memory. ! 388: * This function will not return if it cannot open /dev or run ! 389: * out of memory. ! 390: */ ! 391: void ReadDevDir() ! 392: { ! 393: register DIR *pDir; ! 394: register stDevices *pstDevNext; ! 395: static stDevices *pstDevPrev; ! 396: register struct dirent *pDrnt; ! 397: struct stat stStat; ! 398: char pFileName[32]; /* File name buffer */ ! 399: ! 400: if ((pDir = opendir( "/dev" )) == NULL) { ! 401: fflush(stdout); ! 402: perror("ps"); ! 403: exit(1); ! 404: } ! 405: ! 406: while ( (pDrnt = readdir( pDir )) != NULL ) { ! 407: sprintf(pFileName, "/dev/%.*s", DIRSIZ, pDrnt->d_name); ! 408: /* We may skip silent the file that we cannot stat. ! 409: */ ! 410: if (stat(pFileName, &stStat) < 0) ! 411: continue; ! 412: if ((stStat.st_mode & S_IFMT) != S_IFCHR) ! 413: continue; ! 414: ! 415: if ((pstDevNext = malloc(sizeof(struct DEVICES))) == NULL) { ! 416: fflush(stdout); ! 417: perror("ps"); ! 418: exit(1); ! 419: } ! 420: if (pstDevFirst == NULL) ! 421: pstDevFirst = pstDevPrev = pstDevNext; ! 422: else ! 423: pstDevPrev->next = pstDevNext; ! 424: ! 425: pstDevNext->dev = stStat.st_rdev; ! 426: strncpy(pstDevNext->pDevName, pDrnt->d_name, DIRSIZ); ! 427: pstDevNext->next = NULL; ! 428: pstDevPrev = pstDevNext; ! 429: } ! 430: closedir(pDir); ! 431: } ! 432: ! 433: /* ! 434: * Get dev_t value for ps controlling terminal. ! 435: * Return 0 is a flag was set or controlling terminal was not found. ! 436: */ ! 437: dev_t dvtGetTerminal() ! 438: { ! 439: register stMonitor *pMonTmp; ! 440: register int iPid; /* Our process id */ ! 441: ! 442: if (iaFlag) ! 443: return 0; ! 444: ! 445: iPid = getpid(); ! 446: ! 447: /* Go through all data until ps id will be found */ ! 448: for (pMonTmp = pMonData + iRet / sizeof(stMonitor) - 1; ! 449: pMonTmp >= pMonData; pMonTmp--) ! 450: if (pMonTmp->p_pid == iPid) ! 451: return pMonTmp->p_ttdev; ! 452: ! 453: return 0; ! 454: } ! 455: ! 456: /* ! 457: * Return 1 if ipFlag is not set or ipFlag is set and process is specified, ! 458: * 0 otherwise. ! 459: */ ! 460: unsigned uOkToPrint(pnum) ! 461: unsigned pnum; ! 462: { ! 463: int i; ! 464: ! 465: if (!ipFlag) ! 466: return 1; ! 467: ! 468: for (i = 0; i < iNumProcessP; i++) ! 469: if (auProcessP[i] == pnum) ! 470: return 1; ! 471: return 0; ! 472: } ! 473: ! 474: usage() ! 475: { ! 476: printf("usage: ps [-][aefglmnrtwx][p#[,#]...]\n"); ! 477: exit(1); ! 478: } ! 479: ! 480: fakeMinus(argc, argv) ! 481: int argc; ! 482: char * argv[]; ! 483: { ! 484: int argn; ! 485: char * malloc(); ! 486: ! 487: for (argn = 1; argn < argc; argn++) { ! 488: if (argv[argn][0] && argv[argn][0] != '-') { ! 489: char * temp = malloc(strlen(argv[argn])+2); ! 490: temp[0] = '-'; ! 491: strcpy(temp+1, argv[argn]); ! 492: argv[argn] = temp; ! 493: } ! 494: } ! 495: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.