1: #ifndef lint 2: static char sccsid[] = "@(#)uuq.c 4.6 (Berkeley) 10/9/85"; 3: #endif 4: 5: /* 6: * uuq - looks at uucp queues 7: * 8: * Lou Salkind 9: * New York University 10: * 11: */ 12: 13: #include "uucp.h" 14: #include <stdio.h> 15: 16: #ifdef NDIR 17: #include "libndir/ndir.h" 18: #else !NDIR 19: #include <sys/dir.h> 20: #endif !NDIR 21: #include <sys/stat.h> 22: 23: #define NOSYS (struct sys *)0 24: 25: #define W_TYPE wrkvec[0] 26: #define W_FILE1 wrkvec[1] 27: #define W_FILE2 wrkvec[2] 28: #define W_USER wrkvec[3] 29: #define W_OPTNS wrkvec[4] 30: #define W_DFILE wrkvec[5] 31: #define W_MODE wrkvec[6] 32: #define WSUFSIZE 5 /* work file name suffix size */ 33: 34: struct sys { 35: char s_name[8]; 36: int s_njobs; 37: off_t s_bytes; 38: struct job *s_jobp; 39: struct sys *s_sysp; 40: }; 41: 42: struct job { 43: int j_files; 44: int j_flags; 45: char j_jobno[WSUFSIZE]; 46: char j_user[22]; 47: char j_fname[128]; 48: char j_grade; 49: off_t j_bytes; 50: time_t j_date; 51: struct job *j_jobp; 52: }; 53: 54: struct sys *syshead; 55: struct sys *getsys(); 56: int jcompare(); 57: char *sysname; 58: char *user; 59: char *rmjob; 60: int hflag; 61: int lflag; 62: 63: char *malloc(), *calloc(); 64: float atof(); 65: float baudrate = 1200.; 66: char Username[BUFSIZ]; 67: char Filename[BUFSIZ]; 68: int Maxulen = 0; 69: struct timeb Now; 70: 71: main(argc, argv) 72: char **argv; 73: { 74: register i; 75: register struct sys *sp; 76: register struct job *jp; 77: struct job **sortjob; 78: int nsys; 79: 80: strcpy(Progname, "uuq"); 81: uucpname(Myname); 82: 83: while (--argc > 0) { 84: argv++; 85: if (argv[0][0] == '-') switch (argv[0][1]) { 86: case 'r': 87: Spool = &argv[0][2]; 88: break; 89: case 's': 90: sysname = &argv[0][2]; 91: if (strlen(sysname) > SYSNSIZE) 92: sysname[SYSNSIZE] = '\0'; 93: break; 94: case 'u': 95: user = &argv[0][2]; 96: break; 97: case 'd': 98: rmjob = &argv[0][2]; 99: break; 100: case 'b': 101: baudrate = atof(&argv[0][2]); 102: break; 103: case 'h': 104: hflag++; 105: break; 106: case 'l': 107: lflag++; 108: break; 109: default: 110: fprintf(stderr, 111: "usage: uuq [-l] [-h] [-ssystem] [-uuser] [-djobno] [-rspool] [-bbaudrate]\n"); 112: exit(0); 113: } 114: } 115: 116: subchdir(Spool); 117: baudrate *= 0.7; /* reduce speed because of protocol overhead */ 118: baudrate *= 6.; /* convert to chars/minute (60/10) */ 119: gather(); 120: nsys = 0; 121: for (sp = syshead; sp; sp = sp->s_sysp) { 122: if (sp->s_njobs == 0) 123: continue; 124: if (!hflag && nsys++ > 0) 125: putchar('\n'); 126: printf("%s: %d %s", sp->s_name, 127: sp->s_njobs, sp->s_njobs > 1 ? "jobs" : "job"); 128: if (lflag) { 129: float minutes; 130: int hours; 131: /* The 80 * njobs is because of the uucp handshaking */ 132: minutes = (float)(sp->s_bytes + 80 * sp->s_njobs)/baudrate; 133: hours = minutes/60; 134: printf(", %d bytes, ", sp->s_bytes); 135: if (minutes > 60){ 136: printf("%d hour%s, ",hours, 137: hours > 1 ? "s": ""); 138: minutes -= 60 * hours; 139: } 140: printf("%3.1f minutes (@ effective baudrate of %d)", 141: minutes,(int)baudrate/6); 142: } 143: putchar('\n'); 144: if (hflag) 145: continue; 146: /* sort them babies! */ 147: sortjob = (struct job **)calloc(sp->s_njobs, sizeof (struct job 148: *)); 149: for (i=0, jp=sp->s_jobp; i < sp->s_njobs; i++, jp=jp->j_jobp) 150: sortjob[i] = jp; 151: qsort(sortjob, sp->s_njobs, sizeof (struct job *), jcompare); 152: for (i = 0; i < sp->s_njobs; i++) { 153: jp = sortjob[i]; 154: if (lflag) { 155: printf("%s %2d %-*s%7d%5.1f %-12.12s %c %.*s\n", 156: jp->j_jobno, jp->j_files, Maxulen, jp->j_user, jp->j_bytes, jp->j_bytes/baudrate, 157: ctime(&jp->j_date) + 4, jp->j_flags, sizeof (jp->j_fname), jp->j_fname 158: ); 159: } else { 160: printf("%s", jp->j_jobno); 161: putchar((i+1)%10 ? '\t' : '\n'); 162: } 163: /* There's no need to keep the force poll if jobs > 1*/ 164: if (sp->s_njobs > 1 && strcmp("POLL", jp->j_jobno)==0) { 165: char pbuf[BUFSIZ]; 166: sprintf(pbuf,"%s/%c.%szPOLL", subdir(Spool, CMDPRE), CMDPRE,sp->s_name); 167: unlink(pbuf); 168: } 169: } 170: if (!lflag && (sp->s_njobs%10)) 171: putchar('\n'); 172: } 173: exit(0); 174: } 175: 176: jcompare(j1, j2) 177: struct job **j1, **j2; 178: { 179: int delta; 180: 181: delta = (*j1)->j_grade - (*j2)->j_grade; 182: if (delta) 183: return delta; 184: return(strcmp((*j1)->j_jobno,(*j2)->j_jobno)); 185: } 186: 187: /* 188: * Get all the command file names 189: */ 190: gather() 191: { 192: struct direct *d; 193: DIR *df; 194: 195: /* 196: * Find all the spool files in the spooling directory 197: */ 198: if ((df = opendir(subdir(Spool, CMDPRE))) == NULL) { 199: fprintf(stderr, "can't examine spooling area"); 200: exit(1); 201: } 202: for (;;) { 203: if ((d = readdir(df)) == NULL) 204: break; 205: if (d->d_namlen <= 2 || d->d_name[0] != CMDPRE || 206: d->d_name[1] != '.') 207: continue; 208: if (analjob(d->d_name) < 0) { 209: fprintf(stderr, "out of memory\n"); 210: break; 211: } 212: } 213: closedir(df); 214: } 215: 216: /* 217: * analjob does the grunge work of verifying jobs 218: */ 219: analjob(filename) 220: char *filename; 221: { 222: struct job *jp; 223: struct sys *sp; 224: char sbuf[MAXNAMLEN+1], str[256], nbuf[256]; 225: char *jptr, *wrkvec[20]; 226: char grade; 227: FILE *fp, *df; 228: struct stat statb; 229: int files, gotname, i; 230: off_t bytes; 231: 232: strncpy(sbuf, filename, MAXNAMLEN); 233: sbuf[MAXNAMLEN] = '\0'; 234: jptr = sbuf + strlen(sbuf) - WSUFSIZE; 235: grade = *jptr; 236: *jptr++ = 0; 237: /* 238: * sbuf+2 now points to sysname name (null terminated) 239: * jptr now points to job number (null terminated) 240: */ 241: if (rmjob) { 242: if (strcmp(rmjob, jptr)) 243: return(0); 244: } else { 245: if ((sp = getsys(sbuf+2)) == NOSYS) 246: return(0); 247: if (!lflag) { 248: /* SHOULD USE A SMALLER STRUCTURE HERE */ 249: jp = (struct job *)malloc(sizeof(struct job)); 250: if (jp == (struct job *)0) 251: return(-1); 252: strcpy(jp->j_jobno, jptr); 253: jp->j_jobp = sp->s_jobp; 254: jp->j_grade = grade; 255: sp->s_jobp = jp; 256: sp->s_njobs++; 257: return(1); 258: } 259: } 260: if ((fp = fopen(subfile(filename), "r")) == NULL) { 261: perror(subfile(filename)); 262: return(0); 263: } 264: files = 0; 265: bytes = 0; 266: gotname = 0; 267: while (fgets(str, sizeof str, fp)) { 268: if (getargs(str, wrkvec, 20) <= 0) 269: continue; 270: if (rmjob) { 271: if (W_TYPE[0] == 'S' && !index(W_OPTNS, 'c')) { 272: unlink(subfile(W_DFILE)); 273: fprintf(stderr, "Removing data file %s\n", W_DFILE); 274: } 275: continue; 276: } 277: if (user && (W_TYPE[0] == 'X' || !prefix(user, W_USER))) { 278: fclose(fp); 279: return(0); 280: } 281: files++; 282: if (W_TYPE[0] == 'S') { 283: if (strcmp(W_DFILE, "D.0") && 284: stat(subfile(W_DFILE), &statb) >= 0) 285: bytes += statb.st_size; 286: else if (stat(subfile(W_FILE1), &statb) >= 0) 287: bytes += statb.st_size; 288: } 289: /* amusing heuristic */ 290: #define isXfile(s) (s[0]=='D' && s[strlen(s)-WSUFSIZE]=='X') 291: if (gotname == 0 && isXfile(W_FILE1)) { 292: if ((df = fopen(subfile(W_FILE1), "r")) == NULL) 293: continue; 294: while (fgets(nbuf, sizeof nbuf, df)) { 295: nbuf[strlen(nbuf) - 1] = '\0'; 296: if (nbuf[0] == 'C' && nbuf[1] == ' ') { 297: strcpy(Filename, nbuf+2); 298: gotname++; 299: } else if (nbuf[0] == 'R' && nbuf[1] == ' ') { 300: register char *p, *q, *r; 301: r = q = p = nbuf+2; 302: do { 303: if (*p == '!' || *p == '@'){ 304: r = q; 305: q = p+1; 306: } 307: } while (*p++); 308: 309: strcpy(Username, r); 310: W_USER = Username; 311: } 312: } 313: fclose(df); 314: } 315: } 316: fclose(fp); 317: if (rmjob) { 318: unlink(subfile(filename)); 319: fprintf(stderr, "Removing command file %s\n", filename); 320: exit(0); 321: } 322: if (files == 0) { 323: static char *wtype = "X"; 324: static char *wfile = "forced poll"; 325: if (strcmp("POLL", &filename[strlen(filename)-4])) { 326: fprintf(stderr, "%.14s: empty command file\n", filename); 327: return(0); 328: } 329: W_TYPE = wtype; 330: W_FILE1 = wfile; 331: } 332: jp = (struct job *)malloc(sizeof(struct job)); 333: if (jp == (struct job *)0) 334: return(-1); 335: strcpy(jp->j_jobno, jptr); 336: jp->j_files = files; 337: jp->j_bytes = bytes; 338: jp->j_grade = grade; 339: jp->j_flags = W_TYPE[0]; 340: strncpy(jp->j_user, W_TYPE[0]=='X' ? "---" : W_USER, 20 ); 341: jp->j_user[20] = '\0'; 342: i = strlen(jp->j_user); 343: if (i > Maxulen) 344: Maxulen = i; 345: /* SHOULD ADD ALL INFORMATION IN THE WHILE LOOP */ 346: if (gotname) 347: strncpy(jp->j_fname, Filename, sizeof jp->j_fname); 348: else 349: strncpy(jp->j_fname, W_FILE1, sizeof jp->j_fname); 350: stat(subfile(filename), &statb); 351: jp->j_date = statb.st_mtime; 352: jp->j_jobp = sp->s_jobp; 353: sp->s_jobp = jp; 354: sp->s_njobs++; 355: sp->s_bytes += jp->j_bytes; 356: return(1); 357: } 358: 359: struct sys * 360: getsys(s) 361: register char *s; 362: { 363: register struct sys *sp; 364: 365: for (sp = syshead; sp; sp = sp->s_sysp) 366: if (strcmp(s, sp->s_name) == 0) 367: return(sp); 368: if (sysname && !prefix(sysname, s)) 369: return(NOSYS); 370: sp = (struct sys *)malloc(sizeof(struct sys)); 371: if (sp == NOSYS) 372: return(NOSYS); 373: strcpy(sp->s_name, s); 374: sp->s_njobs = 0; 375: sp->s_jobp = (struct job *)0; 376: sp->s_sysp = syshead; 377: sp->s_bytes = 0; 378: syshead = sp; 379: return(sp); 380: }