/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #pragma ident "%Z%%M% %I% %E% SMI" #include <time.h> #include "uucp.h" #ifdef V7 #define O_RDONLY 0 #endif #define KILLMSG "the system administrator has killed job" #define USAGE1 "[-q] | [-m] | [-k JOB [-n]] | [-r JOB [-n]] | [-p]" #define USAGE2 "[-a] [-s SYSTEM [-j]] [-u USER] [-S STATE]" #define USAGE3 "-t SYSTEM [-d number] [-c]" #define LOCK "LCK.." #define STST_MAX 132 #define MAXDATE 12 #define MINTIME 60 #define MINUTES 60 #define CHAR "a" #define MAXSTATE 4 /* #include "logs.h" */ struct m { char mach[15]; /* machine name */ char locked; int ccount, xcount; int count, type; long retrytime; time_t lasttime; short c_age; /* age of oldest C. file */ short x_age; /* age of oldest X. file */ char stst[STST_MAX]; } M[UUSTAT_TBL+2]; struct userdate { char uhour[3]; char umin[3]; char lhour[3]; char lmin[3]; }; struct userdate userformat; struct userdate *friendlyptr = &userformat; extern long atol(); static int whattodo(); static int readperf(); static void queuetime(); static void xfertime(); static char * gmt(); static char * gmts(); static void errortn(); static void friendlytime(); static void complete(); static int state(); static int gnameflck(); static void kprocessC(); static int convert(); void uprocessC(), printit(), docalc(), procState(); static short State, Queued, Running, Complete, Interrupted; static char mailmsg[BUFSIZ]; static char outbuf[BUFSIZ+1]; static int count; static short jobcount; static short execute; static char lowerlimit[MAXDATE+1], upperlimit[MAXDATE+1]; static float totalque, totalxfer; static long totaljob, totalbytes; static long inputsecs; #ifdef ATTSV extern void qsort(); /* qsort(3) and comparison test */ #endif /* ATTSV */ int sortcnt = -1; extern int machcmp(); extern int _age(); /* find the age of a file */ static long calcnum; extern char Jobid[]; /* jobid for status or kill option */ short Kill; /* == 1 if -k specified */ short Rejuvenate; /* == 1 for -r specified */ short Uopt; /* == 1 if -u option specified */ short Sysopt; /* == 1 if -s option specified */ static short Calctime; /* == 1 if -t parameter set */ short Summary; /* == 1 if -q or -m is specified */ short Queue; /* == 1 if -q option set - queue summary */ short Machines; /* == 1 if -m option set - machines summary */ short Psopt; /* == 1 if -p option set - output "ps" of LCK pids */ static short Window; /* == 1 if -d parameter set with -t option */ static short nonotf; /* == 1 if -n parameter set with -k option */ short avgqueue; /* == 1 if -c parameter set with -t option */ short avgxfer; /* will be set to 1 if -c not specified */ short Jobcount; /* == 1 if -j parameter set with -s option */ char f[NAMESIZE]; int main(argc, argv, envp) char *argv[]; char **envp; { struct m *m, *machine(); DIR *spooldir, *subdir, *machdir, *gradedir; char *str, *rindex(); char subf[256], gradef[256]; char *c, lckdir[BUFSIZ]; char buf[BUFSIZ]; char chkname[MAXFULLNAME]; char *vec[7]; int i, chkid; char fullpath[MAXFULLNAME]; long temp; char arglist[MAXSTATE+1]; /* Set locale environment variables local definitions */ (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ #endif (void) textdomain(TEXT_DOMAIN); User[0] = '\0'; Rmtname[0] = '\0'; Jobid[0] = '\0'; Psopt=Machines=Summary=Queue=Kill=Rejuvenate=Uopt=Sysopt=Jobcount=0; execute=avgqueue=avgxfer=Calctime=Window=0; jobcount=nonotf=0; /* set calcnum to default time in minutes */ calcnum=MINTIME; (void) strcpy(Progname, "uustat"); Uid = getuid(); Euid = geteuid(); guinfo(Uid, Loginuser); uucpname(Myname); while ((i = getopt(argc, argv, "acjk:mnpr:qs:u:x:t:d:S:")) != EOF) { switch(i){ case 'a': Sysopt = 1; break; case 'c': avgqueue = 1; break; case 'd': Window = 1; calcnum = atoi(optarg); if (calcnum <= 0) calcnum = MINTIME; break; case 'k': (void) strncpy(Jobid, optarg, NAMESIZE); Jobid[NAMESIZE-1] = '\0'; Kill = 1; break; case 'j': Jobcount = 1; break; case 'm': Machines = Summary = 1; break; case 'n': nonotf = 1; break; case 'p': Psopt = 1; break; case 'r': (void) strncpy(Jobid, optarg, NAMESIZE); Jobid[NAMESIZE-1] = '\0'; Rejuvenate = 1; break; case 'q': Queue = Summary = 1; break; case 's': (void) strncpy(Rmtname, optarg, MAXBASENAME); Rmtname[MAXBASENAME] = '\0'; if (versys(Rmtname)) { fprintf(stderr, gettext("Invalid system\n")); exit(1); } Sysopt = 1; break; case 't': Calctime = 1; (void) strncpy(Rmtname, optarg, MAXBASENAME); Rmtname[MAXBASENAME] = '\0'; if (versys(Rmtname)) { fprintf(stderr, gettext("Invalid system\n")); exit(1); } break; case 'u': (void) strncpy(User, optarg, 8); User[8] = '\0'; if(gninfo(User, &chkid, chkname)) { fprintf(stderr, gettext("Invalid user\n")); exit(1); } Uopt = 1; execute = 1; break; case 'x': Debug = atoi(optarg); if (Debug <= 0) Debug = 1; break; case 'S': if (strlen(optarg) > sizeof (arglist)) { errortn(); exit(1); } State = 1; (void) strlcpy(arglist, optarg, sizeof (arglist)); procState(arglist); break; default: errortn(); exit(1); } } if (argc != optind) { errortn(); exit(1); } DEBUG(9, "Progname (%s): STARTED\n", Progname); DEBUG(9, "User=%s, ", User); DEBUG(9, "Loginuser=%s, ", Loginuser); DEBUG(9, "Jobid=%s, ", Jobid); DEBUG(9, "Rmtname=%s\n", Rmtname); /* -j only allowed with -s */ if (Jobcount && !Sysopt) { errortn(); exit(1); } if ((Calctime + Psopt + Machines + Queue + Kill + Rejuvenate + (Uopt|Sysopt |State)) >1) { /* only -u, -S and -s can be used together */ errortn(); exit(1); } if ((avgqueue | Window) & (!Calctime)) { errortn(); exit(1); } if ( !(Calctime | Kill | Rejuvenate | Uopt | Sysopt | Queue| Machines | State) ) { (void) strcpy(User, Loginuser); Uopt = 1; } if ( nonotf && !(Kill | Rejuvenate) ) { errortn(); exit(1); } /*****************************************/ /* PROCESS THE OPTIONS */ /*****************************************/ if (State && Complete) { DEBUG(9, "calling complete %d\n",Complete); complete(); } if (Calctime) { count = readperf(calcnum); if (count != 0) docalc(); } if (Psopt) { /* do "ps -flp" or pids in LCK files */ lckpid(); /* lckpid will not return */ } if (Summary) { /* Gather data for Summary option report */ if (chdir(STATDIR) || (spooldir = opendir(STATDIR)) == NULL) exit(101); /* good old code 101 */ while (gnamef(spooldir, f) == TRUE) { if (freopen(f, "r", stdin) == NULL) continue; m = machine(f); if (fgets(buf, sizeof(buf), stdin) == NULL) continue; if (getargs(buf, vec, 5) < 5) continue; m->type = atoi(vec[0]); m->count = atoi(vec[1]); m->lasttime = atol(vec[2]); m->retrytime = atol(vec[3]); (void) strncpy(m->stst, vec[4], STST_MAX); str = rindex(m->stst, ' '); (void) machine(++str); /* longer name? */ *str = '\0'; } closedir(spooldir); } if (Summary) { /* search for LCK machines */ char flck[MAXNAMESIZE]; (void) strcpy(lckdir, LOCKPRE); *strrchr(lckdir, '/') = '\0'; /* open lock directory */ if (chdir(lckdir) != 0 || (subdir = opendir(lckdir)) == NULL) exit(101); /* good old code 101 */ while (gnameflck(subdir, flck) == TRUE) { /* XXX - this is disgusting... */ if (EQUALSN("LCK..", flck, 5)) { if (!EQUALSN(flck + 5, "cul", 3) && !EQUALSN(flck + 5, "cua", 3) && !EQUALSN(flck + 5, "tty", 3) && !EQUALSN(flck + 5, "dtsw", 4) && !EQUALSN(flck + 5, "vadic", 5) && !EQUALSN(flck + 5, "micom", 5)) machine(flck + 5)->locked++; } } } if (chdir(SPOOL) != 0 || (spooldir = opendir(SPOOL)) == NULL) exit(101); /* good old code 101 */ while (gnamef(spooldir, f) == TRUE) { /* at /var/spool/uucp directory */ /* f will contain remote machine names */ if (EQUALSN("LCK..", f, 5)) continue; if (*Rmtname && !EQUALSN(Rmtname, f, MAXBASENAME)) continue; if ( (Kill || Rejuvenate) && (!EQUALSN(f, Jobid, strlen(Jobid)-5)) ) continue; if (DIRECTORY(f)) { if (chdir(f) != 0) exit(101); (void) sprintf(fullpath, "%s/%s", SPOOL, f); machdir = opendir(fullpath); if (machdir == NULL) exit(101); m = machine(f); while (gnamef(machdir, gradef) == TRUE) { /* at /var/spool/uucp/remote_name */ /* gradef will contain job_grade directory names */ if (DIRECTORY(gradef) && (gradedir = opendir(gradef))) { /* at /var/spool/uucp/remote_name/job_grade */ while (gnamef(gradedir, subf) == TRUE) { /* subf will contain file names */ /* files can be C. or D. or A., etc.. */ if (subf[1] == '.') { if (subf[0] == CMDPRE) { /* if file name is C. */ m->ccount++; if (Kill || Rejuvenate) kprocessC(gradef, subf); else if (Uopt | Sysopt | Queued | Running | Interrupted) /* go print out C. file info */ uprocessC(f ,gradef, subf); else /* get the age of the C. file */ if ( (i = _age(gradef, subf))>m->c_age) m->c_age = i; } } } closedir(gradedir); } else if (gradef[0] == XQTPRE && gradef[1] == '.') { m->xcount++; if ( (i = _age(machdir, gradef)) > m->x_age) m->x_age = i; } } closedir(machdir); } /* cd back to /var/spoool/uucp dir */ if (chdir(SPOOL) != 0) exit(101); } /* while more files in spooldir */ closedir(spooldir); if (Jobcount && (jobcount != 0)) printf("job count = %d\n",jobcount); /* for Kill or Rejuvenate - will not get here unless it failed */ if (Kill) { printf(gettext("Can't find Job %s; Not killed\n"), Jobid); exit(1); } else if (Rejuvenate) { printf(gettext("Can't find Job %s; Not rejuvenated\n"), Jobid); exit(1); } /* Make sure the overflow entry is null since it may be incorrect */ M[UUSTAT_TBL].mach[0] = NULLCHAR; if (Summary) { for((sortcnt = 0, m = &M[0]);*(m->mach) != NULL;(sortcnt++,m++)) ; qsort((char *)M, (unsigned int)sortcnt, sizeof(struct m), machcmp); for (m = M; m->mach[0] != NULLCHAR; m++) printit(m); } return (0); } /* * uprocessC - get information about C. file * */ void uprocessC(machine, dir, file) char *machine, *dir, *file; { struct stat s; struct tm *tp; char fullname[MAXFULLNAME], buf[BUFSIZ], user[9]; char xfullname[MAXFULLNAME]; char file1[BUFSIZ], file2[BUFSIZ], file3[BUFSIZ], type[2], opt[256]; short goodRecord = 0; FILE *fp, *xfp; short first = 1; int statefound = 0; extern long fsize(); char format_tmp[BUFSIZ+1]; fp=xfp=NULL; /*********************************************/ /* initialize output buffer to blanks */ /*********************************************/ if (Complete && !Queued && !Running && !Interrupted) return; outbuf[0] = NULLCHAR; DEBUG(9, "uprocessC(%s, ", dir); DEBUG(9, "%s);\n", file); if (Jobid[0] != '\0' && (!EQUALS(Jobid, &file[2])) ) { /* kill job - not this one */ return; } (void) sprintf(fullname, "%s/%s", dir, file); if (stat(fullname, &s) != 0) { /* error - can't stat */ DEBUG(4, "Can't stat file (%s),", fullname); DEBUG(4, " errno (%d) -- skip it!\n", errno); } fp = fopen(fullname, "r"); if (fp == NULL) { DEBUG(4, "Can't open file (%s), ", fullname); DEBUG(4, "errno=%d -- skip it!\n", errno); return; } tp = localtime(&s.st_mtime); if (s.st_size == 0 && User[0] == '\0') { /* dummy D. for polling */ sprintf(format_tmp,"%-12s %2.2d/%2.2d-%2.2d:%2.2d:%2.2d (POLL)\n", &file[2], tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec); (void) strcat(outbuf, format_tmp); } else while (fgets(buf, BUFSIZ, fp) != NULL) { if (sscanf(buf,"%s%s%s%s%s%s", type, file1, file2, user, opt, file3) <5) { DEBUG(4, "short line (%s)\n", buf); continue; } DEBUG(9, "type (%s), ", type); DEBUG(9, "file1 (%s)", file1); DEBUG(9, "file2 (%s)", file2); DEBUG(9, "file3 (%s)", file3); DEBUG(9, "user (%s)", user); goodRecord = 0; if (User[0] != '\0' && (!EQUALS(User, user)) ) continue; if (first) { sprintf(format_tmp,"%-12s", &file[2]); (void) strcat(outbuf, format_tmp); /* if the job state is requested call the state function to determine this job's state */ if (State) { statefound = state(dir, file); DEBUG(9, "uprocessC: statefound value = %d\n", statefound); if ((whattodo(statefound) != TRUE)) { outbuf[0] = NULLCHAR; return; } else { if (statefound == 1) (void) strcat(outbuf, "queued"); else if (statefound == 2) (void) strcat(outbuf, "running"); else if (statefound == 3) (void) strcat(outbuf, "interrupted"); } } sprintf(format_tmp, " %2.2d/%2.2d-%2.2d:%2.2d ", tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min); (void) strcat(outbuf, format_tmp); } else { sprintf(format_tmp,"%-12s %2.2d/%2.2d-%2.2d:%2.2d ", "", tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min); (void) strcat(outbuf, format_tmp); } first = 0; sprintf(format_tmp,"%s %s ", type, machine); (void) strcat(outbuf, format_tmp); if (*type == 'R') { sprintf(format_tmp,"%s %s ", user, file1); (void) strcat(outbuf, format_tmp); } else if (file2[0] != 'X') { sprintf(format_tmp,"%s %ld %s ", user, fsize(dir, file3, file1), file1); (void) strcat(outbuf, format_tmp); } else if (*type == 'S' && file2[0] == 'X') { (void) sprintf(xfullname, "%s/%s", dir, file1); xfp = fopen(xfullname, "r"); if (xfp == NULL) { /* program error */ DEBUG(4, "Can't read %s, ", xfullname); DEBUG(4, "errno=%d -- skip it!\n", errno); sprintf(format_tmp,"%s ", user); (void) strcat(outbuf, format_tmp); (void) strcat(outbuf,"????\n"); } else { char command[BUFSIZ], uline_u[BUFSIZ], uline_m[BUFSIZ]; char retaddr[BUFSIZ], *username; *retaddr = *uline_u = *uline_m = '\0'; while (fgets(buf, BUFSIZ, xfp) != NULL) { switch(buf[0]) { case 'C': strcpy(command, buf + 2); break; case 'U': sscanf(buf + 2, "%s%s", uline_u, uline_m); break; case 'R': sscanf(buf+2, "%s", retaddr); break; } } username = user; if (*uline_u != '\0') username = uline_u; if (*retaddr != '\0') username = retaddr; if (!EQUALS(uline_m, Myname)) printf("%s!", uline_m); sprintf(format_tmp,"%s %s", username, command); (void) strcat(outbuf, format_tmp); } } strcat(outbuf, "\n"); fputs(outbuf, stdout); outbuf[0] = NULLCHAR; goodRecord = 1; } /* end of while more data in buffer */ /* successful processing of a job, increment job count counter */ if (goodRecord) jobcount++; if (xfp != NULL) fclose(xfp); fclose(fp); return; } /* * whattodo - determine what to do with current C dot file * depending on any combination (2**3 - 1) of input * job states */ static int whattodo(inputint) int inputint; { /* Maybe some commentary here will help explain this truth table. Queued |Running |Interrupted ------------------------------------------------- X | | ------------------------------------------------- | X | ------------------------------------------------- | | X ------------------------------------------------- X | X | ------------------------------------------------- | X | X ------------------------------------------------- X | | X ------------------------------------------------- X | X | X ------------------------------------------------- Now do you understand. All possible combinations have to be evaluated to determine whether or not to print the C dot information out or not! Well, all but 000, because if neither of these states are input by the user we would not be examing the C dot file anyway! */ if (Queued && Running && Interrupted) return(TRUE); else if ((Queued && !Running && !Interrupted) && (inputint == 1)) return(TRUE); else if ((Running && !Queued && !Interrupted) && (inputint == 2)) return(TRUE); else if ((Interrupted && !Queued && !Running) && (inputint == 3)) return(TRUE); else if ((Queued && Running && !Interrupted) && (inputint == 1 || inputint == 2)) return(TRUE); else if ((!Queued && Running && Interrupted) && (inputint == 2 || inputint == 3)) return(TRUE); else if ((Queued && !Running && Interrupted) && (inputint ==1 || inputint == 3)) return(TRUE); else return(FALSE); } /* * kprocessC - process kill or rejuvenate job */ static void kprocessC(dir, file) char *file, *dir; { struct stat s; struct tm *tp; extern struct tm *localtime(); char fullname[MAXFULLNAME], buf[BUFSIZ], user[9]; char rfullname[MAXFULLNAME]; char file1[BUFSIZ], file2[BUFSIZ], file3[BUFSIZ], type[2], opt[256]; FILE *fp, *xfp; struct utimbuf times; short ret; short first = 1; DEBUG(9, "kprocessC(%s, ", dir); DEBUG(9, "%s);\n", file); if ((!EQUALS(Jobid, &file[2])) ) { /* kill job - not this one */ return; } (void) sprintf(fullname, "%s/%s", dir, file); if (stat(fullname, &s) != 0) { /* error - can't stat */ if(Kill) { fprintf(stderr, gettext("Can't stat:%s, errno (%d)--can't kill it!\n"), fullname, errno); } else { fprintf(stderr, gettext("Can't stat:%s, errno (%d)--can't rejuvenate it!\n"), fullname, errno); } exit(1); } fp = fopen(fullname, "r"); if (fp == NULL) { if(Kill) { fprintf(stderr, gettext("Can't read:%s, errno (%d)--can't kill it!\n"), fullname, errno); } else { fprintf(stderr, gettext("Can't read:%s, errno (%d)--can't rejuvenate it!\n"), fullname, errno); } exit(1); } times.actime = times.modtime = time((time_t *)NULL); while (fgets(buf, BUFSIZ, fp) != NULL) { if (sscanf(buf,"%s%s%s%s%s%s", type, file1, file2, user, opt, file3) <6) { if(Kill) { fprintf(stderr, gettext("Bad format:%s, errno (%d)--can't kill it!\n"), fullname, errno); } else { fprintf(stderr, gettext("Bad format:%s, errno (%d)--can't rejuvenate it!\n"), fullname, errno); } exit(1); } DEBUG(9, "buf in uprocessK = %s\n ", buf); DEBUG(9, "fullname is %s\n",fullname); DEBUG(9, "type (%s), ", type); DEBUG(9, "file1 (%s)", file1); DEBUG(9, "file2 (%s)", file2); DEBUG(9, "file3 (%s)", file3); DEBUG(9, "user (%s)", user); if (first) { if ((access(fullname, 02) != 0) && !PREFIX(Loginuser, user) && !PREFIX(user, Loginuser) ) { /* not allowed - not owner or root */ if(Kill) fprintf(stderr, gettext("Not owner," " uucp or root - can't kill job %s\n"), Jobid); else fprintf(stderr, gettext("Not owner, uucp or root -" " can't rejuvenate job %s\n"), Jobid); exit(1); } first = 0; } /* remove D. file */ (void) sprintf(rfullname, "%s/%s", dir, file3); DEBUG(4, "Remove %s\n", rfullname); if (Kill) ret = unlink(rfullname); else /* Rejuvenate */ ret = utime(rfullname, ×); if (ret != 0 && errno != ENOENT) { /* program error?? */ if(Kill) fprintf(stderr, gettext("Error: Can't kill," " File (%s), errno (%d)\n"), rfullname, errno); else fprintf(stderr, gettext("Error: Can't rejuvenated," " File (%s), errno (%d)\n"), rfullname, errno); exit(1); } } DEBUG(4, "Remove %s\n", fullname); if (Kill) ret = unlink(fullname); else /* Rejuvenate */ ret = utime(fullname, ×); if (ret != 0) { /* program error?? */ if(Kill) fprintf(stderr, gettext("Error1: Can't kill," " File (%s), errno (%d)\n"), fullname, errno); else fprintf(stderr, gettext("Error1: Can't rejuvenate," " File (%s), errno (%d)\n"), fullname, errno); exit(1); } /* if kill done by SA then send user mail */ else if (!EQUALS(Loginuser, user)) { sprintf(mailmsg, "%s %s", KILLMSG, Jobid); mailst(user, "job killed", mailmsg, "", ""); } fclose(fp); if (!nonotf) { if(Kill) printf(gettext("Job: %s successfully killed\n"), Jobid); else printf(gettext("Job: %s successfully rejuvenated\n"), Jobid); } exit(0); } /* * fsize - return the size of f1 or f2 (if f1 does not exist) * f1 is the local name * */ long fsize(dir, f1, f2) char *dir, *f1, *f2; { struct stat s; char fullname[BUFSIZ]; (void) sprintf(fullname, "%s/%s", dir, f1); if (stat(fullname, &s) == 0) { return(s.st_size); } if (stat(f2, &s) == 0) { return(s.st_size); } return(-99999); } void cleanup(){} void logent(){} /* to load ulockf.c */ void systat(){} /* to load utility.c */ struct m * machine(name) char *name; { struct m *m; size_t namelen; DEBUG(9, "machine(%s), ", name); namelen = strlen(name); for (m = M; m->mach[0] != NULLCHAR; m++) /* match on overlap? */ if (EQUALSN(name, m->mach, MAXBASENAME)) { /* use longest name */ if (namelen > strlen(m->mach)) (void) strcpy(m->mach, name); return(m); } /* * The table is set up with 2 extra entries * When we go over by one, output error to errors log * When more than one over, just reuse the previous entry */ DEBUG(9, "m-M=%d\n", m-M); if (m-M >= UUSTAT_TBL) { if (m-M == UUSTAT_TBL) { errent("MACHINE TABLE FULL", "", UUSTAT_TBL, __FILE__, __LINE__); (void) fprintf(stderr, gettext("WARNING: Table Overflow--output not complete\n")); } else /* use the last entry - overwrite it */ m = &M[UUSTAT_TBL]; } (void) strcpy(m->mach, name); m->c_age= m->x_age= m->lasttime= m->locked= m->ccount= m->xcount= 0; m->stst[0] = '\0'; return(m); } void printit(m) struct m *m; { struct tm *tp; time_t t; int minimum; extern struct tm *localtime(); if (m->ccount == 0 && m->xcount == 0 /*&& m->stst[0] == '\0'*/ && m->locked == 0 && Queue && m->type == 0) return; printf("%-10s", m->mach); if (Queue) { if (m->ccount) printf("%3dC", m->ccount); else printf(" "); if (m->c_age) printf("(%d)", m->c_age); else printf(" "); if (m->xcount) printf("%3dX", m->xcount); else printf(" "); if (m->x_age) printf("(%d) ", m->x_age); else printf(" "); } else printf(" "); if (m->lasttime) { tp = localtime(&m->lasttime); printf("%2.2d/%2.2d-%2.2d:%2.2d ", tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min); } /* if (m->locked && m->type != SS_INPROGRESS) */ if (m->locked) printf("Locked "); if (m->stst[0] != '\0') { printf("%s", m->stst); switch (m->type) { case SS_SEQBAD: case SS_LOGIN_FAILED: case SS_DIAL_FAILED: case SS_BAD_LOG_MCH: case SS_BADSYSTEM: case SS_CANT_ACCESS_DEVICE: case SS_DEVICE_FAILED: case SS_WRONG_MCH: case SS_RLOCKED: case SS_RUNKNOWN: case SS_RLOGIN: case SS_UNKNOWN_RESPONSE: case SS_STARTUP: case SS_CHAT_FAILED: (void) time(&t); t = m->retrytime - (t - m->lasttime); if (t > 0) { minimum = (t + 59) / 60; printf("Retry: %d:%2.2d", minimum/60, minimum%60); } if (m->count > 1) printf(" Count: %d", m->count); } } putchar('\n'); return; } #define MAXLOCKS 100 /* Maximum number of lock files this will handle */ int lckpid() { int i; int fd, ret; pid_t pid, list[MAXLOCKS]; char alpid[SIZEOFPID+2]; /* +2 for '\n' and null */ char buf[BUFSIZ], f[MAXNAMESIZE]; char *c, lckdir[BUFSIZ]; DIR *dir; DEBUG(9, "lckpid() - entered\n%s", ""); for (i=0; i<MAXLOCKS; i++) list[i] = -1; (void) strcpy(lckdir, LOCKPRE); *strrchr(lckdir, '/') = '\0'; DEBUG(9, "lockdir (%s)\n", lckdir); /* open lock directory */ if (chdir(lckdir) != 0 || (dir = opendir(lckdir)) == NULL) exit(101); /* good old code 101 */ while (gnameflck(dir, f) == TRUE) { /* find all lock files */ DEBUG(9, "f (%s)\n", f); if (EQUALSN("LCK.", f, 4) || EQUALSN("LK.", f, 3)) { /* read LCK file */ fd = open(f, O_RDONLY); printf("%s: ", f); ret = read(fd, alpid, SIZEOFPID+2); /* +2 for '\n' and null */ pid = strtol(alpid, (char **) NULL, 10); (void) close(fd); if (ret != -1) { printf("%ld\n", (long) pid); for(i=0; i<MAXLOCKS; i++) { if (list[i] == pid) break; if (list[i] == -1) { list[i] = pid; break; } } } else printf("????\n"); } } fflush(stdout); *buf = NULLCHAR; for (i=0; i<MAXLOCKS; i++) { if( list[i] == -1) break; (void) sprintf(&buf[strlen(buf)], "%d ", list[i]); } if (i > 0) #ifdef V7 execl("/bin/ps", "uustat-ps", buf, (char *) 0); #else execl("/usr/bin/ps", "ps", "-flp", buf, (char *) 0); #endif exit(0); } /* * get next file name from lock directory * p -> file description of directory file to read * filename -> address of buffer to return filename in * must be of size NAMESIZE * returns: * FALSE -> end of directory read * TRUE -> returned name */ static int gnameflck(p, filename) char *filename; DIR *p; { struct dirent dentry; struct dirent *dp = &dentry; for (;;) { if ((dp = readdir(p)) == NULL) return(FALSE); if (dp->d_ino != 0 && dp->d_name[0] != '.') break; } (void) strncpy(filename, dp->d_name, MAXNAMESIZE-1); filename[MAXNAMESIZE-1] = '\0'; return(TRUE); } int machcmp(a,b) char *a,*b; { return(strcmp(((struct m *) a)->mach,((struct m *) b)->mach)); } static long _sec_per_day = 86400L; /* * _age - find the age of "file" in days * return: * age of file * 0 - if stat fails */ int _age(dir, file) char * file; /* the file name */ char * dir; /* system spool directory */ { char fullname[MAXFULLNAME]; static time_t ptime = 0; time_t time(); struct stat stbuf; if (!ptime) (void) time(&ptime); (void) sprintf(fullname, "%s/%s", dir, file); if (stat(fullname, &stbuf) != -1) { return ((int)((ptime - stbuf.st_mtime)/_sec_per_day)); } else return(0); } /* Function: complete - find and print jobids of completed jobs for * user. * * Look thru the /var/uucp/.Admin/account file (if present) * for all jobs initiated by user and print. * * Parameters: * * Username - user that initiated uustat request * * Returns: * */ static void complete() { /* Function name: complete Author: Roland T. Conwell Date: July 31, 1986 Naration: This function will search through /var/uucp/.Admin/account file for all jobs submitted by User. If User jobs are found the state of 'completed' will be printed on stdout. Module called by uustat main */ char abuf[BUFSIZ]; FILE *fp; char accno[15], jobid[15], system[15], loginame[15], time[20], dest[15]; char size[15]; char grade[2], jgrade[2]; char status[2]; int x; fp = fopen(ACCOUNT, "r"); if (fp == NULL) { fprintf(stderr, gettext("Can't open account log\n")); return; } while (fgets(abuf, BUFSIZ, fp) != NULL) { x = sscanf(abuf, "%s%s%s%s%s%s%s%s%s%s", accno,jobid, size, status, grade, jgrade, system, loginame, time, dest); if (x < 6) continue; if (!EQUALS(status, "C")) continue; DEBUG(9, "COMPLETE: accno = %s\n", accno); DEBUG(9, "COMPLETE: jobid = %s\n", jobid); DEBUG(9, "COMPLETE: size = %s\n", size); DEBUG(9, "COMPLETE: status = %s\n", status); DEBUG(9, "COMPLETE: grade = %s\n", grade); DEBUG(9, "COMPLETE: jgrade = %s\n", jgrade); DEBUG(9, "COMPLETE: system = %s\n", system); DEBUG(9, "COMPLETE: loginame = %s\n", loginame); DEBUG(9, "COMPLETE: time = %s\n", time); DEBUG(9, "COMPLETE: dest = %s\n", dest); if (*Rmtname && !EQUALS(Rmtname, dest)) continue; if (*User && !EQUALS(User, loginame)) continue; if (State && !Uopt) { if (EQUALS(Loginuser, loginame)) { printf("%s completed\n",jobid); jobcount++; } } else { printf("%s completed\n", jobid); jobcount++; } } fclose(fp); return; } /* Function: state - determine if Cdotfile is queued or running * * This function searches thru the directory jcdir for a Adotfile * that matches the Cdotfile. If found then look for a matching * lock file. If a Adotfile and a lock file is found then the * job is in the running state. If no Adotfile is found then the * job is in the queued state. If a Adotfile is found and no * lock file is found then the job is queued. * * Parameters: * * jcdir - the job grade directory to search * cdotfile - the Cdotfile whose state is to be determined * * Returns: * */ static int state(jcdir, cdotfile) char *jcdir, *cdotfile; { short found, foundlck, CequalA; char comparef[MAXBASENAME+1], afile[MAXBASENAME+1], cfile[MAXBASENAME+1]; char lckfile[MAXBASENAME+1], lockname[MAXBASENAME+1]; char lckdir[BUFSIZ+1]; DIR *subjcdir, *sjcdir; int rtnstate = 0; foundlck = 0; CequalA = 0; sjcdir = opendir(jcdir); if (sjcdir == NULL) return (0); while (gnamef(sjcdir, comparef) == TRUE) { if (comparef[0] == 'A') { (void) strcpy(afile, comparef); *strchr(afile, 'A') = ' '; (void) strcpy(cfile, cdotfile); *strchr(cfile, 'C') = ' '; if (EQUALS(cfile, afile)) { /* now we have a C. and A. for same job */ /* check for LCK..machine.job_grade */ /* if no LCK file at this point we will */ /* print the RUNNING state */ CequalA = 1; (void) strcpy(lckdir, LOCKPRE); *strrchr(lckdir, '/') = '\0'; /* open lock directory */ subjcdir = opendir(lckdir); if (subjcdir == NULL) exit(101); /* I know, I know! */ (void) sprintf(lockname,"%s%s.%s",LOCK, f, jcdir); while (gnamef(subjcdir, lckfile) == TRUE) { DEBUG(9, "STATE: lockfile = %s\n",lckfile); if (EQUALS(lockname, lckfile)) foundlck = 1; } closedir(subjcdir); } } } closedir(sjcdir); /* got adot, cdot and lock file */ if (Running && foundlck) rtnstate = 2; else if (Interrupted && CequalA && !foundlck) rtnstate = 3; else if (Queued && !CequalA && !foundlck) rtnstate = 1; DEBUG(9, "STATE: returning with value %d\n",rtnstate); return(rtnstate); } /* end of state.c */ static int readperf(timerange) long timerange; { char proto[2], jc[2], role[2]; char rectype[5], time[MAXDATE+1], pid[10],wmachine[10]; char remote[10],device[10], netid[20], jobid[20]; static float queuetime, tat; static long size; struct tm tm_tmp; time_t t_time, t_starttime, t_upperlimit; char options[10]; static float rst, ust, kst, xferrate, utt, ktt; static float rtt, wfield, xfield, yfield; struct perfrec *recptr; static float tqt; static int jobs; char abuf[BUFSIZ]; FILE *fp; static int x; char *strptr, *startime; int recordcnt; totalxfer=totalbytes=recordcnt=totaljob=totalque=0; lowerlimit[0] = '\0'; upperlimit[0] = '\0'; inputsecs = convert(timerange); startime = gmts(); strncpy(lowerlimit, startime, MAXDATE); strncpy(upperlimit, gmt(), MAXDATE); /* convert lowerlimit and upperlimit to HH:MM format */ friendlytime(lowerlimit, upperlimit); fp = fopen(PERFLOG, "r"); if (fp == NULL) { (void) fprintf(stderr, gettext("Can't open performance log\n")); return(0); } while (fgets(abuf, BUFSIZ, fp) != NULL) { DEBUG(9, "READPERF: abuf before = %s\n",abuf); if (!EQUALSN(abuf, "xfer", 4)) continue; /* convert all '|'s to blanks for sscanf */ for (strptr = abuf; *strptr != '\0'; strptr++) if (*strptr == '|') *strptr = ' '; DEBUG(9, "READPERF: abuf = %s\n",abuf); 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", rectype, time, pid, wmachine, role, remote, device, netid, jobid, &queuetime, &tat, &size, options, &rst, &ust, &kst, &xferrate, &utt, &ktt, &rtt, &wfield, &xfield); DEBUG(9, "READPERF: rectype = %s\n",rectype); DEBUG(9, "READPERF: time = %s\n",time); DEBUG(9, "READPERF: pid = %s\n",pid); DEBUG(9, "READPERF: remote = %s\n",remote); DEBUG(9, "READPERF: jobid = %s\n",jobid); DEBUG(9, "READPERF: queuetime = %f\n",queuetime); DEBUG(9, "READPERF: tat = %f\n",tat); DEBUG(9, "READPERF: xferrate = %f\n",xferrate); abuf[0] = '\0'; if (!EQUALS(Rmtname, remote)) continue; if (!EQUALS(role, "M")) continue; if (x < 18) continue; DEBUG(9, "READPERF: startime = %s\n", startime); DEBUG(9, "READPERF: lowerlimit = %s\n", lowerlimit); DEBUG(9, "READPERF: time = %s\n", time); DEBUG(9, "READPERF: upperlimit = %s\n", upperlimit); strptime(time, "%y %m %d %H %M %S", &tm_tmp); t_time = mktime(&tm_tmp); strptime(startime, "%y %m %d %H %M %S", &tm_tmp); t_starttime = mktime(&tm_tmp); strptime(upperlimit, "%y %m %d %H %M %S", &tm_tmp); t_upperlimit = mktime(&tm_tmp); DEBUG(9, "READPERF: t_time = %d\n", t_time); DEBUG(9, "READPERF: t_starttime = %d\n", t_starttime); DEBUG(9, "READPERF: t_upperlimit = %d\n", t_upperlimit); if (t_starttime <= t_time && t_upperlimit >= t_time) { totaljob++; totalque = totalque + queuetime; totalxfer = totalxfer + xferrate; totalbytes = totalbytes + size; recordcnt = recordcnt + 1; DEBUG(9, " processing recordcnt %d\n", recordcnt); } DEBUG(9, "END step 1 %d\n", recordcnt); } /* while */ DEBUG(9, "END step 2 recordcnt %d\n", recordcnt); fclose(fp); return(recordcnt); } /* end of readperf */ void docalc() { if (avgqueue) queuetime(); else xfertime(); return; } static int convert(intime) long intime; { long outtime; outtime = intime * 60; return(outtime); } static void queuetime() { static double avgqtime; avgqtime = totalque / totaljob; printf("average queue time to [%s] for last [%ld] minutes: %6.2f seconds\n",Rmtname, calcnum, avgqtime); printf("data gathered from %s:%s to %s:%s GMT\n", friendlyptr->uhour, friendlyptr->umin, friendlyptr->lhour, friendlyptr->lmin); return; } static void xfertime() { static double avgxrate; avgxrate = totalbytes / totalxfer; printf("average transfer rate with [ %s ] for last [%ld] minutes: %6.2f bytes/sec\n", Rmtname, calcnum, avgxrate); printf("data gathered from %s:%s to %s:%s GMT\n", friendlyptr->uhour, friendlyptr->umin, friendlyptr->lhour, friendlyptr->lmin); return; } /* * Local Function: gmts - Generate Start Time String * * This function returns the address to a string containing the start * time, or upperlimit, for searching the PERFLOG. * The start time is in GMT in the form YYMMDDhhmmss. * * Parameters: * * none * * Return: * * An address of a static character array containing the date. */ static char * gmts() { static char date[] = "YYMMDDhhmmss"; struct tm *td; time_t now; /* Current time. */ time_t temp; now = time((time_t *) 0); /* inputsecs is declared global to this file */ DEBUG(9, "GMTS: now = %ld\n", now); DEBUG(9, "GMTS: inputsecs = %ld\n", inputsecs); temp = (now - inputsecs); td = gmtime(&temp); (void) sprintf(date, "%02d%02d%02d%02d%02d%02d", (td->tm_year % 100), td->tm_mon + 1, td->tm_mday, td->tm_hour, td->tm_min, td->tm_sec ); return date; } /* * Local Function: gmt - Generate Current Time String * * This function returns the address to a string containing the current * GMT in the form YYMMDDhhmmss. * * Parameters: * * none * * Return: * * An address of a static character array containing the date. */ static char * gmt() { static char date[] = "YYMMDDhhmmss"; struct tm *td; time_t now; /* Current time. */ now = time((time_t *) 0); td = gmtime(&now); (void) sprintf(date, "%02d%02d%02d%02d%02d%02d", (td->tm_year % 100), td->tm_mon + 1, td->tm_mday, td->tm_hour, td->tm_min, td->tm_sec ); return date; } static void friendlytime(uplimit, lolimit) char *uplimit, *lolimit; { char c; c = *(uplimit+6); friendlyptr->uhour[0] = *(uplimit+6); friendlyptr->uhour[1] = *(uplimit+7); friendlyptr->lhour[0] = *(lolimit+6); friendlyptr->lhour[1] = *(lolimit+7); friendlyptr->umin[0] = *(uplimit+8); friendlyptr->umin[1] = *(uplimit+9); friendlyptr->lmin[0] = *(lolimit+8); friendlyptr->lmin[1] = *(lolimit+9); friendlyptr->uhour[2] = '\0'; friendlyptr->lhour[2] = '\0'; friendlyptr->umin[2] = '\0'; friendlyptr->lmin[2] = '\0'; return; } void procState(inputargs) char * inputargs; { if (strchr(inputargs, 'q') != NULL) Queued = 1; if (strchr(inputargs, 'r') != NULL) Running = 1; if (strchr(inputargs, 'i') != NULL) Interrupted = 1; if (strchr(inputargs, 'c') != NULL) Complete = 1; if ((size_t)(Queued + Running + Interrupted + Complete) < strlen(inputargs)) { errortn(); exit(1); } return; } static void errortn() { (void) fprintf(stderr, gettext("\tUsage: %s " USAGE1 "\n"), Progname); (void) fprintf(stderr, gettext("or\n\tUsage: %s " USAGE2 "\n"), Progname); (void) fprintf(stderr, gettext("or\n\tUsage: %s " USAGE3 "\n"), Progname); return; }