|
|
1.1 root 1: /* uuxqt.c
2: Run uux commands.
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 uuxqt_rcsid[] = "$Id: uuxqt.c,v 1.1 93/07/30 08:00:15 bin Exp Locker: bin $";
30: #endif
31:
32: #include <errno.h>
33: #include <ctype.h>
34:
35: #include "getopt.h"
36:
37: #include "uudefs.h"
38: #include "uuconf.h"
39: #include "system.h"
40:
41: /* The program name. */
42: char abProgram[] = "uuxqt";
43:
44: /* Static variables used to unlock things if we get a fatal error. */
45: static int iQlock_seq = -1;
46: static const char *zQunlock_cmd;
47: static const char *zQunlock_file;
48: static boolean fQunlock_directory;
49: int cQmaxuuxqts;
50:
51: /* Static variables to free in uqcleanup. */
52: static char *zQoutput;
53: static char *zQmail;
54:
55: /* Local functions. */
56: static void uqusage P((void));
57: static void uqabort P((void));
58: static void uqdo_xqt_file P((pointer puuconf, const char *zfile,
59: const char *zbase,
60: const struct uuconf_system *qsys,
61: const char *zlocalname,
62: const char *zcmd, boolean *pfprocessed));
63: static void uqcleanup P((const char *zfile, int iflags));
64: static boolean fqforward P((const char *zfile, char **pzallowed,
65: const char *zlog, const char *zmail));
66:
67: /* Long getopt options. */
68: static const struct option asQlongopts[] = { { NULL, 0, NULL, 0 } };
69:
70: int
71: main (argc, argv)
72: int argc;
73: char **argv;
74: {
75: /* The type of command to execute (NULL for any type). */
76: const char *zcmd = NULL;
77: /* The configuration file name. */
78: const char *zconfig = NULL;
79: /* The system to execute commands for. */
80: const char *zdosys = NULL;
81: int iopt;
82: pointer puuconf;
83: int iuuconf;
84: const char *zlocalname;
85: boolean fany;
86: char *z, *zgetsys;
87: boolean ferr;
88: boolean fsys;
89: struct uuconf_system ssys;
90:
91: while ((iopt = getopt_long (argc, argv, "c:I:s:x:", asQlongopts,
92: (int *) NULL)) != EOF)
93: {
94: switch (iopt)
95: {
96: case 'c':
97: /* Set the type of command to execute. */
98: zcmd = optarg;
99: break;
100:
101: case 'I':
102: /* Set the configuration file name. */
103: if (fsysdep_other_config (optarg))
104: zconfig = optarg;
105: break;
106:
107: case 's':
108: zdosys = optarg;
109: break;
110:
111: case 'x':
112: #if DEBUG > 1
113: /* Set the debugging level. */
114: iDebug |= idebug_parse (optarg);
115: #endif
116: break;
117:
118: case 0:
119: /* Long option found and flag set. */
120: break;
121:
122: default:
123: uqusage ();
124: break;
125: }
126: }
127:
128: if (optind != argc)
129: uqusage ();
130:
131: iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig);
132: if (iuuconf != UUCONF_SUCCESS)
133: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
134:
135: #if DEBUG > 1
136: {
137: const char *zdebug;
138:
139: iuuconf = uuconf_debuglevel (puuconf, &zdebug);
140: if (iuuconf != UUCONF_SUCCESS)
141: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
142: if (zdebug != NULL)
143: iDebug |= idebug_parse (zdebug);
144: }
145: #endif
146:
147: iuuconf = uuconf_maxuuxqts (puuconf, &cQmaxuuxqts);
148: if (iuuconf != UUCONF_SUCCESS)
149: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
150:
151: #ifdef SIGINT
152: usysdep_signal (SIGINT);
153: #endif
154: #ifdef SIGHUP
155: usysdep_signal (SIGHUP);
156: #endif
157: #ifdef SIGQUIT
158: usysdep_signal (SIGQUIT);
159: #endif
160: #ifdef SIGTERM
161: usysdep_signal (SIGTERM);
162: #endif
163: #ifdef SIGPIPE
164: usysdep_signal (SIGPIPE);
165: #endif
166:
167: usysdep_initialize (puuconf, INIT_SUID);
168:
169: ulog_to_file (puuconf, TRUE);
170: ulog_fatal_fn (uqabort);
171:
172: iuuconf = uuconf_localname (puuconf, &zlocalname);
173: if (iuuconf == UUCONF_NOT_FOUND)
174: {
175: zlocalname = zsysdep_localname ();
176: if (zlocalname == NULL)
177: exit (EXIT_FAILURE);
178: }
179: else if (iuuconf != UUCONF_SUCCESS)
180: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
181:
182: fsys = FALSE;
183:
184: /* If we were given a system name, canonicalize it, since the system
185: dependent layer will not be returning aliases. */
186: if (zdosys != NULL)
187: {
188: iuuconf = uuconf_system_info (puuconf, zdosys, &ssys);
189: if (iuuconf == UUCONF_NOT_FOUND)
190: ulog (LOG_FATAL, "%s: System not found", zdosys);
191: else if (iuuconf != UUCONF_SUCCESS)
192: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
193:
194: zdosys = zbufcpy (ssys.uuconf_zname);
195: fsys = TRUE;
196: }
197:
198: /* Limit the number of uuxqt processes, and make sure we're the only
199: uuxqt daemon running for this command. */
200: iQlock_seq = ixsysdep_lock_uuxqt (zcmd, cQmaxuuxqts);
201: if (iQlock_seq < 0)
202: {
203: ulog_close ();
204: usysdep_exit (TRUE);
205: }
206: zQunlock_cmd = zcmd;
207:
208: /* Keep scanning the execute files until we don't process any of
209: them. */
210: do
211: {
212: fany = FALSE;
213:
214: /* Look for each execute file, and run it. */
215:
216: if (! fsysdep_get_xqt_init ())
217: {
218: ulog_close ();
219: usysdep_exit (FALSE);
220: }
221:
222: while ((z = zsysdep_get_xqt (&zgetsys, &ferr)) != NULL)
223: {
224: const char *zloc;
225: boolean fprocessed;
226: char *zbase;
227:
228: /* It would be more efficient to pass zdosys down to the
229: routines which retrieve execute files. */
230: if (zdosys != NULL && strcmp (zdosys, zgetsys) != 0)
231: {
232: ubuffree (z);
233: ubuffree (zgetsys);
234: continue;
235: }
236:
237: if (! fsys || strcmp (ssys.uuconf_zname, zgetsys) != 0)
238: {
239: if (fsys)
240: (void) uuconf_system_free (puuconf, &ssys);
241:
242: iuuconf = uuconf_system_info (puuconf, zgetsys,
243: &ssys);
244: if (iuuconf != UUCONF_SUCCESS)
245: {
246: if (iuuconf != UUCONF_NOT_FOUND)
247: {
248: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
249: ubuffree (z);
250: ubuffree (zgetsys);
251: continue;
252: }
253: else if (strcmp (zgetsys, zlocalname) == 0)
254: {
255: iuuconf = uuconf_system_local (puuconf, &ssys);
256: if (iuuconf != UUCONF_SUCCESS)
257: {
258: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
259: ubuffree (z);
260: ubuffree (zgetsys);
261: continue;
262: }
263: }
264: else
265: {
266: if (! funknown_system (puuconf, zgetsys, &ssys))
267: {
268: ulog (LOG_ERROR,
269: "%s: Execute file for unknown system %s",
270: z, zgetsys);
271: (void) remove (z);
272: ubuffree (z);
273: ubuffree (zgetsys);
274: continue;
275: }
276: }
277: }
278:
279: fsys = TRUE;
280: }
281:
282: /* If we've received a signal, get out of the loop. */
283: if (FGOT_SIGNAL ())
284: {
285: ubuffree (z);
286: ubuffree (zgetsys);
287: break;
288: }
289:
290: zloc = ssys.uuconf_zlocalname;
291: if (zloc == NULL)
292: zloc = zlocalname;
293:
294: ulog_system (ssys.uuconf_zname);
295: zbase = zsysdep_base_name (z);
296: uqdo_xqt_file (puuconf, z, zbase, &ssys, zloc, zcmd, &fprocessed);
297: ubuffree (zbase);
298: ulog_system ((const char *) NULL);
299: ulog_user ((const char *) NULL);
300:
301: if (fprocessed)
302: fany = TRUE;
303: ubuffree (z);
304: ubuffree (zgetsys);
305: }
306:
307: usysdep_get_xqt_free ();
308: }
309: while (fany && ! FGOT_SIGNAL ());
310:
311: (void) fsysdep_unlock_uuxqt (iQlock_seq, zcmd, cQmaxuuxqts);
312: iQlock_seq = -1;
313:
314: ulog_close ();
315:
316: if (FGOT_SIGNAL ())
317: ferr = TRUE;
318:
319: usysdep_exit (! ferr);
320:
321: /* Avoid errors about not returning a value. */
322: return 0;
323: }
324:
325: static void
326: uqusage ()
327: {
328: fprintf (stderr,
329: "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
330: VERSION);
331: fprintf (stderr,
332: "Usage: uuxqt [-c cmd] [-I file] [-s system] [-x debug]\n");
333: fprintf (stderr,
334: " -c cmd: Set type of command to execute\n");
335: fprintf (stderr,
336: " -s system: Execute commands only for named system\n");
337: fprintf (stderr,
338: " -x debug: Set debugging level (0 for none, 9 is max)\n");
339: #if HAVE_TAYLOR_CONFIG
340: fprintf (stderr,
341: " -I file: Set configuration file to use\n");
342: #endif /* HAVE_TAYLOR_CONFIG */
343: exit (EXIT_FAILURE);
344: }
345:
346: /* This is the abort function called when we get a fatal error. */
347:
348: static void
349: uqabort ()
350: {
351: #if ! HAVE_HDB_LOGGING
352: /* When using HDB logging, it's a pain to have no system name. */
353: ulog_system ((const char *) NULL);
354: #endif
355:
356: ulog_user ((const char *) NULL);
357:
358: if (fQunlock_directory)
359: (void) fsysdep_unlock_uuxqt_dir (iQlock_seq);
360:
361: if (zQunlock_file != NULL)
362: (void) fsysdep_unlock_uuxqt_file (zQunlock_file);
363:
364: if (iQlock_seq >= 0)
365: (void) fsysdep_unlock_uuxqt (iQlock_seq, zQunlock_cmd, cQmaxuuxqts);
366:
367: ulog_close ();
368:
369: usysdep_exit (FALSE);
370: }
371:
372: /* An execute file is a series of lines. The first character of each
373: line is a command. The following commands are defined:
374:
375: C command-line
376: I standard-input
377: O standard-output [ system ]
378: F required-file filename-to-use
379: R requestor-address
380: U user system
381: Z (acknowledge if command failed; default)
382: N (no acknowledgement on failure)
383: n (acknowledge if command succeeded)
384: B (return command input on error)
385: e (process with sh)
386: E (process with exec)
387: M status-file
388: # comment
389:
390: Unrecognized commands are ignored. We actually do not recognize
391: the Z command, since it requests default behaviour. We always send
392: mail on failure, unless the N command appears. We never send mail
393: on success, unless the n command appears.
394:
395: This code does not currently support the B or M commands. */
396:
397: /* Command arguments. */
398: static char **azQargs;
399: /* Command as a complete string. */
400: static char *zQcmd;
401: /* Standard input file name. */
402: static char *zQinput;
403: /* Standard output file name. */
404: static char *zQoutfile;
405: /* Standard output system. */
406: static char *zQoutsys;
407: /* Number of required files. */
408: static int cQfiles;
409: /* Names of required files. */
410: static char **azQfiles;
411: /* Names required files should be renamed to (NULL if original is OK). */
412: static char **azQfiles_to;
413: /* Requestor address (this is where mail should be sent). */
414: static char *zQrequestor;
415: /* User name. */
416: static const char *zQuser;
417: /* System name. */
418: static const char *zQsystem;
419: /* This is set by the N flag, meaning that no acknowledgement should
420: be mailed on failure. */
421: static boolean fQno_ack;
422: /* This is set by the n flag, meaning that acknowledgement should be
423: mailed if the command succeeded. */
424: static boolean fQsuccess_ack;
425: /* This is set by the B flag, meaning that command input should be
426: mailed to the requestor if an error occurred. */
427: static boolean fQsend_input;
428: /* This is set by the E flag, meaning that exec should be used to
429: execute the command. */
430: static boolean fQuse_exec;
431: /* The status should be copied to this file on the requesting host. */
432: static const char *zQstatus_file;
433: #if ALLOW_SH_EXECUTION
434: /* This is set by the e flag, meaning that sh should be used to
435: execute the command. */
436: static boolean fQuse_sh;
437: #endif /* ALLOW_SH_EXECUTION */
438:
439: static int iqcmd P((pointer puuconf, int argc, char **argv, pointer pvar,
440: pointer pinfo));
441: static int iqout P((pointer puuconf, int argc, char **argv, pointer pvar,
442: pointer pinfo));
443: static int iqfile P((pointer puuconf, int argc, char **argv, pointer pvar,
444: pointer pinfo));
445: static int iqrequestor P((pointer puuconf, int argc, char **argv,
446: pointer pvar, pointer pinfo));
447: static int iquser P((pointer puuconf, int argc, char **argv, pointer pvar,
448: pointer pinfo));
449: static int iqset P((pointer puuconf, int argc, char **argv, pointer pvar,
450: pointer pinfo));
451:
452: static const struct uuconf_cmdtab asQcmds[] =
453: {
454: { "C", UUCONF_CMDTABTYPE_FN | 0, NULL, iqcmd },
455: { "I", UUCONF_CMDTABTYPE_STRING, (pointer) &zQinput, NULL },
456: { "O", UUCONF_CMDTABTYPE_FN | 0, NULL, iqout },
457: { "F", UUCONF_CMDTABTYPE_FN | 0, NULL, iqfile },
458: { "R", UUCONF_CMDTABTYPE_FN, NULL, iqrequestor },
459: { "U", UUCONF_CMDTABTYPE_FN | 3, NULL, iquser },
460: { "N", UUCONF_CMDTABTYPE_FN | 1, (pointer) &fQno_ack, iqset },
461: { "n", UUCONF_CMDTABTYPE_FN | 1, (pointer) &fQsuccess_ack, iqset },
462: /* Some systems create execution files in which B takes an argument;
463: I don't know what it means, so I just ignore it. */
464: { "B", UUCONF_CMDTABTYPE_FN | 0, (pointer) &fQsend_input, iqset },
465: #if ALLOW_SH_EXECUTION
466: { "e", UUCONF_CMDTABTYPE_FN | 1, (pointer) &fQuse_sh, iqset },
467: #endif
468: { "E", UUCONF_CMDTABTYPE_FN | 1, (pointer) &fQuse_exec, iqset },
469: { "M", UUCONF_CMDTABTYPE_STRING, (pointer) &zQstatus_file, NULL },
470: { NULL, 0, NULL, NULL }
471: };
472:
473: /* Handle the C command: store off the arguments. */
474:
475: /*ARGSUSED*/
476: static int
477: iqcmd (puuconf, argc, argv, pvar, pinfo)
478: pointer puuconf;
479: int argc;
480: char **argv;
481: pointer pvar;
482: pointer pinfo;
483: {
484: int i;
485: size_t clen;
486:
487: if (argc <= 1)
488: return UUCONF_CMDTABRET_CONTINUE;
489:
490: azQargs = (char **) xmalloc (argc * sizeof (char *));
491: clen = 0;
492: for (i = 1; i < argc; i++)
493: {
494: azQargs[i - 1] = zbufcpy (argv[i]);
495: clen += strlen (argv[i]) + 1;
496: }
497: azQargs[i - 1] = NULL;
498:
499: zQcmd = (char *) xmalloc (clen);
500: zQcmd[0] = '\0';
501: for (i = 1; i < argc - 1; i++)
502: {
503: strcat (zQcmd, argv[i]);
504: strcat (zQcmd, " ");
505: }
506: strcat (zQcmd, argv[i]);
507:
508: return UUCONF_CMDTABRET_CONTINUE;
509: }
510:
511: /* Handle the O command, which may have one or two arguments. */
512:
513: /*ARGSUSED*/
514: static int
515: iqout (puuconf, argc, argv, pvar, pinfo)
516: pointer puuconf;
517: int argc;
518: char **argv;
519: pointer pvar;
520: pointer pinfo;
521: {
522: const char *zbase = (const char *) pinfo;
523:
524: if (argc != 2 && argc != 3)
525: {
526: ulog (LOG_ERROR, "%s: %s: Wrong number of arguments",
527: zbase, argv[0]);
528: return UUCONF_CMDTABRET_CONTINUE;
529: }
530:
531: zQoutfile = zbufcpy (argv[1]);
532: if (argc == 3)
533: zQoutsys = zbufcpy (argv[2]);
534:
535: return UUCONF_CMDTABRET_CONTINUE;
536: }
537:
538: /* Handle the F command, which may have one or two arguments. */
539:
540: /*ARGSUSED*/
541: static int
542: iqfile (puuconf, argc, argv, pvar, pinfo)
543: pointer puuconf;
544: int argc;
545: char **argv;
546: pointer pvar;
547: pointer pinfo;
548: {
549: const char *zbase = (const char *) pinfo;
550:
551: if (argc != 2 && argc != 3)
552: {
553: ulog (LOG_ERROR, "%s: %s: Wrong number of arguments",
554: zbase, argv[0]);
555: return UUCONF_CMDTABRET_CONTINUE;
556: }
557:
558: /* If this file is not in the spool directory, just ignore it. */
559: if (! fspool_file (argv[1]))
560: return UUCONF_CMDTABRET_CONTINUE;
561:
562: ++cQfiles;
563: azQfiles = (char **) xrealloc ((pointer) azQfiles,
564: cQfiles * sizeof (char *));
565: azQfiles_to = (char **) xrealloc ((pointer) azQfiles_to,
566: cQfiles * sizeof (char *));
567:
568: azQfiles[cQfiles - 1] = zbufcpy (argv[1]);
569: if (argc == 3)
570: azQfiles_to[cQfiles - 1] = zbufcpy (argv[2]);
571: else
572: azQfiles_to[cQfiles - 1] = NULL;
573:
574: return UUCONF_CMDTABRET_CONTINUE;
575: }
576:
577: /* Handle the R command, which may have one or two arguments. */
578:
579: /*ARGSUSED*/
580: static int
581: iqrequestor (puuconf, argc, argv, pvar, pinfo)
582: pointer puuconf;
583: int argc;
584: char **argv;
585: pointer pvar;
586: pointer pinfo;
587: {
588: const char *zbase = (const char *) pinfo;
589:
590: if (argc != 2 && argc != 3)
591: {
592: ulog (LOG_ERROR, "%s: %s: Wrong number of arguments",
593: zbase, argv[0]);
594: return UUCONF_CMDTABRET_CONTINUE;
595: }
596:
597: /* We normally have a single argument, which is the ``requestor''
598: address, to which we should send any success or error messages.
599: Apparently the DOS program UUPC sends two arguments, which are
600: the username and the host. */
601: if (argc == 2)
602: zQrequestor = zbufcpy (argv[1]);
603: else
604: {
605: zQrequestor = zbufalc (strlen (argv[1]) + strlen (argv[2])
606: + sizeof "!");
607: sprintf (zQrequestor, "%s!%s", argv[2], argv[1]);
608: }
609:
610: return UUCONF_CMDTABRET_CONTINUE;
611: }
612:
613: /* Handle the U command, which takes two arguments. */
614:
615: /*ARGSUSED*/
616: static int
617: iquser (puuconf, argc, argv, pvar, pinfo)
618: pointer puuconf;
619: int argc;
620: char **argv;
621: pointer pvar;
622: pointer pinfo;
623: {
624: zQuser = argv[1];
625: zQsystem = argv[2];
626: return UUCONF_CMDTABRET_KEEP;
627: }
628:
629: /* Handle various commands which just set boolean variables. */
630:
631: /*ARGSUSED*/
632: static int
633: iqset (puuconf, argc, argv, pvar, pinfo)
634: pointer puuconf;
635: int argc;
636: char **argv;
637: pointer pvar;
638: pointer pinfo;
639: {
640: boolean *pf = (boolean *) pvar;
641:
642: *pf = TRUE;
643: return UUCONF_CMDTABRET_CONTINUE;
644: }
645:
646: /* The execution processing does a lot of things that have to be
647: cleaned up. Rather than try to add the appropriate statements
648: to each return point, we keep a set of flags indicating what
649: has to be cleaned up. The actual clean up is done by the
650: function uqcleanup. */
651: #define REMOVE_FILE (01)
652: #define REMOVE_NEEDED (02)
653: #define FREE_QINPUT (04)
654: #define FREE_OUTPUT (010)
655: #define FREE_MAIL (020)
656:
657: /* Process an execute file. The zfile argument is the name of the
658: execute file. The zbase argument is the base name of zfile. The
659: qsys argument describes the system it came from. The zcmd argument
660: is the name of the command we are executing (from the -c option) or
661: NULL if any command is OK. This sets *pfprocessed to TRUE if the
662: file is ready to be executed. */
663:
664: static void
665: uqdo_xqt_file (puuconf, zfile, zbase, qsys, zlocalname, zcmd, pfprocessed)
666: pointer puuconf;
667: const char *zfile;
668: const char *zbase;
669: const struct uuconf_system *qsys;
670: const char *zlocalname;
671: const char *zcmd;
672: boolean *pfprocessed;
673: {
674: char *zabsolute;
675: boolean ferr;
676: FILE *e;
677: int iuuconf;
678: int i;
679: int iclean;
680: const char *zmail;
681: char *zoutput;
682: char *zinput;
683: char abtemp[CFILE_NAME_LEN];
684: char abdata[CFILE_NAME_LEN];
685: char *zerror;
686: struct uuconf_system soutsys;
687: const struct uuconf_system *qoutsys;
688: boolean fshell;
689: size_t clen;
690: char *zfullcmd;
691: boolean ftemp;
692:
693: *pfprocessed = FALSE;
694:
695: e = fopen (zfile, "r");
696: if (e == NULL)
697: return;
698:
699: azQargs = NULL;
700: zQcmd = NULL;
701: zQinput = NULL;
702: zQoutfile = NULL;
703: zQoutsys = NULL;
704: cQfiles = 0;
705: azQfiles = NULL;
706: azQfiles_to = NULL;
707: zQrequestor = NULL;
708: zQuser = NULL;
709: zQsystem = NULL;
710: fQno_ack = FALSE;
711: fQsuccess_ack = FALSE;
712: fQsend_input = FALSE;
713: fQuse_exec = FALSE;
714: zQstatus_file = NULL;
715: #if ALLOW_SH_EXECUTION
716: fQuse_sh = FALSE;
717: #endif
718:
719: iuuconf = uuconf_cmd_file (puuconf, e, asQcmds, (pointer) zbase,
720: (uuconf_cmdtabfn) NULL,
721: UUCONF_CMDTABFLAG_CASE, (pointer) NULL);
722: (void) fclose (e);
723:
724: if (iuuconf != UUCONF_SUCCESS)
725: {
726: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
727: return;
728: }
729:
730: iclean = 0;
731:
732: if (azQargs == NULL)
733: {
734: ulog (LOG_ERROR, "%s: No command given", zbase);
735: uqcleanup (zfile, iclean | REMOVE_FILE);
736: return;
737: }
738:
739: if (zcmd != NULL)
740: {
741: if (strcmp (zcmd, azQargs[0]) != 0)
742: {
743: uqcleanup (zfile, iclean);
744: return;
745: }
746: }
747: else
748: {
749: /* If there is a lock file for this particular command already,
750: it means that some other uuxqt is supposed to handle it. */
751: if (fsysdep_uuxqt_locked (azQargs[0]))
752: {
753: uqcleanup (zfile, iclean);
754: return;
755: }
756: }
757:
758: /* Lock this particular file. */
759: if (! fsysdep_lock_uuxqt_file (zfile))
760: {
761: uqcleanup (zfile, iclean);
762: return;
763: }
764:
765: zQunlock_file = zfile;
766:
767: /* Now that we have the file locked, make sure it still exists.
768: Otherwise another uuxqt could have just finished processing it
769: and removed the lock file. */
770: if (! fsysdep_file_exists (zfile))
771: {
772: uqcleanup (zfile, iclean);
773: return;
774: }
775:
776: if (zQuser != NULL)
777: ulog_user (zQuser);
778: else if (zQrequestor != NULL)
779: ulog_user (zQrequestor);
780: else
781: ulog_user ("unknown");
782:
783: /* Make sure that all the required files exist, and get their
784: full names in the spool directory. */
785: for (i = 0; i < cQfiles; i++)
786: {
787: char *zreal;
788:
789: zreal = zsysdep_spool_file_name (qsys, azQfiles[i], (pointer) NULL);
790: if (zreal == NULL)
791: {
792: uqcleanup (zfile, iclean);
793: return;
794: }
795: if (! fsysdep_file_exists (zreal))
796: {
797: uqcleanup (zfile, iclean);
798: return;
799: }
800: ubuffree (azQfiles[i]);
801: azQfiles[i] = zbufcpy (zreal);
802: ubuffree (zreal);
803: }
804:
805: /* Lock the execution directory. */
806: if (! fsysdep_lock_uuxqt_dir (iQlock_seq))
807: {
808: ulog (LOG_ERROR, "Could not lock execute directory");
809: uqcleanup (zfile, iclean);
810: return;
811: }
812: fQunlock_directory = TRUE;
813:
814: iclean |= REMOVE_FILE | REMOVE_NEEDED;
815: *pfprocessed = TRUE;
816:
817: /* Get the address to mail results to. Prepend the system from
818: which the execute file originated, since mail addresses are
819: relative to it. */
820: zmail = NULL;
821: if (zQrequestor != NULL)
822: zmail = zQrequestor;
823: else if (zQuser != NULL)
824: zmail = zQuser;
825: if (zmail != NULL
826: && zQsystem != NULL
827: #if HAVE_INTERNET_MAIL
828: && strchr (zmail, '@') == NULL
829: #endif
830: && strcmp (zQsystem, zlocalname) != 0)
831: {
832: char *zset;
833:
834: zset = zbufalc (strlen (zQsystem) + strlen (zmail) + 2);
835: sprintf (zset, "%s!%s", zQsystem, zmail);
836: zmail = zset;
837: zQmail = zset;
838: iclean |= FREE_MAIL;
839: }
840:
841: /* The command "uucp" is handled specially. We make sure that the
842: appropriate forwarding is permitted, and we add a -u argument to
843: specify the user. */
844: if (strcmp (azQargs[0], "uucp") == 0)
845: {
846: char *zfrom, *zto;
847: boolean fmany;
848: char **azargs;
849: const char *zuser, *zsystem;
850:
851: zfrom = NULL;
852: zto = NULL;
853: fmany = FALSE;
854:
855: /* Skip all the options, and get the from and to specs. We
856: don't permit multiple arguments. */
857: for (i = 1; azQargs[i] != NULL; i++)
858: {
859: if (azQargs[i][0] == '-')
860: {
861: char *zopts;
862:
863: for (zopts = azQargs[i] + 1; *zopts != '\0'; zopts++)
864: {
865: /* The -g, -n, and -s options take an argument. */
866: if (*zopts == 'g' || *zopts == 'n' || *zopts == 's')
867: {
868: if (zopts[1] == '\0')
869: ++i;
870: break;
871: }
872: /* The -I, -u and -x options are not permitted. */
873: if (*zopts == 'I' || *zopts == 'u' || *zopts == 'x')
874: {
875: *zopts = 'r';
876: if (zopts[1] != '\0')
877: zopts[1] = '\0';
878: else
879: {
880: ++i;
881: azQargs[i] = zbufcpy ("-r");
882: }
883: break;
884: }
885: }
886: }
887: else if (zfrom == NULL)
888: zfrom = azQargs[i];
889: else if (zto == NULL)
890: zto = azQargs[i];
891: else
892: {
893: fmany = TRUE;
894: break;
895: }
896: }
897:
898: /* Add the -u argument. This is required to let uucp do the
899: correct permissions checking on the file transfer. */
900: for (i = 0; azQargs[i] != NULL; i++)
901: ;
902: azargs = (char **) xmalloc ((i + 2) * sizeof (char *));
903: azargs[0] = azQargs[0];
904: zuser = zQuser;
905: if (zuser == NULL)
906: zuser = "uucp";
907: zsystem = zQsystem;
908: if (zsystem == NULL)
909: zsystem = qsys->uuconf_zname;
910: azargs[1] = zbufalc (strlen (zsystem) + strlen (zuser)
911: + sizeof "-u!");
912: sprintf (azargs[1], "-u%s!%s", zsystem, zuser);
913: memcpy (azargs + 2, azQargs + 1, i * sizeof (char *));
914: xfree ((pointer) azQargs);
915: azQargs = azargs;
916:
917: /* Find the uucp binary. */
918: zabsolute = zsysdep_find_command ("uucp", qsys->uuconf_pzcmds,
919: qsys->uuconf_pzpath, &ferr);
920: if (zabsolute == NULL && ! ferr)
921: {
922: const char *azcmds[2];
923:
924: /* If "uucp" is not a permitted command, then the forwarding
925: entries must be set. */
926: if (! fqforward (zfrom, qsys->uuconf_pzforward_from, "from", zmail)
927: || ! fqforward (zto, qsys->uuconf_pzforward_to, "to", zmail))
928: {
929: uqcleanup (zfile, iclean);
930: return;
931: }
932:
933: /* If "uucp" is not a permitted command, then only uucp
934: requests with a single source are permitted, since that
935: is all that will be generated by uucp or uux. */
936: if (fmany)
937: {
938: ulog (LOG_ERROR, "Bad uucp request %s", zQcmd);
939:
940: if (zmail != NULL && ! fQno_ack)
941: {
942: const char *az[20];
943:
944: i = 0;
945: az[i++] = "Your execution request failed because it was an";
946: az[i++] = " unsupported uucp request.\n";
947: az[i++] = "Execution requested was:\n\t";
948: az[i++] = zQcmd;
949: az[i++] = "\n";
950:
951: (void) fsysdep_mail (zmail, "Execution failed", i, az);
952: }
953:
954: uqcleanup (zfile, iclean);
955: return;
956: }
957:
958: azcmds[0] = "uucp";
959: azcmds[1] = NULL;
960: zabsolute = zsysdep_find_command ("uucp", (char **) azcmds,
961: qsys->uuconf_pzpath, &ferr);
962: }
963: if (zabsolute == NULL)
964: {
965: if (! ferr)
966: ulog (LOG_ERROR, "Can't find uucp executable");
967:
968: uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
969: *pfprocessed = FALSE;
970: return;
971: }
972: }
973: else
974: {
975: /* Get the pathname to execute. */
976: zabsolute = zsysdep_find_command (azQargs[0], qsys->uuconf_pzcmds,
977: qsys->uuconf_pzpath,
978: &ferr);
979: if (zabsolute == NULL)
980: {
981: if (ferr)
982: {
983: /* If we get an error, try again later. */
984: uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
985: *pfprocessed = FALSE;
986: return;
987: }
988:
989: /* Not permitted. Send mail to requestor. */
990: ulog (LOG_ERROR, "Not permitted to execute %s",
991: azQargs[0]);
992:
993: if (zmail != NULL && ! fQno_ack)
994: {
995: const char *az[20];
996:
997: i = 0;
998: az[i++] = "Your execution request failed because you are not";
999: az[i++] = " permitted to execute\n\t";
1000: az[i++] = azQargs[0];
1001: az[i++] = "\non this system.\n";
1002: az[i++] = "Execution requested was:\n\t";
1003: az[i++] = zQcmd;
1004: az[i++] = "\n";
1005:
1006: (void) fsysdep_mail (zmail, "Execution failed", i, az);
1007: }
1008:
1009: uqcleanup (zfile, iclean);
1010: return;
1011: }
1012: }
1013:
1014: ubuffree (azQargs[0]);
1015: azQargs[0] = zabsolute;
1016:
1017: for (i = 1; azQargs[i] != NULL; i++)
1018: {
1019: char *zlocal;
1020:
1021: zlocal = zsysdep_xqt_local_file (qsys, azQargs[i]);
1022: if (zlocal != NULL)
1023: {
1024: ubuffree (azQargs[i]);
1025: azQargs[i] = zlocal;
1026: }
1027: }
1028:
1029: #if ! ALLOW_FILENAME_ARGUMENTS
1030:
1031: /* Check all the arguments to make sure they don't try to specify
1032: files they are not permitted to access. */
1033: for (i = 1; azQargs[i] != NULL; i++)
1034: {
1035: if (! fsysdep_xqt_check_file (qsys, azQargs[i]))
1036: {
1037: if (zmail != NULL && ! fQno_ack)
1038: {
1039: const char *az[20];
1040: const char *zfailed;
1041:
1042: zfailed = azQargs[i];
1043: i = 0;
1044: az[i++] = "Your execution request failed because you are not";
1045: az[i++] = " permitted to refer to file\n\t";
1046: az[i++] = zfailed;
1047: az[i++] = "\non this system.\n";
1048: az[i++] = "Execution requested was:\n\t";
1049: az[i++] = zQcmd;
1050: az[i++] = "\n";
1051:
1052: (void) fsysdep_mail (zmail, "Execution failed", i, az);
1053: }
1054:
1055: uqcleanup (zfile, iclean);
1056: return;
1057: }
1058: }
1059:
1060: #endif /* ! ALLOW_FILENAME_ARGUMENTS */
1061:
1062: ulog (LOG_NORMAL, "Executing %s (%s)", zbase, zQcmd);
1063:
1064: if (zQinput != NULL)
1065: {
1066: boolean fspool;
1067: char *zreal;
1068:
1069: fspool = fspool_file (zQinput);
1070: if (fspool)
1071: zreal = zsysdep_spool_file_name (qsys, zQinput, (pointer) NULL);
1072: else
1073: zreal = zsysdep_local_file (zQinput, qsys->uuconf_zpubdir);
1074: if (zreal == NULL)
1075: {
1076: /* If we get an error, try again later. */
1077: uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
1078: *pfprocessed = FALSE;
1079: return;
1080: }
1081:
1082: zQinput = zreal;
1083: iclean |= FREE_QINPUT;
1084:
1085: if (! fspool
1086: && ! fin_directory_list (zQinput, qsys->uuconf_pzremote_send,
1087: qsys->uuconf_zpubdir, TRUE, TRUE,
1088: (const char *) NULL))
1089: {
1090: ulog (LOG_ERROR, "Not permitted to read %s", zQinput);
1091:
1092: if (zmail != NULL && ! fQno_ack)
1093: {
1094: const char *az[20];
1095:
1096: i = 0;
1097: az[i++] = "Your execution request failed because you are";
1098: az[i++] = " not permitted to read\n\t";
1099: az[i++] = zQinput;
1100: az[i++] = "\non this system.\n";
1101: az[i++] = "Execution requested was:\n\t";
1102: az[i++] = zQcmd;
1103: az[i++] = "\n";
1104:
1105: (void) fsysdep_mail (zmail, "Execution failed", i, az);
1106: }
1107:
1108: uqcleanup (zfile, iclean);
1109: return;
1110: }
1111: }
1112:
1113: zoutput = NULL;
1114: if (zQoutfile == NULL)
1115: qoutsys = NULL;
1116: else if (zQoutsys != NULL
1117: && strcmp (zQoutsys, zlocalname) != 0)
1118: {
1119: char *zdata;
1120:
1121: /* The output file is destined for some other system, so we must
1122: use a temporary file to catch standard output. */
1123: if (strcmp (zQoutsys, qsys->uuconf_zname) == 0)
1124: qoutsys = qsys;
1125: else
1126: {
1127: iuuconf = uuconf_system_info (puuconf, zQoutsys, &soutsys);
1128: if (iuuconf != UUCONF_SUCCESS)
1129: {
1130: if (iuuconf != UUCONF_NOT_FOUND)
1131: {
1132: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1133: uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
1134: *pfprocessed = FALSE;
1135: return;
1136: }
1137:
1138: if (! funknown_system (puuconf, zQoutsys, &soutsys))
1139: {
1140: ulog (LOG_ERROR,
1141: "Can't send standard output to unknown system %s",
1142: zQoutsys);
1143: /* We don't send mail to unknown systems, either.
1144: Maybe we should. */
1145: uqcleanup (zfile, iclean);
1146: return;
1147: }
1148: }
1149:
1150: qoutsys = &soutsys;
1151: }
1152:
1153: zdata = zsysdep_data_file_name (qoutsys, zlocalname,
1154: BDEFAULT_UUX_GRADE, FALSE, abtemp,
1155: abdata, (char *) NULL);
1156: if (zdata == NULL)
1157: {
1158: /* If we get an error, try again later. */
1159: uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
1160: *pfprocessed = FALSE;
1161: return;
1162: }
1163: zoutput = zdata;
1164: zQoutput = zoutput;
1165: iclean |= FREE_OUTPUT;
1166: }
1167: else
1168: {
1169: boolean fok;
1170:
1171: qoutsys = NULL;
1172:
1173: /* If we permitted the standard output to be redirected into
1174: the spool directory, people could set up phony commands. */
1175: if (fspool_file (zQoutfile))
1176: fok = FALSE;
1177: else
1178: {
1179: zoutput = zsysdep_local_file (zQoutfile, qsys->uuconf_zpubdir);
1180: if (zoutput == NULL)
1181: {
1182: /* If we get an error, try again later. */
1183: uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
1184: *pfprocessed = FALSE;
1185: return;
1186: }
1187: ubuffree (zQoutfile);
1188: zQoutfile = zoutput;
1189:
1190: /* Make sure it's OK to receive this file. */
1191: fok = fin_directory_list (zQoutfile,
1192: qsys->uuconf_pzremote_receive,
1193: qsys->uuconf_zpubdir, TRUE, FALSE,
1194: (const char *) NULL);
1195: }
1196:
1197: if (! fok)
1198: {
1199: ulog (LOG_ERROR, "Not permitted to write to %s", zQoutfile);
1200:
1201: if (zmail != NULL && ! fQno_ack)
1202: {
1203: const char *az[20];
1204:
1205: i = 0;
1206: az[i++] = "Your execution request failed because you are";
1207: az[i++] = " not permitted to write to\n\t";
1208: az[i++] = zQoutfile;
1209: az[i++] = "\non this system.\n";
1210: az[i++] = "Execution requested was:\n\t";
1211: az[i++] = zQcmd;
1212: az[i++] = "\n";
1213:
1214: (void) fsysdep_mail (zmail, "Execution failed", i, az);
1215: }
1216:
1217: uqcleanup (zfile, iclean);
1218: return;
1219: }
1220: }
1221:
1222: /* Move the required files to the execution directory if necessary. */
1223: zinput = zQinput;
1224: if (! fsysdep_move_uuxqt_files (cQfiles, (const char **) azQfiles,
1225: (const char **) azQfiles_to,
1226: TRUE, iQlock_seq, &zinput))
1227: {
1228: /* If we get an error, try again later. */
1229: uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
1230: *pfprocessed = FALSE;
1231: return;
1232: }
1233: if (zQinput != NULL && strcmp (zQinput, zinput) != 0)
1234: {
1235: if ((iclean & FREE_QINPUT) != 0)
1236: ubuffree (zQinput);
1237: zQinput = zinput;
1238: iclean |= FREE_QINPUT;
1239: }
1240:
1241: #if ALLOW_SH_EXECUTION
1242: fshell = fQuse_sh;
1243: #else
1244: fshell = FALSE;
1245: #endif
1246:
1247: /* Get a shell command which uses the full path of the command to
1248: execute. */
1249: clen = 0;
1250: for (i = 0; azQargs[i] != NULL; i++)
1251: clen += strlen (azQargs[i]) + 1;
1252: zfullcmd = zbufalc (clen);
1253: strcpy (zfullcmd, azQargs[0]);
1254: for (i = 1; azQargs[i] != NULL; i++)
1255: {
1256: strcat (zfullcmd, " ");
1257: strcat (zfullcmd, azQargs[i]);
1258: }
1259:
1260: if (! fsysdep_execute (qsys,
1261: zQuser == NULL ? (const char *) "uucp" : zQuser,
1262: (const char **) azQargs, zfullcmd, zQinput,
1263: zoutput, fshell, iQlock_seq, &zerror, &ftemp))
1264: {
1265: ubuffree (zfullcmd);
1266:
1267: if (ftemp)
1268: {
1269: ulog (LOG_NORMAL, "Will retry later (%s)", zbase);
1270: if (zoutput != NULL)
1271: (void) remove (zoutput);
1272: if (zerror != NULL)
1273: {
1274: (void) remove (zerror);
1275: ubuffree (zerror);
1276: }
1277: (void) fsysdep_move_uuxqt_files (cQfiles, (const char **) azQfiles,
1278: (const char **) azQfiles_to,
1279: FALSE, iQlock_seq,
1280: (char **) NULL);
1281: uqcleanup (zfile, iclean &~ (REMOVE_FILE | REMOVE_NEEDED));
1282: *pfprocessed = FALSE;
1283: return;
1284: }
1285:
1286: ulog (LOG_NORMAL, "Execution failed (%s)", zbase);
1287:
1288: if (zmail != NULL && ! fQno_ack)
1289: {
1290: const char **pz;
1291: int cgot;
1292: FILE *eerr;
1293: int istart;
1294:
1295: cgot = 20;
1296: pz = (const char **) xmalloc (cgot * sizeof (const char *));
1297: i = 0;
1298: pz[i++] = "Execution request failed:\n\t";
1299: pz[i++] = zQcmd;
1300: pz[i++] = "\n";
1301:
1302: if (zerror == NULL)
1303: eerr = NULL;
1304: else
1305: eerr = fopen (zerror, "r");
1306: if (eerr == NULL)
1307: {
1308: pz[i++] = "There was no output on standard error\n";
1309: istart = i;
1310: }
1311: else
1312: {
1313: char *zline;
1314: size_t cline;
1315:
1316: pz[i++] = "Standard error output was:\n";
1317: istart = i;
1318:
1319: zline = NULL;
1320: cline = 0;
1321: while (getline (&zline, &cline, eerr) > 0)
1322: {
1323: if (i >= cgot)
1324: {
1325: cgot += 20;
1326: pz = ((const char **)
1327: xrealloc ((pointer) pz,
1328: cgot * sizeof (const char *)));
1329: }
1330: pz[i++] = zbufcpy (zline);
1331: }
1332:
1333: (void) fclose (eerr);
1334: xfree ((pointer) zline);
1335: }
1336:
1337: (void) fsysdep_mail (zmail, "Execution failed", i, pz);
1338:
1339: for (; istart < i; istart++)
1340: ubuffree ((char *) pz[istart]);
1341: xfree ((pointer) pz);
1342: }
1343:
1344: if (qoutsys != NULL)
1345: (void) remove (zoutput);
1346: }
1347: else
1348: {
1349: ubuffree (zfullcmd);
1350:
1351: if (zmail != NULL && fQsuccess_ack)
1352: {
1353: const char *az[20];
1354:
1355: i = 0;
1356: az[i++] = "\nExecution request succeeded:\n\t";
1357: az[i++] = zQcmd;
1358: az[i++] = "\n";
1359:
1360: (void) fsysdep_mail (zmail, "Execution succeded", i, az);
1361: }
1362:
1363: /* Now we may have to uucp the output to some other machine. */
1364:
1365: if (qoutsys != NULL)
1366: {
1367: struct scmd s;
1368:
1369: /* Fill in the command structure. */
1370:
1371: s.bcmd = 'S';
1372: s.pseq = NULL;
1373: s.zfrom = abtemp;
1374: s.zto = zQoutfile;
1375: if (zQuser != NULL)
1376: s.zuser = zQuser;
1377: else
1378: s.zuser = "uucp";
1379: if (zmail != NULL && fQsuccess_ack)
1380: s.zoptions = "Cn";
1381: else
1382: s.zoptions = "C";
1383: s.ztemp = abtemp;
1384: s.imode = 0666;
1385: if (zmail != NULL && fQsuccess_ack)
1386: s.znotify = zmail;
1387: else
1388: s.znotify = "";
1389: s.cbytes = -1;
1390: s.zcmd = NULL;
1391: s.ipos = 0;
1392:
1393: ubuffree (zsysdep_spool_commands (qoutsys, BDEFAULT_UUX_GRADE,
1394: 1, &s));
1395: }
1396: }
1397:
1398: if (zerror != NULL)
1399: {
1400: (void) remove (zerror);
1401: ubuffree (zerror);
1402: }
1403:
1404: uqcleanup (zfile, iclean);
1405: }
1406:
1407: /* Clean up the results of uqdo_xqt_file. */
1408:
1409: static void
1410: uqcleanup (zfile, iflags)
1411: const char *zfile;
1412: int iflags;
1413: {
1414: int i;
1415:
1416: DEBUG_MESSAGE2 (DEBUG_SPOOLDIR,
1417: "uqcleanup: %s, %d", zfile, iflags);
1418:
1419: if (zQunlock_file != NULL)
1420: {
1421: (void) fsysdep_unlock_uuxqt_file (zQunlock_file);
1422: zQunlock_file = NULL;
1423: }
1424:
1425: if ((iflags & REMOVE_FILE) != 0)
1426: (void) remove (zfile);
1427:
1428: if ((iflags & REMOVE_NEEDED) != 0)
1429: {
1430: for (i = 0; i < cQfiles; i++)
1431: {
1432: if (azQfiles[i] != NULL)
1433: (void) remove (azQfiles[i]);
1434: }
1435: }
1436:
1437: if ((iflags & FREE_QINPUT) != 0)
1438: ubuffree (zQinput);
1439:
1440: if ((iflags & FREE_OUTPUT) != 0)
1441: ubuffree (zQoutput);
1442: if ((iflags & FREE_MAIL) != 0)
1443: ubuffree (zQmail);
1444:
1445: if (fQunlock_directory)
1446: {
1447: (void) fsysdep_unlock_uuxqt_dir (iQlock_seq);
1448: fQunlock_directory = FALSE;
1449: }
1450:
1451: for (i = 0; i < cQfiles; i++)
1452: {
1453: ubuffree (azQfiles[i]);
1454: ubuffree (azQfiles_to[i]);
1455: }
1456:
1457: ubuffree (zQoutfile);
1458: ubuffree (zQoutsys);
1459: ubuffree (zQrequestor);
1460:
1461: if (azQargs != NULL)
1462: {
1463: for (i = 0; azQargs[i] != NULL; i++)
1464: ubuffree (azQargs[i]);
1465: xfree ((pointer) azQargs);
1466: azQargs = NULL;
1467: }
1468:
1469: xfree ((pointer) zQcmd);
1470: zQcmd = NULL;
1471:
1472: xfree ((pointer) azQfiles);
1473: azQfiles = NULL;
1474:
1475: xfree ((pointer) azQfiles_to);
1476: azQfiles_to = NULL;
1477: }
1478:
1479: /* Check whether forwarding is permitted. */
1480:
1481: static boolean
1482: fqforward (zfile, pzallowed, zlog, zmail)
1483: const char *zfile;
1484: char **pzallowed;
1485: const char *zlog;
1486: const char *zmail;
1487: {
1488: const char *zexclam;
1489:
1490: zexclam = strchr (zfile, '!');
1491: if (zexclam != NULL)
1492: {
1493: size_t clen;
1494: char *zsys;
1495: boolean fret;
1496:
1497: clen = zexclam - zfile;
1498: zsys = zbufalc (clen + 1);
1499: memcpy (zsys, zfile, clen);
1500: zsys[clen] = '\0';
1501:
1502: fret = FALSE;
1503: if (pzallowed != NULL)
1504: {
1505: char **pz;
1506:
1507: for (pz = pzallowed; *pz != NULL; pz++)
1508: {
1509: if (strcmp (*pz, "ANY") == 0
1510: || strcmp (*pz, zsys) == 0)
1511: {
1512: fret = TRUE;
1513: break;
1514: }
1515: }
1516: }
1517:
1518: if (! fret)
1519: {
1520: ulog (LOG_ERROR, "Not permitted to forward %s %s (%s)",
1521: zlog, zsys, zQcmd);
1522:
1523: if (zmail != NULL && ! fQno_ack)
1524: {
1525: int i;
1526: const char *az[20];
1527:
1528: i = 0;
1529: az[i++] = "Your execution request failed because you are";
1530: az[i++] = " not permitted to forward files\n";
1531: az[i++] = zlog;
1532: az[i++] = " the system\n\t";
1533: az[i++] = zsys;
1534: az[i++] = "\n";
1535: az[i++] = "Execution requested was:\n\t";
1536: az[i++] = zQcmd;
1537: az[i++] = "\n";
1538:
1539: (void) fsysdep_mail (zmail, "Execution failed", i, az);
1540: }
1541: }
1542:
1543: ubuffree (zsys);
1544:
1545: return fret;
1546: }
1547:
1548: return TRUE;
1549: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.