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