117829Sralph /* 2*35466Sbostic * Copyright (c) 1988 The Regents of the University of California. 3*35466Sbostic * All rights reserved. 4*35466Sbostic * 5*35466Sbostic * This code is derived from software contributed to Berkeley by 6*35466Sbostic * Rick Adams. 7*35466Sbostic * 8*35466Sbostic * Redistribution and use in source and binary forms are permitted 9*35466Sbostic * provided that the above copyright notice and this paragraph are 10*35466Sbostic * duplicated in all such forms and that any documentation, 11*35466Sbostic * advertising materials, and other materials related to such 12*35466Sbostic * distribution and use acknowledge that the software was developed 13*35466Sbostic * by the University of California, Berkeley. The name of the 14*35466Sbostic * University may not be used to endorse or promote products derived 15*35466Sbostic * from this software without specific prior written permission. 16*35466Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17*35466Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18*35466Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1933576Srick */ 2033576Srick 21*35466Sbostic #ifndef lint 22*35466Sbostic char copyright[] = 23*35466Sbostic "@(#) Copyright (c) 1988 The Regents of the University of California.\n\ 24*35466Sbostic All rights reserved.\n"; 25*35466Sbostic #endif /* not lint */ 26*35466Sbostic 27*35466Sbostic #ifndef lint 28*35466Sbostic static char sccsid[] = "@(#)uuq.c 4.11 (Berkeley) 09/02/88"; 29*35466Sbostic #endif /* not lint */ 30*35466Sbostic 3133576Srick /* 3217829Sralph * uuq - looks at uucp queues 3317829Sralph * 3417829Sralph * Lou Salkind 3517829Sralph * New York University 3617829Sralph * 3717829Sralph */ 3817829Sralph 3917829Sralph #include "uucp.h" 4017829Sralph #include <stdio.h> 4117829Sralph 4217829Sralph #ifdef NDIR 4317829Sralph #include "libndir/ndir.h" 4417829Sralph #else !NDIR 4517829Sralph #include <sys/dir.h> 4617829Sralph #endif !NDIR 4717829Sralph #include <sys/stat.h> 4817829Sralph 4917829Sralph #define NOSYS (struct sys *)0 5017829Sralph 5117829Sralph #define W_TYPE wrkvec[0] 5217829Sralph #define W_FILE1 wrkvec[1] 5317829Sralph #define W_FILE2 wrkvec[2] 5417829Sralph #define W_USER wrkvec[3] 5517829Sralph #define W_OPTNS wrkvec[4] 5617829Sralph #define W_DFILE wrkvec[5] 5717829Sralph #define W_MODE wrkvec[6] 5817829Sralph #define WSUFSIZE 5 /* work file name suffix size */ 5917829Sralph 6017829Sralph struct sys { 6117829Sralph char s_name[8]; 6217829Sralph int s_njobs; 6317829Sralph off_t s_bytes; 6417829Sralph struct job *s_jobp; 6517829Sralph struct sys *s_sysp; 6617829Sralph }; 6717829Sralph 6817829Sralph struct job { 6917829Sralph int j_files; 7017829Sralph int j_flags; 7117829Sralph char j_jobno[WSUFSIZE]; 7217829Sralph char j_user[22]; 7317829Sralph char j_fname[128]; 7417829Sralph char j_grade; 7517829Sralph off_t j_bytes; 7617829Sralph time_t j_date; 7717829Sralph struct job *j_jobp; 7817829Sralph }; 7917829Sralph 8017829Sralph struct sys *syshead; 8117829Sralph struct sys *getsys(); 8217829Sralph int jcompare(); 8317829Sralph char *sysname; 8417829Sralph char *user; 8517829Sralph char *rmjob; 8617829Sralph int hflag; 8717829Sralph int lflag; 8817829Sralph 8917829Sralph char *malloc(), *calloc(); 9033971Srick double atof(); 9133576Srick float baudrate = 2400.; 9217829Sralph char Username[BUFSIZ]; 9317829Sralph char Filename[BUFSIZ]; 9417829Sralph int Maxulen = 0; 9525144Sbloom struct timeb Now; 9617829Sralph 9717829Sralph main(argc, argv) 9833971Srick int argc; 9917829Sralph char **argv; 10017829Sralph { 10133971Srick register int i; 10217829Sralph register struct sys *sp; 10317829Sralph register struct job *jp; 10417829Sralph struct job **sortjob; 10517829Sralph int nsys; 10633971Srick extern char *optarg; 10733971Srick extern int optind; 10817829Sralph 10917829Sralph strcpy(Progname, "uuq"); 11017829Sralph uucpname(Myname); 11117829Sralph 11234174Srick while ((i = getopt(argc, argv, "r:S:s:u:d:b:hl")) != EOF) 11333971Srick switch (i) { 11417829Sralph case 'r': 11534174Srick case 'S': 11633971Srick Spool = optarg; 11717829Sralph break; 11817829Sralph case 's': 11933971Srick sysname = optarg; 12023689Sbloom if (strlen(sysname) > SYSNSIZE) 12123689Sbloom sysname[SYSNSIZE] = '\0'; 12217829Sralph break; 12317829Sralph case 'u': 12433971Srick user = optarg; 12517829Sralph break; 12617829Sralph case 'd': 12733971Srick rmjob = optarg; 12817829Sralph break; 12917829Sralph case 'b': 13033971Srick baudrate = atof(optarg); 13117829Sralph break; 13217829Sralph case 'h': 13317829Sralph hflag++; 13417829Sralph break; 13517829Sralph case 'l': 13617829Sralph lflag++; 13717829Sralph break; 13817829Sralph default: 13917829Sralph fprintf(stderr, 14017829Sralph "usage: uuq [-l] [-h] [-ssystem] [-uuser] [-djobno] [-rspool] [-bbaudrate]\n"); 14117829Sralph exit(0); 14217829Sralph } 14317829Sralph 14417829Sralph subchdir(Spool); 14523689Sbloom baudrate *= 0.7; /* reduce speed because of protocol overhead */ 14633576Srick baudrate *= 7.5; /* convert to chars/minute (60/8) */ 14717829Sralph gather(); 14817829Sralph nsys = 0; 14917829Sralph for (sp = syshead; sp; sp = sp->s_sysp) { 15017829Sralph if (sp->s_njobs == 0) 15117829Sralph continue; 15217829Sralph if (!hflag && nsys++ > 0) 15317829Sralph putchar('\n'); 15417829Sralph printf("%s: %d %s", sp->s_name, 15517829Sralph sp->s_njobs, sp->s_njobs > 1 ? "jobs" : "job"); 15617829Sralph if (lflag) { 15717829Sralph float minutes; 15817829Sralph int hours; 15917829Sralph /* The 80 * njobs is because of the uucp handshaking */ 16017829Sralph minutes = (float)(sp->s_bytes + 80 * sp->s_njobs)/baudrate; 16117829Sralph hours = minutes/60; 16233576Srick printf(", %ld bytes, ", sp->s_bytes); 16317829Sralph if (minutes > 60){ 16417829Sralph printf("%d hour%s, ",hours, 16517829Sralph hours > 1 ? "s": ""); 16617829Sralph minutes -= 60 * hours; 16717829Sralph } 16823729Sbloom printf("%3.1f minutes (@ effective baudrate of %d)", 16933971Srick minutes,(int)(baudrate/6)); 17017829Sralph } 17117829Sralph putchar('\n'); 17217829Sralph if (hflag) 17317829Sralph continue; 17417829Sralph /* sort them babies! */ 17533576Srick sortjob = (struct job **)calloc(sp->s_njobs, sizeof (struct job *)); 17617829Sralph for (i=0, jp=sp->s_jobp; i < sp->s_njobs; i++, jp=jp->j_jobp) 17717829Sralph sortjob[i] = jp; 17817829Sralph qsort(sortjob, sp->s_njobs, sizeof (struct job *), jcompare); 17917829Sralph for (i = 0; i < sp->s_njobs; i++) { 18017829Sralph jp = sortjob[i]; 18117829Sralph if (lflag) { 18233576Srick printf("%s %2d %-*s%7ld%5.1f %-12.12s %c %.*s\n", 18317829Sralph jp->j_jobno, jp->j_files, Maxulen, jp->j_user, jp->j_bytes, jp->j_bytes/baudrate, 18417829Sralph ctime(&jp->j_date) + 4, jp->j_flags, sizeof (jp->j_fname), jp->j_fname 18517829Sralph ); 18617829Sralph } else { 18717829Sralph printf("%s", jp->j_jobno); 18817829Sralph putchar((i+1)%10 ? '\t' : '\n'); 18917829Sralph } 19017829Sralph /* There's no need to keep the force poll if jobs > 1*/ 19117829Sralph if (sp->s_njobs > 1 && strcmp("POLL", jp->j_jobno)==0) { 19217829Sralph char pbuf[BUFSIZ]; 19333576Srick sprintf(pbuf,"%s/%c.%s%cPOLL", 19433576Srick subdir(Spool, CMDPRE), CMDPRE, 19533576Srick sp->s_name, jp->j_grade); 19633576Srick (void) unlink(pbuf); 19717829Sralph } 19817829Sralph } 19917829Sralph if (!lflag && (sp->s_njobs%10)) 20017829Sralph putchar('\n'); 20117829Sralph } 20217829Sralph exit(0); 20317829Sralph } 20417829Sralph 20517829Sralph jcompare(j1, j2) 20617829Sralph struct job **j1, **j2; 20717829Sralph { 20817829Sralph int delta; 20917829Sralph 21017829Sralph delta = (*j1)->j_grade - (*j2)->j_grade; 21117829Sralph if (delta) 21217829Sralph return delta; 21317829Sralph return(strcmp((*j1)->j_jobno,(*j2)->j_jobno)); 21417829Sralph } 21517829Sralph 21617829Sralph /* 21717829Sralph * Get all the command file names 21817829Sralph */ 21917829Sralph gather() 22017829Sralph { 22117829Sralph struct direct *d; 22217829Sralph DIR *df; 22317829Sralph 22417829Sralph /* 22517829Sralph * Find all the spool files in the spooling directory 22617829Sralph */ 22717829Sralph if ((df = opendir(subdir(Spool, CMDPRE))) == NULL) { 22833971Srick fprintf(stderr, "can't examine spooling area\n"); 22917829Sralph exit(1); 23017829Sralph } 23117829Sralph for (;;) { 23217829Sralph if ((d = readdir(df)) == NULL) 23317829Sralph break; 23417829Sralph if (d->d_namlen <= 2 || d->d_name[0] != CMDPRE || 23517829Sralph d->d_name[1] != '.') 23617829Sralph continue; 23717829Sralph if (analjob(d->d_name) < 0) { 23817829Sralph fprintf(stderr, "out of memory\n"); 23917829Sralph break; 24017829Sralph } 24117829Sralph } 24217829Sralph closedir(df); 24317829Sralph } 24417829Sralph 24517829Sralph /* 24617829Sralph * analjob does the grunge work of verifying jobs 24717829Sralph */ 24833971Srick #include <pwd.h> 24917829Sralph analjob(filename) 25017829Sralph char *filename; 25117829Sralph { 25217829Sralph struct job *jp; 25317829Sralph struct sys *sp; 25417829Sralph char sbuf[MAXNAMLEN+1], str[256], nbuf[256]; 25517829Sralph char *jptr, *wrkvec[20]; 25617829Sralph char grade; 25717829Sralph FILE *fp, *df; 25817829Sralph struct stat statb; 25917829Sralph int files, gotname, i; 26017829Sralph off_t bytes; 26117829Sralph 26217829Sralph strncpy(sbuf, filename, MAXNAMLEN); 26317829Sralph sbuf[MAXNAMLEN] = '\0'; 26417829Sralph jptr = sbuf + strlen(sbuf) - WSUFSIZE; 26517829Sralph grade = *jptr; 26617829Sralph *jptr++ = 0; 26717829Sralph /* 26817829Sralph * sbuf+2 now points to sysname name (null terminated) 26917829Sralph * jptr now points to job number (null terminated) 27017829Sralph */ 27117829Sralph if (rmjob) { 27217829Sralph if (strcmp(rmjob, jptr)) 27317829Sralph return(0); 27417829Sralph } else { 27517829Sralph if ((sp = getsys(sbuf+2)) == NOSYS) 27617829Sralph return(0); 27717829Sralph if (!lflag) { 27817829Sralph /* SHOULD USE A SMALLER STRUCTURE HERE */ 27917829Sralph jp = (struct job *)malloc(sizeof(struct job)); 28017829Sralph if (jp == (struct job *)0) 28117829Sralph return(-1); 28217829Sralph strcpy(jp->j_jobno, jptr); 28317829Sralph jp->j_jobp = sp->s_jobp; 28417829Sralph jp->j_grade = grade; 28517829Sralph sp->s_jobp = jp; 28617829Sralph sp->s_njobs++; 28717829Sralph return(1); 28817829Sralph } 28917829Sralph } 29017829Sralph if ((fp = fopen(subfile(filename), "r")) == NULL) { 29117829Sralph perror(subfile(filename)); 29217829Sralph return(0); 29317829Sralph } 29417829Sralph files = 0; 29517829Sralph bytes = 0; 29617829Sralph gotname = 0; 29717829Sralph while (fgets(str, sizeof str, fp)) { 29817829Sralph if (getargs(str, wrkvec, 20) <= 0) 29917829Sralph continue; 30017829Sralph if (rmjob) { 30133971Srick int myuid; 30233971Srick struct passwd *pw; 30333971Srick /* 30433971Srick * Make sure person who is removing data files is 30533971Srick * the person who created it or root. 30633971Srick */ 30733971Srick myuid = getuid(); 30833971Srick pw = getpwnam(W_USER); 30933971Srick if (myuid && (pw == NULL || myuid != pw->pw_uid)) { 31033971Srick fprintf(stderr, "Permission denied.\n"); 31133971Srick exit(1); 31233971Srick } 31317829Sralph if (W_TYPE[0] == 'S' && !index(W_OPTNS, 'c')) { 31417829Sralph unlink(subfile(W_DFILE)); 31517829Sralph fprintf(stderr, "Removing data file %s\n", W_DFILE); 31617829Sralph } 31717829Sralph continue; 31817829Sralph } 31917829Sralph if (user && (W_TYPE[0] == 'X' || !prefix(user, W_USER))) { 32017829Sralph fclose(fp); 32117829Sralph return(0); 32217829Sralph } 32317829Sralph files++; 32417829Sralph if (W_TYPE[0] == 'S') { 32517829Sralph if (strcmp(W_DFILE, "D.0") && 32617829Sralph stat(subfile(W_DFILE), &statb) >= 0) 32717829Sralph bytes += statb.st_size; 32817829Sralph else if (stat(subfile(W_FILE1), &statb) >= 0) 32917829Sralph bytes += statb.st_size; 33017829Sralph } 33117829Sralph /* amusing heuristic */ 33217829Sralph #define isXfile(s) (s[0]=='D' && s[strlen(s)-WSUFSIZE]=='X') 33317829Sralph if (gotname == 0 && isXfile(W_FILE1)) { 33417829Sralph if ((df = fopen(subfile(W_FILE1), "r")) == NULL) 33517829Sralph continue; 33617829Sralph while (fgets(nbuf, sizeof nbuf, df)) { 33717829Sralph nbuf[strlen(nbuf) - 1] = '\0'; 33817829Sralph if (nbuf[0] == 'C' && nbuf[1] == ' ') { 33917829Sralph strcpy(Filename, nbuf+2); 34017829Sralph gotname++; 34117829Sralph } else if (nbuf[0] == 'R' && nbuf[1] == ' ') { 34217829Sralph register char *p, *q, *r; 34317829Sralph r = q = p = nbuf+2; 34417829Sralph do { 34517829Sralph if (*p == '!' || *p == '@'){ 34617829Sralph r = q; 34717829Sralph q = p+1; 34817829Sralph } 34917829Sralph } while (*p++); 35017829Sralph 35117829Sralph strcpy(Username, r); 35217829Sralph W_USER = Username; 35317829Sralph } 35417829Sralph } 35517829Sralph fclose(df); 35617829Sralph } 35717829Sralph } 35817829Sralph fclose(fp); 35917829Sralph if (rmjob) { 36017829Sralph unlink(subfile(filename)); 36117829Sralph fprintf(stderr, "Removing command file %s\n", filename); 36217829Sralph exit(0); 36317829Sralph } 36417829Sralph if (files == 0) { 36517829Sralph static char *wtype = "X"; 36617829Sralph static char *wfile = "forced poll"; 36717829Sralph if (strcmp("POLL", &filename[strlen(filename)-4])) { 36817829Sralph fprintf(stderr, "%.14s: empty command file\n", filename); 36917829Sralph return(0); 37017829Sralph } 37117829Sralph W_TYPE = wtype; 37217829Sralph W_FILE1 = wfile; 37317829Sralph } 37417829Sralph jp = (struct job *)malloc(sizeof(struct job)); 37517829Sralph if (jp == (struct job *)0) 37617829Sralph return(-1); 37717829Sralph strcpy(jp->j_jobno, jptr); 37817829Sralph jp->j_files = files; 37917829Sralph jp->j_bytes = bytes; 38017829Sralph jp->j_grade = grade; 38117829Sralph jp->j_flags = W_TYPE[0]; 38217829Sralph strncpy(jp->j_user, W_TYPE[0]=='X' ? "---" : W_USER, 20 ); 38317829Sralph jp->j_user[20] = '\0'; 38417829Sralph i = strlen(jp->j_user); 38517829Sralph if (i > Maxulen) 38617829Sralph Maxulen = i; 38717829Sralph /* SHOULD ADD ALL INFORMATION IN THE WHILE LOOP */ 38817829Sralph if (gotname) 38917829Sralph strncpy(jp->j_fname, Filename, sizeof jp->j_fname); 39017829Sralph else 39117829Sralph strncpy(jp->j_fname, W_FILE1, sizeof jp->j_fname); 39217829Sralph stat(subfile(filename), &statb); 39317829Sralph jp->j_date = statb.st_mtime; 39417829Sralph jp->j_jobp = sp->s_jobp; 39517829Sralph sp->s_jobp = jp; 39617829Sralph sp->s_njobs++; 39717829Sralph sp->s_bytes += jp->j_bytes; 39817829Sralph return(1); 39917829Sralph } 40017829Sralph 40117829Sralph struct sys * 40217829Sralph getsys(s) 40317829Sralph register char *s; 40417829Sralph { 40517829Sralph register struct sys *sp; 40617829Sralph 40717829Sralph for (sp = syshead; sp; sp = sp->s_sysp) 40817829Sralph if (strcmp(s, sp->s_name) == 0) 40917829Sralph return(sp); 41017829Sralph if (sysname && !prefix(sysname, s)) 41117829Sralph return(NOSYS); 41217829Sralph sp = (struct sys *)malloc(sizeof(struct sys)); 41317829Sralph if (sp == NOSYS) 41417829Sralph return(NOSYS); 41517829Sralph strcpy(sp->s_name, s); 41617829Sralph sp->s_njobs = 0; 41717829Sralph sp->s_jobp = (struct job *)0; 41817829Sralph sp->s_sysp = syshead; 41917829Sralph sp->s_bytes = 0; 42017829Sralph syshead = sp; 42117829Sralph return(sp); 42217829Sralph } 423