|
|
1.1 root 1: /* uustat.c
2: UUCP status program
3:
4: Copyright (C) 1991, 1992 Ian Lance Taylor
5:
6: This file is part of the Taylor UUCP package.
7:
8: This program is free software; you can redistribute it and/or
9: modify it under the terms of the GNU General Public License as
10: published by the Free Software Foundation; either version 2 of the
11: License, or (at your option) any later version.
12:
13: This program is distributed in the hope that it will be useful, but
14: WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16: General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with this program; if not, write to the Free Software
20: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21:
22: The author of the program may be contacted at [email protected] or
23: c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
24: */
25:
26: #include "uucp.h"
27:
28: #if USE_RCS_ID
29: const char uustat_rcsid[] = "$Id: uustat.c,v 1.1 93/07/30 07:59:49 bin Exp Locker: bin $";
30: #endif
31:
32: #include <ctype.h>
33: #include <errno.h>
34:
35: #if HAVE_TIME_H
36: #include <time.h>
37: #endif
38:
39: #include "getopt.h"
40:
41: #include "uudefs.h"
42: #include "uuconf.h"
43: #include "system.h"
44:
45: /* The uustat program permits various listings and manipulations of
46: files in the spool directory. This implementation supports the
47: following switches:
48:
49: -a list all jobs
50: -Blines number of lines of standard input to mail
51: -ccommand list only executions of specified command
52: -Ccommand list only jobs other than executions of specified command
53: -e list execute jobs rather than command requests
54: -i ask user whether to kill each listed job
55: -Ifile set configuration file name
56: -kjobid kill job with specified ID
57: -K kill each listed job
58: -m report status for all remote machines
59: -M mail uucp about each job killed with -K
60: -N mail requestor about each job killed with -K
61: -ohour report jobs older than specified number of hours
62: -p do "ps -flp" on all processes holding lock files (Unix specific)
63: -q list number of jobs for all systems
64: -Q don't list jobs, just do -K processing
65: -rjobid rejuvenate job with specified ID
66: -ssystem report on all jobs for specified system
67: -Ssystem report on all jobs other than for specified system
68: -uuser report on all jobs for specified user
69: -Uuser report on all jobs other than for specified user
70: -Wcomment comment to include in mail messages
71: -xdebug set debugging level
72: -yhour report jobs younger than specified number of hours */
73:
74: /* The program name. */
75: char abProgram[] = "uustat";
76:
77: /* What to do with a job that matches the selection criteria; these
78: values may be or'red together. */
79: #define JOB_SHOW (01)
80: #define JOB_INQUIRE (02)
81: #define JOB_KILL (04)
82: #define JOB_MAIL (010)
83: #define JOB_NOTIFY (020)
84:
85: /* This structure is used to accumulate all the lines in a single
86: command file, so that they can all be displayed at once and so that
87: executions can be displayed reasonably. */
88:
89: struct scmdlist
90: {
91: struct scmdlist *qnext;
92: struct scmd s;
93: long itime;
94: };
95:
96: /* Local functions. */
97:
98: static void ususage P((void));
99: static boolean fsxqt_file_read P((pointer puuconf, const char *zfile));
100: static void usxqt_file_free P((void));
101: static int isxqt_cmd P((pointer puuconf, int argc, char **argv, pointer pvar,
102: pointer pinfo));
103: static int isxqt_file P((pointer puuconf, int argc, char **argv, pointer pvar,
104: pointer pinfo));
105: static int isxqt_user P((pointer puuconf, int argc, char **argv, pointer pvar,
106: pointer pinfo));
107: static boolean fsworkfiles P((pointer puuconf, int icmd, int csystems,
108: char **pazsystems, boolean fnotsystems,
109: int cusers, char **pazusers,
110: boolean fnotusers, long iold, long iyoung,
111: int ccommands, char **pazcommands,
112: boolean fnotcommands, const char *zcomment,
113: int cstdin));
114: static boolean fsworkfiles_system P((pointer puuconf,int icmd,
115: const struct uuconf_system *qsys,
116: int cusers, char **pazusers,
117: boolean fnotusers, long iold,
118: long iyoung, int ccommands,
119: char **pazcommands,
120: boolean fnotcommands,
121: const char *zcomment, int cstdin));
122: static boolean fsworkfile_show P((pointer puuconf, int icmd,
123: const struct uuconf_system *qsys,
124: const struct scmd *qcmd,
125: long itime, int ccommands,
126: char **pazcommands, boolean fnotcommands,
127: const char *zcomment, int cstdin));
128: static void usworkfile_header P((const struct uuconf_system *qsys,
129: const struct scmd *qcmd,
130: const char *zjobid,
131: long itime, boolean ffirst));
132: static boolean fsexecutions P((pointer puuconf, int icmd, int csystems,
133: char **pazsystems, boolean fnotsystems,
134: int cusers, char **pazusers,
135: boolean fnotusers, long iold, long iyoung,
136: int ccommands, char **pazcommands,
137: boolean fnotcommands, const char *zcomment,
138: int cstdin));
139: static boolean fsnotify P((pointer puuconf, int icmd, const char *zcomment,
140: int cstdin, boolean fkilled, const char *zcmd,
141: struct scmdlist *qcmd, const char *zid,
142: const char *zuser,
143: const struct uuconf_system *qsys,
144: const char *zstdin, pointer pstdinseq,
145: const char *zrequestor));
146: static boolean fsquery P((pointer puuconf));
147: static int csunits_show P((long idiff));
148: static boolean fsmachines P((void));
149:
150: /* Long getopt options. */
151: static const struct option asSlongopts[] = { { NULL, 0, NULL, 0 } };
152:
153: int
154: main (argc, argv)
155: int argc;
156: char **argv;
157: {
158: /* -a: list all jobs. */
159: boolean fall = FALSE;
160: /* -B lines: number of lines of standard input to mail. */
161: int cstdin = 100;
162: /* -c,-C command: list only specified command. */
163: int ccommands = 0;
164: char **pazcommands = NULL;
165: boolean fnotcommands = FALSE;
166: /* -e: list execute jobs. */
167: boolean fexecute = FALSE;
168: /* -k jobid: kill specified job. */
169: int ckills = 0;
170: char **pazkills = NULL;
171: /* -m: report machine status. */
172: boolean fmachine = FALSE;
173: /* -o hour: report jobs older than given number of hours. */
174: int ioldhours = -1;
175: /* -p: report status of jobs holding lock files. */
176: boolean fps = FALSE;
177: /* -q: list number of jobs for each system. */
178: boolean fquery = FALSE;
179: /* -r jobid: rejuvenate specified job. */
180: int crejuvs = 0;
181: char **pazrejuvs = NULL;
182: /* -s,-S system: list all jobs for specified system. */
183: int csystems = 0;
184: char **pazsystems = NULL;
185: boolean fnotsystems = FALSE;
186: /* -u,-U user: list all jobs for specified user. */
187: int cusers = 0;
188: char **pazusers = NULL;
189: boolean fnotusers = FALSE;
190: /* -W comment: comment to include in mail messages. */
191: const char *zcomment = NULL;
192: /* -y hour: report jobs younger than given number of hours. */
193: int iyounghours = -1;
194: /* -I file: set configuration file. */
195: const char *zconfig = NULL;
196: /* -Q, -i, -K, -M, -N: what to do with each job. */
197: int icmd = JOB_SHOW;
198: int ccmds;
199: int iopt;
200: pointer puuconf;
201: int iuuconf;
202: long iold;
203: long iyoung;
204: const char *azoneuser[1];
205: boolean fret;
206:
207: while ((iopt = getopt_long (argc, argv,
208: "aB:c:C:eiI:k:KmMNo:pqQr:s:S:u:U:W:x:y:",
209: asSlongopts, (int *) NULL)) != EOF)
210: {
211: switch (iopt)
212: {
213: case 'a':
214: /* List all jobs. */
215: fall = TRUE;
216: break;
217:
218: case 'B':
219: /* Number of lines of standard input to mail. */
220: cstdin = (int) strtol (optarg, (char **) NULL, 10);
221: break;
222:
223: case 'C':
224: /* List jobs for other than specified command. */
225: fnotcommands = TRUE;
226: /* Fall through. */
227: case 'c':
228: /* List specified command. */
229: ++ccommands;
230: pazcommands = (char **) xrealloc ((pointer) pazcommands,
231: ccommands * sizeof (char *));
232: pazcommands[ccommands - 1] = optarg;
233: break;
234:
235: case 'e':
236: /* List execute jobs. */
237: fexecute = TRUE;
238: break;
239:
240: case 'i':
241: /* Prompt the user whether to kill each job. */
242: icmd |= JOB_INQUIRE;
243: break;
244:
245: case 'I':
246: /* Set configuration file name. */
247: if (fsysdep_other_config (optarg))
248: zconfig = optarg;
249: break;
250:
251: case 'k':
252: /* Kill specified job. */
253: ++ckills;
254: pazkills = (char **) xrealloc ((pointer) pazkills,
255: ckills * sizeof (char *));
256: pazkills[ckills - 1] = optarg;
257: break;
258:
259: case 'K':
260: /* Kill each listed job. */
261: icmd |= JOB_KILL;
262: break;
263:
264: case 'm':
265: /* Report machine status. */
266: fmachine = TRUE;
267: break;
268:
269: case 'M':
270: /* Mail to uucp action taken on each job. */
271: icmd |= JOB_MAIL;
272: break;
273:
274: case 'N':
275: /* Mail to requestor action taken on each job. */
276: icmd |= JOB_NOTIFY;
277: break;
278:
279: case 'o':
280: /* Report old jobs. */
281: ioldhours = (int) strtol (optarg, (char **) NULL, 10);
282: break;
283:
284: case 'p':
285: /* Get status of processes holding locks. */
286: fps = TRUE;
287: break;
288:
289: case 'q':
290: /* List number of jobs for each system. */
291: fquery = TRUE;
292: break;
293:
294: case 'Q':
295: /* Don't list jobs, just do -K processing. */
296: icmd &=~ JOB_SHOW;
297: break;
298:
299: case 'r':
300: /* Rejuvenate specified job. */
301: ++crejuvs;
302: pazrejuvs = (char **) xrealloc ((pointer) pazrejuvs,
303: crejuvs * sizeof (char *));
304: pazrejuvs[crejuvs - 1] = optarg;
305: break;
306:
307: case 'S':
308: /* List jobs for other than specified system. */
309: fnotsystems = TRUE;
310: /* Fall through. */
311: case 's':
312: /* List jobs for specified system. */
313: ++csystems;
314: pazsystems = (char **) xrealloc ((pointer) pazsystems,
315: csystems * sizeof (char *));
316: pazsystems[csystems - 1] = optarg;
317: break;
318:
319: case 'U':
320: /* List jobs for other than specified user. */
321: fnotusers = TRUE;
322: /* Fall through. */
323: case 'u':
324: /* List jobs for specified user. */
325: ++cusers;
326: pazusers = (char **) xrealloc ((pointer) pazusers,
327: cusers * sizeof (char *));
328: pazusers[cusers - 1] = optarg;
329: break;
330:
331: case 'W':
332: /* Comment to include in mail messages. */
333: zcomment = optarg;
334: break;
335:
336: case 'x':
337: #if DEBUG > 1
338: /* Set debugging level. */
339: iDebug |= idebug_parse (optarg);
340: #endif
341: break;
342:
343: case 'y':
344: /* List jobs younger than given number of hours. */
345: iyounghours = (int) strtol (optarg, (char **) NULL, 10);
346: break;
347:
348: case 0:
349: /* Long option found and flag set. */
350: break;
351:
352: default:
353: ususage ();
354: break;
355: }
356: }
357:
358: if (optind != argc)
359: ususage ();
360:
361: /* To avoid confusion, most options are only permitted by
362: themselves. This restriction might be removed later, but it is
363: imposed by most implementations. We do permit any combination of
364: -c, -s, -u, -o and -y, and any combination of -k and -r. */
365: ccmds = 0;
366: if (fall)
367: ++ccmds;
368: if (ckills > 0 || crejuvs > 0)
369: ++ccmds;
370: if (fmachine)
371: ++ccmds;
372: if (fps)
373: ++ccmds;
374: if (fquery)
375: ++ccmds;
376: if (fexecute || csystems > 0 || cusers > 0 || ioldhours != -1
377: || iyounghours != -1 || ccommands > 0)
378: ++ccmds;
379:
380: if (ccmds > 1)
381: {
382: ulog (LOG_ERROR, "Too many options");
383: ususage ();
384: }
385:
386: iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig);
387: if (iuuconf != UUCONF_SUCCESS)
388: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
389:
390: #if DEBUG > 1
391: {
392: const char *zdebug;
393:
394: iuuconf = uuconf_debuglevel (puuconf, &zdebug);
395: if (iuuconf != UUCONF_SUCCESS)
396: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
397: if (zdebug != NULL)
398: iDebug |= idebug_parse (zdebug);
399: }
400: #endif
401:
402: usysdep_initialize (puuconf, INIT_SUID);
403:
404: /* If no commands were specified, we list all commands for the given
405: user. */
406: if (ccmds == 0)
407: {
408: cusers = 1;
409: azoneuser[0] = zsysdep_login_name ();
410: pazusers = (char **) azoneuser;
411: }
412:
413: /* Canonicalize the system names. */
414: if (csystems > 0)
415: {
416: int i;
417:
418: for (i = 0; i < csystems; i++)
419: {
420: struct uuconf_system ssys;
421:
422: iuuconf = uuconf_system_info (puuconf, pazsystems[i], &ssys);
423: if (iuuconf != UUCONF_SUCCESS)
424: {
425: if (iuuconf == UUCONF_NOT_FOUND)
426: ulog (LOG_FATAL, "%s: System not found", pazsystems[i]);
427: else
428: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
429: }
430: if (strcmp (pazsystems[i], ssys.uuconf_zname) != 0)
431: pazsystems[i] = zbufcpy (ssys.uuconf_zname);
432: (void) uuconf_system_free (puuconf, &ssys);
433: }
434: }
435:
436: if (ioldhours == -1)
437: iold = (long) -1;
438: else
439: {
440: iold = (ixsysdep_time ((long *) NULL)
441: - (long) ioldhours * (long) 60 * (long) 60);
442: if (iold < 0L)
443: iold = 0L;
444: }
445: if (iyounghours == -1)
446: iyoung = (long) -1;
447: else
448: {
449: iyoung = (ixsysdep_time ((long *) NULL)
450: - (long) iyounghours * (long) 60 * (long) 60);
451: if (iyoung < 0L)
452: iyoung = 0L;
453: }
454:
455: if (! fexecute
456: && (fall
457: || csystems > 0
458: || cusers > 0
459: || ioldhours != -1
460: || iyounghours != -1
461: || ccommands > 0))
462: fret = fsworkfiles (puuconf, icmd, csystems, pazsystems, fnotsystems,
463: cusers, pazusers, fnotusers, iold, iyoung,
464: ccommands, pazcommands, fnotcommands, zcomment,
465: cstdin);
466: else if (fexecute)
467: fret = fsexecutions (puuconf, icmd, csystems, pazsystems, fnotsystems,
468: cusers, pazusers, fnotusers, iold, iyoung,
469: ccommands, pazcommands, fnotcommands, zcomment,
470: cstdin);
471: else if (icmd != JOB_SHOW)
472: {
473: ulog (LOG_ERROR,
474: "-i, -K, -M, -N, -Q not supported with -k, -m, -p, -q, -r");
475: ususage ();
476: fret = FALSE;
477: }
478: else if (fquery)
479: fret = fsquery (puuconf);
480: else if (fmachine)
481: fret = fsmachines ();
482: else if (ckills > 0 || crejuvs > 0)
483: {
484: int i;
485:
486: fret = TRUE;
487: for (i = 0; i < ckills; i++)
488: if (! fsysdep_kill_job (puuconf, pazkills[i]))
489: fret = FALSE;
490:
491: for (i = 0; i < crejuvs; i++)
492: if (! fsysdep_rejuvenate_job (puuconf, pazrejuvs[i]))
493: fret = FALSE;
494: }
495: else if (fps)
496: fret = fsysdep_lock_status ();
497: else
498: {
499: #if DEBUG > 0
500: ulog (LOG_FATAL, "Can't happen");
501: #endif
502: fret = FALSE;
503: }
504:
505: ulog_close ();
506:
507: usysdep_exit (fret);
508:
509: /* Avoid errors about not returning a value. */
510: return 0;
511: }
512:
513: /* Print a usage message and die. */
514:
515: static void
516: ususage ()
517: {
518: fprintf (stderr,
519: "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
520: VERSION);
521: fprintf (stderr,
522: "Usage: uustat [options]\n");
523: fprintf (stderr,
524: " -a: list all UUCP jobs\n");
525: fprintf (stderr,
526: " -B num: number of lines to return in -M or -N mail message\n");
527: fprintf (stderr,
528: " -c command: list requests for named command\n");
529: fprintf (stderr,
530: " -C command: list requests for other than named command\n");
531: fprintf (stderr,
532: " -e: list queued executions rather than job requests\n");
533: fprintf (stderr,
534: " -i: prompt for whether to kill each listed job\n");
535: fprintf (stderr,
536: " -k job: kill specified UUCP job\n");
537: fprintf (stderr,
538: " -K: kill each listed job\n");
539: fprintf (stderr,
540: " -m: report status for all remote machines\n");
541: fprintf (stderr,
542: " -M: mail report on each listed job to UUCP administrator\n");
543: fprintf (stderr,
544: " -N: mail report on each listed job to requestor\n");
545: fprintf (stderr,
546: " -o hours: list all jobs older than given number of hours\n");
547: fprintf (stderr,
548: " -p: show status of all processes holding UUCP locks\n");
549: fprintf (stderr,
550: " -q: list number of jobs for each system\n");
551: fprintf (stderr,
552: " -Q: don't list jobs, just take actions (-i, -K, -M, -N)\n");
553: fprintf (stderr,
554: " -r job: rejuvenate specified UUCP job\n");
555: fprintf (stderr,
556: " -s system: list all jobs for specified system\n");
557: fprintf (stderr,
558: " -S system: list all jobs for other than specified system\n");
559: fprintf (stderr,
560: " -u user: list all jobs for specified user\n");
561: fprintf (stderr,
562: " -U user: list all jobs for other than specified user\n");
563: fprintf (stderr,
564: " -W comment: comment to include in mail messages\n");
565: fprintf (stderr,
566: " -y hours: list all jobs younger than given number of hours\n");
567: fprintf (stderr,
568: " -x debug: Set debugging level (0 for none, 9 is max)\n");
569: #if HAVE_TAYLOR_CONFIG
570: fprintf (stderr,
571: " -I file: Set configuration file to use\n");
572: #endif /* HAVE_TAYLOR_CONFIG */
573: exit (EXIT_FAILURE);
574: }
575:
576: /* We need to be able to read information from an execution file. */
577:
578: /* The user name extracted from an execution file. */
579: static char *zSxqt_user;
580:
581: /* The system name from an execution file. */
582: static char *zSxqt_system;
583:
584: /* Address of requesting user (who to send mail to). */
585: static const char *zSxqt_requestor;
586:
587: /* The command (no arguments) from an execution file. */
588: static char *zSxqt_prog;
589:
590: /* The full command line from an execution file. */
591: static char *zSxqt_cmd;
592:
593: /* Number of files associated with an execution file. */
594: static int cSxqt_files;
595:
596: /* Names of files associated with execution file. */
597: static char **pazSxqt_files;
598:
599: /* Standard input file name. */
600: static const char *zSxqt_stdin;
601:
602: /* A command table used to dispatch an execution file. */
603: static const struct uuconf_cmdtab asSxqt_cmds[] =
604: {
605: { "C", UUCONF_CMDTABTYPE_FN | 0, NULL, isxqt_cmd },
606: { "I", UUCONF_CMDTABTYPE_STRING, (pointer) &zSxqt_stdin, NULL },
607: { "F", UUCONF_CMDTABTYPE_FN | 0, NULL, isxqt_file },
608: { "R", UUCONF_CMDTABTYPE_STRING, (pointer) &zSxqt_requestor, NULL },
609: { "U", UUCONF_CMDTABTYPE_FN | 3, NULL, isxqt_user },
610: { NULL, 0, NULL, NULL }
611: };
612:
613: /* Read an execution file, setting the above variables. */
614:
615: static boolean
616: fsxqt_file_read (puuconf, zfile)
617: pointer puuconf;
618: const char *zfile;
619: {
620: FILE *e;
621: int iuuconf;
622: boolean fret;
623:
624: e = fopen (zfile, "r");
625: if (e == NULL)
626: {
627: ulog (LOG_ERROR, "fopen (%s): %s", zfile, strerror (errno));
628: return FALSE;
629: }
630:
631: zSxqt_user = NULL;
632: zSxqt_system = NULL;
633: zSxqt_stdin = NULL;
634: zSxqt_requestor = NULL;
635: zSxqt_prog = NULL;
636: zSxqt_cmd = NULL;
637: cSxqt_files = 0;
638: pazSxqt_files = NULL;
639:
640: iuuconf = uuconf_cmd_file (puuconf, e, asSxqt_cmds, (pointer) NULL,
641: (uuconf_cmdtabfn) NULL,
642: UUCONF_CMDTABFLAG_CASE, (pointer) NULL);
643: (void) fclose (e);
644: if (iuuconf == UUCONF_SUCCESS)
645: fret = TRUE;
646: else
647: {
648: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
649: fret = FALSE;
650: }
651:
652: if (zSxqt_user == NULL)
653: zSxqt_user = zbufcpy ("*unknown*");
654: if (zSxqt_system == NULL)
655: zSxqt_system = zbufcpy ("*unknown*");
656: if (zSxqt_prog == NULL)
657: {
658: zSxqt_prog = zbufcpy ("*none*");
659: zSxqt_cmd = zbufcpy ("*none*");
660: }
661:
662: return fret;
663: }
664:
665: /* Free up the information read from an execution file. */
666:
667: static void
668: usxqt_file_free ()
669: {
670: int i;
671:
672: ubuffree (zSxqt_user);
673: zSxqt_user = NULL;
674: ubuffree (zSxqt_system);
675: zSxqt_system = NULL;
676: ubuffree (zSxqt_prog);
677: zSxqt_prog = NULL;
678: ubuffree (zSxqt_cmd);
679: zSxqt_cmd = NULL;
680: for (i = 0; i < cSxqt_files; i++)
681: ubuffree (pazSxqt_files[i]);
682: cSxqt_files = 0;
683: xfree ((pointer) pazSxqt_files);
684: pazSxqt_files = NULL;
685: zSxqt_stdin = NULL;
686: zSxqt_requestor = NULL;
687: }
688:
689: /* Get the command from an execution file. */
690:
691: /*ARGSUSED*/
692: static int
693: isxqt_cmd (puuconf, argc, argv, pvar, pinfo)
694: pointer puuconf;
695: int argc;
696: char **argv;
697: pointer pvar;
698: pointer pinfo;
699: {
700: size_t clen;
701: int i;
702:
703: if (argc <= 1)
704: return UUCONF_CMDTABRET_CONTINUE;
705:
706: zSxqt_prog = zbufcpy (argv[1]);
707:
708: clen = 0;
709: for (i = 1; i < argc; i++)
710: clen += strlen (argv[i]) + 1;
711:
712: zSxqt_cmd = zbufalc (clen);
713: zSxqt_cmd[0] = '\0';
714: for (i = 1; i < argc - 1; i++)
715: {
716: strcat (zSxqt_cmd, argv[i]);
717: strcat (zSxqt_cmd, " ");
718: }
719: strcat (zSxqt_cmd, argv[i]);
720:
721: return UUCONF_CMDTABRET_CONTINUE;
722: }
723:
724: /* Get the associated files from an execution file. */
725:
726: /*ARGSUSED*/
727: static int
728: isxqt_file (puuconf, argc, argv, pvar, pinfo)
729: pointer puuconf;
730: int argc;
731: char **argv;
732: pointer pvar;
733: pointer pinfo;
734: {
735: if (argc != 2 && argc != 3)
736: return UUCONF_CMDTABRET_CONTINUE;
737:
738: /* If this file is not in the spool directory, just ignore it. */
739: if (! fspool_file (argv[1]))
740: return UUCONF_CMDTABRET_CONTINUE;
741:
742: ++cSxqt_files;
743: pazSxqt_files = (char **) xrealloc ((pointer) pazSxqt_files,
744: cSxqt_files * sizeof (char *));
745:
746: pazSxqt_files[cSxqt_files - 1] = zbufcpy (argv[1]);
747:
748: return UUCONF_CMDTABRET_CONTINUE;
749: }
750:
751: /* Get the requesting user and system from an execution file. */
752:
753: /*ARGSUSED*/
754: static int
755: isxqt_user (puuconf, argc, argv, pvar, pinfo)
756: pointer puuconf;
757: int argc;
758: char **argv;
759: pointer pvar;
760: pointer pinfo;
761: {
762: zSxqt_user = zbufcpy (argv[1]);
763: zSxqt_system = zbufcpy (argv[2]);
764: return UUCONF_CMDTABRET_CONTINUE;
765: }
766:
767: /* Handle various possible requests to look at work files. */
768:
769: static boolean
770: fsworkfiles (puuconf, icmd, csystems, pazsystems, fnotsystems, cusers,
771: pazusers, fnotusers, iold, iyoung, ccommands, pazcommands,
772: fnotcommands, zcomment, cstdin)
773: pointer puuconf;
774: int icmd;
775: int csystems;
776: char **pazsystems;
777: boolean fnotsystems;
778: int cusers;
779: char **pazusers;
780: boolean fnotusers;
781: long iold;
782: long iyoung;
783: int ccommands;
784: char **pazcommands;
785: boolean fnotcommands;
786: const char *zcomment;
787: int cstdin;
788: {
789: boolean fret;
790: int i;
791: int iuuconf;
792: struct uuconf_system ssys;
793:
794: fret = TRUE;
795:
796: if (csystems > 0 && ! fnotsystems)
797: {
798: for (i = 0; i < csystems; i++)
799: {
800: iuuconf = uuconf_system_info (puuconf, pazsystems[i], &ssys);
801: if (iuuconf != UUCONF_SUCCESS)
802: {
803: if (iuuconf == UUCONF_NOT_FOUND)
804: ulog (LOG_ERROR, "%s: System not found", pazsystems[i]);
805: else
806: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
807: fret = FALSE;
808: continue;
809: }
810:
811: if (! fsworkfiles_system (puuconf, icmd, &ssys, cusers, pazusers,
812: fnotusers, iold, iyoung, ccommands,
813: pazcommands, fnotcommands, zcomment,
814: cstdin))
815: fret = FALSE;
816:
817: (void) uuconf_system_free (puuconf, &ssys);
818: }
819: }
820: else
821: {
822: char **pznames, **pz;
823:
824: iuuconf = uuconf_system_names (puuconf, &pznames, 0);
825: if (iuuconf != UUCONF_SUCCESS)
826: {
827: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
828: return FALSE;
829: }
830:
831: for (pz = pznames; *pz != NULL; pz++)
832: {
833: if (csystems > 0)
834: {
835: for (i = 0; i < csystems; i++)
836: if (strcmp (*pz, pazsystems[i]) == 0)
837: break;
838: if (i < csystems)
839: continue;
840: }
841:
842: iuuconf = uuconf_system_info (puuconf, *pz, &ssys);
843: if (iuuconf != UUCONF_SUCCESS)
844: {
845: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
846: fret = FALSE;
847: continue;
848: }
849:
850: if (! fsworkfiles_system (puuconf, icmd, &ssys, cusers, pazusers,
851: fnotusers, iold, iyoung, ccommands,
852: pazcommands, fnotcommands, zcomment,
853: cstdin))
854: fret = FALSE;
855:
856: (void) uuconf_system_free (puuconf, &ssys);
857: xfree ((pointer) *pz);
858: }
859: xfree ((pointer) pznames);
860: }
861:
862: return fret;
863: }
864:
865: /* Look at the work files for a particular system. */
866:
867: static boolean
868: fsworkfiles_system (puuconf, icmd, qsys, cusers, pazusers, fnotusers, iold,
869: iyoung, ccommands, pazcommands, fnotcommands, zcomment,
870: cstdin)
871: pointer puuconf;
872: int icmd;
873: const struct uuconf_system *qsys;
874: int cusers;
875: char **pazusers;
876: boolean fnotusers;
877: long iold;
878: long iyoung;
879: int ccommands;
880: char **pazcommands;
881: boolean fnotcommands;
882: const char *zcomment;
883: int cstdin;
884: {
885: boolean fret;
886:
887: if (! fsysdep_get_work_init (qsys, UUCONF_GRADE_LOW))
888: return FALSE;
889:
890: while (TRUE)
891: {
892: struct scmd s;
893: long itime;
894:
895: if (! fsysdep_get_work (qsys, UUCONF_GRADE_LOW, &s))
896: {
897: usysdep_get_work_free (qsys);
898: return FALSE;
899: }
900: if (s.bcmd == 'H')
901: break;
902:
903: if (cusers > 0)
904: {
905: boolean fmatch;
906: int i;
907:
908: fmatch = fnotusers;
909: for (i = 0; i < cusers; i++)
910: {
911: if (s.zuser != NULL
912: && strcmp (pazusers[i], s.zuser) == 0)
913: {
914: fmatch = ! fmatch;
915: break;
916: }
917: }
918: if (! fmatch)
919: continue;
920: }
921:
922: itime = ixsysdep_work_time (qsys, s.pseq);
923:
924: if (iold != (long) -1 && itime > iold)
925: continue;
926:
927: if (iyoung != (long) -1 && itime < iyoung)
928: continue;
929:
930: if (! fsworkfile_show (puuconf, icmd, qsys, &s, itime, ccommands,
931: pazcommands, fnotcommands, zcomment, cstdin))
932: {
933: usysdep_get_work_free (qsys);
934: return FALSE;
935: }
936: }
937:
938: fret = fsworkfile_show (puuconf, icmd, qsys, (const struct scmd *) NULL,
939: 0L, ccommands, pazcommands, fnotcommands, zcomment,
940: cstdin);
941:
942: usysdep_get_work_free (qsys);
943:
944: return fret;
945: }
946:
947: /* Show a single workfile. This is actually called once for each line
948: in the workfile, so we accumulate the lines and show them all at
949: once. This lets us show an execution in a useful fashion. */
950:
951: static boolean
952: fsworkfile_show (puuconf, icmd, qsys, qcmd, itime, ccommands, pazcommands,
953: fnotcommands, zcomment, cstdin)
954: pointer puuconf;
955: int icmd;
956: const struct uuconf_system *qsys;
957: const struct scmd *qcmd;
958: long itime;
959: int ccommands;
960: char **pazcommands;
961: boolean fnotcommands;
962: const char *zcomment;
963: int cstdin;
964: {
965: static struct scmdlist *qlist;
966: static char *zlistid;
967: char *zid;
968:
969: if (qcmd == NULL)
970: zid = NULL;
971: else
972: {
973: zid = zsysdep_jobid (qsys, qcmd->pseq);
974: if (zid == NULL)
975: return FALSE;
976: }
977:
978: /* If this is the same jobid as the list, put it on the end. */
979:
980: if (qcmd != NULL
981: && qlist != NULL
982: && strcmp (zlistid, zid) == 0)
983: {
984: struct scmdlist *qnew, **pq;
985:
986: ubuffree (zid);
987: qnew = (struct scmdlist *) xmalloc (sizeof (struct scmdlist));
988: qnew->qnext = NULL;
989: qnew->s = *qcmd;
990: qnew->itime = itime;
991: for (pq = &qlist; *pq != NULL; pq = &(*pq)->qnext)
992: ;
993: *pq = qnew;
994: return TRUE;
995: }
996:
997: /* Here we have found a different job ID, so we print the scmd
998: structures that we have accumulated. We look for the special
999: case of an execution (an E command, or one of the destination
1000: files begins with X.). We could be more clever about other
1001: situations as well. */
1002: if (qlist != NULL)
1003: {
1004: boolean fmatch;
1005: const char *zprog, *zcmd, *zrequestor, *zstdin;
1006: char *zfree;
1007: struct scmdlist *qxqt;
1008: struct scmdlist *qfree;
1009:
1010: fmatch = FALSE;
1011: zprog = zcmd = zrequestor = zstdin = NULL;
1012: zfree = NULL;
1013:
1014: for (qxqt = qlist; qxqt != NULL; qxqt = qxqt->qnext)
1015: if (qxqt->s.bcmd == 'E'
1016: || (qxqt->s.bcmd == 'S'
1017: && qxqt->s.zto[0] == 'X'
1018: && qxqt->s.zto[1] == '.'
1019: && fspool_file (qxqt->s.zfrom)))
1020: break;
1021:
1022: if (qxqt == NULL)
1023: {
1024: if (ccommands == 0
1025: || (fnotcommands
1026: && strcmp (pazcommands[0], "ALL") == 0))
1027: {
1028: /* Show all the lines in a regular work file. */
1029: fmatch = TRUE;
1030:
1031: if ((icmd & JOB_SHOW) != 0)
1032: {
1033: struct scmdlist *qshow;
1034:
1035: for (qshow = qlist; qshow != NULL; qshow = qshow->qnext)
1036: {
1037: char *zfile;
1038: long cbytes;
1039:
1040: usworkfile_header (qsys, &qshow->s, zlistid,
1041: qshow->itime, qshow == qlist);
1042:
1043: switch (qshow->s.bcmd)
1044: {
1045: case 'S':
1046: if (strchr (qshow->s.zoptions, 'C') != NULL
1047: || fspool_file (qshow->s.zfrom))
1048: zfile = zsysdep_spool_file_name (qsys,
1049: qshow->s.ztemp,
1050: qshow->s.pseq);
1051: else
1052: zfile = zbufcpy (qshow->s.zfrom);
1053: if (zfile == NULL)
1054: cbytes = 0;
1055: else
1056: {
1057: cbytes = csysdep_size (zfile);
1058: if (cbytes < 0)
1059: cbytes = 0;
1060: }
1061: printf ("Sending %s (%ld bytes) to %s",
1062: qshow->s.zfrom, cbytes, qshow->s.zto);
1063: ubuffree (zfile);
1064: break;
1065: case 'R':
1066: printf ("Requesting %s to %s", qshow->s.zfrom,
1067: qshow->s.zto);
1068: break;
1069: case 'X':
1070: printf ("Requesting %s to %s", qshow->s.zfrom,
1071: qshow->s.zto);
1072: break;
1073: case 'P':
1074: printf ("(poll file)");
1075: break;
1076: #if DEBUG > 0
1077: default:
1078: printf ("Bad line %d", qshow->s.bcmd);
1079: break;
1080: #endif
1081: }
1082:
1083: printf ("\n");
1084: }
1085: }
1086: }
1087: }
1088: else
1089: {
1090: long csize;
1091: struct scmdlist *qsize;
1092:
1093: /* Show the command for an execution file. */
1094: if (qxqt->s.bcmd == 'E')
1095: {
1096: zfree = zbufcpy (qxqt->s.zcmd);
1097: zfree[strcspn (zfree, " \t")] = '\0';
1098: zprog = zfree;
1099: zcmd = qxqt->s.zcmd;
1100: if (strchr (qxqt->s.zoptions, 'R') != NULL)
1101: zrequestor = qxqt->s.znotify;
1102: }
1103: else
1104: {
1105: char *zxqt;
1106:
1107: zxqt = zsysdep_spool_file_name (qsys, qxqt->s.zfrom,
1108: qxqt->s.pseq);
1109: if (zxqt == NULL)
1110: return FALSE;
1111:
1112: if (! fsxqt_file_read (puuconf, zxqt))
1113: {
1114: ubuffree (zxqt);
1115: return FALSE;
1116: }
1117:
1118: ubuffree (zxqt);
1119:
1120: zprog = zSxqt_prog;
1121: zcmd = zSxqt_cmd;
1122: zrequestor = zSxqt_requestor;
1123: }
1124:
1125: csize = 0L;
1126: for (qsize = qlist; qsize != NULL; qsize = qsize->qnext)
1127: {
1128: if (qsize->s.bcmd == 'S' || qsize->s.bcmd == 'E')
1129: {
1130: char *zfile;
1131:
1132: if (strchr (qsize->s.zoptions, 'C') != NULL
1133: || fspool_file (qsize->s.zfrom))
1134: zfile = zsysdep_spool_file_name (qsys, qsize->s.ztemp,
1135: qsize->s.pseq);
1136: else
1137: zfile = zbufcpy (qsize->s.zfrom);
1138: if (zfile != NULL)
1139: {
1140: long cbytes;
1141:
1142: cbytes = csysdep_size (zfile);
1143: if (cbytes > 0)
1144: csize += cbytes;
1145: ubuffree (zfile);
1146: }
1147: }
1148: }
1149:
1150: if (ccommands == 0)
1151: fmatch = TRUE;
1152: else
1153: {
1154: int i;
1155:
1156: fmatch = fnotcommands;
1157: for (i = 0; i < ccommands; i++)
1158: {
1159: if (strcmp (pazcommands[i], "ALL") == 0
1160: || strcmp (pazcommands[i], zprog) == 0)
1161: {
1162: fmatch = ! fmatch;
1163: break;
1164: }
1165: }
1166: }
1167:
1168: /* To get the name of the standard input file on this system
1169: we have to look through the list of file transfers to
1170: find the right one on the remote system. */
1171: if (fmatch)
1172: {
1173: struct scmdlist *qstdin;
1174:
1175: if (qxqt->s.bcmd == 'E')
1176: qstdin = qxqt;
1177: else if (zSxqt_stdin != NULL)
1178: {
1179: for (qstdin = qlist;
1180: qstdin != NULL;
1181: qstdin = qstdin->qnext)
1182: if (qstdin->s.bcmd == 'S'
1183: && strcmp (qstdin->s.zto, zSxqt_stdin) == 0)
1184: break;
1185: }
1186: else
1187: qstdin = NULL;
1188:
1189: if (qstdin != NULL)
1190: {
1191: if (strchr (qstdin->s.zoptions, 'C') != NULL
1192: || fspool_file (qstdin->s.zfrom))
1193: zstdin = qstdin->s.ztemp;
1194: else
1195: zstdin = qstdin->s.zfrom;
1196: }
1197: }
1198:
1199: if (fmatch && (icmd & JOB_SHOW) != 0)
1200: {
1201: usworkfile_header (qsys, &qxqt->s, zlistid, qxqt->itime,
1202: TRUE);
1203: printf ("Executing %s (sending %ld bytes)\n", zcmd, csize);
1204: }
1205: }
1206:
1207: if (fmatch)
1208: {
1209: boolean fkill;
1210:
1211: fkill = FALSE;
1212: if ((icmd & JOB_INQUIRE) != 0)
1213: {
1214: int b;
1215:
1216: /* Ask stdin whether this job should be killed. */
1217: fprintf (stderr, "%s: Kill %s? ", abProgram, zlistid);
1218: (void) fflush (stderr);
1219: b = getchar ();
1220: fkill = b == 'y' || b == 'Y';
1221: while (b != EOF && b != '\n')
1222: b = getchar ();
1223: }
1224: else if ((icmd & JOB_KILL) != 0)
1225: fkill = TRUE;
1226:
1227: if (fkill
1228: && (qlist->s.zuser == NULL
1229: || strcmp (zsysdep_login_name (), qlist->s.zuser) != 0)
1230: && ! fsysdep_privileged ())
1231: ulog (LOG_ERROR, "%s: Not submitted by you", zlistid);
1232: else
1233: {
1234: if ((icmd & (JOB_MAIL | JOB_NOTIFY)) != 0)
1235: {
1236: if (! fsnotify (puuconf, icmd, zcomment, cstdin, fkill,
1237: zcmd, qlist, zlistid, qlist->s.zuser,
1238: qsys, zstdin, qlist->s.pseq, zrequestor))
1239: return FALSE;
1240: }
1241:
1242: if (fkill)
1243: {
1244: if (! fsysdep_kill_job (puuconf, zlistid))
1245: return FALSE;
1246: }
1247: }
1248: }
1249:
1250: if (qxqt != NULL)
1251: {
1252: if (qxqt->s.bcmd == 'E')
1253: ubuffree (zfree);
1254: else
1255: usxqt_file_free ();
1256: }
1257:
1258: /* Free up the list of entries. */
1259: qfree = qlist;
1260: while (qfree != NULL)
1261: {
1262: struct scmdlist *qnext;
1263:
1264: qnext = qfree->qnext;
1265: xfree ((pointer) qfree);
1266: qfree = qnext;
1267: }
1268:
1269: ubuffree (zlistid);
1270:
1271: qlist = NULL;
1272: zlistid = NULL;
1273: }
1274:
1275: /* Start a new list with the entry we just got. */
1276: if (qcmd != NULL)
1277: {
1278: qlist = (struct scmdlist *) xmalloc (sizeof (struct scmdlist));
1279: qlist->qnext = NULL;
1280: qlist->s = *qcmd;
1281: qlist->itime = itime;
1282: zlistid = zid;
1283: }
1284:
1285: return TRUE;
1286: }
1287:
1288: /* Show the header of the line describing a workfile. */
1289:
1290: static void
1291: usworkfile_header (qsys, qcmd, zjobid, itime, ffirst)
1292: const struct uuconf_system *qsys;
1293: const struct scmd *qcmd;
1294: const char *zjobid;
1295: long itime;
1296: boolean ffirst;
1297: {
1298: const char *zshowid;
1299: struct tm stime;
1300:
1301: if (ffirst)
1302: zshowid = zjobid;
1303: else
1304: zshowid = "-";
1305:
1306: printf ("%s %s %s ", zshowid, qsys->uuconf_zname,
1307: qcmd->zuser != NULL ? qcmd->zuser : OWNER);
1308:
1309: usysdep_localtime (itime, &stime);
1310: printf ("%02d-%02d %02d:%02d ",
1311: stime.tm_mon + 1, stime.tm_mday, stime.tm_hour, stime.tm_min);
1312: }
1313:
1314: /* List queued executions that have not been processed by uuxqt for
1315: one reason or another. */
1316:
1317: static boolean
1318: fsexecutions (puuconf, icmd, csystems, pazsystems, fnotsystems, cusers,
1319: pazusers, fnotusers, iold, iyoung, ccommands, pazcommands,
1320: fnotcommands, zcomment, cstdin)
1321: pointer puuconf;
1322: int icmd;
1323: int csystems;
1324: char **pazsystems;
1325: boolean fnotsystems;
1326: int cusers;
1327: char **pazusers;
1328: boolean fnotusers;
1329: long iold;
1330: long iyoung;
1331: int ccommands;
1332: char **pazcommands;
1333: boolean fnotcommands;
1334: const char *zcomment;
1335: int cstdin;
1336: {
1337: const char *zlocalname;
1338: int iuuconf;
1339: char *zfile;
1340: char *zsystem;
1341: boolean ferr;
1342:
1343: iuuconf = uuconf_localname (puuconf, &zlocalname);
1344: if (iuuconf == UUCONF_NOT_FOUND)
1345: {
1346: zlocalname = zsysdep_localname ();
1347: if (zlocalname == NULL)
1348: return FALSE;
1349: }
1350: else if (iuuconf != UUCONF_SUCCESS)
1351: {
1352: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1353: return FALSE;
1354: }
1355:
1356: if (! fsysdep_get_xqt_init ())
1357: return FALSE;
1358:
1359: while ((zfile = zsysdep_get_xqt (&zsystem, &ferr)) != NULL)
1360: {
1361: boolean fmatch;
1362: int i;
1363: long itime;
1364:
1365: if (csystems > 0)
1366: {
1367: fmatch = fnotsystems;
1368: for (i = 0; i < csystems; i++)
1369: {
1370: if (strcmp (pazsystems[i], zsystem) == 0)
1371: {
1372: fmatch = ! fmatch;
1373: break;
1374: }
1375: }
1376: if (! fmatch)
1377: {
1378: ubuffree (zfile);
1379: ubuffree (zsystem);
1380: continue;
1381: }
1382: }
1383:
1384: itime = ixsysdep_file_time (zfile);
1385:
1386: if ((iold != (long) -1 && itime > iold)
1387: || (iyoung != (long) -1 && itime < iyoung))
1388: {
1389: ubuffree (zfile);
1390: ubuffree (zsystem);
1391: continue;
1392: }
1393:
1394: /* We need to read the execution file before we can check the
1395: user name. */
1396: if (! fsxqt_file_read (puuconf, zfile))
1397: {
1398: ubuffree (zfile);
1399: ubuffree (zsystem);
1400: continue;
1401: }
1402:
1403: if (cusers == 0)
1404: fmatch = TRUE;
1405: else
1406: {
1407: fmatch = fnotusers;
1408: for (i = 0; i < cusers; i++)
1409: {
1410: if (strcmp (zSxqt_user, pazusers[i]) == 0
1411: || (zSxqt_requestor != NULL
1412: && strcmp (zSxqt_requestor, pazusers[i]) == 0))
1413: {
1414: fmatch = ! fmatch;
1415: break;
1416: }
1417: }
1418: }
1419:
1420: if (fmatch && ccommands > 0)
1421: {
1422: fmatch = fnotcommands;
1423: for (i = 0; i < ccommands; i++)
1424: {
1425: if (strcmp (pazcommands[i], "ALL") == 0
1426: || strcmp (pazcommands[i], zSxqt_prog) == 0)
1427: {
1428: fmatch = ! fmatch;
1429: break;
1430: }
1431: }
1432: }
1433:
1434: if (fmatch)
1435: {
1436: boolean fbad, fkill;
1437: struct uuconf_system ssys;
1438:
1439: fbad = FALSE;
1440:
1441: if ((icmd & JOB_SHOW) != 0)
1442: {
1443: struct tm stime;
1444:
1445: printf ("%s %s!", zsystem, zSxqt_system);
1446: if (zSxqt_requestor != NULL)
1447: printf ("%s", zSxqt_requestor);
1448: else
1449: printf ("%s", zSxqt_user);
1450:
1451: usysdep_localtime (itime, &stime);
1452: printf (" %02d-%02d %02d:%02d ",
1453: stime.tm_mon + 1, stime.tm_mday, stime.tm_hour,
1454: stime.tm_min);
1455:
1456: printf ("%s\n", zSxqt_cmd);
1457: }
1458:
1459: fkill = FALSE;
1460: if ((icmd & JOB_INQUIRE) != 0)
1461: {
1462: int b;
1463:
1464: /* Ask stdin whether this job should be killed. */
1465: fprintf (stderr, "%s: Kill %s? ", abProgram, zSxqt_cmd);
1466: (void) fflush (stderr);
1467: b = getchar ();
1468: fkill = b == 'y' || b == 'Y';
1469: while (b != EOF && b != '\n')
1470: b = getchar ();
1471: }
1472: else if ((icmd & JOB_KILL) != 0)
1473: fkill = TRUE;
1474:
1475: if (fkill)
1476: {
1477: if ((strcmp (zSxqt_user, zsysdep_login_name ()) != 0
1478: || strcmp (zsystem, zlocalname) != 0)
1479: && ! fsysdep_privileged ())
1480: {
1481: ulog (LOG_ERROR, "Job not submitted by you\n");
1482: fbad = TRUE;
1483: }
1484: }
1485:
1486: if (! fbad)
1487: {
1488: iuuconf = uuconf_system_info (puuconf, zsystem, &ssys);
1489: if (iuuconf != UUCONF_SUCCESS)
1490: {
1491: if (iuuconf != UUCONF_NOT_FOUND)
1492: {
1493: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1494: fbad = TRUE;
1495: }
1496: else if (strcmp (zsystem, zlocalname) == 0)
1497: {
1498: iuuconf = uuconf_system_local (puuconf, &ssys);
1499: if (iuuconf != UUCONF_SUCCESS)
1500: {
1501: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1502: fbad = TRUE;
1503: }
1504: }
1505: else if (! funknown_system (puuconf, zsystem, &ssys))
1506: {
1507: ulog (LOG_ERROR, "Job for unknown system %s",
1508: zsystem);
1509: fbad = TRUE;
1510: }
1511: }
1512: }
1513:
1514: if (! fbad && (icmd & (JOB_MAIL | JOB_NOTIFY)) != 0)
1515: {
1516: if (! fsnotify (puuconf, icmd, zcomment, cstdin, fkill,
1517: zSxqt_cmd, (struct scmdlist *) NULL,
1518: (const char *) NULL, zSxqt_user, &ssys,
1519: zSxqt_stdin, (pointer) NULL, zSxqt_requestor))
1520: {
1521: ferr = TRUE;
1522: usxqt_file_free ();
1523: ubuffree (zfile);
1524: ubuffree (zsystem);
1525: break;
1526: }
1527: }
1528:
1529: if (! fbad && fkill)
1530: {
1531: for (i = 0; i < cSxqt_files; i++)
1532: {
1533: char *z;
1534:
1535: z = zsysdep_spool_file_name (&ssys, pazSxqt_files[i],
1536: (pointer) NULL);
1537: if (z != NULL)
1538: {
1539: (void) remove (z);
1540: ubuffree (z);
1541: }
1542: }
1543: if (remove (zfile) != 0)
1544: ulog (LOG_ERROR, "remove (%s): %s", zfile,
1545: strerror (errno));
1546: }
1547:
1548: if (! fbad)
1549: (void) uuconf_system_free (puuconf, &ssys);
1550: }
1551:
1552: usxqt_file_free ();
1553: ubuffree (zfile);
1554: ubuffree (zsystem);
1555: }
1556:
1557: usysdep_get_xqt_free ();
1558:
1559: return ferr;
1560: }
1561:
1562: /* When a job is killed, send mail to the appropriate people. */
1563:
1564: static boolean
1565: fsnotify (puuconf, icmd, zcomment, cstdin, fkilled, zcmd, qcmd, zid, zuser,
1566: qsys, zstdin, pstdinseq, zrequestor)
1567: pointer puuconf;
1568: int icmd;
1569: const char *zcomment;
1570: int cstdin;
1571: boolean fkilled;
1572: const char *zcmd;
1573: struct scmdlist *qcmd;
1574: const char *zid;
1575: const char *zuser;
1576: const struct uuconf_system *qsys;
1577: const char *zstdin;
1578: pointer pstdinseq;
1579: const char *zrequestor;
1580: {
1581: const char **pz;
1582: int cgot;
1583: int i, istdin;
1584: const char *zsubject;
1585: boolean fret;
1586:
1587: pz = (const char **) xmalloc (20 * sizeof (const char *));
1588: cgot = 20;
1589:
1590: i = 0;
1591: if (zid == NULL)
1592: pz[i++] = "A UUCP execution request";
1593: else
1594: {
1595: pz[i++] = "UUCP job\n\t";
1596: pz[i++] = zid;
1597: pz[i++] = "\nfor system\n\t";
1598: pz[i++] = qsys->uuconf_zname;
1599: }
1600: pz[i++] = "\nrequested by\n\t";
1601: pz[i++] = zuser != NULL ? zuser : OWNER;
1602: if (zid == NULL)
1603: {
1604: pz[i++] = "\non system\n\t";
1605: pz[i++] = qsys->uuconf_zname;
1606: }
1607: pz[i++] = "\n";
1608:
1609: if (fkilled)
1610: pz[i++] = "has been killed.\n";
1611:
1612: if (zcomment != NULL)
1613: {
1614: pz[i++] = zcomment;
1615: pz[i++] = "\n";
1616: }
1617:
1618: pz[i++] = "The job ";
1619: if (fkilled)
1620: pz[i++] = "was\n";
1621: else
1622: pz[i++] = "is\n";
1623:
1624: if (zcmd != NULL)
1625: {
1626: pz[i++] = "\t";
1627: pz[i++] = zcmd;
1628: }
1629: else
1630: {
1631: struct scmdlist *qshow;
1632:
1633: for (qshow = qcmd; qshow != NULL; qshow = qshow->qnext)
1634: {
1635: if (i + 10 > cgot)
1636: {
1637: cgot += 20;
1638: pz = (const char **) xrealloc ((pointer) pz,
1639: cgot * sizeof (const char *));
1640: }
1641:
1642: switch (qshow->s.bcmd)
1643: {
1644: case 'S':
1645: pz[i++] = "\tsend ";
1646: break;
1647: default:
1648: case 'R':
1649: case 'X':
1650: pz[i++] = "\trequest ";
1651: break;
1652: case 'P':
1653: pz[i++] = "\tpoll ";
1654: #if DEBUG > 0
1655: case 'E':
1656: ulog (LOG_FATAL, "fsnotify: Can't happen");
1657: break;
1658: #endif
1659: }
1660: if (qshow->s.zfrom != NULL && qshow->s.zto != NULL)
1661: {
1662: pz[i++] = qshow->s.zfrom;
1663: pz[i++] = " to ";
1664: pz[i++] = qshow->s.zto;
1665: }
1666: }
1667: }
1668:
1669: istdin = i;
1670: if (cstdin > 0 && zstdin != NULL)
1671: {
1672: boolean fspool;
1673: char *zfile;
1674: FILE *e;
1675:
1676: fspool = fspool_file (zstdin);
1677: if (fspool)
1678: zfile = zsysdep_spool_file_name (qsys, zstdin, pstdinseq);
1679: else
1680: zfile = zsysdep_local_file (zstdin, qsys->uuconf_zpubdir);
1681:
1682: if (zfile != NULL
1683: && (fspool
1684: || fin_directory_list (zfile, qsys->uuconf_pzremote_send,
1685: qsys->uuconf_zpubdir, TRUE, TRUE,
1686: (const char *) NULL)))
1687: {
1688: e = fopen (zfile, "r");
1689: if (e != NULL)
1690: {
1691: int clines, clen;
1692: char *zline;
1693: size_t cline;
1694:
1695: pz[i++] = "\n";
1696: istdin = i;
1697:
1698: clines = 0;
1699:
1700: zline = NULL;
1701: cline = 0;
1702: while ((clen = getline (&zline, &cline, e)) > 0)
1703: {
1704: if (memchr (zline, '\0', (size_t) clen) != NULL)
1705: {
1706: int ifree;
1707:
1708: /* A null character means this is probably a
1709: binary file. */
1710: for (ifree = istdin; ifree < i; ifree++)
1711: ubuffree ((char *) pz[ifree]);
1712: i = istdin - 1;
1713: break;
1714: }
1715: ++clines;
1716: if (clines > cstdin)
1717: break;
1718: if (i >= cgot)
1719: {
1720: cgot += 20;
1721: pz = (const char **) xrealloc ((pointer) pz,
1722: (cgot
1723: * sizeof (char *)));
1724: }
1725: pz[i++] = zbufcpy (zline);
1726: }
1727: xfree ((pointer) zline);
1728: (void) fclose (e);
1729: }
1730: }
1731:
1732: ubuffree (zfile);
1733: }
1734:
1735: if (fkilled)
1736: zsubject = "UUCP job killed";
1737: else
1738: zsubject = "UUCP notification";
1739:
1740: fret = TRUE;
1741:
1742: if ((icmd & JOB_MAIL) != 0)
1743: {
1744: if (! fsysdep_mail (OWNER, zsubject, i, pz))
1745: fret = FALSE;
1746: }
1747:
1748: if ((icmd & JOB_NOTIFY) != 0
1749: && (zrequestor != NULL || zuser != NULL))
1750: {
1751: const char *zmail;
1752: char *zfree;
1753:
1754: if (zrequestor != NULL)
1755: zmail = zrequestor;
1756: else
1757: zmail = zuser;
1758:
1759: zfree = NULL;
1760:
1761: if (zid == NULL)
1762: {
1763: int iuuconf;
1764: const char *zloc;
1765:
1766: /* This is an execution request, which may be from another
1767: system. If it is, we must prepend that system name to
1768: the user name extracted from the X. file. */
1769: iuuconf = uuconf_localname (puuconf, &zloc);
1770: if (iuuconf == UUCONF_NOT_FOUND)
1771: {
1772: zloc = zsysdep_localname ();
1773: if (zloc == NULL)
1774: return FALSE;
1775: }
1776: else if (iuuconf != UUCONF_SUCCESS)
1777: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
1778:
1779: if (strcmp (qsys->uuconf_zname, zloc) != 0
1780: #if HAVE_INTERNET_MAIL
1781: && strchr (zmail, '@') == NULL
1782: #endif
1783: )
1784: {
1785: zfree = zbufalc (strlen (qsys->uuconf_zname)
1786: + strlen (zmail)
1787: + sizeof "!");
1788: sprintf (zfree, "%s!%s", qsys->uuconf_zname, zmail);
1789: zmail = zfree;
1790: }
1791: }
1792:
1793: if (! fsysdep_mail (zmail, zsubject, i, pz))
1794: fret = FALSE;
1795:
1796: ubuffree (zfree);
1797: }
1798:
1799: while (istdin < i)
1800: {
1801: ubuffree ((char *) pz[istdin]);
1802: istdin++;
1803: }
1804:
1805: xfree ((pointer) pz);
1806:
1807: return fret;
1808: }
1809:
1810: /* Handle the -q option. For each remote system this lists the number
1811: of jobs queued, the number of executions queued, and the current
1812: call status. We get the executions all at once, because they are
1813: not accessed by system. They could be, but it is possible to have
1814: executions pending for an unknown system, so special handling would
1815: still be required. */
1816:
1817: struct sxqtlist
1818: {
1819: struct sxqtlist *qnext;
1820: char *zsystem;
1821: int cxqts;
1822: long ifirst;
1823: };
1824:
1825: /* These local functions need the definition of sxqtlist for the
1826: prototype. */
1827:
1828: static boolean fsquery_system P((const struct uuconf_system *qsys,
1829: struct sxqtlist **pq,
1830: long inow, const char *zlocalname));
1831: static boolean fsquery_show P((const struct uuconf_system *qsys, int cwork,
1832: long ifirstwork,
1833: struct sxqtlist *qxqt,
1834: long inow, const char *zlocalname));
1835:
1836: static boolean
1837: fsquery (puuconf)
1838: pointer puuconf;
1839: {
1840: int iuuconf;
1841: const char *zlocalname;
1842: struct sxqtlist *qlist;
1843: char *zfile, *zsystem;
1844: boolean ferr;
1845: long inow;
1846: char **pznames, **pz;
1847: boolean fret;
1848:
1849: iuuconf = uuconf_localname (puuconf, &zlocalname);
1850: if (iuuconf == UUCONF_NOT_FOUND)
1851: {
1852: zlocalname = zsysdep_localname ();
1853: if (zlocalname == NULL)
1854: return FALSE;
1855: }
1856: else if (iuuconf != UUCONF_SUCCESS)
1857: {
1858: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1859: return FALSE;
1860: }
1861:
1862: /* Get a count of all the execution files. */
1863: if (! fsysdep_get_xqt_init ())
1864: return FALSE;
1865:
1866: qlist = NULL;
1867: while ((zfile = zsysdep_get_xqt (&zsystem, &ferr)) != NULL)
1868: {
1869: struct sxqtlist *qlook;
1870:
1871: for (qlook = qlist; qlook != NULL; qlook = qlook->qnext)
1872: if (strcmp (zsystem, qlook->zsystem) == 0)
1873: break;
1874:
1875: if (qlook != NULL)
1876: {
1877: long itime;
1878:
1879: ubuffree (zsystem);
1880: ++qlook->cxqts;
1881: itime = ixsysdep_file_time (zfile);
1882: if (itime < qlook->ifirst)
1883: qlook->ifirst = itime;
1884: }
1885: else
1886: {
1887: struct sxqtlist *qnew;
1888:
1889: qnew = (struct sxqtlist *) xmalloc (sizeof (struct sxqtlist));
1890: qnew->qnext = qlist;
1891: qnew->zsystem = zsystem;
1892: qnew->cxqts = 1;
1893: qnew->ifirst = ixsysdep_file_time (zfile);
1894: qlist = qnew;
1895: }
1896:
1897: ubuffree (zfile);
1898: }
1899:
1900: usysdep_get_xqt_free ();
1901:
1902: if (ferr)
1903: return FALSE;
1904:
1905: inow = ixsysdep_time ((long *) NULL);
1906:
1907: /* Show the information for each system. */
1908: iuuconf = uuconf_system_names (puuconf, &pznames, 0);
1909: if (iuuconf != UUCONF_SUCCESS)
1910: {
1911: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1912: return FALSE;
1913: }
1914:
1915: fret = TRUE;
1916:
1917: for (pz = pznames; *pz != NULL; pz++)
1918: {
1919: struct uuconf_system ssys;
1920:
1921: iuuconf = uuconf_system_info (puuconf, *pz, &ssys);
1922: if (iuuconf != UUCONF_SUCCESS)
1923: {
1924: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1925: fret = FALSE;
1926: continue;
1927: }
1928:
1929: if (! fsquery_system (&ssys, &qlist, inow, zlocalname))
1930: fret = FALSE;
1931:
1932: (void) uuconf_system_free (puuconf, &ssys);
1933: xfree ((pointer) *pz);
1934: }
1935:
1936: /* Check for the local system in the list of execution files. */
1937: if (qlist != NULL)
1938: {
1939: struct sxqtlist **pq;
1940:
1941: for (pq = &qlist; *pq != NULL; pq = &(*pq)->qnext)
1942: {
1943: if (strcmp ((*pq)->zsystem, zlocalname) == 0)
1944: {
1945: struct uuconf_system ssys;
1946: struct sxqtlist *qfree;
1947:
1948: iuuconf = uuconf_system_info (puuconf, zlocalname, &ssys);
1949: if (iuuconf != UUCONF_SUCCESS)
1950: {
1951: if (iuuconf != UUCONF_NOT_FOUND)
1952: {
1953: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1954: fret = FALSE;
1955: break;
1956: }
1957:
1958: iuuconf = uuconf_system_local (puuconf, &ssys);
1959: if (iuuconf != UUCONF_SUCCESS)
1960: {
1961: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1962: fret = FALSE;
1963: break;
1964: }
1965: ssys.uuconf_zname = (char *) zlocalname;
1966: }
1967:
1968: if (! fsquery_show (&ssys, 0, 0L, *pq, inow, zlocalname))
1969: fret = FALSE;
1970: (void) uuconf_system_free (puuconf, &ssys);
1971: qfree = *pq;
1972: *pq = qfree->qnext;
1973: ubuffree (qfree->zsystem);
1974: xfree ((pointer) qfree);
1975: break;
1976: }
1977: }
1978: }
1979:
1980: /* Print out information for any unknown systems for which we have
1981: execution files. */
1982: while (qlist != NULL)
1983: {
1984: struct uuconf_system ssys;
1985: struct sxqtlist *qnext;
1986:
1987: if (! funknown_system (puuconf, qlist->zsystem, &ssys))
1988: {
1989: ulog (LOG_ERROR, "Executions queued up for unknown systems");
1990: fret = FALSE;
1991: break;
1992: }
1993:
1994: if (! fsquery_show (&ssys, 0, 0L, qlist, inow, zlocalname))
1995: fret = FALSE;
1996: (void) uuconf_system_free (puuconf, &ssys);
1997: qnext = qlist->qnext;
1998: ubuffree (qlist->zsystem);
1999: xfree ((pointer) qlist);
2000: qlist = qnext;
2001: }
2002:
2003: return fret;
2004: }
2005:
2006: /* Query a single known system. */
2007:
2008: static boolean
2009: fsquery_system (qsys, pq, inow, zlocalname)
2010: const struct uuconf_system *qsys;
2011: struct sxqtlist **pq;
2012: long inow;
2013: const char *zlocalname;
2014: {
2015: int cwork;
2016: long ifirstwork;
2017: char *zid;
2018: boolean fret;
2019:
2020: if (! fsysdep_get_work_init (qsys, UUCONF_GRADE_LOW))
2021: return FALSE;
2022:
2023: cwork = 0;
2024: ifirstwork = 0L;
2025: zid = NULL;
2026: while (TRUE)
2027: {
2028: struct scmd s;
2029: long itime;
2030: char *zthisid;
2031:
2032: if (! fsysdep_get_work (qsys, UUCONF_GRADE_LOW, &s))
2033: return FALSE;
2034: if (s.bcmd == 'H')
2035: break;
2036:
2037: zthisid = zsysdep_jobid (qsys, s.pseq);
2038: if (zid != NULL && strcmp (zid, zthisid) == 0)
2039: ubuffree (zthisid);
2040: else
2041: {
2042: ++cwork;
2043: ubuffree (zid);
2044: zid = zthisid;
2045: }
2046:
2047: itime = ixsysdep_work_time (qsys, s.pseq);
2048: if (ifirstwork == 0L || ifirstwork > itime)
2049: ifirstwork = itime;
2050: }
2051:
2052: usysdep_get_work_free (qsys);
2053: ubuffree (zid);
2054:
2055: /* Find the execution information, if any. */
2056: while (*pq != NULL)
2057: {
2058: if (strcmp ((*pq)->zsystem, qsys->uuconf_zname) == 0)
2059: break;
2060: pq = &(*pq)->qnext;
2061: }
2062:
2063: /* If there are no commands and no executions, don't print any
2064: information for this system. */
2065: if (cwork == 0 && *pq == NULL)
2066: return TRUE;
2067:
2068: fret = fsquery_show (qsys, cwork, ifirstwork, *pq, inow, zlocalname);
2069:
2070: if (*pq != NULL)
2071: {
2072: struct sxqtlist *qfree;
2073:
2074: qfree = *pq;
2075: *pq = qfree->qnext;
2076: ubuffree (qfree->zsystem);
2077: xfree ((pointer) qfree);
2078: }
2079:
2080: return fret;
2081: }
2082:
2083: /* Print out the query information for a single system. We handle the
2084: local system specially. */
2085:
2086: static boolean
2087: fsquery_show (qsys, cwork, ifirstwork, qxqt, inow, zlocalname)
2088: const struct uuconf_system *qsys;
2089: int cwork;
2090: long ifirstwork;
2091: struct sxqtlist *qxqt;
2092: long inow;
2093: const char *zlocalname;
2094: {
2095: boolean flocal;
2096: struct sstatus sstat;
2097: boolean fnostatus;
2098: struct tm stime;
2099: int cpad;
2100:
2101: flocal = strcmp (qsys->uuconf_zname, zlocalname) == 0;
2102:
2103: if (! flocal)
2104: {
2105: if (! fsysdep_get_status (qsys, &sstat, &fnostatus))
2106: return FALSE;
2107: }
2108:
2109: printf ("%-10s %3dC (", qsys->uuconf_zname, cwork);
2110:
2111: if (cwork == 0)
2112: {
2113: printf ("0 secs");
2114: cpad = 3;
2115: }
2116: else
2117: cpad = csunits_show (inow - ifirstwork);
2118:
2119: printf (") ");
2120: while (cpad-- != 0)
2121: printf (" ");
2122:
2123: if (qxqt == NULL)
2124: printf (" 0X (0 secs) ");
2125: else
2126: {
2127: printf ("%3dX (", qxqt->cxqts);
2128: cpad = csunits_show (inow - qxqt->ifirst);
2129: printf (")");
2130: while (cpad-- != 0)
2131: printf (" ");
2132: }
2133:
2134: if (flocal || fnostatus)
2135: {
2136: printf ("\n");
2137: return TRUE;
2138: }
2139:
2140: usysdep_localtime (sstat.ilast, &stime);
2141:
2142: printf (" %02d-%02d %02d:%02d ",
2143: stime.tm_mon + 1,stime.tm_mday, stime.tm_hour, stime.tm_min);
2144:
2145: printf ("%s\n", azStatus[(int) sstat.ttype]);
2146:
2147: return TRUE;
2148: }
2149:
2150: /* Print a time difference in the largest applicable units. */
2151:
2152: static int
2153: csunits_show (idiff)
2154: long idiff;
2155: {
2156: const char *zunit;
2157: long iunits;
2158: int cpad;
2159:
2160: if (idiff > (long) 24 * (long) 60 * (long) 60)
2161: {
2162: iunits = idiff / ((long) 24 * (long) 60 * (long) 60);
2163: zunit = "day";
2164: cpad = 4;
2165: }
2166: else if (idiff > (long) 60 * 60)
2167: {
2168: iunits = idiff / (long) (60 * 60);
2169: zunit = "hour";
2170: cpad = 3;
2171: }
2172: else if (idiff > (long) 60)
2173: {
2174: iunits = idiff / (long) 60;
2175: zunit = "min";
2176: cpad = 4;
2177: }
2178: else
2179: {
2180: iunits = idiff;
2181: zunit = "sec";
2182: cpad = 4;
2183: }
2184:
2185: printf ("%ld %s%s", iunits, zunit, iunits == 1 ? "" : "s");
2186:
2187: if (iunits != 1)
2188: --cpad;
2189: if (iunits > 99)
2190: --cpad;
2191: if (iunits > 9)
2192: --cpad;
2193: return cpad;
2194: }
2195:
2196: /* Give a list of all status entries for all machines that we have
2197: status entries for. We need to get a list of status entries in a
2198: system dependent fashion, since we may have status for unknown
2199: systems. */
2200:
2201: static boolean
2202: fsmachines ()
2203: {
2204: pointer phold;
2205: char *zsystem;
2206: boolean ferr;
2207: struct sstatus sstat;
2208:
2209: if (! fsysdep_all_status_init (&phold))
2210: return FALSE;
2211:
2212: while ((zsystem = zsysdep_all_status (phold, &ferr, &sstat)) != NULL)
2213: {
2214: struct tm stime;
2215:
2216: usysdep_localtime (sstat.ilast, &stime);
2217: printf ("%-14s %02d-%02d %02d:%02d %s", zsystem,
2218: stime.tm_mon + 1, stime.tm_mday, stime.tm_hour,
2219: stime.tm_min, azStatus[(int) sstat.ttype]);
2220: ubuffree (zsystem);
2221: if (sstat.ttype != STATUS_TALKING
2222: && sstat.cwait > 0)
2223: {
2224: printf (" (%d %s", sstat.cretries,
2225: sstat.cretries == 1 ? "try" : "tries");
2226: if (sstat.ilast + sstat.cwait > ixsysdep_time ((long *) NULL))
2227: {
2228: usysdep_localtime (sstat.ilast + sstat.cwait, &stime);
2229: printf (", next after %02d-%02d %02d:%02d",
2230: stime.tm_mon + 1, stime.tm_mday, stime.tm_hour,
2231: stime.tm_min);
2232: }
2233: printf (")");
2234: }
2235: printf ("\n");
2236: }
2237:
2238: usysdep_all_status_free (phold);
2239:
2240: return ! ferr;
2241: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.