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