|
|
1.1 root 1: /* @(#)uustat.c 1.14
2: */
3: #include "uucp.h"
4: VERSION(@(#)uustat.c 1.14)
5:
6: #ifdef V7
7: #define O_RDONLY 0
8: #endif
9:
10: #define USAGE1 "[-a] [-q] or [-m] or [-kJOB] or [-rJOB] or [-p]"
11: #define USAGE2 "[-sSYSTEM] [-uUSER]"
12:
13: #define STST_MAX 132
14: struct m {
15: char mach[15]; /* machine name */
16: char locked;
17: int ccount, xcount;
18: int count, type;
19: long retrytime;
20: time_t lasttime;
21: short c_age; /* age of oldest C. file */
22: short x_age; /* age of oldest X. file */
23: char stst[STST_MAX];
24: } M[UUSTAT_TBL+2];
25:
26: extern long atol();
27: extern void qsort(); /* qsort(3) and comparison test */
28: int sortcnt = -1;
29: extern int machcmp();
30: extern int _age(); /* find the age of a file */
31:
32: extern char Jobid[]; /* jobid for status or kill option */
33: short Kill; /* == 1 if -k specified */
34: short Rejuvenate; /* == 1 for -r specified */
35: short Uopt; /* == 1 if -u option specified */
36: short Sysopt; /* == 1 if -s option specified */
37: short Summary; /* == 1 if -q or -m is specified */
38: short Queue; /* == 1 if -q option set - queue summary */
39: short Machines; /* == 1 if -m option set - machines summary */
40: short Psopt; /* == 1 if -p option set - output "ps" of LCK pids */
41:
42: main(argc, argv, envp)
43: char *argv[];
44: char **envp;
45: {
46: struct m *m, *machine();
47: DIR *spooldir, *subdir;
48: char *str, *rindex();
49: char f[256], subf[256];
50: char *c, lckdir[BUFSIZ];
51: char buf[BUFSIZ];
52: char chkname[MAXFULLNAME];
53: char *vec[7];
54: int i, chkid;
55:
56:
57: User[0] = '\0';
58: Rmtname[0] = '\0';
59: Jobid[0] = '\0';
60: Psopt=Machines=Summary=Queue=Kill=Rejuvenate=Uopt=Sysopt=0;
61: (void) strcpy(Progname, "uustat");
62: Uid = getuid();
63: Euid = geteuid();
64: guinfo(Uid, Loginuser);
65: uucpname(Myname);
66: while ((i = getopt(argc, argv, "ak:mpr:qs:u:x:")) != EOF) {
67: switch(i){
68: case 'a':
69: Sysopt = 1;
70: break;
71: case 'k':
72: (void) strncpy(Jobid, optarg, NAMESIZE);
73: Jobid[NAMESIZE] = '\0';
74: Kill = 1;
75: break;
76: case 'm':
77: Machines = Summary = 1;
78: break;
79: case 'p':
80: Psopt = 1;
81: break;
82: case 'r':
83: (void) strncpy(Jobid, optarg, NAMESIZE);
84: Jobid[NAMESIZE] = '\0';
85: Rejuvenate = 1;
86: break;
87: case 'q':
88: Queue = Summary = 1;
89: break;
90: case 's':
91: (void) strncpy(Rmtname, optarg, MAXBASENAME);
92: Rmtname[MAXBASENAME] = '\0';
93: if (versys(Rmtname, 0)) {
94: fprintf(stderr, "Invalid system\n");
95: exit(1);
96: }
97: Sysopt = 1;
98: break;
99: case 'u':
100: (void) strncpy(User, optarg, 8);
101: User[8] = '\0';
102: if(gninfo(User, &chkid, chkname)) {
103: fprintf(stderr, "Invalid user\n");
104: exit(1);
105: }
106: Uopt = 1;
107: break;
108: case 'x':
109: Debug = atoi(optarg);
110: if (Debug <= 0)
111: Debug = 1;
112: break;
113: default:
114: (void) fprintf(stderr, "\tusage: %s %s\n",
115: Progname, USAGE1);
116: (void) fprintf(stderr, "or\n\tusage: %s %s\n",
117: Progname, USAGE2);
118: exit(1);
119: }
120: }
121:
122: if (argc != optind) {
123: (void) fprintf(stderr, "\tusage: %s %s\n", Progname, USAGE1);
124: (void) fprintf(stderr, "or\n\tusage: %s %s\n",
125: Progname, USAGE2);
126: exit(1);
127: }
128:
129: DEBUG(9, "Progname (%s): STARTED\n", Progname);
130: DEBUG(9, "User=%s, ", User);
131: DEBUG(9, "Loginuser=%s, ", Loginuser);
132: DEBUG(9, "Jobid=%s, ", Jobid);
133: DEBUG(9, "Rmtname=%s\n", Rmtname);
134:
135: if ((Psopt + Machines + Queue + Kill + Rejuvenate + (Uopt|Sysopt)) >1) {
136: /* only -u and -s can be used together */
137: printf("\tusage: %s %s\n", Progname, USAGE1);
138: printf("or\n\tusage: %s %s\n", Progname, USAGE2);
139: exit(1);
140: }
141: if ( !(Kill | Rejuvenate | Uopt | Sysopt | Queue | Machines) ) {
142: (void) strcpy(User, Loginuser);
143: Uopt = 1;
144: }
145:
146: if (Psopt) {
147: /* do "ps -flp" or pids in LCK files */
148: lckpid();
149: /* lckpid will not return */
150: }
151:
152: if (Summary) {
153: /* Gather data for Summary option report */
154: if (chdir(STATDIR) || (spooldir = opendir(STATDIR)) == NULL)
155: exit(101); /* good old code 101 */
156: while (gnamef(spooldir, f) == TRUE) {
157: if (freopen(f, "r", stdin) == NULL)
158: continue;
159: m = machine(f);
160: if (gets(buf) == NULL)
161: continue;
162: if (getargs(buf, vec, 5) < 5)
163: continue;
164: m->type = atoi(vec[0]);
165: m->count = atoi(vec[1]);
166: m->lasttime = atol(vec[2]);
167: m->retrytime = atol(vec[3]);
168: (void) strncpy(m->stst, vec[4], STST_MAX);
169: str = rindex(m->stst, ' ');
170: (void) machine(++str); /* longer name? */
171: *str = '\0';
172:
173: }
174: closedir(spooldir);
175: }
176:
177:
178: if (Summary) {
179: /* search for LCK machines */
180:
181: (void) strcpy(lckdir, LOCKPRE);
182: *strrchr(lckdir, '/') = '\0';
183: /* open lock directory */
184: if (chdir(lckdir) != 0 || (subdir = opendir(lckdir)) == NULL)
185: exit(101); /* good old code 101 */
186:
187: while (gnamef(subdir, f) == TRUE) {
188: if (EQUALSN("LCK..", f, 5)) {
189: if (!EQUALSN(f + 5, "cul", 3)
190: && !EQUALSN(f + 5, "tty", 3)
191: && !EQUALSN(f + 5, "dtsw", 4)
192: && !EQUALSN(f + 5, "vadic", 5)
193: && !EQUALSN(f + 5, "micom", 5))
194: machine(f + 5)->locked++;
195: }
196: }
197: }
198:
199: if (chdir(SPOOL) != 0 || (spooldir = opendir(SPOOL)) == NULL)
200: exit(101); /* good old code 101 */
201: while (gnamef(spooldir, f) == TRUE) {
202: if (EQUALSN("LCK..", f, 5))
203: continue;
204:
205: if (*Rmtname && !EQUALSN(Rmtname, f, SYSNSIZE))
206: continue;
207:
208: if ( (Kill || Rejuvenate)
209: && (!EQUALSN(f, Jobid, strlen(Jobid)-5)) )
210: continue;
211:
212: if (DIRECTORY(f) && (subdir = opendir(f))) {
213: m = machine(f);
214: while (gnamef(subdir, subf) == TRUE)
215: if (subf[1] == '.') {
216: if (subf[0] == CMDPRE) {
217: m->ccount++;
218: if (Kill || Rejuvenate)
219: kprocessC(f, subf);
220: else if (Uopt | Sysopt)
221: uprocessC(f, subf);
222: else /* get the age of the C. file */
223: if ( (i = _age(f, subf))>m->c_age)
224: m->c_age = i;
225: }
226:
227: else if (subf[0] == XQTPRE) {
228: m->xcount++;
229: if ( (i = _age(f, subf)) > m->x_age)
230: m->x_age = i;
231: }
232:
233: }
234: closedir(subdir);
235: }
236: }
237: /* for Kill or Rejuvenate - will not get here unless it failed */
238: if (Kill || Rejuvenate) {
239: printf("Can't find Job %s; Not %s\n", Jobid,
240: Kill ? "killed" : "rejuvenated");
241: exit(1);
242: }
243:
244: /* Make sure the overflow entry is null since it may be incorrect */
245: M[UUSTAT_TBL].mach[0] = NULLCHAR;
246: if (Summary) {
247: for((sortcnt = 0, m = &M[0]);*(m->mach) != NULL;(sortcnt++,m++))
248: ;
249: qsort((char *)M, (unsigned int)sortcnt, sizeof(struct m), machcmp);
250: for (m = M; m->mach[0] != NULLCHAR; m++)
251: printit(m);
252: }
253: exit(0);
254: }
255:
256:
257: /*
258: * uprocessC - get information about C. file
259: *
260: */
261:
262: uprocessC(dir, file)
263: char *file, *dir;
264: {
265: struct stat s;
266: register struct tm *tp;
267: char fullname[MAXFULLNAME], buf[BUFSIZ], user[9];
268: char xfullname[MAXFULLNAME];
269: char file1[BUFSIZ], file2[BUFSIZ], file3[BUFSIZ], type[2], opt[256];
270: FILE *fp, *xfp;
271: short first = 1;
272: extern long fsize();
273:
274: DEBUG(9, "uprocessC(%s, ", dir);
275: DEBUG(9, "%s);\n", file);
276:
277: if (Jobid[0] != '\0' && (!EQUALS(Jobid, &file[2])) ) {
278: /* kill job - not this one */
279: return;
280: }
281:
282: (void) sprintf(fullname, "%s/%s", dir, file);
283: if (stat(fullname, &s) != 0) {
284: /* error - can't stat */
285: DEBUG(4, "Can't stat file (%s),", fullname);
286: DEBUG(4, " errno (%d) -- skip it!\n", errno);
287: }
288:
289: fp = fopen(fullname, "r");
290: if (fp == NULL) {
291: DEBUG(4, "Can't open file (%s), ", fullname);
292: DEBUG(4, "errno=%d -- skip it!\n", errno);
293: return;
294: }
295: tp = localtime(&s.st_mtime);
296:
297: if (s.st_size == 0 && User[0] == '\0') { /* dummy D. for polling */
298: printf("%-12s %2.2d/%2.2d-%2.2d:%2.2d:%2.2d (POLL)\n",
299: &file[2], tp->tm_mon + 1, tp->tm_mday, tp->tm_hour,
300: tp->tm_min, tp->tm_sec);
301: }
302: else while (fgets(buf, BUFSIZ, fp) != NULL) {
303: if (sscanf(buf,"%s%s%s%s%s%s", type, file1, file2,
304: user, opt, file3) <5) {
305: DEBUG(4, "short line (%s)\n", buf);
306: continue;
307: }
308: DEBUG(9, "type (%s), ", type);
309: DEBUG(9, "file1 (%s)", file1);
310: DEBUG(9, "file2 (%s)", file2);
311: DEBUG(9, "file3 (%s)", file3);
312: DEBUG(9, "user (%s)", user);
313:
314: if (User[0] != '\0' && (!EQUALS(User, user)) )
315: continue;
316:
317: /*
318: if ( (*file2 != 'X')
319: && (*file1 != '/' && *file1 != '~')
320: && (*file2 != '/' && *file2!= '~') )
321: continue;
322: */
323:
324: if (first)
325: printf("%-12s %2.2d/%2.2d-%2.2d:%2.2d ",
326: &file[2], tp->tm_mon + 1, tp->tm_mday, tp->tm_hour,
327: tp->tm_min);
328: else
329: printf("%-12s %2.2d/%2.2d-%2.2d:%2.2d ",
330: "", tp->tm_mon + 1, tp->tm_mday, tp->tm_hour,
331: tp->tm_min);
332: first = 0;
333:
334: printf("%s %s ", type, dir);
335: if (*type == 'R')
336: printf("%s %s\n", user, file1);
337: else if (file2[0] != 'X')
338: printf("%s %ld %s\n", user, fsize(dir, file3, file1), file1);
339: else if (*type == 'S' && file2[0] == 'X') {
340: (void) sprintf(xfullname, "%s/%s", dir, file1);
341: xfp = fopen(xfullname, "r");
342: if (xfp == NULL) { /* program error */
343: DEBUG(4, "Can't read %s, ", xfullname);
344: DEBUG(4, "errno=%d -- skip it!\n", errno);
345: printf("%s %s %s ", type, dir, user);
346: printf("????\n");
347: }
348: else {
349: char command[BUFSIZ], uline_u[BUFSIZ], uline_m[BUFSIZ];
350: char retaddr[BUFSIZ], *username;
351:
352: *retaddr = *uline_u = *uline_m = '\0';
353: while (fgets(buf, BUFSIZ, xfp) != NULL) {
354: switch(buf[0]) {
355: case 'C':
356: strcpy(command, buf + 2);
357: break;
358: case 'U':
359: sscanf(buf + 2, "%s%s", uline_u, uline_m);
360: break;
361: case 'R':
362: sscanf(buf+2, "%s", retaddr);
363: break;
364: }
365: }
366: username = user;
367: if (*uline_u != '\0')
368: username = uline_u;
369: if (*retaddr != '\0')
370: username = retaddr;
371: if (!EQUALS(uline_m, Myname))
372: printf("%s!", uline_m);
373: printf("%s %s", username, command);
374: }
375: if (xfp != NULL)
376: fclose(xfp);
377: }
378: }
379:
380: fclose(fp);
381: return;
382: }
383:
384:
385: /*
386: * kprocessC - process kill or rejuvenate job
387: */
388:
389: kprocessC(dir, file)
390: char *file, *dir;
391: {
392: struct stat s;
393: register struct tm *tp;
394: extern struct tm *localtime();
395: extern int errno;
396: char fullname[MAXFULLNAME], buf[BUFSIZ], user[9];
397: char rfullname[MAXFULLNAME];
398: char file1[BUFSIZ], file2[BUFSIZ], file3[BUFSIZ], type[2], opt[256];
399: FILE *fp, *xfp;
400: time_t times[2];
401: short ret;
402: short first = 1;
403:
404: DEBUG(9, "kprocessC(%s, ", dir);
405: DEBUG(9, "%s);\n", file);
406:
407: if ((!EQUALS(Jobid, &file[2])) ) {
408: /* kill job - not this one */
409: return;
410: }
411:
412: (void) sprintf(fullname, "%s/%s", dir, file);
413: if (stat(fullname, &s) != 0) {
414: /* error - can't stat */
415: fprintf(stderr, "Can't stat:%s, errno (%d)--can't %s it!\n",
416: fullname, errno, Kill ? "kill" : "rejuvenate");
417: exit(1);
418: }
419:
420: fp = fopen(fullname, "r");
421: if (fp == NULL) {
422: fprintf(stderr, "Can't read:%s, errno (%d)--can't %s it!\n",
423: fullname, errno, Kill ? "kill" : "rejuvenate");
424: exit(1);
425: }
426:
427: times[0] = times[1] = time((time_t *)NULL);
428:
429: while (fgets(buf, BUFSIZ, fp) != NULL) {
430: if (sscanf(buf,"%s%s%s%s%s%s", type, file1, file2,
431: user, opt, file3) <6) {
432: fprintf(stderr, "Bad format:%s, errno (%d)--can't %s it!\n",
433: fullname, errno, Kill ? "kill" : "rejuvenate");
434: exit(1);
435: }
436: DEBUG(9, "type (%s), ", type);
437: DEBUG(9, "file1 (%s)", file1);
438: DEBUG(9, "file2 (%s)", file2);
439: DEBUG(9, "file3 (%s)", file3);
440: DEBUG(9, "user (%s)", user);
441:
442:
443: if (first) {
444: if (Uid != 0
445: && !PREFIX(Loginuser, user)
446: && !PREFIX(user, Loginuser) ) {
447: /* not allowed - not owner or root */
448: fprintf(stderr,
449: "Not owner or root - can't %s job %s\n",
450: Kill ? "kill" : "rejuvenate", Jobid);
451: exit(1);
452: }
453: first = 0;
454: }
455:
456: /* remove D. file */
457: (void) sprintf(rfullname, "%s/%s", dir, file3);
458: DEBUG(4, "Remove %s\n", rfullname);
459: if (Kill)
460: ret = unlink(rfullname);
461: else /* Rejuvenate */
462: ret = utime(rfullname, times);
463: if (ret != 0 && errno != ENOENT) {
464: /* program error?? */
465: fprintf(stderr, "Error: Can't %s, File ( %s), errno (%d)\n",
466: Kill ? "kill" : "rejuvenate", rfullname, errno);
467: exit(1);
468: }
469: }
470:
471: DEBUG(4, "Remove %s\n", fullname);
472: if (Kill)
473: ret = unlink(fullname);
474: else /* Rejuvenate */
475: ret = utime(fullname, times);
476:
477: if (ret != 0) {
478: /* program error?? */
479: fprintf(stderr, "Error: Can't %s, File ( %s), errno (%d)\n",
480: Kill ? "kill" : "rejuvenate", fullname, errno);
481: exit(1);
482: }
483: fclose(fp);
484: printf("Job: %s successfully %s\n", Jobid,
485: Kill ? "killed" : "rejuvenated");
486: exit(0);
487: }
488:
489: /*
490: * fsize - return the size of f1 or f2 (if f1 does not exist)
491: * f1 is the local name
492: *
493: */
494:
495: long
496: fsize(dir, f1, f2)
497: char *dir, *f1, *f2;
498: {
499: struct stat s;
500: char fullname[BUFSIZ];
501:
502: (void) sprintf(fullname, "%s/%s", dir, f1);
503: if (stat(fullname, &s) == 0) {
504: return(s.st_size);
505: }
506: if (stat(f2, &s) == 0) {
507: return(s.st_size);
508: }
509:
510: return(-99999);
511: }
512:
513: cleanup(){}
514: void logent(){} /* to load ulockf.c */
515: void systat(){} /* to load utility.c */
516:
517: struct m *
518: machine(name)
519: char *name;
520: {
521: struct m *m;
522: int namelen;
523:
524: DEBUG(9, "machine(%s), ", name);
525: namelen = strlen(name);
526: for (m = M; m->mach[0] != NULLCHAR; m++)
527: /* match on overlap? */
528: if (EQUALSN(name, m->mach, SYSNSIZE)) {
529: /* use longest name */
530: if (namelen > strlen(m->mach))
531: (void) strcpy(m->mach, name);
532: return(m);
533: }
534:
535: /*
536: * The table is set up with 2 extra entries
537: * When we go over by one, output error to errors log
538: * When more than one over, just reuse the previous entry
539: */
540: DEBUG(9, "m-M=%d\n", m-M);
541: if (m-M >= UUSTAT_TBL) {
542: if (m-M == UUSTAT_TBL) {
543: errent("MACHINE TABLE FULL", "", UUSTAT_TBL,
544: sccsid, __FILE__, __LINE__);
545: (void) fprintf(stderr,
546: "WARNING: Table Overflow--output not complete\n");
547: }
548: else
549: /* use the last entry - overwrite it */
550: m = &M[UUSTAT_TBL];
551: }
552:
553: (void) strcpy(m->mach, name);
554: m->c_age= m->x_age= m->lasttime= m->locked= m->ccount= m->xcount= 0;
555: m->stst[0] = '\0';
556: return(m);
557: }
558:
559: printit(m)
560: struct m *m;
561: {
562: register struct tm *tp;
563: time_t t;
564: int min;
565: extern struct tm *localtime();
566:
567: if (m->ccount == 0
568: && m->xcount == 0
569: /*&& m->stst[0] == '\0'*/
570: && m->locked == 0
571: && Queue
572: && m->type == 0)
573: return;
574: printf("%-10s", m->mach);
575: if (m->ccount)
576: printf("%3dC", m->ccount);
577: else
578: printf(" ");
579: if (m->c_age)
580: printf("(%d)", m->c_age);
581: else
582: printf(" ");
583: if (m->xcount)
584: printf("%4dX", m->xcount);
585: else
586: printf(" ");
587: if (m->x_age)
588: printf("(%d) ", m->x_age);
589: else
590: printf(" ");
591:
592: if (m->lasttime) {
593: tp = localtime(&m->lasttime);
594: printf("%2.2d/%2.2d-%2.2d:%2.2d ",
595: tp->tm_mon + 1, tp->tm_mday, tp->tm_hour,
596: tp->tm_min);
597: }
598: /* if (m->locked && m->type != SS_INPROGRESS) */
599: if (m->locked)
600: printf("Locked ");
601: if (m->stst[0] != '\0') {
602: printf("%s", m->stst);
603: switch (m->type) {
604: case SS_SEQBAD:
605: case SS_LOGIN_FAILED:
606: case SS_DIAL_FAILED:
607: case SS_BAD_LOG_MCH:
608: case SS_BADSYSTEM:
609: case SS_CANT_ACCESS_DEVICE:
610: case SS_DEVICE_FAILED:
611: case SS_WRONG_MCH:
612: case SS_RLOCKED:
613: case SS_RUNKNOWN:
614: case SS_RLOGIN:
615: case SS_UNKNOWN_RESPONSE:
616: case SS_STARTUP:
617: case SS_CHAT_FAILED:
618: (void) time(&t);
619: t = m->retrytime - (t - m->lasttime);
620: if (t > 0) {
621: min = (t + 59) / 60;
622: printf("Retry: %d:%2.2d", min/60, min%60);
623: }
624: if (m->count > 1)
625: printf(" Count: %d", m->count);
626: }
627: }
628: putchar('\n');
629: }
630:
631: #define MAXLOCKS 100 /* Maximum number of lock files this will handle */
632:
633: lckpid()
634: {
635: register i;
636: long pid, ret, fd;
637: #ifdef ASCIILOCKS
638: char alpid[SIZEOFPID+2]; /* +2 for '\n' and null */
639: #endif
640: long list[MAXLOCKS];
641: char buf[BUFSIZ], f[MAXBASENAME];
642: char *c, lckdir[BUFSIZ];
643: DIR *dir;
644:
645: DEBUG(9, "lckpid() - entered\n", "");
646: for (i=0; i<MAXLOCKS; i++)
647: list[i] = -1;
648: (void) strcpy(lckdir, LOCKPRE);
649: *strrchr(lckdir, '/') = '\0';
650: DEBUG(9, "lockdir (%s)\n", lckdir);
651:
652: /* open lock directory */
653: if (chdir(lckdir) != 0 || (dir = opendir(lckdir)) == NULL)
654: exit(101); /* good old code 101 */
655: while (gnamef(dir, f) == TRUE) {
656: /* find all lock files */
657: DEBUG(9, "f (%s)\n", f);
658: if (EQUALSN("LCK.", f, 4)) {
659: /* read LCK file */
660: fd = open(f, O_RDONLY);
661: printf("%s: ", f);
662: #ifdef ASCIILOCKS
663: ret = read(fd, alpid, SIZEOFPID+2); /* +2 for '\n' and null */
664: pid = atoi(alpid);
665: #else
666: ret = read(fd, &pid, sizeof (int));
667: #endif
668: (void) close(fd);
669: if (ret != -1) {
670: printf("%d\n", pid);
671: for(i=0; i<MAXLOCKS; i++) {
672: if (list[i] == pid)
673: break;
674: if (list[i] == -1) {
675: list[i] = pid;
676: break;
677: }
678: }
679: }
680: else
681: printf("????\n");
682: }
683: }
684: fflush(stdout);
685: *buf = NULLCHAR;
686: for (i=0; i<MAXLOCKS; i++) {
687: if( list[i] == -1)
688: break;
689: (void) sprintf(&buf[strlen(buf)], "%d ", list[i]);
690: }
691:
692: if (i > 0)
693: #ifdef V7
694: execlp(UUPS, "uustat-ps", buf, 0);
695: #else
696: execl("/bin/ps", "ps", "-flp", buf, 0);
697: #endif
698: exit(0);
699: }
700:
701: int machcmp(a,b)
702: char *a,*b;
703: {
704: return(strcmp(((struct m *) a)->mach,((struct m *) b)->mach));
705: }
706:
707: static long _sec_per_day = 86400L;
708:
709: /*
710: * _age - find the age of "file" in days
711: * return:
712: * age of file
713: * 0 - if stat fails
714: */
715:
716: int
717: _age(dir, file)
718: char * file; /* the file name */
719: char * dir; /* system spool directory */
720: {
721: char fullname[MAXFULLNAME];
722: static time_t ptime = 0;
723: time_t time();
724: struct stat stbuf;
725:
726: if (!ptime)
727: (void) time(&ptime);
728: (void) sprintf(fullname, "%s/%s", dir, file);
729: if (stat(fullname, &stbuf) != -1) {
730: return ((int)((ptime - stbuf.st_mtime)/_sec_per_day));
731: }
732: else
733: return(0);
734: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.