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