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