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