Annotation of coherent/b/bin/ps/ps.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.