|
|
1.1 root 1: /* uucp.c
2: Prepare to copy a file to or from a remote system.
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 uucp_rcsid[] = "$Id: uucp.c,v 1.1 93/07/30 07:58:25 bin Exp Locker: bin $";
30: #endif
31:
32: #include <ctype.h>
33: #include <errno.h>
34:
35: #include "getopt.h"
36:
37: #include "uudefs.h"
38: #include "uuconf.h"
39: #include "system.h"
40:
41: /* Local functions. */
42:
43: static void ucusage P((void));
44: static void ucdirfile P((const char *zdir, const char *zfile,
45: pointer pinfo));
46: static void uccopy P((const char *zfile, const char *zdest));
47: static void ucadd_cmd P((const struct uuconf_system *qsys,
48: const struct scmd *qcmd, const char *zlog));
49: static void ucspool_cmds P((boolean fjobid));
50: static const char *zcone_system P((boolean *pfany));
51: static void ucrecord_file P((const char *zfile));
52: static void ucabort P((void));
53:
54: /* The program name. */
55: char abProgram[] = "uucp";
56:
57: /* Long getopt options. */
58: static const struct option asClongopts[] = { { NULL, 0, NULL, 0 } };
59:
60: /* Local variables. There are a bunch of these, mostly set by the
61: options and the last (the destination) argument. These have file
62: scope so that they may be easily passed into uccopy; they could for
63: the most part also be wrapped up in a structure and passed in. */
64:
65: /* The uuconf global pointer. */
66: static pointer pCuuconf;
67:
68: /* TRUE if source files should be copied to the spool directory. */
69: static boolean fCcopy = TRUE;
70:
71: /* Grade to use. */
72: static char bCgrade = BDEFAULT_UUCP_GRADE;
73:
74: /* Whether to send mail to the requesting user when the copy is
75: complete. */
76: static boolean fCmail = FALSE;
77:
78: /* User to notify on remote system. */
79: static const char *zCnotify = "";
80:
81: /* TRUE if remote files should be prefixed with the current working
82: directory. */
83: static boolean fCexpand = TRUE;
84:
85: /* TRUE if necessary directories should be created on the destination
86: system. */
87: static boolean fCmkdirs = TRUE;
88:
89: /* Local name. */
90: static const char *zClocalname;
91:
92: /* User name. */
93: static const char *zCuser = NULL;
94:
95: /* TRUE if this is a remote request. */
96: static boolean fCremote = FALSE;
97:
98: /* TRUE if the destination is this system. */
99: static boolean fClocaldest;
100:
101: /* Destination system. */
102: static struct uuconf_system sCdestsys;
103:
104: /* Systems to forward to, if not NULL. */
105: static char *zCforward;
106:
107: /* Options to use when sending a file. */
108: static char abCsend_options[20];
109:
110: /* Options to use when receiving a file. */
111: static char abCrec_options[20];
112:
113: /* TRUE if the current file being copied from is in the cwd. */
114: static boolean fCneeds_cwd;
115:
116: /* The main program. */
117:
118: int
119: main (argc, argv)
120: int argc;
121: char **argv;
122: {
123: /* -I: configuration file name. */
124: const char *zconfig = NULL;
125: /* -j: output job id. */
126: boolean fjobid = FALSE;
127: /* -r: don't start uucico when finished. */
128: boolean fuucico = TRUE;
129: /* -R: copy directories recursively. */
130: boolean frecursive = FALSE;
131: /* -s: report status to named file. */
132: const char *zstatus_file = NULL;
133: /* -t: emulate uuto. */
134: boolean fuuto = FALSE;
135: int iopt;
136: pointer puuconf;
137: int iuuconf;
138: int i;
139: boolean fgetcwd;
140: char *zexclam;
141: char *zdestfile;
142: const char *zdestsys;
143: char *zoptions;
144: boolean fexit;
145:
146: while ((iopt = getopt_long (argc, argv, "cCdfg:I:jmn:prRs:tu:Wx:",
147: asClongopts, (int *) NULL)) != EOF)
148: {
149: switch (iopt)
150: {
151: case 'c':
152: /* Do not copy local files to spool directory. */
153: fCcopy = FALSE;
154: break;
155:
156: case 'p':
157: case 'C':
158: /* Copy local files to spool directory. */
159: fCcopy = TRUE;
160: break;
161:
162: case 'd':
163: /* Create directories if necessary. */
164: fCmkdirs = TRUE;
165: break;
166:
167: case 'f':
168: /* Do not create directories if they don't exist. */
169: fCmkdirs = FALSE;
170: break;
171:
172: case 'g':
173: /* Set job grade. */
174: bCgrade = optarg[0];
175: break;
176:
177: case 'I':
178: /* Name configuration file. */
179: if (fsysdep_other_config (optarg))
180: zconfig = optarg;
181: break;
182:
183: case 'j':
184: /* Output job id. */
185: fjobid = TRUE;
186: break;
187:
188: case 'm':
189: /* Mail to requesting user. */
190: fCmail = TRUE;
191: break;
192:
193: case 'n':
194: /* Notify remote user. */
195: zCnotify = optarg;
196: break;
197:
198: case 'r':
199: /* Don't start uucico when finished. */
200: fuucico = FALSE;
201: break;
202:
203: case 'R':
204: /* Copy directories recursively. */
205: frecursive = TRUE;
206: break;
207:
208: case 's':
209: /* Report status to named file. */
210: zstatus_file = optarg;
211: break;
212:
213: case 't':
214: /* Emulate uuto. */
215: fuuto = TRUE;
216: break;
217:
218: case 'u':
219: /* Set user name. */
220: zCuser = optarg;
221: break;
222:
223: case 'W':
224: /* Expand only local file names. */
225: fCexpand = FALSE;
226: break;
227:
228: case 'x':
229: #if DEBUG > 1
230: /* Set debugging level. */
231: iDebug |= idebug_parse (optarg);
232: #endif
233: break;
234:
235: case 0:
236: /* Long option found and flag set. */
237: break;
238:
239: default:
240: ucusage ();
241: break;
242: }
243: }
244:
245: if (! UUCONF_GRADE_LEGAL (bCgrade))
246: {
247: ulog (LOG_ERROR, "Ignoring illegal grade");
248: bCgrade = BDEFAULT_UUCP_GRADE;
249: }
250:
251: /* The user name must contain a '!', which is treated as a remote
252: name, to avoid spoofing of other users (there is no advantage to
253: spoofing remote users, except to send them random bits of mail,
254: which you can do anyhow). */
255: if (zCuser != NULL)
256: {
257: if (strchr (zCuser, '!') != NULL)
258: fCremote = TRUE;
259: else
260: {
261: ulog (LOG_ERROR, "Ignoring local user name");
262: zCuser = NULL;
263: }
264: }
265:
266: if (argc - optind < 2)
267: ucusage ();
268:
269: iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig);
270: if (iuuconf != UUCONF_SUCCESS)
271: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
272: pCuuconf = puuconf;
273:
274: #if DEBUG > 1
275: {
276: const char *zdebug;
277:
278: iuuconf = uuconf_debuglevel (puuconf, &zdebug);
279: if (iuuconf != UUCONF_SUCCESS)
280: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
281: if (zdebug != NULL)
282: iDebug |= idebug_parse (zdebug);
283: }
284: #endif
285:
286: /* See if we are going to need to know the current directory. We
287: just check each argument to see whether it's an absolute
288: pathname. We actually aren't going to need the cwd if fCexpand
289: is FALSE and the file is remote, but so what. */
290: fgetcwd = FALSE;
291: for (i = optind; i < argc; i++)
292: {
293: zexclam = strrchr (argv[i], '!');
294: if (zexclam == NULL)
295: zexclam = argv[i];
296: else
297: ++zexclam;
298: if (fsysdep_needs_cwd (zexclam))
299: {
300: fgetcwd = TRUE;
301: break;
302: }
303: }
304:
305: #ifdef SIGINT
306: usysdep_signal (SIGINT);
307: #endif
308: #ifdef SIGHUP
309: usysdep_signal (SIGHUP);
310: #endif
311: #ifdef SIGQUIT
312: usysdep_signal (SIGQUIT);
313: #endif
314: #ifdef SIGTERM
315: usysdep_signal (SIGTERM);
316: #endif
317: #ifdef SIGPIPE
318: usysdep_signal (SIGPIPE);
319: #endif
320:
321: usysdep_initialize (puuconf, INIT_SUID | (fgetcwd ? INIT_GETCWD : 0));
322:
323: ulog_fatal_fn (ucabort);
324:
325: if (zCuser == NULL)
326: zCuser = zsysdep_login_name ();
327:
328: iuuconf = uuconf_localname (puuconf, &zClocalname);
329: if (iuuconf == UUCONF_NOT_FOUND)
330: {
331: zClocalname = zsysdep_localname ();
332: if (zClocalname == NULL)
333: exit (EXIT_FAILURE);
334: }
335: else if (iuuconf != UUCONF_SUCCESS)
336: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
337:
338: /* If we are emulating uuto, translate the destination argument, and
339: notify the destination user. This had better not turn into
340: something that requires the current directory, or we may have
341: passed INIT_GETCWD incorrectly. */
342: if (fuuto)
343: {
344: if (*zCnotify == '\0')
345: {
346: zexclam = strrchr (argv[argc - 1], '!');
347: if (zexclam == NULL)
348: ucusage ();
349: zCnotify = zexclam + 1;
350: }
351: argv[argc - 1] = zsysdep_uuto (argv[argc - 1], zClocalname);
352: if (argv[argc - 1] == NULL)
353: ucusage ();
354: }
355:
356: /* Set up the file transfer options. */
357: zoptions = abCsend_options;
358: if (fCcopy)
359: *zoptions++ = 'C';
360: else
361: *zoptions++ = 'c';
362: if (fCmkdirs)
363: *zoptions++ = 'd';
364: else
365: *zoptions++ = 'f';
366: if (fCmail)
367: *zoptions++ = 'm';
368: if (*zCnotify != '\0')
369: *zoptions++ = 'n';
370: *zoptions = '\0';
371:
372: zoptions = abCrec_options;
373: if (fCmkdirs)
374: *zoptions++ = 'd';
375: else
376: *zoptions++ = 'f';
377: if (fCmail)
378: *zoptions++ = 'm';
379: *zoptions = '\0';
380:
381: zexclam = strchr (argv[argc - 1], '!');
382: if (zexclam == NULL)
383: {
384: zdestsys = zClocalname;
385: zdestfile = argv[argc - 1];
386: fClocaldest = TRUE;
387: }
388: else
389: {
390: size_t clen;
391: char *zcopy;
392:
393: clen = zexclam - argv[argc - 1];
394: zcopy = zbufalc (clen + 1);
395: memcpy (zcopy, argv[argc - 1], clen);
396: zcopy[clen] = '\0';
397: zdestsys = zcopy;
398:
399: zdestfile = zexclam + 1;
400:
401: fClocaldest = FALSE;
402: }
403:
404: iuuconf = uuconf_system_info (puuconf, zdestsys, &sCdestsys);
405: if (iuuconf != UUCONF_SUCCESS)
406: {
407: if (iuuconf != UUCONF_NOT_FOUND)
408: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
409: if (fClocaldest)
410: {
411: iuuconf = uuconf_system_local (puuconf, &sCdestsys);
412: if (iuuconf != UUCONF_SUCCESS)
413: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
414: sCdestsys.uuconf_zname = (char *) zClocalname;
415: }
416: else
417: {
418: if (! funknown_system (puuconf, zdestsys, &sCdestsys))
419: ulog (LOG_FATAL, "%s: System not found", zdestsys);
420: }
421: }
422:
423: /* Here zdestfile is the destination file name following the
424: destination system name (if any); it may contain other systems to
425: forward the files through. Isolate the file from the list of
426: systems. */
427: zexclam = strrchr (zdestfile, '!');
428: if (zexclam == NULL)
429: zCforward = NULL;
430: else
431: {
432: size_t clen;
433:
434: #if DEBUG > 0
435: if (fClocaldest)
436: ulog (LOG_FATAL, "Can't happen");
437: #endif
438: clen = zexclam - zdestfile;
439: zCforward = zbufalc (clen + 1);
440: memcpy (zCforward, zdestfile, clen);
441: zCforward[clen] = '\0';
442: zdestfile = zexclam + 1;
443: }
444:
445: /* Turn the destination into an absolute path, unless it is on a
446: remote system and -W was used. */
447: if (fClocaldest)
448: zdestfile = zsysdep_local_file_cwd (zdestfile, sCdestsys.uuconf_zpubdir);
449: else if (fCexpand)
450: zdestfile = zsysdep_add_cwd (zdestfile);
451: if (zdestfile == NULL)
452: {
453: ulog_close ();
454: usysdep_exit (FALSE);
455: }
456:
457: /* Process each source argument. */
458: for (i = optind; i < argc - 1 && ! FGOT_SIGNAL (); i++)
459: {
460: boolean flocal;
461: char *zfrom;
462:
463: fCneeds_cwd = FALSE;
464:
465: if (strchr (argv[i], '!') != NULL)
466: {
467: flocal = FALSE;
468: zfrom = zbufcpy (argv[i]);
469: }
470: else
471: {
472: /* This is a local file. Make sure we get it out of the
473: original directory. We don't support local wildcards,
474: leaving that to the shell. */
475: flocal = TRUE;
476: if (fsysdep_needs_cwd (argv[i]))
477: fCneeds_cwd = TRUE;
478: zfrom = zsysdep_local_file_cwd (argv[i],
479: sCdestsys.uuconf_zpubdir);
480: if (zfrom == NULL)
481: ucabort ();
482: }
483:
484: if (! flocal || ! fsysdep_directory (zfrom))
485: uccopy (zfrom, zdestfile);
486: else
487: {
488: char *zbase, *zindir;
489:
490: if (! frecursive)
491: ulog (LOG_FATAL, "%s: directory without -R", zfrom);
492:
493: zbase = zsysdep_base_name (zfrom);
494: if (zbase == NULL)
495: ucabort ();
496: zindir = zsysdep_in_dir (zdestfile, zbase);
497: ubuffree (zbase);
498: if (zindir == NULL)
499: ucabort ();
500: usysdep_walk_tree (zfrom, ucdirfile, zindir);
501: ubuffree (zindir);
502: }
503:
504: ubuffree (zfrom);
505: }
506:
507: /* See if we got an interrupt, presumably from the user. */
508: if (FGOT_SIGNAL ())
509: ucabort ();
510:
511: /* Now push out the actual commands, making log entries for them. */
512: ulog_to_file (puuconf, TRUE);
513: ulog_user (zCuser);
514:
515: ucspool_cmds (fjobid);
516:
517: ulog_close ();
518:
519: if (! fuucico)
520: fexit = TRUE;
521: else
522: {
523: const char *zsys;
524: boolean fany;
525:
526: zsys = zcone_system (&fany);
527: if (zsys != NULL)
528: fexit = fsysdep_run ("uucico", "-s", zsys);
529: else if (fany)
530: fexit = fsysdep_run ("uucico", "-r1", (const char *) NULL);
531: else
532: fexit = TRUE;
533: }
534:
535: usysdep_exit (fexit);
536:
537: /* Avoid error about not returning. */
538: return 0;
539: }
540:
541: static void
542: ucusage ()
543: {
544: fprintf (stderr,
545: "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
546: VERSION);
547: fprintf (stderr,
548: "Usage: uucp [options] file1 [file2 ...] dest\n");
549: fprintf (stderr,
550: " -c: Do not copy local files to spool directory\n");
551: fprintf (stderr,
552: " -C, -p: Copy local files to spool directory (default)\n");
553: fprintf (stderr,
554: " -d: Create necessary directories (default)\n");
555: fprintf (stderr,
556: " -f: Do not create directories (fail if they do not exist)\n");
557: fprintf (stderr,
558: " -g grade: Set job grade (must be alphabetic)\n");
559: fprintf (stderr,
560: " -m: Report status of copy by mail\n");
561: fprintf (stderr,
562: " -n user: Report status of copy by mail to remote user\n");
563: fprintf (stderr,
564: " -R: Copy directories recursively\n");
565: fprintf (stderr,
566: " -r: Do not start uucico daemon\n");
567: fprintf (stderr,
568: " -s file: Report completion status to file\n");
569: fprintf (stderr,
570: " -j: Report job id\n");
571: fprintf (stderr,
572: " -W: Do not add current directory to remote filenames\n");
573: fprintf (stderr,
574: " -t: Emulate uuto\n");
575: fprintf (stderr,
576: " -u name: Set user name\n");
577: fprintf (stderr,
578: " -x debug: Set debugging level\n");
579: #if HAVE_TAYLOR_CONFIG
580: fprintf (stderr,
581: " -I file: Set configuration file to use\n");
582: #endif /* HAVE_TAYLOR_CONFIG */
583: exit (EXIT_FAILURE);
584: }
585:
586: /* This is called for each file in a directory heirarchy. */
587:
588: static void
589: ucdirfile (zfull, zrelative, pinfo)
590: const char *zfull;
591: const char *zrelative;
592: pointer pinfo;
593: {
594: const char *zdestfile = (const char *) pinfo;
595: char *zto;
596:
597: zto = zsysdep_in_dir (zdestfile, zrelative);
598: if (zto == NULL)
599: ucabort ();
600:
601: uccopy (zfull, zto);
602:
603: ubuffree (zto);
604: }
605:
606: /* Handle the copying of one regular file. The zdest argument is the
607: destination file; if we are recursively copying a directory, it
608: will be extended by any subdirectory names. Note that zdest is an
609: absolute path. */
610:
611: static void
612: uccopy (zfile, zdest)
613: const char *zfile;
614: const char *zdest;
615: {
616: struct scmd s;
617: char *zexclam;
618: char *zto;
619:
620: zexclam = strchr (zfile, '!');
621:
622: if (zexclam == NULL)
623: {
624: openfile_t efrom;
625:
626: /* Copy from a local file. Make sure the user has access to
627: this file, since we are running setuid. */
628: if (! fsysdep_access (zfile))
629: ucabort ();
630:
631: /* If this copy is being requested by a remote system, we may
632: transfer the file if it needs the current working directory
633: (meaning, I hope, that it is in the execution directory) or
634: it is on the permitted transfer list. Note that unlike most
635: of the other checks, this one is not double-checked by
636: uucico. */
637: if (fCremote
638: && ! fCneeds_cwd
639: && ! fin_directory_list (zfile, sCdestsys.uuconf_pzremote_send,
640: sCdestsys.uuconf_zpubdir, TRUE,
641: TRUE, (const char *) NULL))
642: ulog (LOG_FATAL, "Not permitted to send %s", zfile);
643:
644: if (fClocaldest)
645: {
646: boolean fok;
647:
648: /* Copy one local file to another. */
649:
650: /* Check that we have permission to receive into the desired
651: directory. */
652: if (fCremote)
653: fok = fin_directory_list (zdest,
654: sCdestsys.uuconf_pzremote_receive,
655: sCdestsys.uuconf_zpubdir, TRUE,
656: FALSE, (const char *) NULL);
657: else
658: fok = fin_directory_list (zdest,
659: sCdestsys.uuconf_pzlocal_receive,
660: sCdestsys.uuconf_zpubdir, TRUE,
661: FALSE, zCuser);
662: if (! fok)
663: ulog (LOG_FATAL, "Not permitted to receive to %s", zdest);
664:
665: zto = zsysdep_add_base (zdest, zfile);
666: if (zto == NULL)
667: ucabort ();
668:
669: efrom = esysdep_user_fopen (zfile, TRUE, TRUE);
670: if (! ffileisopen (efrom))
671: ucabort ();
672: if (! fcopy_open_file (efrom, zto, FALSE, fCmkdirs))
673: ucabort ();
674: (void) ffileclose (efrom);
675: ubuffree (zto);
676: }
677: else
678: {
679: const char *zloc;
680: char abtname[CFILE_NAME_LEN];
681: unsigned int imode;
682: char *ztemp;
683:
684: /* Copy a local file to a remote file. We may have to
685: copy the local file to the spool directory. */
686: imode = ixsysdep_file_mode (zfile);
687: if (imode == 0)
688: ucabort ();
689:
690: zloc = sCdestsys.uuconf_zlocalname;
691: if (zloc == NULL)
692: zloc = zClocalname;
693:
694: ztemp = zsysdep_data_file_name (&sCdestsys, zloc, bCgrade,
695: FALSE, abtname, (char *) NULL,
696: (char *) NULL);
697: if (ztemp == NULL)
698: ucabort ();
699:
700: if (! fCcopy)
701: {
702: /* If we are copying the file, we don't actually use the
703: temporary file; we still want to get a name for the
704: other system to use as a key for file restart. */
705: ubuffree (ztemp);
706:
707: /* Make sure the daemon will be permitted to send
708: this file. */
709: if (! fsysdep_daemon_access (zfile))
710: ucabort ();
711: if (! fin_directory_list (zfile, sCdestsys.uuconf_pzlocal_send,
712: sCdestsys.uuconf_zpubdir, TRUE, TRUE,
713: (fCremote
714: ? (const char *) NULL
715: : zCuser)))
716: ulog (LOG_FATAL, "Not permitted to send %s", zfile);
717: }
718: else
719: {
720: efrom = esysdep_user_fopen (zfile, TRUE, TRUE);
721: if (! ffileisopen (efrom))
722: ucabort ();
723: ucrecord_file (ztemp);
724: if (! fcopy_open_file (efrom, ztemp, FALSE, TRUE))
725: ucabort ();
726: (void) ffileclose (efrom);
727: }
728:
729: if (zCforward == NULL)
730: {
731: /* We're not forwarding. Just send the file. */
732: s.bcmd = 'S';
733: s.pseq = NULL;
734: s.zfrom = zbufcpy (zfile);
735: s.zto = zbufcpy (zdest);
736: s.zuser = zCuser;
737: s.zoptions = abCsend_options;
738: s.ztemp = zbufcpy (abtname);
739: s.imode = imode;
740: s.znotify = zCnotify;
741: s.cbytes = -1;
742: s.zcmd = NULL;
743: s.ipos = 0;
744:
745: ucadd_cmd (&sCdestsys, &s, (const char *) NULL);
746: }
747: else
748: {
749: char *zbase;
750: char *zxqt;
751: char abxtname[CFILE_NAME_LEN];
752: char abdname[CFILE_NAME_LEN];
753: char abxname[CFILE_NAME_LEN];
754: FILE *e;
755: char *zlog;
756:
757: /* We want to forward this file through sCdestsys to
758: some other system(s). We set up a remote execution
759: of uucp on sCdestsys to forward the file along. */
760: zbase = zsysdep_base_name (zfile);
761: if (zbase == NULL)
762: ucabort ();
763:
764: zxqt = zsysdep_data_file_name (&sCdestsys, zloc, bCgrade,
765: TRUE, abxtname, abdname,
766: abxname);
767: if (zxqt == NULL)
768: ucabort ();
769: e = esysdep_fopen (zxqt, FALSE, FALSE, TRUE);
770: if (e == NULL)
771: ucabort ();
772: ucrecord_file (zxqt);
773:
774: fprintf (e, "U %s %s\n", zCuser, zloc);
775: fprintf (e, "F %s %s\n", abdname, zbase);
776: fprintf (e, "C uucp -C");
777: if (fCmkdirs)
778: fprintf (e, " -d");
779: else
780: fprintf (e, " -f");
781: fprintf (e, " -g %c", bCgrade);
782: if (fCmail)
783: fprintf (e, " -m");
784: if (*zCnotify != '\0')
785: fprintf (e, " -n %s", zCnotify);
786: if (! fCexpand)
787: fprintf (e, " -W");
788: fprintf (e, " %s %s!%s\n", zbase, zCforward, zdest);
789:
790: ubuffree (zbase);
791:
792: if (fclose (e) != 0)
793: ulog (LOG_FATAL, "fclose: %s", strerror (errno));
794:
795: /* Send the execution file. */
796: s.bcmd = 'S';
797: s.pseq = NULL;
798: s.zfrom = zbufcpy (abxtname);
799: s.zto = zbufcpy (abxname);
800: s.zuser = zCuser;
801: s.zoptions = "C";
802: s.ztemp = s.zfrom;
803: s.imode = 0666;
804: s.znotify = NULL;
805: s.cbytes = -1;
806: s.zcmd = NULL;
807: s.ipos = 0;
808:
809: zlog = zbufalc (sizeof "Queuing uucp !" + strlen (zfile)
810: + strlen (zCforward) + strlen (zdest));
811: sprintf (zlog, "Queuing uucp %s %s!%s", zfile, zCforward,
812: zdest);
813:
814: ucadd_cmd (&sCdestsys, &s, zlog);
815:
816: /* Send the data file. */
817: s.bcmd = 'S';
818: s.pseq = NULL;
819: s.zfrom = zbufcpy (zfile);
820: s.zto = zbufcpy (abdname);
821: s.zuser = zCuser;
822: s.zoptions = fCcopy ? "C" : "c";
823: s.ztemp = zbufcpy (abtname);
824: s.imode = 0666;
825: s.znotify = NULL;
826: s.cbytes = -1;
827: s.zcmd = NULL;
828: s.ipos = 0;
829:
830: ucadd_cmd (&sCdestsys, &s, "");
831: }
832: }
833: }
834: else
835: {
836: char *zfrom;
837: char *zforward;
838: size_t clen;
839: char *zcopy;
840: struct uuconf_system *qfromsys;
841: int iuuconf;
842: const char *zloc;
843:
844: /* Copy from a remote file. Get the file name after any systems
845: we may need to forward the file from. */
846: zfrom = strrchr (zfile, '!');
847: if (zfrom == zexclam)
848: zforward = NULL;
849: else
850: {
851: clen = zfrom - zexclam - 1;
852: zforward = zbufalc (clen + 1);
853: memcpy (zforward, zexclam + 1, clen);
854: }
855:
856: ++zfrom;
857: if (fCexpand)
858: {
859: /* Add the current directory to the filename if it's not
860: already there. */
861: zfrom = zsysdep_add_cwd (zfrom);
862: if (zfrom == NULL)
863: ucabort ();
864: }
865:
866: /* Read the system information. */
867: clen = zexclam - zfile;
868: zcopy = zbufalc (clen + 1);
869: memcpy (zcopy, zfile, clen);
870: zcopy[clen] = '\0';
871:
872: qfromsys = ((struct uuconf_system *)
873: xmalloc (sizeof (struct uuconf_system)));
874:
875: iuuconf = uuconf_system_info (pCuuconf, zcopy, qfromsys);
876: if (iuuconf == UUCONF_NOT_FOUND)
877: {
878: if (! funknown_system (pCuuconf, zcopy, qfromsys))
879: ulog (LOG_FATAL, "%s: System not found", zcopy);
880: }
881: else if (iuuconf != UUCONF_SUCCESS)
882: ulog_uuconf (LOG_FATAL, pCuuconf, iuuconf);
883: ubuffree (zcopy);
884:
885: zloc = qfromsys->uuconf_zlocalname;
886: if (zloc == NULL)
887: zloc = zClocalname;
888:
889: if (zforward == NULL && fClocaldest)
890: {
891: boolean fok;
892:
893: /* The file is to come directly from qfromsys to the local
894: system. */
895:
896: /* Check that we have permission to receive into the desired
897: directory. If we don't have permission, uucico will
898: fail. */
899: if (fCremote)
900: fok = fin_directory_list (zdest,
901: qfromsys->uuconf_pzremote_receive,
902: qfromsys->uuconf_zpubdir, TRUE,
903: FALSE, (const char *) NULL);
904: else
905: fok = fin_directory_list (zdest,
906: qfromsys->uuconf_pzlocal_receive,
907: qfromsys->uuconf_zpubdir, TRUE,
908: FALSE, zCuser);
909: if (! fok)
910: ulog (LOG_FATAL, "Not permitted to receive to %s", zdest);
911:
912: /* If the remote filespec is wildcarded, we must generate an
913: 'X' request. We currently check for Unix shell
914: wildcards. Note that it should do no harm to mistake a
915: non-wildcard for a wildcard. */
916: if (zfrom[strcspn (zfrom, "*?[")] != '\0')
917: {
918: s.bcmd = 'X';
919: zto = zbufalc (strlen (zloc) + strlen (zdest) + sizeof "!");
920: sprintf (zto, "%s!%s", zloc, zdest);
921: }
922: else
923: {
924: s.bcmd = 'R';
925: zto = zbufcpy (zdest);
926: }
927:
928: s.pseq = NULL;
929: s.zfrom = zfrom;
930: s.zto = zto;
931: s.zuser = zCuser;
932: s.zoptions = abCrec_options;
933: s.ztemp = "";
934: s.imode = 0;
935: s.znotify = "";
936: s.cbytes = -1;
937: s.zcmd = NULL;
938: s.ipos = 0;
939:
940: ucadd_cmd (qfromsys, &s, (const char *) NULL);
941: }
942: else
943: {
944: char *zxqt;
945: char abtname[CFILE_NAME_LEN];
946: char abxname[CFILE_NAME_LEN];
947: FILE *e;
948: char *zcmd;
949: char *zlog;
950:
951: /* The file either comes from some other system through
952: qfromsys or is intended for some other system. Send an
953: execution request to qfromsys to handle everything. */
954: zxqt = zsysdep_data_file_name (qfromsys, zloc, bCgrade, TRUE,
955: abtname, (char *) NULL,
956: abxname);
957: if (zxqt == NULL)
958: ucabort ();
959: e = esysdep_fopen (zxqt, FALSE, FALSE, TRUE);
960: if (e == NULL)
961: ucabort ();
962: ucrecord_file (zxqt);
963:
964: fprintf (e, "U %s %s\n", zCuser, zloc);
965: fprintf (e, "C uucp -C");
966: if (fCmkdirs)
967: fprintf (e, " -d");
968: else
969: fprintf (e, " -f");
970: fprintf (e, " -g %c", bCgrade);
971: if (fCmail)
972: fprintf (e, " -m");
973: if (*zCnotify != '\0')
974: fprintf (e, " -n %s", zCnotify);
975: if (! fCexpand)
976: fprintf (e, " -W");
977:
978: clen = (strlen (zfrom) + strlen (zloc)
979: + strlen (sCdestsys.uuconf_zname) + strlen (zdest));
980: if (zforward != NULL)
981: clen += strlen (zforward);
982: if (zCforward != NULL)
983: clen += strlen (zCforward);
984: zcmd = zbufalc (sizeof "! !!!" + clen);
985: *zcmd = '\0';
986: if (zforward != NULL)
987: sprintf (zcmd + strlen (zcmd), "%s!", zforward);
988: sprintf (zcmd + strlen (zcmd), "%s %s!", zfrom, zloc);
989: if (! fClocaldest)
990: sprintf (zcmd + strlen (zcmd), "%s!", sCdestsys.uuconf_zname);
991: if (zCforward != NULL)
992: sprintf (zcmd + strlen (zcmd), "%s!", zCforward);
993: sprintf (zcmd + strlen (zcmd), "%s", zdest);
994:
995: fprintf (e, " %s\n", zcmd);
996:
997: if (fclose (e) != 0)
998: ulog (LOG_FATAL, "fclose: %s", strerror (errno));
999:
1000: /* Send the execution file. */
1001: s.bcmd = 'S';
1002: s.pseq = NULL;
1003: s.zfrom = zbufcpy (abtname);
1004: s.zto = zbufcpy (abxname);
1005: s.zuser = zCuser;
1006: s.zoptions = "C";
1007: s.ztemp = s.zfrom;
1008: s.imode = 0666;
1009: s.znotify = NULL;
1010: s.cbytes = -1;
1011: s.zcmd = NULL;
1012: s.ipos = 0;
1013:
1014: zlog = zbufalc (sizeof "Queueing uucp " + strlen (zcmd));
1015: sprintf (zlog, "Queueing uucp %s", zcmd);
1016:
1017: ucadd_cmd (qfromsys, &s, zlog);
1018:
1019: ubuffree (zcmd);
1020: ubuffree (zforward);
1021: }
1022: }
1023: }
1024:
1025: /* We keep a list of jobs for each system. */
1026:
1027: struct sjob
1028: {
1029: struct sjob *qnext;
1030: const struct uuconf_system *qsys;
1031: int ccmds;
1032: struct scmd *pascmds;
1033: const char **pazlogs;
1034: };
1035:
1036: static struct sjob *qCjobs;
1037:
1038: static void
1039: ucadd_cmd (qsys, qcmd, zlog)
1040: const struct uuconf_system *qsys;
1041: const struct scmd *qcmd;
1042: const char *zlog;
1043: {
1044: struct sjob *qjob;
1045:
1046: if (! qsys->uuconf_fcall_transfer
1047: && ! qsys->uuconf_fcalled_transfer)
1048: ulog (LOG_FATAL, "Not permitted to transfer files to or from %s",
1049: qsys->uuconf_zname);
1050:
1051: for (qjob = qCjobs; qjob != NULL; qjob = qjob->qnext)
1052: if (strcmp (qjob->qsys->uuconf_zname, qsys->uuconf_zname) == 0)
1053: break;
1054:
1055: if (qjob == NULL)
1056: {
1057: qjob = (struct sjob *) xmalloc (sizeof (struct sjob));
1058: qjob->qnext = qCjobs;
1059: qjob->qsys = qsys;
1060: qjob->ccmds = 0;
1061: qjob->pascmds = NULL;
1062: qjob->pazlogs = NULL;
1063: qCjobs = qjob;
1064: }
1065:
1066: qjob->pascmds = ((struct scmd *)
1067: xrealloc ((pointer) qjob->pascmds,
1068: (qjob->ccmds + 1) * sizeof (struct scmd)));
1069: qjob->pascmds[qjob->ccmds] = *qcmd;
1070: qjob->pazlogs = ((const char **)
1071: xrealloc ((pointer) qjob->pazlogs,
1072: (qjob->ccmds + 1) * sizeof (const char *)));
1073: qjob->pazlogs[qjob->ccmds] = zlog;
1074: ++qjob->ccmds;
1075: }
1076:
1077: static void
1078: ucspool_cmds (fjobid)
1079: boolean fjobid;
1080: {
1081: struct sjob *qjob;
1082: char *zjobid;
1083:
1084: for (qjob = qCjobs; qjob != NULL; qjob = qjob->qnext)
1085: {
1086: ulog_system (qjob->qsys->uuconf_zname);
1087: zjobid = zsysdep_spool_commands (qjob->qsys, bCgrade, qjob->ccmds,
1088: qjob->pascmds);
1089: if (zjobid != NULL)
1090: {
1091: int i;
1092: struct scmd *qcmd;
1093: const char **pz;
1094:
1095: for (i = 0, qcmd = qjob->pascmds, pz = qjob->pazlogs;
1096: i < qjob->ccmds;
1097: i++, qcmd++, pz++)
1098: {
1099: if (*pz != NULL)
1100: {
1101: if (**pz != '\0')
1102: ulog (LOG_NORMAL, "%s", *pz);
1103: }
1104: else if (qcmd->bcmd == 'S')
1105: ulog (LOG_NORMAL, "Queuing send of %s to %s",
1106: qcmd->zfrom, qcmd->zto);
1107: else if (qcmd->bcmd == 'R')
1108: ulog (LOG_NORMAL, "Queuing request of %s to %s",
1109: qcmd->zfrom, qcmd->zto);
1110: else
1111: {
1112: const char *zto;
1113:
1114: zto = strrchr (qcmd->zto, '!');
1115: if (zto != NULL)
1116: ++zto;
1117: else
1118: zto = qcmd->zto;
1119: ulog (LOG_NORMAL, "Queuing request of %s to %s",
1120: qcmd->zfrom, zto);
1121: }
1122: }
1123:
1124: if (fjobid)
1125: printf ("%s\n", zjobid);
1126:
1127: ubuffree (zjobid);
1128: }
1129: }
1130: }
1131:
1132: /* Return the system name for which we have created commands, or NULL
1133: if we've created commands for more than one system. Set *pfany to
1134: FALSE if we didn't create work for any system. */
1135:
1136: static const char *
1137: zcone_system (pfany)
1138: boolean *pfany;
1139: {
1140: if (qCjobs == NULL)
1141: {
1142: *pfany = FALSE;
1143: return NULL;
1144: }
1145:
1146: *pfany = TRUE;
1147:
1148: if (qCjobs->qnext == NULL)
1149: return qCjobs->qsys->uuconf_zname;
1150: else
1151: return NULL;
1152: }
1153:
1154: /* Keep track of all files we have created so that we can delete them
1155: if we get a signal. The argument will be on the heap. */
1156:
1157: static int cCfiles;
1158: static const char **pCaz;
1159:
1160: static void
1161: ucrecord_file (zfile)
1162: const char *zfile;
1163: {
1164: pCaz = (const char **) xrealloc ((pointer) pCaz,
1165: (cCfiles + 1) * sizeof (const char *));
1166: pCaz[cCfiles] = zfile;
1167: ++cCfiles;
1168: }
1169:
1170: /* Delete all the files we have recorded and exit. */
1171:
1172: static void
1173: ucabort ()
1174: {
1175: int i;
1176:
1177: for (i = 0; i < cCfiles; i++)
1178: (void) remove (pCaz[i]);
1179: ulog_close ();
1180: usysdep_exit (FALSE);
1181: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.