xref: /illumos-gate/usr/src/cmd/bnu/uustat.c (revision f875b4ebb1dd9fdbeb043557cab38ab3bf7f6e01)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 #include <time.h>
32 #include "uucp.h"
33 
34 #ifdef	V7
35 #define O_RDONLY	0
36 #endif
37 #define KILLMSG "the system administrator has killed job"
38 #define USAGE1	"[-q] | [-m] | [-k JOB [-n]] | [-r JOB [-n]] | [-p]"
39 #define USAGE2	"[-a] [-s SYSTEM [-j]] [-u USER] [-S STATE]"
40 #define USAGE3  "-t SYSTEM [-d number] [-c]"
41 #define LOCK "LCK.."
42 #define STST_MAX	132
43 #define MAXDATE		12
44 #define MINTIME		60
45 #define MINUTES		60
46 #define CHAR		"a"
47 #define MAXSTATE	4
48 /* #include "logs.h" */
49 struct m {
50 	char	mach[15];		/* machine name */
51 	char	locked;
52 	int	ccount, xcount;
53 	int	count, type;
54 	long	retrytime;
55 	time_t lasttime;
56 	short	c_age;			/* age of oldest C. file */
57 	short	x_age;			/* age of oldest X. file */
58 	char	stst[STST_MAX];
59 } M[UUSTAT_TBL+2];
60 
61 
62 struct userdate {
63 	char uhour[3];
64 	char umin[3];
65 	char lhour[3];
66 	char lmin[3];
67 };
68 
69 struct userdate userformat;
70 struct userdate *friendlyptr = &userformat;
71 
72 extern long atol();
73 static int whattodo();
74 static int readperf();
75 static void queuetime();
76 static void xfertime();
77 static char * gmt();
78 static char * gmts();
79 static void errortn();
80 static void friendlytime();
81 static void complete();
82 static int state();
83 static int gnameflck();
84 static void kprocessC();
85 static int convert();
86 void uprocessC(), printit(), docalc(), procState();
87 
88 static short State, Queued, Running, Complete, Interrupted;
89 
90 static char mailmsg[BUFSIZ];
91 static char outbuf[BUFSIZ+1];
92 static int count;
93 static short jobcount;
94 static short execute;
95 static char lowerlimit[MAXDATE+1], upperlimit[MAXDATE+1];
96 static float totalque, totalxfer;
97 static long totaljob, totalbytes;
98 static long inputsecs;
99 #ifdef ATTSV
100 extern void qsort();		/* qsort(3) and comparison test */
101 #endif /* ATTSV */
102 int sortcnt = -1;
103 extern int machcmp();
104 extern int _age();		/* find the age of a file */
105 static long calcnum;
106 extern char Jobid[];	/* jobid for status or kill option */
107 short Kill;		/*  == 1 if -k specified */
108 short Rejuvenate;	/*  == 1 for -r specified */
109 short Uopt;		/*  == 1 if -u option specified */
110 short Sysopt;		/*  == 1 if -s option specified */
111 static short Calctime;   /*  == 1 if -t parameter set */
112 short Summary;		/*  == 1 if -q or -m is specified */
113 short Queue;		/*  == 1 if -q option set - queue summary */
114 short Machines;		/*  == 1 if -m option set - machines summary */
115 short Psopt;		/*  == 1 if -p option set - output "ps" of LCK pids */
116 static short Window;    /*  == 1 if -d parameter set with -t option */
117 static short nonotf;    /*  == 1 if -n parameter set with -k option */
118 short avgqueue;		/*  == 1 if -c parameter set with -t option */
119 short avgxfer;		/*  will be set to 1 if -c not specified    */
120 short Jobcount;		/* == 1 if -j parameter set with -s option */
121 char f[NAMESIZE];
122 
123 int
124 main(argc, argv, envp)
125 char *argv[];
126 char **envp;
127 {
128 	struct m *m, *machine();
129 	DIR *spooldir, *subdir, *machdir, *gradedir;
130 	char *str, *rindex();
131 	char subf[256], gradef[256];
132 	char *c, lckdir[BUFSIZ];
133 	char buf[BUFSIZ];
134 	char chkname[MAXFULLNAME];
135 	char *vec[7];
136 	int i, chkid;
137 	char fullpath[MAXFULLNAME];
138 	long temp;
139 
140 	char arglist[MAXSTATE+1];
141 
142 	/* Set locale environment variables local definitions */
143 	(void) setlocale(LC_ALL, "");
144 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
145 #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it wasn't */
146 #endif
147 	(void) textdomain(TEXT_DOMAIN);
148 
149 	User[0] = '\0';
150 	Rmtname[0] = '\0';
151 	Jobid[0] = '\0';
152 	Psopt=Machines=Summary=Queue=Kill=Rejuvenate=Uopt=Sysopt=Jobcount=0;
153 	execute=avgqueue=avgxfer=Calctime=Window=0;
154 	jobcount=nonotf=0;
155 
156 	/* set calcnum to default time in minutes */
157 	calcnum=MINTIME;
158 
159 	(void) strcpy(Progname, "uustat");
160 	Uid = getuid();
161 	Euid = geteuid();
162 	guinfo(Uid, Loginuser);
163 	uucpname(Myname);
164 	while ((i = getopt(argc, argv, "acjk:mnpr:qs:u:x:t:d:S:")) != EOF) {
165 		switch(i){
166 		case 'a':
167 			Sysopt = 1;
168 			break;
169 		case 'c':
170 			avgqueue = 1;
171 			break;
172 		case 'd':
173 			Window = 1;
174 			calcnum = atoi(optarg);
175 			if (calcnum <= 0)
176 				calcnum = MINTIME;
177 			break;
178 		case 'k':
179 			(void) strncpy(Jobid, optarg, NAMESIZE);
180 			Jobid[NAMESIZE-1] = '\0';
181 			Kill = 1;
182 			break;
183 		case 'j':
184 			Jobcount = 1;
185 			break;
186 		case 'm':
187 			Machines = Summary = 1;
188 			break;
189 		case 'n':
190 			nonotf = 1;
191 			break;
192 		case 'p':
193 			Psopt = 1;
194 			break;
195 		case 'r':
196 			(void) strncpy(Jobid, optarg, NAMESIZE);
197 			Jobid[NAMESIZE-1] = '\0';
198 			Rejuvenate = 1;
199 			break;
200 		case 'q':
201 			Queue = Summary = 1;
202 			break;
203 		case 's':
204 			(void) strncpy(Rmtname, optarg, MAXBASENAME);
205 
206 			Rmtname[MAXBASENAME] = '\0';
207 			if (versys(Rmtname)) {
208 				fprintf(stderr, gettext("Invalid system\n"));
209 				exit(1);
210 			}
211 			Sysopt = 1;
212 			break;
213 		case 't':
214 			Calctime = 1;
215 			(void) strncpy(Rmtname, optarg, MAXBASENAME);
216 			Rmtname[MAXBASENAME] = '\0';
217 			if (versys(Rmtname)) {
218 				fprintf(stderr, gettext("Invalid system\n"));
219 				exit(1);
220 			}
221 			break;
222 		case 'u':
223 			(void) strncpy(User, optarg, 8);
224 			User[8] = '\0';
225 			if(gninfo(User, &chkid, chkname)) {
226 				fprintf(stderr, gettext("Invalid user\n"));
227 				exit(1);
228 			}
229 			Uopt = 1;
230 			execute = 1;
231 			break;
232 		case 'x':
233 			Debug = atoi(optarg);
234 			if (Debug <= 0)
235 				Debug = 1;
236 			break;
237 		case 'S':
238 			if (strlen(optarg) > sizeof (arglist)) {
239 				errortn();
240 				exit(1);
241 			}
242 			State = 1;
243 			(void) strlcpy(arglist, optarg, sizeof (arglist));
244 			procState(arglist);
245 			break;
246 		default:
247 			errortn();
248 			exit(1);
249 		}
250 	}
251 
252 	if (argc != optind) {
253 		errortn();
254 		exit(1);
255 	}
256 
257 	DEBUG(9, "Progname (%s): STARTED\n", Progname);
258 	DEBUG(9, "User=%s, ", User);
259 	DEBUG(9, "Loginuser=%s, ", Loginuser);
260 	DEBUG(9, "Jobid=%s, ", Jobid);
261 	DEBUG(9, "Rmtname=%s\n", Rmtname);
262 
263 	/* -j only allowed with -s */
264 	if (Jobcount && !Sysopt)
265 		{
266 		errortn();
267 		exit(1);
268 		}
269        if ((Calctime + Psopt + Machines + Queue + Kill + Rejuvenate + (Uopt|Sysopt |State)) >1) {
270 		/* only -u, -S and -s can be used together */
271 		errortn();
272 		exit(1);
273 	}
274 	if ((avgqueue | Window) & (!Calctime))
275 		{
276 		errortn();
277 		exit(1);
278 	}
279 
280 	if (  !(Calctime | Kill | Rejuvenate | Uopt | Sysopt | Queue| Machines | State) ) {
281 		(void) strcpy(User, Loginuser);
282 		Uopt = 1;
283 	}
284 
285 	if ( nonotf && !(Kill | Rejuvenate) ) {
286 		errortn();
287 		exit(1);
288 	}
289 
290 	/*****************************************/
291 	/* PROCESS THE OPTIONS                   */
292 	/*****************************************/
293 
294 	if (State && Complete)
295 		{
296 		   DEBUG(9, "calling complete %d\n",Complete);
297 		   complete();
298 		}
299 
300 	if (Calctime) {
301 		count = readperf(calcnum);
302 
303 		if (count != 0)
304 			docalc();
305 
306 	}
307 
308 	if (Psopt) {
309 		/* do "ps -flp" or pids in LCK files */
310 		lckpid();
311 		/* lckpid will not return */
312 	}
313 
314 	if (Summary) {
315 	    /*   Gather data for Summary option report  */
316 	    if (chdir(STATDIR) || (spooldir = opendir(STATDIR)) == NULL)
317 		exit(101);		/* good old code 101 */
318 	    while (gnamef(spooldir, f) == TRUE) {
319 		if (freopen(f, "r", stdin) == NULL)
320 			continue;
321 		m = machine(f);
322 		if (fgets(buf, sizeof(buf), stdin) == NULL)
323 			continue;
324 		if (getargs(buf, vec, 5) < 5)
325 			continue;
326 		m->type = atoi(vec[0]);
327 		m->count = atoi(vec[1]);
328 		m->lasttime = atol(vec[2]);
329 		m->retrytime = atol(vec[3]);
330 		(void) strncpy(m->stst, vec[4], STST_MAX);
331 		str = rindex(m->stst, ' ');
332 		(void) machine(++str);	/* longer name? */
333 		*str = '\0';
334 
335 	    }
336 	    closedir(spooldir);
337 	}
338 
339 
340 	if (Summary) {
341 	    /*  search for LCK machines  */
342 	    char flck[MAXNAMESIZE];
343 
344 	    (void) strcpy(lckdir, LOCKPRE);
345 	    *strrchr(lckdir, '/') = '\0';
346 	    /* open lock directory */
347 	    if (chdir(lckdir) != 0 || (subdir = opendir(lckdir)) == NULL)
348 		exit(101);		/* good old code 101 */
349 
350 	    while (gnameflck(subdir, flck) == TRUE) {
351 		/* XXX - this is disgusting... */
352 		if (EQUALSN("LCK..", flck, 5)) {
353 		    if (!EQUALSN(flck + 5, "cul", 3)
354 		     && !EQUALSN(flck + 5, "cua", 3)
355 		     && !EQUALSN(flck + 5, "tty", 3)
356 		     && !EQUALSN(flck + 5, "dtsw", 4)
357 		     && !EQUALSN(flck + 5, "vadic", 5)
358 		     && !EQUALSN(flck + 5, "micom", 5))
359 			machine(flck + 5)->locked++;
360 		}
361 	    }
362 	}
363 
364 	if (chdir(SPOOL) != 0 || (spooldir = opendir(SPOOL)) == NULL)
365 		exit(101);		/* good old code 101 */
366 
367 	while (gnamef(spooldir, f) == TRUE) {
368 	 /* at /var/spool/uucp directory */
369 	 /* f will contain remote machine names */
370 
371           if (EQUALSN("LCK..", f, 5))
372 		continue;
373 
374           if (*Rmtname && !EQUALSN(Rmtname, f, MAXBASENAME))
375 		continue;
376 
377           if ( (Kill || Rejuvenate)
378 	      && (!EQUALSN(f, Jobid, strlen(Jobid)-5)) )
379 		    continue;
380 
381 	  if (DIRECTORY(f))  {
382 		if (chdir(f) != 0)
383 			exit(101);
384 		(void) sprintf(fullpath, "%s/%s", SPOOL, f);
385 		machdir = opendir(fullpath);
386 		if (machdir == NULL)
387 			exit(101);
388 
389 		m = machine(f);
390 		while (gnamef(machdir, gradef) == TRUE) {
391 			/* at /var/spool/uucp/remote_name */
392 			/* gradef will contain job_grade directory names */
393 
394 	     		if (DIRECTORY(gradef) && (gradedir = opendir(gradef))) {
395 				/* at /var/spool/uucp/remote_name/job_grade */
396 
397 		  		while (gnamef(gradedir, subf) == TRUE) {
398 				    /* subf will contain file names */
399 				    /* files can be C. or D. or A., etc.. */
400 
401 				    if (subf[1] == '.') {
402 		  		      if (subf[0] == CMDPRE) {
403 					/* if file name is C. */
404 					m->ccount++;
405 
406 					if (Kill || Rejuvenate)
407 					    kprocessC(gradef, subf);
408 					else if (Uopt | Sysopt | Queued | Running | Interrupted)
409 				 	   /* go print out C. file info */
410 				  	   uprocessC(f ,gradef, subf);
411 
412 					else 	/* get the age of the C. file */
413 				 	   if ( (i = _age(gradef, subf))>m->c_age)
414 						m->c_age = i;
415 					}
416 		    		    }
417 				}
418 				closedir(gradedir);
419 			}
420 
421 			else if (gradef[0] == XQTPRE && gradef[1] == '.') {
422 			   m->xcount++;
423 			   if ( (i = _age(machdir, gradef)) > m->x_age)
424 				m->x_age = i;
425 			}
426 		}
427 		closedir(machdir);
428 	  }
429 	  /* cd back to /var/spoool/uucp dir */
430 	  if (chdir(SPOOL) != 0)
431 		exit(101);
432 	} /* while more files in spooldir */
433 	closedir(spooldir);
434 
435 	if (Jobcount && (jobcount != 0))
436 		printf("job count = %d\n",jobcount);
437 
438 	/* for Kill or Rejuvenate - will not get here unless it failed */
439 	if (Kill) {
440 	    printf(gettext("Can't find Job %s; Not killed\n"), Jobid);
441 	    exit(1);
442 	} else if (Rejuvenate) {
443 	    printf(gettext("Can't find Job %s; Not rejuvenated\n"), Jobid);
444 	    exit(1);
445 	}
446 
447 	/* Make sure the overflow entry is null since it may be incorrect */
448 	M[UUSTAT_TBL].mach[0] = NULLCHAR;
449 	if (Summary) {
450 	    for((sortcnt = 0, m = &M[0]);*(m->mach) != NULL;(sortcnt++,m++))
451 			;
452 	    qsort((char *)M, (unsigned int)sortcnt, sizeof(struct m), machcmp);
453 	    for (m = M; m->mach[0] != NULLCHAR; m++)
454 		printit(m);
455 	}
456 	return (0);
457 }
458 
459 
460 /*
461  * uprocessC - get information about C. file
462  *
463  */
464 
465 void
466 uprocessC(machine, dir, file)
467 char   *machine, *dir, *file;
468 {
469 	struct stat s;
470 	struct tm *tp;
471 	char fullname[MAXFULLNAME], buf[BUFSIZ], user[9];
472 	char xfullname[MAXFULLNAME];
473 	char file1[BUFSIZ], file2[BUFSIZ], file3[BUFSIZ], type[2], opt[256];
474 	short goodRecord = 0;
475 	FILE *fp, *xfp;
476 	short first = 1;
477 	int statefound = 0;
478 	extern long fsize();
479 	char format_tmp[BUFSIZ+1];
480 	fp=xfp=NULL;
481 
482 	/*********************************************/
483 	/* initialize output buffer to blanks        */
484 	/*********************************************/
485 
486 	if (Complete && !Queued && !Running && !Interrupted)
487 		return;
488 	outbuf[0] = NULLCHAR;
489 
490 	DEBUG(9, "uprocessC(%s, ", dir);
491 	DEBUG(9, "%s);\n", file);
492 
493 	if (Jobid[0] != '\0' && (!EQUALS(Jobid, &file[2])) ) {
494 		/* kill job - not this one */
495 		return;
496 	}
497 
498 	(void) sprintf(fullname, "%s/%s", dir, file);
499 	if (stat(fullname, &s) != 0) {
500 	     /* error - can't stat */
501 	    DEBUG(4, "Can't stat file (%s),", fullname);
502 	    DEBUG(4, " errno (%d) -- skip it!\n", errno);
503 	}
504 
505 	fp = fopen(fullname, "r");
506 	if (fp == NULL) {
507 		DEBUG(4, "Can't open file (%s), ", fullname);
508 		DEBUG(4, "errno=%d -- skip it!\n", errno);
509 		return;
510 	}
511 	tp = localtime(&s.st_mtime);
512 
513 	if (s.st_size == 0 && User[0] == '\0') { /* dummy D. for polling */
514 	    sprintf(format_tmp,"%-12s  %2.2d/%2.2d-%2.2d:%2.2d:%2.2d  (POLL)\n",
515 		&file[2], tp->tm_mon + 1, tp->tm_mday, tp->tm_hour,
516 		tp->tm_min, tp->tm_sec);
517 		(void) strcat(outbuf, format_tmp);
518 	}
519 	else while (fgets(buf, BUFSIZ, fp) != NULL) {
520 	    if (sscanf(buf,"%s%s%s%s%s%s", type, file1, file2,
521 	      user, opt, file3) <5) {
522 		DEBUG(4, "short line (%s)\n", buf);
523 		continue;
524 	    }
525 	    DEBUG(9, "type (%s), ", type);
526 	    DEBUG(9, "file1 (%s)", file1);
527 	    DEBUG(9, "file2 (%s)", file2);
528 	    DEBUG(9, "file3 (%s)", file3);
529 	    DEBUG(9, "user (%s)", user);
530 
531 	    goodRecord = 0;
532 
533 	    if (User[0] != '\0' && (!EQUALS(User, user)) )
534 		continue;
535 
536 
537 	    if (first)
538 	       {
539 	        sprintf(format_tmp,"%-12s", &file[2]);
540 		(void) strcat(outbuf, format_tmp);
541 
542 		/* if the job state is requested call the
543 		   state function to determine this job's state */
544 
545 		if (State)
546 		{
547 		   statefound = state(dir, file);
548 	           DEBUG(9, "uprocessC: statefound value = %d\n", statefound);
549  		   if ((whattodo(statefound) != TRUE))
550 			{
551 			   outbuf[0] = NULLCHAR;
552 			   return;
553 			}
554 		   else
555 			{
556 			   if (statefound == 1)
557 				(void) strcat(outbuf, "queued");
558 			   else if (statefound == 2)
559 				(void) strcat(outbuf, "running");
560 			   else if (statefound == 3)
561 				(void) strcat(outbuf, "interrupted");
562 			}
563 		}
564 		sprintf(format_tmp, " %2.2d/%2.2d-%2.2d:%2.2d ",
565 		    tp->tm_mon + 1, tp->tm_mday, tp->tm_hour,
566 		    tp->tm_min);
567 		(void) strcat(outbuf, format_tmp);
568 	       }
569 	    else
570 	       {
571 		sprintf(format_tmp,"%-12s %2.2d/%2.2d-%2.2d:%2.2d ",
572 		    "", tp->tm_mon + 1, tp->tm_mday, tp->tm_hour,
573 		    tp->tm_min);
574 		(void) strcat(outbuf, format_tmp);
575 		}
576 	    first = 0;
577 
578 	    sprintf(format_tmp,"%s  %s  ", type, machine);
579 	    (void) strcat(outbuf, format_tmp);
580 	    if (*type == 'R')
581 	       {
582 	        sprintf(format_tmp,"%s  %s ", user, file1);
583 	        (void) strcat(outbuf, format_tmp);
584 	       }
585 	    else if (file2[0] != 'X')
586 		{
587 		 sprintf(format_tmp,"%s %ld %s ", user, fsize(dir, file3, file1), file1);
588 		 (void) strcat(outbuf, format_tmp);
589 		}
590 	    else if (*type == 'S' && file2[0] == 'X') {
591 		(void) sprintf(xfullname, "%s/%s", dir, file1);
592 		xfp = fopen(xfullname, "r");
593 		if (xfp == NULL) { /* program error */
594 		    DEBUG(4, "Can't read %s, ", xfullname);
595 		    DEBUG(4, "errno=%d -- skip it!\n", errno);
596 		    sprintf(format_tmp,"%s  ", user);
597 		    (void) strcat(outbuf, format_tmp);
598 		    (void) strcat(outbuf,"????\n");
599 		}
600 		else {
601 		    char command[BUFSIZ], uline_u[BUFSIZ], uline_m[BUFSIZ];
602 		    char retaddr[BUFSIZ], *username;
603 
604 		    *retaddr = *uline_u = *uline_m = '\0';
605 		    while (fgets(buf, BUFSIZ, xfp) != NULL) {
606 			switch(buf[0]) {
607 			case 'C':
608 				strcpy(command, buf + 2);
609 				break;
610 			case 'U':
611 				sscanf(buf + 2, "%s%s", uline_u, uline_m);
612 				break;
613 			case 'R':
614 				sscanf(buf+2, "%s", retaddr);
615 				break;
616 			}
617 		    }
618 		    username = user;
619 		    if (*uline_u != '\0')
620 			    username = uline_u;
621 		    if (*retaddr != '\0')
622 			username = retaddr;
623 		    if (!EQUALS(uline_m, Myname))
624 			printf("%s!", uline_m);
625 		    sprintf(format_tmp,"%s  %s", username, command);
626 		    (void) strcat(outbuf, format_tmp);
627 		}
628 	    }
629        	strcat(outbuf, "\n");
630 	fputs(outbuf, stdout);
631         outbuf[0] = NULLCHAR;
632 	goodRecord = 1;
633        } /* end of while more data in buffer */
634 
635        /* successful processing of a job, increment job count
636 	  counter */
637 	if (goodRecord)
638             jobcount++;
639 
640 	if (xfp != NULL)
641 	    fclose(xfp);
642 
643 	fclose(fp);
644 	return;
645 }
646 /*
647  * whattodo - determine what to do with current C dot file
648  *  	     depending on any combination (2**3 - 1) of input
649  *	     job states
650  */
651 static int
652 whattodo(inputint)
653 int inputint;
654 {
655 	/* Maybe some commentary here will help explain this truth
656 	   table.
657 
658 	Queued		|Running	|Interrupted
659 	-------------------------------------------------
660 		X	|		|
661 	-------------------------------------------------
662 			|	X	|
663 	-------------------------------------------------
664 			|		|      X
665 	-------------------------------------------------
666 		X	|	X	|
667 	-------------------------------------------------
668 			|	X	|      X
669 	-------------------------------------------------
670 		X	|		|      X
671 	-------------------------------------------------
672 		X	|	X	|      X
673 	-------------------------------------------------
674 
675 	Now do you understand.  All  possible combinations have to
676 	be evaluated to determine whether or not to print the C dot
677 	information out or not! Well, all but 000, because if neither
678 	of these states are input by the user we would not be
679 	examing the C dot file anyway!
680 	*/
681 
682 	if (Queued && Running && Interrupted)
683 		return(TRUE);
684 	else if ((Queued && !Running && !Interrupted) && (inputint == 1))
685 		return(TRUE);
686 	else if ((Running && !Queued && !Interrupted) && (inputint == 2))				return(TRUE);
687 	else if ((Interrupted && !Queued && !Running) && (inputint == 3))				return(TRUE);
688 	else if ((Queued && Running && !Interrupted) &&
689 		(inputint == 1 || inputint == 2))
690 	  		return(TRUE);
691 	else if ((!Queued && Running && Interrupted) &&
692 		(inputint == 2 || inputint == 3))
693 			return(TRUE);
694 	else if ((Queued && !Running && Interrupted) &&
695 		(inputint ==1 || inputint == 3))
696 			return(TRUE);
697 	else return(FALSE);
698 }
699 /*
700  * kprocessC - process kill or rejuvenate job
701  */
702 
703 static void
704 kprocessC(dir, file)
705 char *file, *dir;
706 {
707 	struct stat s;
708 	struct tm *tp;
709 	extern struct tm *localtime();
710 	char fullname[MAXFULLNAME], buf[BUFSIZ], user[9];
711 	char rfullname[MAXFULLNAME];
712 	char file1[BUFSIZ], file2[BUFSIZ], file3[BUFSIZ], type[2], opt[256];
713 	FILE *fp, *xfp;
714  	struct utimbuf times;
715 	short ret;
716 	short first = 1;
717 
718 	DEBUG(9, "kprocessC(%s, ", dir);
719 	DEBUG(9, "%s);\n", file);
720 
721 	if ((!EQUALS(Jobid, &file[2])) ) {
722 		/* kill job - not this one */
723 		return;
724 	}
725 
726 	(void) sprintf(fullname, "%s/%s", dir, file);
727 	if (stat(fullname, &s) != 0) {
728 	     /* error - can't stat */
729 	    if(Kill) {
730 		fprintf(stderr,
731 		  gettext("Can't stat:%s, errno (%d)--can't kill it!\n"),
732 		  fullname, errno);
733 	    } else {
734 		fprintf(stderr,
735 		  gettext("Can't stat:%s, errno (%d)--can't rejuvenate it!\n"),
736 		  fullname, errno);
737 	    }
738 	    exit(1);
739 	}
740 
741 	fp = fopen(fullname, "r");
742 	if (fp == NULL) {
743 	    if(Kill) {
744 		fprintf(stderr,
745 		  gettext("Can't read:%s, errno (%d)--can't kill it!\n"),
746 		  fullname, errno);
747 	    } else {
748 		fprintf(stderr,
749 		  gettext("Can't read:%s, errno (%d)--can't rejuvenate it!\n"),
750 		  fullname, errno);
751 	    }
752 	    exit(1);
753 	}
754 
755  	times.actime = times.modtime = time((time_t *)NULL);
756 
757 	while (fgets(buf, BUFSIZ, fp) != NULL) {
758 	    if (sscanf(buf,"%s%s%s%s%s%s", type, file1, file2,
759 	      user, opt, file3) <6) {
760 		if(Kill) {
761 		    fprintf(stderr,
762 		      gettext("Bad format:%s, errno (%d)--can't kill it!\n"),
763 		      fullname, errno);
764 		} else {
765 		    fprintf(stderr,
766 		      gettext("Bad format:%s, errno (%d)--can't rejuvenate it!\n"),
767 		      fullname, errno);
768 		}
769 	        exit(1);
770 	    }
771 
772 	    DEBUG(9, "buf in uprocessK = %s\n ", buf);
773 	    DEBUG(9, "fullname is %s\n",fullname);
774 	    DEBUG(9, "type (%s), ", type);
775 	    DEBUG(9, "file1 (%s)", file1);
776 	    DEBUG(9, "file2 (%s)", file2);
777 	    DEBUG(9, "file3 (%s)", file3);
778 	    DEBUG(9, "user (%s)", user);
779 
780 
781 	    if (first) {
782 	        if ((access(fullname, 02) != 0)
783 		    && !PREFIX(Loginuser, user)
784 		    && !PREFIX(user, Loginuser) ) {
785 			/* not allowed - not owner or root */
786 			if(Kill)
787 			    fprintf(stderr, gettext("Not owner,"
788 			      " uucp or root - can't kill job %s\n"), Jobid);
789 			else
790 			    fprintf(stderr, gettext("Not owner, uucp or root -"
791 			      " can't rejuvenate job %s\n"), Jobid);
792 		    exit(1);
793 		}
794 		first = 0;
795 	    }
796 
797 	    /* remove D. file */
798 	    (void) sprintf(rfullname, "%s/%s", dir, file3);
799 	    DEBUG(4, "Remove %s\n", rfullname);
800 	    if (Kill)
801 		ret = unlink(rfullname);
802 	    else /* Rejuvenate */
803  		ret = utime(rfullname, &times);
804 	    if (ret != 0 && errno != ENOENT) {
805 		/* program error?? */
806 		if(Kill)
807 		    fprintf(stderr, gettext("Error: Can't kill,"
808 		      " File (%s), errno (%d)\n"), rfullname, errno);
809 		else
810 		    fprintf(stderr, gettext("Error: Can't rejuvenated,"
811 		      " File (%s), errno (%d)\n"), rfullname, errno);
812 		exit(1);
813 	    }
814 	}
815 
816 	DEBUG(4, "Remove %s\n", fullname);
817 	if (Kill)
818 	    ret = unlink(fullname);
819 	else /* Rejuvenate */
820 		ret = utime(fullname, &times);
821 
822 	if (ret != 0) {
823 	    /* program error?? */
824 	    if(Kill)
825 	        fprintf(stderr, gettext("Error1: Can't kill,"
826 	          " File (%s), errno (%d)\n"), fullname, errno);
827 	    else
828 	        fprintf(stderr, gettext("Error1: Can't rejuvenate,"
829 	          " File (%s), errno (%d)\n"), fullname, errno);
830 	    exit(1);
831 	}
832 	/* if kill done by SA then send user mail */
833 	else if (!EQUALS(Loginuser, user))
834 	   {
835 		sprintf(mailmsg, "%s %s", KILLMSG, Jobid);
836 		mailst(user, "job killed", mailmsg, "", "");
837 	   }
838 	fclose(fp);
839 	if (!nonotf) {
840 		if(Kill)
841 			printf(gettext("Job: %s successfully killed\n"), Jobid);
842 		else
843 			printf(gettext("Job: %s successfully rejuvenated\n"),
844 			    Jobid);
845 		}
846 	exit(0);
847 }
848 
849 /*
850  * fsize - return the size of f1 or f2 (if f1 does not exist)
851  *	f1 is the local name
852  *
853  */
854 
855 long
856 fsize(dir, f1, f2)
857 char *dir, *f1, *f2;
858 {
859 	struct stat s;
860 	char fullname[BUFSIZ];
861 
862 	(void) sprintf(fullname, "%s/%s", dir, f1);
863 	if (stat(fullname, &s) == 0) {
864 	    return(s.st_size);
865 	}
866 	if (stat(f2, &s) == 0) {
867 	    return(s.st_size);
868 	}
869 
870 	return(-99999);
871 }
872 
873 void cleanup(){}
874 void logent(){}		/* to load ulockf.c */
875 void systat(){}		/* to load utility.c */
876 
877 struct m	*
878 machine(name)
879 char	*name;
880 {
881 	struct m *m;
882 	size_t	namelen;
883 
884 	DEBUG(9, "machine(%s), ", name);
885 	namelen = strlen(name);
886 	for (m = M; m->mach[0] != NULLCHAR; m++)
887 		/* match on overlap? */
888 		if (EQUALSN(name, m->mach, MAXBASENAME)) {
889 			/* use longest name */
890 			if (namelen > strlen(m->mach))
891 				(void) strcpy(m->mach, name);
892 			return(m);
893 		}
894 
895 	/*
896 	 * The table is set up with 2 extra entries
897 	 * When we go over by one, output error to errors log
898 	 * When more than one over, just reuse the previous entry
899 	 */
900 	DEBUG(9, "m-M=%d\n", m-M);
901 	if (m-M >= UUSTAT_TBL) {
902 	    if (m-M == UUSTAT_TBL) {
903 		errent("MACHINE TABLE FULL", "", UUSTAT_TBL,
904 		__FILE__, __LINE__);
905 		(void) fprintf(stderr,
906 		    gettext("WARNING: Table Overflow--output not complete\n"));
907 	    }
908 	    else
909 		/* use the last entry - overwrite it */
910 		m = &M[UUSTAT_TBL];
911 	}
912 
913 	(void) strcpy(m->mach, name);
914 	m->c_age= m->x_age= m->lasttime= m->locked= m->ccount= m->xcount= 0;
915 	m->stst[0] = '\0';
916 	return(m);
917 }
918 
919 void
920 printit(m)
921 struct m *m;
922 {
923 	struct tm *tp;
924 	time_t	t;
925 	int	minimum;
926 	extern struct tm *localtime();
927 
928 	if (m->ccount == 0
929 	 && m->xcount == 0
930 	 /*&& m->stst[0] == '\0'*/
931 	 && m->locked == 0
932 	 && Queue
933 	 && m->type == 0)
934 		return;
935 	printf("%-10s", m->mach);
936 	if (Queue) {
937 		if (m->ccount)
938 			printf("%3dC", m->ccount);
939 		else
940 			printf("    ");
941 		if (m->c_age)
942 			printf("(%d)", m->c_age);
943 		else
944 			printf("   ");
945 		if (m->xcount)
946 			printf("%3dX", m->xcount);
947 		else
948 			printf("    ");
949 		if (m->x_age)
950 			printf("(%d) ", m->x_age);
951 		else
952 			printf("    ");
953 	} else
954 		printf(" ");
955 
956 	if (m->lasttime) {
957 	    tp = localtime(&m->lasttime);
958 	    printf("%2.2d/%2.2d-%2.2d:%2.2d ",
959 		tp->tm_mon + 1, tp->tm_mday, tp->tm_hour,
960 		tp->tm_min);
961 	}
962 /*	if (m->locked && m->type != SS_INPROGRESS) */
963 	if (m->locked)
964 		printf("Locked ");
965 	if (m->stst[0] != '\0') {
966 		printf("%s", m->stst);
967 		switch (m->type) {
968 		case SS_SEQBAD:
969 		case SS_LOGIN_FAILED:
970 		case SS_DIAL_FAILED:
971 		case SS_BAD_LOG_MCH:
972 		case SS_BADSYSTEM:
973 		case SS_CANT_ACCESS_DEVICE:
974 		case SS_DEVICE_FAILED:
975 		case SS_WRONG_MCH:
976 		case SS_RLOCKED:
977 		case SS_RUNKNOWN:
978 		case SS_RLOGIN:
979 		case SS_UNKNOWN_RESPONSE:
980 		case SS_STARTUP:
981 		case SS_CHAT_FAILED:
982 			(void) time(&t);
983 			t = m->retrytime - (t - m->lasttime);
984 			if (t > 0) {
985 				minimum = (t + 59) / 60;
986 				printf("Retry: %d:%2.2d", minimum/60, minimum%60);
987 			}
988 			if (m->count > 1)
989 				printf(" Count: %d", m->count);
990 		}
991 	}
992 	putchar('\n');
993 	return;
994 }
995 
996 #define MAXLOCKS 100	/* Maximum number of lock files this will handle */
997 
998 int
999 lckpid()
1000 {
1001     int i;
1002     int fd, ret;
1003     pid_t pid, list[MAXLOCKS];
1004     char alpid[SIZEOFPID+2];	/* +2 for '\n' and null */
1005     char buf[BUFSIZ], f[MAXNAMESIZE];
1006     char *c, lckdir[BUFSIZ];
1007     DIR *dir;
1008 
1009     DEBUG(9, "lckpid() - entered\n%s", "");
1010     for (i=0; i<MAXLOCKS; i++)
1011 	list[i] = -1;
1012     (void) strcpy(lckdir, LOCKPRE);
1013     *strrchr(lckdir, '/') = '\0';
1014     DEBUG(9, "lockdir (%s)\n", lckdir);
1015 
1016     /* open lock directory */
1017     if (chdir(lckdir) != 0 || (dir = opendir(lckdir)) == NULL)
1018 		exit(101);		/* good old code 101 */
1019     while (gnameflck(dir, f) == TRUE) {
1020 	/* find all lock files */
1021 	DEBUG(9, "f (%s)\n", f);
1022 	if (EQUALSN("LCK.", f, 4) || EQUALSN("LK.", f, 3)) {
1023 	    /* read LCK file */
1024 	    fd = open(f, O_RDONLY);
1025 	    printf("%s: ", f);
1026 	    ret = read(fd, alpid, SIZEOFPID+2); /* +2 for '\n' and null */
1027 	    pid = strtol(alpid, (char **) NULL, 10);
1028 	    (void) close(fd);
1029 	    if (ret != -1) {
1030 		printf("%ld\n", (long) pid);
1031 		for(i=0; i<MAXLOCKS; i++) {
1032 		    if (list[i] == pid)
1033 			break;
1034 		    if (list[i] == -1) {
1035 		        list[i] = pid;
1036 		        break;
1037 		    }
1038 		}
1039 	    }
1040 	    else
1041 		printf("????\n");
1042 	}
1043     }
1044     fflush(stdout);
1045     *buf = NULLCHAR;
1046     for (i=0; i<MAXLOCKS; i++) {
1047 	if( list[i] == -1)
1048 		break;
1049 	(void) sprintf(&buf[strlen(buf)], "%d ", list[i]);
1050     }
1051 
1052     if (i > 0)
1053 #ifdef V7
1054 	execl("/bin/ps", "uustat-ps", buf, (char *) 0);
1055 #else
1056 	execl("/usr/bin/ps", "ps", "-flp", buf, (char *) 0);
1057 #endif
1058     exit(0);
1059 }
1060 
1061 /*
1062  * get next file name from lock directory
1063  *	p	 -> file description of directory file to read
1064  *	filename -> address of buffer to return filename in
1065  *		    must be of size NAMESIZE
1066  * returns:
1067  *	FALSE	-> end of directory read
1068  *	TRUE	-> returned name
1069  */
1070 static int
1071 gnameflck(p, filename)
1072 char *filename;
1073 DIR *p;
1074 {
1075 	struct dirent dentry;
1076 	struct dirent *dp = &dentry;
1077 
1078 	for (;;) {
1079 		if ((dp = readdir(p)) == NULL)
1080 			return(FALSE);
1081 		if (dp->d_ino != 0 && dp->d_name[0] != '.')
1082 			break;
1083 	}
1084 
1085 	(void) strncpy(filename, dp->d_name, MAXNAMESIZE-1);
1086 	filename[MAXNAMESIZE-1] = '\0';
1087 	return(TRUE);
1088 }
1089 
1090 int
1091 machcmp(a,b)
1092 char *a,*b;
1093 {
1094 	return(strcmp(((struct m *) a)->mach,((struct m *) b)->mach));
1095 }
1096 
1097 static long _sec_per_day = 86400L;
1098 
1099 /*
1100  * _age - find the age of "file" in days
1101  * return:
1102  *	age of file
1103  *	0 - if stat fails
1104  */
1105 
1106 int
1107 _age(dir, file)
1108 char * file;	/* the file name */
1109 char * dir;	/* system spool directory */
1110 {
1111 	char fullname[MAXFULLNAME];
1112 	static time_t ptime = 0;
1113 	time_t time();
1114 	struct stat stbuf;
1115 
1116 	if (!ptime)
1117 		(void) time(&ptime);
1118 	(void) sprintf(fullname, "%s/%s", dir, file);
1119 	if (stat(fullname, &stbuf) != -1) {
1120 		return ((int)((ptime - stbuf.st_mtime)/_sec_per_day));
1121 	}
1122 	else
1123 		return(0);
1124 }
1125 /* Function:  complete - find and print jobids of completed jobs for
1126  *		         user.
1127  *
1128  * Look thru the /var/uucp/.Admin/account file (if present)
1129  * for all jobs initiated by user and print.
1130  *
1131  * Parameters:
1132  *
1133  *		Username - user that initiated uustat request
1134  *
1135  * Returns:
1136  *
1137  */
1138 static void
1139 complete()
1140 {
1141 
1142 	/* Function name: complete
1143 	   Author:	  Roland T. Conwell
1144 	   Date:	  July 31, 1986
1145 	   Naration: This function will search through
1146 		     /var/uucp/.Admin/account file
1147 		     for all jobs submitted by User.  If User jobs are
1148 		     found the state of 'completed' will be
1149 		     printed on stdout. Module called by uustat main
1150 
1151 	*/
1152 char abuf[BUFSIZ];
1153 FILE *fp;
1154 char accno[15], jobid[15], system[15], loginame[15], time[20], dest[15];
1155 char size[15];
1156 char grade[2], jgrade[2];
1157 char status[2];
1158 int x;
1159 
1160 fp = fopen(ACCOUNT, "r");
1161 if (fp == NULL)
1162    {
1163 	fprintf(stderr, gettext("Can't open account log\n"));
1164 		return;
1165    }
1166 while (fgets(abuf, BUFSIZ, fp) != NULL)
1167    {
1168 
1169 	x = sscanf(abuf, "%s%s%s%s%s%s%s%s%s%s",
1170 		accno,jobid, size, status, grade, jgrade, system, loginame,
1171 		time, dest);
1172 	if (x < 6)
1173 		continue;
1174 
1175 	if (!EQUALS(status, "C"))
1176 		continue;
1177 
1178 	DEBUG(9, "COMPLETE: accno = %s\n", accno);
1179 	DEBUG(9, "COMPLETE: jobid = %s\n", jobid);
1180 	DEBUG(9, "COMPLETE: size = %s\n", size);
1181 	DEBUG(9, "COMPLETE: status = %s\n", status);
1182 	DEBUG(9, "COMPLETE: grade = %s\n", grade);
1183 	DEBUG(9, "COMPLETE: jgrade = %s\n", jgrade);
1184 	DEBUG(9, "COMPLETE: system = %s\n", system);
1185 	DEBUG(9, "COMPLETE: loginame = %s\n", loginame);
1186 	DEBUG(9, "COMPLETE: time = %s\n", time);
1187 	DEBUG(9, "COMPLETE: dest = %s\n", dest);
1188 
1189 	if (*Rmtname && !EQUALS(Rmtname, dest))
1190 		continue;
1191 	if (*User && !EQUALS(User, loginame))
1192 		continue;
1193 	if (State && !Uopt)
1194 	  {
1195 	   if (EQUALS(Loginuser, loginame))
1196 		{
1197 			printf("%s completed\n",jobid);
1198 			jobcount++;
1199 		}
1200 	  }
1201 	else
1202 	  {
1203 		printf("%s completed\n", jobid);
1204 		jobcount++;
1205 	  }
1206    }
1207    fclose(fp);
1208    return;
1209 }
1210 
1211 /* Function: state - determine if Cdotfile is queued or running
1212  *
1213  * This function searches thru the directory jcdir for a Adotfile
1214  * that matches the Cdotfile.  If found then look for a matching
1215  * lock file.  If a Adotfile and a lock file is found then the
1216  * job is in the running state.  If no Adotfile is found then the
1217  * job is in the queued state.  If a Adotfile is found and no
1218  * lock file is found then the job is queued.
1219  *
1220  * Parameters:
1221  *
1222  *	jcdir    -   the job grade directory to search
1223  *	cdotfile -   the Cdotfile whose state is to be determined
1224  *
1225  * Returns:
1226  *
1227  */
1228 static int
1229 state(jcdir, cdotfile)
1230 char *jcdir, *cdotfile;
1231 {
1232 	short found, foundlck, CequalA;
1233 	char comparef[MAXBASENAME+1], afile[MAXBASENAME+1], cfile[MAXBASENAME+1];
1234 	char lckfile[MAXBASENAME+1], lockname[MAXBASENAME+1];
1235 	char lckdir[BUFSIZ+1];
1236 	DIR *subjcdir, *sjcdir;
1237 	int rtnstate = 0;
1238 	foundlck = 0;
1239 	CequalA = 0;
1240 	sjcdir = opendir(jcdir);
1241 	if (sjcdir == NULL)
1242 		return (0);
1243 
1244 	while (gnamef(sjcdir, comparef) == TRUE) {
1245 	    if (comparef[0] == 'A') {
1246 
1247 		(void) strcpy(afile, comparef);
1248 		*strchr(afile, 'A') = ' ';
1249 		(void) strcpy(cfile, cdotfile);
1250 		*strchr(cfile, 'C') = ' ';
1251 
1252 		if (EQUALS(cfile, afile)) {
1253 	 	    /* now we have a C. and A. for same job */
1254 	  	    /* check for LCK..machine.job_grade     */
1255 		    /* if no LCK file at this point we will */
1256 		    /* print the RUNNING state	        */
1257 			CequalA = 1;
1258 
1259 			(void) strcpy(lckdir, LOCKPRE);
1260 			*strrchr(lckdir, '/') = '\0';
1261 			/* open lock directory */
1262 
1263 			subjcdir = opendir(lckdir);
1264 			if (subjcdir == NULL)
1265 			   exit(101); /* I know, I know! */
1266 			(void) sprintf(lockname,"%s%s.%s",LOCK, f, jcdir);
1267 			while (gnamef(subjcdir, lckfile) == TRUE)
1268 			  {
1269 			    DEBUG(9, "STATE: lockfile = %s\n",lckfile);
1270 			    if (EQUALS(lockname, lckfile))
1271 			          foundlck = 1;
1272 			  }
1273 			closedir(subjcdir);
1274 
1275 			}
1276 		}
1277 
1278 	}
1279 
1280 	closedir(sjcdir);
1281 	/* got adot, cdot and lock file */
1282 
1283 	if (Running && foundlck)
1284 		rtnstate = 2;
1285 	else if (Interrupted && CequalA && !foundlck)
1286 		rtnstate = 3;
1287 	else if (Queued && !CequalA && !foundlck)
1288 		rtnstate = 1;
1289 	DEBUG(9, "STATE: returning with value %d\n",rtnstate);
1290 	return(rtnstate);
1291 
1292 } /* end of state.c */
1293 
1294 
1295 
1296 static int
1297 readperf(timerange)
1298 long timerange;
1299 {
1300 
1301 	char proto[2], jc[2], role[2];
1302 	char rectype[5],  time[MAXDATE+1], pid[10],wmachine[10];
1303 	char remote[10],device[10], netid[20], jobid[20];
1304 	static float queuetime, tat;
1305 	static long size;
1306         struct tm tm_tmp;
1307 	time_t t_time, t_starttime, t_upperlimit;
1308 
1309 	char options[10];
1310 	static float rst, ust, kst, xferrate, utt, ktt;
1311 	static float rtt, wfield, xfield, yfield;
1312 
1313 	struct perfrec *recptr;
1314 	static float tqt;
1315 	static int jobs;
1316 	char abuf[BUFSIZ];
1317 	FILE *fp;
1318 	static int x;
1319 	char *strptr, *startime;
1320 	int recordcnt;
1321 
1322 	totalxfer=totalbytes=recordcnt=totaljob=totalque=0;
1323 	lowerlimit[0] = '\0';
1324 	upperlimit[0] = '\0';
1325 
1326 
1327 	inputsecs = convert(timerange);
1328 	startime = gmts();
1329 	strncpy(lowerlimit, startime, MAXDATE);
1330 	strncpy(upperlimit, gmt(), MAXDATE);
1331 
1332 	/* convert lowerlimit and upperlimit to HH:MM format */
1333 	friendlytime(lowerlimit, upperlimit);
1334 
1335 	fp = fopen(PERFLOG, "r");
1336 	if (fp == NULL)
1337  	  {
1338 		(void) fprintf(stderr, gettext("Can't open performance log\n"));
1339 			return(0);
1340 	   }
1341 
1342 
1343 	while (fgets(abuf, BUFSIZ, fp) != NULL)
1344 	  {
1345 	    DEBUG(9, "READPERF: abuf before = %s\n",abuf);
1346 
1347 	    if (!EQUALSN(abuf, "xfer", 4))
1348 		continue;
1349 
1350             /* convert all '|'s to blanks for sscanf */
1351 	    for (strptr = abuf; *strptr != '\0'; strptr++)
1352 		if (*strptr == '|')
1353 		    *strptr = ' ';
1354 	    DEBUG(9, "READPERF: abuf = %s\n",abuf);
1355 
1356 	    x = sscanf(abuf, "%s%*s%s%s%s%s%s%s%*s%s%s%f%f%ld%s%f%f%f%f%f%f%f%f%f%*s",
1357 		rectype, time, pid, wmachine, role, remote, device, netid,
1358 		jobid, &queuetime, &tat, &size, options, &rst,
1359 		&ust, &kst, &xferrate, &utt, &ktt, &rtt, &wfield,
1360 		&xfield);
1361 
1362 		DEBUG(9, "READPERF: rectype = %s\n",rectype);
1363 		DEBUG(9, "READPERF: time = %s\n",time);
1364 		DEBUG(9, "READPERF: pid = %s\n",pid);
1365 		DEBUG(9, "READPERF: remote = %s\n",remote);
1366 		DEBUG(9, "READPERF: jobid = %s\n",jobid);
1367 		DEBUG(9, "READPERF: queuetime = %f\n",queuetime);
1368 		DEBUG(9, "READPERF: tat = %f\n",tat);
1369 		DEBUG(9, "READPERF: xferrate = %f\n",xferrate);
1370 
1371 		abuf[0] = '\0';
1372 
1373 		if (!EQUALS(Rmtname, remote))
1374 			continue;
1375 
1376 		if (!EQUALS(role, "M"))
1377 			continue;
1378 
1379 		if (x < 18)
1380 			continue;
1381 
1382 		DEBUG(9, "READPERF: startime = %s\n", startime);
1383 		DEBUG(9, "READPERF: lowerlimit = %s\n", lowerlimit);
1384 		DEBUG(9, "READPERF: time = %s\n", time);
1385 		DEBUG(9, "READPERF: upperlimit = %s\n", upperlimit);
1386 
1387 		strptime(time, "%y %m %d %H %M %S", &tm_tmp);
1388 		t_time = mktime(&tm_tmp);
1389 		strptime(startime, "%y %m %d %H %M %S", &tm_tmp);
1390 		t_starttime = mktime(&tm_tmp);
1391 		strptime(upperlimit, "%y %m %d %H %M %S", &tm_tmp);
1392 		t_upperlimit = mktime(&tm_tmp);
1393 
1394 		DEBUG(9, "READPERF: t_time = %d\n", t_time);
1395 		DEBUG(9, "READPERF: t_starttime = %d\n", t_starttime);
1396 		DEBUG(9, "READPERF: t_upperlimit = %d\n", t_upperlimit);
1397 		if (t_starttime <= t_time && t_upperlimit >= t_time)
1398 		{
1399 			totaljob++;
1400 			totalque = totalque + queuetime;
1401 			totalxfer = totalxfer + xferrate;
1402 			totalbytes = totalbytes + size;
1403 			recordcnt = recordcnt + 1;
1404 		DEBUG(9, "  processing recordcnt %d\n", recordcnt);
1405 		}
1406 	DEBUG(9, "END step 1 %d\n", recordcnt);
1407   	 } /* while */
1408 	DEBUG(9, "END step 2 recordcnt %d\n", recordcnt);
1409 
1410 	fclose(fp);
1411 	return(recordcnt);
1412 
1413 
1414 } /* end of readperf */
1415 
1416 void
1417 docalc()
1418 {
1419    if (avgqueue)
1420 	queuetime();
1421    else
1422 	xfertime();
1423    return;
1424 }
1425 
1426 static int
1427 convert(intime)
1428 long intime;
1429 {
1430 	long outtime;
1431 
1432 	outtime = intime * 60;
1433 	return(outtime);
1434 
1435 }
1436 static void
1437 queuetime()
1438 {
1439  	static double avgqtime;
1440 
1441 	avgqtime = totalque / totaljob;
1442 
1443 	printf("average queue time to [%s] for last [%ld] minutes:  %6.2f seconds\n",Rmtname, calcnum, avgqtime);
1444  	 printf("data gathered from %s:%s to %s:%s GMT\n", friendlyptr->uhour, friendlyptr->umin, friendlyptr->lhour, friendlyptr->lmin);
1445 	return;
1446 }
1447 
1448 
1449 static void
1450 xfertime()
1451 {
1452          static double avgxrate;
1453 
1454 	avgxrate = totalbytes / totalxfer;
1455 
1456 	printf("average transfer rate with [ %s ] for last [%ld] minutes: %6.2f bytes/sec\n", Rmtname, calcnum, avgxrate);
1457  	 printf("data gathered from %s:%s to %s:%s GMT\n", friendlyptr->uhour, friendlyptr->umin, friendlyptr->lhour, friendlyptr->lmin);
1458 	return;
1459 }
1460 
1461 /*
1462  * Local Function:	gmts - Generate Start Time String
1463  *
1464  * This function returns the address to a string containing the start
1465  * time, or upperlimit, for searching the PERFLOG.
1466  * The start time is in GMT in the form YYMMDDhhmmss.
1467  *
1468  * Parameters:
1469  *
1470  *	none
1471  *
1472  * Return:
1473  *
1474  *	An address of a static character array containing the date.
1475  */
1476 
1477 static char *
1478 gmts()
1479 {
1480 	static char	date[] = "YYMMDDhhmmss";
1481 
1482 	struct tm 		*td;
1483 	time_t			now;	/* Current time. */
1484 	time_t			temp;
1485 	now = time((time_t *) 0);
1486 
1487 	/* inputsecs is declared global to this file */
1488 	DEBUG(9, "GMTS: now = %ld\n", now);
1489 	DEBUG(9, "GMTS: inputsecs = %ld\n", inputsecs);
1490 
1491 	temp = (now - inputsecs);
1492 	td = gmtime(&temp);
1493 	(void) sprintf(date, "%02d%02d%02d%02d%02d%02d",
1494 				(td->tm_year % 100),
1495 				td->tm_mon + 1,
1496 				td->tm_mday,
1497 				td->tm_hour,
1498 				td->tm_min,
1499 				td->tm_sec
1500 		      );
1501 	return date;
1502 }
1503 
1504 /*
1505  * Local Function:	gmt - Generate Current Time String
1506  *
1507  * This function returns the address to a string containing the current
1508  * GMT in the form YYMMDDhhmmss.
1509  *
1510  * Parameters:
1511  *
1512  *	none
1513  *
1514  * Return:
1515  *
1516  *	An address of a static character array containing the date.
1517  */
1518 
1519 static char *
1520 gmt()
1521 {
1522 	static char	date[] = "YYMMDDhhmmss";
1523 
1524 	struct tm	*td;
1525 	time_t			now;	/* Current time. */
1526 
1527 	now = time((time_t *) 0);
1528 	td = gmtime(&now);
1529 	(void) sprintf(date, "%02d%02d%02d%02d%02d%02d",
1530 				(td->tm_year % 100),
1531 				td->tm_mon + 1,
1532 				td->tm_mday,
1533 				td->tm_hour,
1534 				td->tm_min,
1535 				td->tm_sec
1536 		      );
1537 	return date;
1538 }
1539 
1540 static void
1541 friendlytime(uplimit, lolimit)
1542 char *uplimit, *lolimit;
1543 {
1544 
1545 	char c;
1546 
1547 	c = *(uplimit+6);
1548 	friendlyptr->uhour[0] = *(uplimit+6);
1549 	friendlyptr->uhour[1] = *(uplimit+7);
1550 	friendlyptr->lhour[0] = *(lolimit+6);
1551 	friendlyptr->lhour[1] = *(lolimit+7);
1552 	friendlyptr->umin[0]  = *(uplimit+8);
1553 	friendlyptr->umin[1]  = *(uplimit+9);
1554 	friendlyptr->lmin[0]  = *(lolimit+8);
1555 	friendlyptr->lmin[1]  = *(lolimit+9);
1556 
1557 	friendlyptr->uhour[2] = '\0';
1558 	friendlyptr->lhour[2] = '\0';
1559 	friendlyptr->umin[2] = '\0';
1560 	friendlyptr->lmin[2] = '\0';
1561 	return;
1562 }
1563 
1564 void
1565 procState(inputargs)
1566 char * inputargs;
1567 {
1568 	if (strchr(inputargs, 'q') != NULL)
1569 		Queued = 1;
1570 	if (strchr(inputargs, 'r') != NULL)
1571 		Running = 1;
1572 	if (strchr(inputargs, 'i') != NULL)
1573 		Interrupted = 1;
1574 	if (strchr(inputargs, 'c') != NULL)
1575 		Complete = 1;
1576 
1577 	if ((size_t)(Queued + Running + Interrupted + Complete) < strlen(inputargs))
1578 		{
1579 			errortn();
1580 			exit(1);
1581 		}
1582 	return;
1583 }
1584 
1585 static void
1586 errortn()
1587 {
1588 
1589 
1590 	(void) fprintf(stderr, gettext("\tUsage: %s " USAGE1 "\n"),
1591 	    Progname);
1592 	(void) fprintf(stderr, gettext("or\n\tUsage: %s " USAGE2 "\n"),
1593 	    Progname);
1594 	(void) fprintf(stderr, gettext("or\n\tUsage: %s " USAGE3 "\n"),
1595 	    Progname);
1596 	return;
1597 }
1598