1*48669Sbostic /*- 235466Sbostic * Copyright (c) 1988 The Regents of the University of California. 335466Sbostic * All rights reserved. 435466Sbostic * 5*48669Sbostic * %sccs.include.redist.c% 633576Srick */ 733576Srick 835466Sbostic #ifndef lint 935466Sbostic char copyright[] = 1035466Sbostic "@(#) Copyright (c) 1988 The Regents of the University of California.\n\ 1135466Sbostic All rights reserved.\n"; 1235466Sbostic #endif /* not lint */ 1335466Sbostic 1435466Sbostic #ifndef lint 15*48669Sbostic static char sccsid[] = "@(#)uuq.c 4.12 (Berkeley) 04/24/91"; 1635466Sbostic #endif /* not lint */ 1735466Sbostic 1833576Srick /* 1917829Sralph * uuq - looks at uucp queues 2017829Sralph * 2117829Sralph * Lou Salkind 2217829Sralph * New York University 2317829Sralph * 2417829Sralph */ 2517829Sralph 2617829Sralph #include "uucp.h" 2717829Sralph #include <stdio.h> 2817829Sralph 2917829Sralph #ifdef NDIR 3017829Sralph #include "libndir/ndir.h" 3117829Sralph #else !NDIR 3217829Sralph #include <sys/dir.h> 3317829Sralph #endif !NDIR 3417829Sralph #include <sys/stat.h> 3517829Sralph 3617829Sralph #define NOSYS (struct sys *)0 3717829Sralph 3817829Sralph #define W_TYPE wrkvec[0] 3917829Sralph #define W_FILE1 wrkvec[1] 4017829Sralph #define W_FILE2 wrkvec[2] 4117829Sralph #define W_USER wrkvec[3] 4217829Sralph #define W_OPTNS wrkvec[4] 4317829Sralph #define W_DFILE wrkvec[5] 4417829Sralph #define W_MODE wrkvec[6] 4517829Sralph #define WSUFSIZE 5 /* work file name suffix size */ 4617829Sralph 4717829Sralph struct sys { 4817829Sralph char s_name[8]; 4917829Sralph int s_njobs; 5017829Sralph off_t s_bytes; 5117829Sralph struct job *s_jobp; 5217829Sralph struct sys *s_sysp; 5317829Sralph }; 5417829Sralph 5517829Sralph struct job { 5617829Sralph int j_files; 5717829Sralph int j_flags; 5817829Sralph char j_jobno[WSUFSIZE]; 5917829Sralph char j_user[22]; 6017829Sralph char j_fname[128]; 6117829Sralph char j_grade; 6217829Sralph off_t j_bytes; 6317829Sralph time_t j_date; 6417829Sralph struct job *j_jobp; 6517829Sralph }; 6617829Sralph 6717829Sralph struct sys *syshead; 6817829Sralph struct sys *getsys(); 6917829Sralph int jcompare(); 7017829Sralph char *sysname; 7117829Sralph char *user; 7217829Sralph char *rmjob; 7317829Sralph int hflag; 7417829Sralph int lflag; 7517829Sralph 7617829Sralph char *malloc(), *calloc(); 7733971Srick double atof(); 7833576Srick float baudrate = 2400.; 7917829Sralph char Username[BUFSIZ]; 8017829Sralph char Filename[BUFSIZ]; 8117829Sralph int Maxulen = 0; 8225144Sbloom struct timeb Now; 8317829Sralph 8417829Sralph main(argc, argv) 8533971Srick int argc; 8617829Sralph char **argv; 8717829Sralph { 8833971Srick register int i; 8917829Sralph register struct sys *sp; 9017829Sralph register struct job *jp; 9117829Sralph struct job **sortjob; 9217829Sralph int nsys; 9333971Srick extern char *optarg; 9433971Srick extern int optind; 9517829Sralph 9617829Sralph strcpy(Progname, "uuq"); 9717829Sralph uucpname(Myname); 9817829Sralph 9934174Srick while ((i = getopt(argc, argv, "r:S:s:u:d:b:hl")) != EOF) 10033971Srick switch (i) { 10117829Sralph case 'r': 10234174Srick case 'S': 10333971Srick Spool = optarg; 10417829Sralph break; 10517829Sralph case 's': 10633971Srick sysname = optarg; 10723689Sbloom if (strlen(sysname) > SYSNSIZE) 10823689Sbloom sysname[SYSNSIZE] = '\0'; 10917829Sralph break; 11017829Sralph case 'u': 11133971Srick user = optarg; 11217829Sralph break; 11317829Sralph case 'd': 11433971Srick rmjob = optarg; 11517829Sralph break; 11617829Sralph case 'b': 11733971Srick baudrate = atof(optarg); 11817829Sralph break; 11917829Sralph case 'h': 12017829Sralph hflag++; 12117829Sralph break; 12217829Sralph case 'l': 12317829Sralph lflag++; 12417829Sralph break; 12517829Sralph default: 12617829Sralph fprintf(stderr, 12717829Sralph "usage: uuq [-l] [-h] [-ssystem] [-uuser] [-djobno] [-rspool] [-bbaudrate]\n"); 12817829Sralph exit(0); 12917829Sralph } 13017829Sralph 13117829Sralph subchdir(Spool); 13223689Sbloom baudrate *= 0.7; /* reduce speed because of protocol overhead */ 13333576Srick baudrate *= 7.5; /* convert to chars/minute (60/8) */ 13417829Sralph gather(); 13517829Sralph nsys = 0; 13617829Sralph for (sp = syshead; sp; sp = sp->s_sysp) { 13717829Sralph if (sp->s_njobs == 0) 13817829Sralph continue; 13917829Sralph if (!hflag && nsys++ > 0) 14017829Sralph putchar('\n'); 14117829Sralph printf("%s: %d %s", sp->s_name, 14217829Sralph sp->s_njobs, sp->s_njobs > 1 ? "jobs" : "job"); 14317829Sralph if (lflag) { 14417829Sralph float minutes; 14517829Sralph int hours; 14617829Sralph /* The 80 * njobs is because of the uucp handshaking */ 14717829Sralph minutes = (float)(sp->s_bytes + 80 * sp->s_njobs)/baudrate; 14817829Sralph hours = minutes/60; 14933576Srick printf(", %ld bytes, ", sp->s_bytes); 15017829Sralph if (minutes > 60){ 15117829Sralph printf("%d hour%s, ",hours, 15217829Sralph hours > 1 ? "s": ""); 15317829Sralph minutes -= 60 * hours; 15417829Sralph } 15523729Sbloom printf("%3.1f minutes (@ effective baudrate of %d)", 15633971Srick minutes,(int)(baudrate/6)); 15717829Sralph } 15817829Sralph putchar('\n'); 15917829Sralph if (hflag) 16017829Sralph continue; 16117829Sralph /* sort them babies! */ 16233576Srick sortjob = (struct job **)calloc(sp->s_njobs, sizeof (struct job *)); 16317829Sralph for (i=0, jp=sp->s_jobp; i < sp->s_njobs; i++, jp=jp->j_jobp) 16417829Sralph sortjob[i] = jp; 16517829Sralph qsort(sortjob, sp->s_njobs, sizeof (struct job *), jcompare); 16617829Sralph for (i = 0; i < sp->s_njobs; i++) { 16717829Sralph jp = sortjob[i]; 16817829Sralph if (lflag) { 16933576Srick printf("%s %2d %-*s%7ld%5.1f %-12.12s %c %.*s\n", 17017829Sralph jp->j_jobno, jp->j_files, Maxulen, jp->j_user, jp->j_bytes, jp->j_bytes/baudrate, 17117829Sralph ctime(&jp->j_date) + 4, jp->j_flags, sizeof (jp->j_fname), jp->j_fname 17217829Sralph ); 17317829Sralph } else { 17417829Sralph printf("%s", jp->j_jobno); 17517829Sralph putchar((i+1)%10 ? '\t' : '\n'); 17617829Sralph } 17717829Sralph /* There's no need to keep the force poll if jobs > 1*/ 17817829Sralph if (sp->s_njobs > 1 && strcmp("POLL", jp->j_jobno)==0) { 17917829Sralph char pbuf[BUFSIZ]; 18033576Srick sprintf(pbuf,"%s/%c.%s%cPOLL", 18133576Srick subdir(Spool, CMDPRE), CMDPRE, 18233576Srick sp->s_name, jp->j_grade); 18333576Srick (void) unlink(pbuf); 18417829Sralph } 18517829Sralph } 18617829Sralph if (!lflag && (sp->s_njobs%10)) 18717829Sralph putchar('\n'); 18817829Sralph } 18917829Sralph exit(0); 19017829Sralph } 19117829Sralph 19217829Sralph jcompare(j1, j2) 19317829Sralph struct job **j1, **j2; 19417829Sralph { 19517829Sralph int delta; 19617829Sralph 19717829Sralph delta = (*j1)->j_grade - (*j2)->j_grade; 19817829Sralph if (delta) 19917829Sralph return delta; 20017829Sralph return(strcmp((*j1)->j_jobno,(*j2)->j_jobno)); 20117829Sralph } 20217829Sralph 20317829Sralph /* 20417829Sralph * Get all the command file names 20517829Sralph */ 20617829Sralph gather() 20717829Sralph { 20817829Sralph struct direct *d; 20917829Sralph DIR *df; 21017829Sralph 21117829Sralph /* 21217829Sralph * Find all the spool files in the spooling directory 21317829Sralph */ 21417829Sralph if ((df = opendir(subdir(Spool, CMDPRE))) == NULL) { 21533971Srick fprintf(stderr, "can't examine spooling area\n"); 21617829Sralph exit(1); 21717829Sralph } 21817829Sralph for (;;) { 21917829Sralph if ((d = readdir(df)) == NULL) 22017829Sralph break; 22117829Sralph if (d->d_namlen <= 2 || d->d_name[0] != CMDPRE || 22217829Sralph d->d_name[1] != '.') 22317829Sralph continue; 22417829Sralph if (analjob(d->d_name) < 0) { 22517829Sralph fprintf(stderr, "out of memory\n"); 22617829Sralph break; 22717829Sralph } 22817829Sralph } 22917829Sralph closedir(df); 23017829Sralph } 23117829Sralph 23217829Sralph /* 23317829Sralph * analjob does the grunge work of verifying jobs 23417829Sralph */ 23533971Srick #include <pwd.h> 23617829Sralph analjob(filename) 23717829Sralph char *filename; 23817829Sralph { 23917829Sralph struct job *jp; 24017829Sralph struct sys *sp; 24117829Sralph char sbuf[MAXNAMLEN+1], str[256], nbuf[256]; 24217829Sralph char *jptr, *wrkvec[20]; 24317829Sralph char grade; 24417829Sralph FILE *fp, *df; 24517829Sralph struct stat statb; 24617829Sralph int files, gotname, i; 24717829Sralph off_t bytes; 24817829Sralph 24917829Sralph strncpy(sbuf, filename, MAXNAMLEN); 25017829Sralph sbuf[MAXNAMLEN] = '\0'; 25117829Sralph jptr = sbuf + strlen(sbuf) - WSUFSIZE; 25217829Sralph grade = *jptr; 25317829Sralph *jptr++ = 0; 25417829Sralph /* 25517829Sralph * sbuf+2 now points to sysname name (null terminated) 25617829Sralph * jptr now points to job number (null terminated) 25717829Sralph */ 25817829Sralph if (rmjob) { 25917829Sralph if (strcmp(rmjob, jptr)) 26017829Sralph return(0); 26117829Sralph } else { 26217829Sralph if ((sp = getsys(sbuf+2)) == NOSYS) 26317829Sralph return(0); 26417829Sralph if (!lflag) { 26517829Sralph /* SHOULD USE A SMALLER STRUCTURE HERE */ 26617829Sralph jp = (struct job *)malloc(sizeof(struct job)); 26717829Sralph if (jp == (struct job *)0) 26817829Sralph return(-1); 26917829Sralph strcpy(jp->j_jobno, jptr); 27017829Sralph jp->j_jobp = sp->s_jobp; 27117829Sralph jp->j_grade = grade; 27217829Sralph sp->s_jobp = jp; 27317829Sralph sp->s_njobs++; 27417829Sralph return(1); 27517829Sralph } 27617829Sralph } 27717829Sralph if ((fp = fopen(subfile(filename), "r")) == NULL) { 27817829Sralph perror(subfile(filename)); 27917829Sralph return(0); 28017829Sralph } 28117829Sralph files = 0; 28217829Sralph bytes = 0; 28317829Sralph gotname = 0; 28417829Sralph while (fgets(str, sizeof str, fp)) { 28517829Sralph if (getargs(str, wrkvec, 20) <= 0) 28617829Sralph continue; 28717829Sralph if (rmjob) { 28833971Srick int myuid; 28933971Srick struct passwd *pw; 29033971Srick /* 29133971Srick * Make sure person who is removing data files is 29233971Srick * the person who created it or root. 29333971Srick */ 29433971Srick myuid = getuid(); 29533971Srick pw = getpwnam(W_USER); 29633971Srick if (myuid && (pw == NULL || myuid != pw->pw_uid)) { 29733971Srick fprintf(stderr, "Permission denied.\n"); 29833971Srick exit(1); 29933971Srick } 30017829Sralph if (W_TYPE[0] == 'S' && !index(W_OPTNS, 'c')) { 30117829Sralph unlink(subfile(W_DFILE)); 30217829Sralph fprintf(stderr, "Removing data file %s\n", W_DFILE); 30317829Sralph } 30417829Sralph continue; 30517829Sralph } 30617829Sralph if (user && (W_TYPE[0] == 'X' || !prefix(user, W_USER))) { 30717829Sralph fclose(fp); 30817829Sralph return(0); 30917829Sralph } 31017829Sralph files++; 31117829Sralph if (W_TYPE[0] == 'S') { 31217829Sralph if (strcmp(W_DFILE, "D.0") && 31317829Sralph stat(subfile(W_DFILE), &statb) >= 0) 31417829Sralph bytes += statb.st_size; 31517829Sralph else if (stat(subfile(W_FILE1), &statb) >= 0) 31617829Sralph bytes += statb.st_size; 31717829Sralph } 31817829Sralph /* amusing heuristic */ 31917829Sralph #define isXfile(s) (s[0]=='D' && s[strlen(s)-WSUFSIZE]=='X') 32017829Sralph if (gotname == 0 && isXfile(W_FILE1)) { 32117829Sralph if ((df = fopen(subfile(W_FILE1), "r")) == NULL) 32217829Sralph continue; 32317829Sralph while (fgets(nbuf, sizeof nbuf, df)) { 32417829Sralph nbuf[strlen(nbuf) - 1] = '\0'; 32517829Sralph if (nbuf[0] == 'C' && nbuf[1] == ' ') { 32617829Sralph strcpy(Filename, nbuf+2); 32717829Sralph gotname++; 32817829Sralph } else if (nbuf[0] == 'R' && nbuf[1] == ' ') { 32917829Sralph register char *p, *q, *r; 33017829Sralph r = q = p = nbuf+2; 33117829Sralph do { 33217829Sralph if (*p == '!' || *p == '@'){ 33317829Sralph r = q; 33417829Sralph q = p+1; 33517829Sralph } 33617829Sralph } while (*p++); 33717829Sralph 33817829Sralph strcpy(Username, r); 33917829Sralph W_USER = Username; 34017829Sralph } 34117829Sralph } 34217829Sralph fclose(df); 34317829Sralph } 34417829Sralph } 34517829Sralph fclose(fp); 34617829Sralph if (rmjob) { 34717829Sralph unlink(subfile(filename)); 34817829Sralph fprintf(stderr, "Removing command file %s\n", filename); 34917829Sralph exit(0); 35017829Sralph } 35117829Sralph if (files == 0) { 35217829Sralph static char *wtype = "X"; 35317829Sralph static char *wfile = "forced poll"; 35417829Sralph if (strcmp("POLL", &filename[strlen(filename)-4])) { 35517829Sralph fprintf(stderr, "%.14s: empty command file\n", filename); 35617829Sralph return(0); 35717829Sralph } 35817829Sralph W_TYPE = wtype; 35917829Sralph W_FILE1 = wfile; 36017829Sralph } 36117829Sralph jp = (struct job *)malloc(sizeof(struct job)); 36217829Sralph if (jp == (struct job *)0) 36317829Sralph return(-1); 36417829Sralph strcpy(jp->j_jobno, jptr); 36517829Sralph jp->j_files = files; 36617829Sralph jp->j_bytes = bytes; 36717829Sralph jp->j_grade = grade; 36817829Sralph jp->j_flags = W_TYPE[0]; 36917829Sralph strncpy(jp->j_user, W_TYPE[0]=='X' ? "---" : W_USER, 20 ); 37017829Sralph jp->j_user[20] = '\0'; 37117829Sralph i = strlen(jp->j_user); 37217829Sralph if (i > Maxulen) 37317829Sralph Maxulen = i; 37417829Sralph /* SHOULD ADD ALL INFORMATION IN THE WHILE LOOP */ 37517829Sralph if (gotname) 37617829Sralph strncpy(jp->j_fname, Filename, sizeof jp->j_fname); 37717829Sralph else 37817829Sralph strncpy(jp->j_fname, W_FILE1, sizeof jp->j_fname); 37917829Sralph stat(subfile(filename), &statb); 38017829Sralph jp->j_date = statb.st_mtime; 38117829Sralph jp->j_jobp = sp->s_jobp; 38217829Sralph sp->s_jobp = jp; 38317829Sralph sp->s_njobs++; 38417829Sralph sp->s_bytes += jp->j_bytes; 38517829Sralph return(1); 38617829Sralph } 38717829Sralph 38817829Sralph struct sys * 38917829Sralph getsys(s) 39017829Sralph register char *s; 39117829Sralph { 39217829Sralph register struct sys *sp; 39317829Sralph 39417829Sralph for (sp = syshead; sp; sp = sp->s_sysp) 39517829Sralph if (strcmp(s, sp->s_name) == 0) 39617829Sralph return(sp); 39717829Sralph if (sysname && !prefix(sysname, s)) 39817829Sralph return(NOSYS); 39917829Sralph sp = (struct sys *)malloc(sizeof(struct sys)); 40017829Sralph if (sp == NOSYS) 40117829Sralph return(NOSYS); 40217829Sralph strcpy(sp->s_name, s); 40317829Sralph sp->s_njobs = 0; 40417829Sralph sp->s_jobp = (struct job *)0; 40517829Sralph sp->s_sysp = syshead; 40617829Sralph sp->s_bytes = 0; 40717829Sralph syshead = sp; 40817829Sralph return(sp); 40917829Sralph } 410