1 #ifndef lint 2 static char sccsid[] = "@(#)uuq.c 4.7 (Berkeley) 08/30/87"; 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 double 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 } 381