|
|
1.1 root 1: /* uucico.c
2: This is the main UUCP communication 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 uucico_rcsid[] = "$Id: uucico.c,v 1.1 93/07/30 07:54:34 bin Exp Locker: bin $";
30: #endif
31:
32: #include <ctype.h>
33:
34: #if HAVE_LIMITS_H
35: #include <limits.h>
36: #else
37: #define LONG_MAX 2147483647L
38: #endif
39:
40: #include "getopt.h"
41:
42: #include "uudefs.h"
43: #include "uuconf.h"
44: #include "conn.h"
45: #include "prot.h"
46: #include "trans.h"
47: #include "system.h"
48:
49: /* The program name. */
50: char abProgram[] = "uucico";
51:
52: /* Define the known protocols. */
53:
54: #define TCP_PROTO \
55: (UUCONF_RELIABLE_ENDTOEND \
56: | UUCONF_RELIABLE_RELIABLE \
57: | UUCONF_RELIABLE_EIGHT)
58:
59: static const struct sprotocol asProtocols[] =
60: {
61: { 't', TCP_PROTO, 1,
62: asTproto_params, ftstart, ftshutdown, ftsendcmd, ztgetspace,
63: ftsenddata, ftwait, ftfile },
64: { 'e', TCP_PROTO, 1,
65: asEproto_params, festart, feshutdown, fesendcmd, zegetspace,
66: fesenddata, fewait, fefile },
67: { 'i', UUCONF_RELIABLE_EIGHT, 7,
68: asIproto_params, fistart, fishutdown, fisendcmd, zigetspace,
69: fisenddata, fiwait, NULL },
70: { 'a', UUCONF_RELIABLE_EIGHT, 1,
71: asZproto_params, fzstart, fzshutdown, fzsendcmd, zzgetspace,
72: fzsenddata, fzwait, fzfile },
73: { 'g', UUCONF_RELIABLE_EIGHT, 1,
74: asGproto_params, fgstart, fgshutdown, fgsendcmd, zggetspace,
75: fgsenddata, fgwait, NULL },
76: { 'G', UUCONF_RELIABLE_EIGHT, 1,
77: asGproto_params, fbiggstart, fgshutdown, fgsendcmd, zggetspace,
78: fgsenddata, fgwait, NULL },
79: { 'j', UUCONF_RELIABLE_EIGHT, 7,
80: asIproto_params, fjstart, fjshutdown, fisendcmd, zigetspace,
81: fisenddata, fiwait, NULL },
82: { 'f', UUCONF_RELIABLE_RELIABLE, 1,
83: asFproto_params, ffstart, ffshutdown, ffsendcmd, zfgetspace,
84: ffsenddata, ffwait, fffile },
85: };
86:
87: #define CPROTOCOLS (sizeof asProtocols / sizeof asProtocols[0])
88:
89: /* Locked system. */
90: static boolean fLocked_system;
91: static struct uuconf_system sLocked_system;
92:
93: /* Daemon structure holding information about the remote system (must
94: be global so the error handler can see it. */
95: static struct sdaemon sDaemon;
96:
97: /* Open connection. */
98: static struct sconnection *qConn;
99:
100: /* uuconf global pointer; need to close the connection after a fatal
101: error. */
102: static pointer pUuconf;
103:
104: /* This structure is passed to iuport_lock via uuconf_find_port. */
105: struct spass
106: {
107: boolean fmatched;
108: boolean flocked;
109: struct sconnection *qconn;
110: };
111:
112: /* Local functions. */
113:
114: static void uusage P((void));
115: static void uabort P((void));
116: static boolean fcall P((pointer puuconf,
117: const struct uuconf_system *qsys,
118: struct uuconf_port *qport, boolean fifwork,
119: boolean fforce, boolean fdetach,
120: boolean ftimewarn));
121: static boolean fconn_call P((struct sdaemon *qdaemon,
122: struct uuconf_port *qport,
123: struct sstatus *qstat, int cretry,
124: boolean *pfcalled));
125: static boolean fdo_call P((struct sdaemon *qdaemon,
126: struct sstatus *qstat,
127: const struct uuconf_dialer *qdialer,
128: boolean *pfcalled, enum tstatus_type *pterr));
129: static int iuport_lock P((struct uuconf_port *qport, pointer pinfo));
130: static boolean flogin_prompt P((pointer puuconf,
131: struct sconnection *qconn));
132: static boolean faccept_call P((pointer puuconf, const char *zlogin,
133: struct sconnection *qconn,
134: const char **pzsystem));
135: static void uapply_proto_params P((pointer puuconf, int bproto,
136: struct uuconf_cmdtab *qcmds,
137: struct uuconf_proto_param *pas));
138: static boolean fsend_uucp_cmd P((struct sconnection *qconn,
139: const char *z));
140: static char *zget_uucp_cmd P((struct sconnection *qconn,
141: boolean frequired));
142: static char *zget_typed_line P((struct sconnection *qconn));
143:
144: /* Long getopt options. */
145: static const struct option asLongopts[] = { { NULL, 0, NULL, 0 } };
146:
147: int
148: main (argc, argv)
149: int argc;
150: char **argv;
151: {
152: /* -c: Whether to warn if a call is attempted at a bad time. */
153: boolean ftimewarn = TRUE;
154: /* -D: don't detach from controlling terminal. */
155: boolean fdetach = TRUE;
156: /* -e: Whether to do an endless loop of accepting calls. */
157: boolean fendless = FALSE;
158: /* -f: Whether to force a call despite status of previous call. */
159: boolean fforce = FALSE;
160: /* -I file: configuration file name. */
161: const char *zconfig = NULL;
162: /* -l: Whether to give a single login prompt. */
163: boolean flogin = FALSE;
164: /* -P port: port to use; in master mode, call out on this port. In
165: slave mode, accept logins on this port. If port not specified,
166: then in master mode figure it out for each system, and in slave
167: mode use stdin and stdout. */
168: const char *zport = NULL;
169: /* -q: Whether to start uuxqt when done. */
170: boolean fuuxqt = TRUE;
171: /* -r1: Whether we are the master. */
172: boolean fmaster = FALSE;
173: /* -s,-S system: system to call. */
174: const char *zsystem = NULL;
175: /* -w: Whether to wait for a call after doing one. */
176: boolean fwait = FALSE;
177: int iopt;
178: struct uuconf_port *qport;
179: struct uuconf_port sport;
180: boolean fret = TRUE;
181: pointer puuconf;
182: int iuuconf;
183: #if defined(__COHERENT__)
184: boolean checkfirst = FALSE;
185: #endif /* COHERENT */
186:
187: #if DEBUG > 1
188: int iholddebug;
189: #endif
190:
191: /* For COHERENT, '-c system' means call the system only if there is
192: * work pending. This is to maintain backward compatibility with earlier
193: * versions of Coherent 4.x uucp.
194: */
195:
196: #if defined(__COHERENT__)
197: while ((iopt = getopt_long (argc, argv,
198: "c:DefI:lp:qr:s:S:u:x:X:w",
199: asLongopts, (int *) NULL)) != EOF)
200: #else
201: while ((iopt = getopt_long (argc, argv,
202: "cDefI:lp:qr:s:S:u:x:X:w",
203: asLongopts, (int *) NULL)) != EOF)
204: #endif
205: {
206: switch (iopt)
207: {
208: #if defined(__COHERENT__)
209: case 'c':
210: /* for COHERENT backward compatibility, -c and -s are
211: * almost synonomous.
212: */
213: checkfirst = TRUE;
214: zsystem = optarg;
215: fmaster = TRUE;
216: break;
217: #else
218: case 'c':
219: /* Don't warn if a call is attempted at a bad time. */
220: ftimewarn = FALSE;
221: break;
222: #endif
223: case 'D':
224: /* Don't detach from controlling terminal. */
225: fdetach = FALSE;
226: break;
227:
228: case 'e':
229: /* Do an endless loop of accepting calls. */
230: fendless = TRUE;
231: break;
232:
233: case 'f':
234: /* Force a call even if it hasn't been long enough since the last
235: failed call. */
236: fforce = TRUE;
237: break;
238:
239: case 'I':
240: /* Set configuration file name (default is in sysdep.h). */
241: if (fsysdep_other_config (optarg))
242: zconfig = optarg;
243: break;
244:
245: case 'l':
246: /* Prompt for login name and password. */
247: flogin = TRUE;
248: break;
249:
250: case 'p':
251: /* Port to use */
252: zport = optarg;
253: break;
254:
255: case 'q':
256: /* Don't start uuxqt. */
257: fuuxqt = FALSE;
258: break;
259:
260: case 'r':
261: /* Set mode: -r1 for master, -r0 for slave (default) */
262: if (strcmp (optarg, "1") == 0)
263: fmaster = TRUE;
264: else if (strcmp (optarg, "0") == 0)
265: fmaster = FALSE;
266: else
267: uusage ();
268: break;
269:
270: case 's':
271: /* Set system name */
272: zsystem = optarg;
273: fmaster = TRUE;
274: break;
275:
276: case 'S':
277: /* Set system name and force call like -f */
278: zsystem = optarg;
279: fforce = TRUE;
280: fmaster = TRUE;
281: break;
282:
283: case 'u':
284: /* Some versions of uucpd invoke uucico with a -u argument
285: specifying the login name. I'm told it is safe to ignore
286: this value, although perhaps we should use it rather than
287: zsysdep_login_name (). */
288: break;
289:
290: case 'x':
291: case 'X':
292: #if DEBUG > 1
293: /* Set debugging level */
294: iDebug |= idebug_parse (optarg);
295: #endif
296: break;
297:
298: case 'w':
299: /* Call out and then wait for a call in */
300: fwait = TRUE;
301: break;
302:
303: case 0:
304: /* Long option found, and flag value set. */
305: break;
306:
307: default:
308: uusage ();
309: break;
310: }
311: }
312:
313: if (optind != argc)
314: uusage ();
315:
316: if (fwait && zport == NULL)
317: {
318: ulog (LOG_ERROR, "-w requires -e");
319: uusage ();
320: }
321:
322: iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig);
323: if (iuuconf != UUCONF_SUCCESS)
324: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
325: pUuconf = puuconf;
326:
327: #if DEBUG > 1
328: {
329: const char *zdebug;
330:
331: iuuconf = uuconf_debuglevel (puuconf, &zdebug);
332: if (iuuconf != UUCONF_SUCCESS)
333: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
334: if (zdebug != NULL)
335: iDebug |= idebug_parse (zdebug);
336: }
337: #endif
338:
339: /* If a port was named, get its information. */
340: if (zport == NULL)
341: qport = NULL;
342: else
343: {
344: iuuconf = uuconf_find_port (puuconf, zport, (long) 0, (long) 0,
345: (int (*) P((struct uuconf_port *,
346: pointer))) NULL,
347: (pointer) NULL, &sport);
348: if (iuuconf == UUCONF_NOT_FOUND)
349: ulog (LOG_FATAL, "%s: Port not found", zport);
350: else if (iuuconf != UUCONF_SUCCESS)
351: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
352: qport = &sport;
353: }
354:
355: #ifdef SIGINT
356: usysdep_signal (SIGINT);
357: #endif
358: #ifdef SIGHUP
359: usysdep_signal (SIGHUP);
360: #endif
361: #ifdef SIGQUIT
362: usysdep_signal (SIGQUIT);
363: #endif
364: #ifdef SIGTERM
365: usysdep_signal (SIGTERM);
366: #endif
367: #ifdef SIGPIPE
368: usysdep_signal (SIGPIPE);
369: #endif
370:
371: usysdep_initialize (puuconf, INIT_SUID);
372:
373: ulog_to_file (puuconf, TRUE);
374: ulog_fatal_fn (uabort);
375:
376: if (fmaster)
377: {
378: if (zsystem != NULL)
379: {
380: /* A system was named. Call it. */
381: iuuconf = uuconf_system_info (puuconf, zsystem,
382: &sLocked_system);
383: if (iuuconf == UUCONF_NOT_FOUND)
384: ulog (LOG_FATAL, "%s: System not found", zsystem);
385: else if (iuuconf != UUCONF_SUCCESS)
386: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
387:
388: /* Detach from the controlling terminal for the call. This
389: probably makes sense only on Unix. We want the modem
390: line to become the controlling terminal. */
391: if (fdetach &&
392: (qport == NULL
393: || qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN))
394: usysdep_detach ();
395:
396: ulog_system (sLocked_system.uuconf_zname);
397:
398: #if DEBUG > 1
399: iholddebug = iDebug;
400: if (sLocked_system.uuconf_zdebug != NULL)
401: iDebug |= idebug_parse (sLocked_system.uuconf_zdebug);
402: #endif
403:
404: #if defined(__COHERENT__) /* backward compatibility with older COH -c option */
405: if((checkfirst && fsysdep_has_work(&sLocked_system)) || (!checkfirst)){
406: #endif /* COHERENT */
407:
408: if (! fsysdep_lock_system (&sLocked_system))
409: {
410: ulog (LOG_ERROR, "System already locked");
411: fret = FALSE;
412: }
413: else
414: {
415: fLocked_system = TRUE;
416: fret = fcall (puuconf, &sLocked_system, qport, FALSE,
417: fforce, fdetach, ftimewarn);
418: if (fLocked_system)
419: {
420: (void) fsysdep_unlock_system (&sLocked_system);
421: fLocked_system = FALSE;
422: }
423: }
424:
425: #if defined(__COHERENT__) /* backward compat. with older COH -c option */
426: }
427: #endif /* COHERENT */
428:
429: #if DEBUG > 1
430: iDebug = iholddebug;
431: #endif
432: ulog_system ((const char *) NULL);
433: (void) uuconf_system_free (puuconf, &sLocked_system);
434: }
435: else
436: {
437: char **pznames, **pz;
438: int c, i;
439: boolean fdidone;
440:
441: /* Call all systems which have work to do. */
442: fret = TRUE;
443: fdidone = FALSE;
444:
445: iuuconf = uuconf_system_names (puuconf, &pznames, 0);
446: if (iuuconf != UUCONF_SUCCESS)
447: ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
448:
449: /* Randomize the order in which we call the systems. */
450: c = 0;
451: for (pz = pznames; *pz != NULL; pz++)
452: c++;
453:
454: srand ((unsigned int) ixsysdep_time ((long *) NULL));
455: for (i = c - 1; i > 0; i--)
456: {
457: int iuse;
458: char *zhold;
459:
460: iuse = rand () % (i + 1);
461: zhold = pznames[i];
462: pznames[i] = pznames[iuse];
463: pznames[iuse] = zhold;
464: }
465:
466: for (pz = pznames; *pz != NULL && ! FGOT_SIGNAL (); pz++)
467: {
468: iuuconf = uuconf_system_info (puuconf, *pz,
469: &sLocked_system);
470: if (iuuconf != UUCONF_SUCCESS)
471: {
472: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
473: xfree ((pointer) *pz);
474: continue;
475: }
476:
477: if (fsysdep_has_work (&sLocked_system))
478: {
479: fdidone = TRUE;
480:
481: /* Detach from the controlling terminal. On Unix
482: this means that we will wind up forking a new
483: process for each system we call. */
484: if (fdetach
485: && (qport == NULL
486: || qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN))
487: usysdep_detach ();
488:
489: ulog_system (sLocked_system.uuconf_zname);
490:
491: #if DEBUG > 1
492: iholddebug = iDebug;
493: if (sLocked_system.uuconf_zdebug != NULL)
494: iDebug |= idebug_parse (sLocked_system.uuconf_zdebug);
495: #endif
496:
497: if (! fsysdep_lock_system (&sLocked_system))
498: {
499: ulog (LOG_ERROR, "System already locked");
500: fret = FALSE;
501: }
502: else
503: {
504: fLocked_system = TRUE;
505: if (! fcall (puuconf, &sLocked_system, qport, TRUE,
506: fforce, fdetach, ftimewarn))
507: fret = FALSE;
508:
509: /* Now ignore any SIGHUP that we got. */
510: afSignal[INDEXSIG_SIGHUP] = FALSE;
511:
512: if (fLocked_system)
513: {
514: (void) fsysdep_unlock_system (&sLocked_system);
515: fLocked_system = FALSE;
516: }
517: }
518: #if DEBUG > 1
519: iDebug = iholddebug;
520: #endif
521: ulog_system ((const char *) NULL);
522: }
523:
524: (void) uuconf_system_free (puuconf, &sLocked_system);
525: xfree ((pointer) *pz);
526: }
527:
528: xfree ((pointer) pznames);
529:
530: if (! fdidone)
531: ulog (LOG_NORMAL, "No work");
532: }
533:
534: /* If requested, wait for calls after dialing out. */
535: if (fwait)
536: {
537: fendless = TRUE;
538: fmaster = FALSE;
539: }
540: }
541:
542: if (! fmaster)
543: {
544: struct sconnection sconn;
545: boolean flocked;
546:
547: /* If a port was specified by name, we go into endless loop
548: mode. In this mode, we wait for calls and prompt them with
549: "login:" and "Password:", so that they think we are a regular
550: UNIX system. If we aren't in endless loop mode, we have been
551: called by some other system. If flogin is TRUE, we prompt
552: with "login:" and "Password:" a single time. */
553:
554: fret = TRUE;
555: zsystem = NULL;
556:
557: if (! fconn_init (qport, &sconn))
558: fret = FALSE;
559:
560: if (qport != NULL)
561: {
562: /* We are not using standard input. Detach from the
563: controlling terminal, so that the port we are about to
564: use becomes our controlling terminal. */
565: if (fdetach
566: && qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN)
567: usysdep_detach ();
568:
569: /* If a port was given, we loop forever. */
570: fendless = TRUE;
571: }
572:
573: if (fconn_lock (&sconn, TRUE))
574: flocked = TRUE;
575: else
576: {
577: flocked = FALSE;
578: ulog (LOG_ERROR, "%s: Port already locked",
579: qport->uuconf_zname);
580: fret = FALSE;
581: }
582:
583: if (fret)
584: {
585: if (! fconn_open (&sconn, (long) 0, (long) 0, TRUE))
586: fret = FALSE;
587: qConn = &sconn;
588: }
589:
590: if (fret)
591: {
592: if (fendless)
593: {
594: while (! FGOT_SIGNAL ()
595: && flogin_prompt (puuconf, &sconn))
596: {
597: /* Now ignore any SIGHUP that we got. */
598: afSignal[INDEXSIG_SIGHUP] = FALSE;
599:
600: if (fLocked_system)
601: {
602: (void) fsysdep_unlock_system (&sLocked_system);
603: fLocked_system = FALSE;
604: }
605: if (! fconn_reset (&sconn))
606: break;
607: }
608: fret = FALSE;
609: }
610: else
611: {
612: if (flogin)
613: fret = flogin_prompt (puuconf, &sconn);
614: else
615: {
616: #if DEBUG > 1
617: iholddebug = iDebug;
618: #endif
619: fret = faccept_call (puuconf, zsysdep_login_name (),
620: &sconn, &zsystem);
621: #if DEBUG > 1
622: iDebug = iholddebug;
623: #endif
624: }
625: }
626: }
627:
628: if (qConn != NULL)
629: {
630: if (! fconn_close (&sconn, puuconf, (struct uuconf_dialer *) NULL,
631: fret))
632: fret = FALSE;
633: qConn = NULL;
634: }
635:
636: if (flocked)
637: (void) fconn_unlock (&sconn);
638:
639: if (fLocked_system)
640: {
641: (void) fsysdep_unlock_system (&sLocked_system);
642: fLocked_system = FALSE;
643: }
644:
645: uconn_free (&sconn);
646: }
647:
648: ulog_close ();
649: ustats_close ();
650:
651: /* If we got a SIGTERM, perhaps because the system is going down,
652: don't run uuxqt. We go ahead and run it for any other signal,
653: since I think they indicate more temporary conditions. */
654: if (afSignal[INDEXSIG_SIGTERM])
655: fuuxqt = FALSE;
656:
657: if (fuuxqt)
658: {
659: /* Detach from the controlling terminal before starting up uuxqt,
660: so that it runs as a true daemon. */
661: if (fdetach)
662: usysdep_detach ();
663: if (zsystem == NULL)
664: {
665: if (! fsysdep_run ("uuxqt", (const char *) NULL,
666: (const char *) NULL))
667: fret = FALSE;
668: }
669: else
670: {
671: if (! fsysdep_run ("uuxqt", "-s", zsystem))
672: fret = FALSE;
673: }
674: }
675:
676: usysdep_exit (fret);
677:
678: /* Avoid complaints about not returning. */
679: return 0;
680: }
681:
682: /* Print out a usage message. */
683:
684: static void
685: uusage ()
686: {
687: fprintf (stderr,
688: "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
689: VERSION);
690: fprintf (stderr,
691: "Usage: uucico [options]\n");
692: fprintf (stderr,
693: " -s,-S system: Call system (-S implies -f)\n");
694: fprintf (stderr,
695: " -f: Force call despite system status\n");
696: fprintf (stderr,
697: " -r state: 1 for master, 0 for slave (default)\n");
698: fprintf (stderr,
699: " -p port: Specify port (implies -e)\n");
700: fprintf (stderr,
701: " -l: prompt for login name and password\n");
702: fprintf (stderr,
703: " -e: Endless loop of login prompts and daemon execution\n");
704: fprintf (stderr,
705: " -w: After calling out, wait for incoming calls\n");
706: fprintf (stderr,
707: " -q: Don't start uuxqt when done\n");
708: fprintf (stderr,
709: " -x,-X debug: Set debugging level\n");
710: #if HAVE_TAYLOR_CONFIG
711: fprintf (stderr,
712: " -I file: Set configuration file to use\n");
713: #endif /* HAVE_TAYLOR_CONFIG */
714:
715: exit (EXIT_FAILURE);
716: }
717:
718: /* This function is called when a LOG_FATAL error occurs. */
719:
720: static void
721: uabort ()
722: {
723: if (fLocked_system)
724: ufailed (&sDaemon);
725:
726: ulog_user ((const char *) NULL);
727:
728: if (qConn != NULL)
729: {
730: (void) fconn_close (qConn, pUuconf, (struct uuconf_dialer *) NULL,
731: FALSE);
732: (void) fconn_unlock (qConn);
733: uconn_free (qConn);
734: }
735:
736: if (fLocked_system)
737: {
738: (void) fsysdep_unlock_system (&sLocked_system);
739: fLocked_system = FALSE;
740: }
741:
742: ulog_system ((const char *) NULL);
743:
744: ulog_close ();
745: ustats_close ();
746:
747: usysdep_exit (FALSE);
748: }
749:
750: /* Call another system, trying all the possible sets of calling
751: instructions. The qsys argument is the system to call. The qport
752: argument is the port to use, and may be NULL. If the fifwork
753: argument is TRUE, the call is only placed if there is work to be
754: done. If the fforce argument is TRUE, a call is forced even if not
755: enough time has passed since the last failed call. If the
756: ftimewarn argument is TRUE (the normal case), then a warning is
757: given if calls are not permitted at this time. */
758:
759: static boolean
760: fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
761: pointer puuconf;
762: const struct uuconf_system *qorigsys;
763: struct uuconf_port *qport;
764: boolean fifwork;
765: boolean fforce;
766: boolean fdetach;
767: boolean ftimewarn;
768: {
769: struct sstatus sstat;
770: long inow;
771: boolean fbadtime, fnevertime;
772: const struct uuconf_system *qsys;
773:
774: if (! fsysdep_get_status (qorigsys, &sstat, (boolean *) NULL))
775: return FALSE;
776:
777: /* Make sure it's been long enough since the last failed call, and
778: that we haven't exceeded the maximum number of retries. Even if
779: we are over the limit on retries, we permit a call to be made if
780: 24 hours have passed. This 24 hour limit is still controlled by
781: the retry time. */
782: inow = ixsysdep_time ((long *) NULL);
783: if (! fforce)
784: {
785: if (qorigsys->uuconf_cmax_retries > 0
786: && sstat.cretries >= qorigsys->uuconf_cmax_retries
787: && sstat.ilast + 24 * 60 * 60 < inow)
788: {
789: ulog (LOG_ERROR, "Too many retries");
790: return FALSE;
791: }
792:
793: if (sstat.ttype == STATUS_COMPLETE
794: ? sstat.ilast + qorigsys->uuconf_csuccess_wait > inow
795: : sstat.ilast + sstat.cwait > inow)
796: {
797: ulog (LOG_NORMAL, "Retry time not reached");
798: return FALSE;
799: }
800: }
801:
802: sDaemon.puuconf = puuconf;
803: sDaemon.qsys = NULL;
804: sDaemon.zlocalname = NULL;
805: sDaemon.qconn = NULL;
806: sDaemon.qproto = NULL;
807: sDaemon.clocal_size = -1;
808: sDaemon.cremote_size = -1;
809: sDaemon.cmax_ever = -2;
810: sDaemon.cmax_receive = -1;
811: sDaemon.ifeatures = 0;
812: sDaemon.frequest_hangup = FALSE;
813: sDaemon.fhangup_requested = FALSE;
814: sDaemon.fhangup = FALSE;
815: sDaemon.fmaster = TRUE;
816: sDaemon.fcaller = TRUE;
817: sDaemon.ireliable = 0;
818: sDaemon.bgrade = '\0';
819:
820: fbadtime = TRUE;
821: fnevertime = TRUE;
822:
823: for (qsys = qorigsys; qsys != NULL; qsys = qsys->uuconf_qalternate)
824: {
825: int cretry;
826: boolean fany, fret, fcalled;
827:
828: if (FGOT_SIGNAL ())
829: return FALSE;
830:
831: if (! qsys->uuconf_fcall || qsys->uuconf_qtimegrade == NULL)
832: continue;
833:
834: fnevertime = FALSE;
835:
836: /* Make sure this is a legal time to call. */
837: if (! ftimespan_match (qsys->uuconf_qtimegrade, (long *) NULL,
838: &cretry))
839: continue;
840:
841: sDaemon.qsys = qsys;
842:
843: /* Queue up any work there is to do. */
844: if (! fqueue (&sDaemon, &fany))
845: return FALSE;
846:
847: /* If we are only supposed to call if there is work, and there
848: isn't any work, check the next alternates. We can't give up
849: at this point because there might be some other alternates
850: with fewer restrictions on grade or file transfer size. */
851: if (fifwork && ! fany)
852: {
853: uclear_queue (&sDaemon);
854: continue;
855: }
856:
857: fbadtime = FALSE;
858:
859: fret = fconn_call (&sDaemon, qport, &sstat, cretry, &fcalled);
860:
861: uclear_queue (&sDaemon);
862:
863: if (fret)
864: return TRUE;
865: if (fcalled)
866: return FALSE;
867:
868: /* Now we have to dump that port so that we can aquire a new
869: one. On Unix this means that we will fork and get a new
870: process ID, so we must unlock and relock the system. */
871: if (fdetach)
872: {
873: (void) fsysdep_unlock_system (&sLocked_system);
874: fLocked_system = FALSE;
875: usysdep_detach ();
876: if (! fsysdep_lock_system (&sLocked_system))
877: return FALSE;
878: fLocked_system = TRUE;
879: }
880: }
881:
882: if (fbadtime && ftimewarn)
883: {
884: ulog (LOG_NORMAL, "Wrong time to call");
885:
886: /* Update the status, unless the system can never be called. If
887: the system can never be called, there is little point to
888: putting in a ``wrong time to call'' message. We don't change
889: the number of retries, although we do set the wait until the
890: next retry to 0. */
891: if (! fnevertime)
892: {
893: sstat.ttype = STATUS_WRONG_TIME;
894: sstat.ilast = inow;
895: sstat.cwait = 0;
896: (void) fsysdep_set_status (qorigsys, &sstat);
897: }
898: }
899:
900: return FALSE;
901: }
902:
903: /* Find a port to use when calling a system, open a connection, and
904: dial the system. The actual call is done in fdo_call. This
905: routine is responsible for opening and closing the connection. */
906:
907: static boolean
908: fconn_call (qdaemon, qport, qstat, cretry, pfcalled)
909: struct sdaemon *qdaemon;
910: struct uuconf_port *qport;
911: struct sstatus *qstat;
912: int cretry;
913: boolean *pfcalled;
914: {
915: pointer puuconf;
916: const struct uuconf_system *qsys;
917: struct uuconf_port sport;
918: struct sconnection sconn;
919: enum tstatus_type terr;
920: boolean fret;
921:
922: puuconf = qdaemon->puuconf;
923: qsys = qdaemon->qsys;
924:
925: *pfcalled = FALSE;
926:
927: /* Ignore any SIGHUP signal we may have received up to this point.
928: This is needed on Unix because we may have gotten one from the
929: shell before we detached from the controlling terminal. */
930: afSignal[INDEXSIG_SIGHUP] = FALSE;
931:
932: /* If no port was specified on the command line, use any port
933: defined for the system. To select the system port: 1) see if
934: port information was specified directly; 2) see if a port was
935: named; 3) get an available port given the baud rate. We don't
936: change the system status if a port is unavailable; i.e. we don't
937: force the system to wait for the retry time. */
938: if (qport == NULL)
939: qport = qsys->uuconf_qport;
940: if (qport != NULL)
941: {
942: if (! fconn_init (qport, &sconn))
943: return FALSE;
944: if (! fconn_lock (&sconn, FALSE))
945: {
946: ulog (LOG_ERROR, "%s: Port already locked",
947: qport->uuconf_zname);
948: return FALSE;
949: }
950: }
951: else
952: {
953: struct spass s;
954: int iuuconf;
955:
956: s.fmatched = FALSE;
957: s.flocked = FALSE;
958: s.qconn = &sconn;
959: iuuconf = uuconf_find_port (puuconf, qsys->uuconf_zport,
960: qsys->uuconf_ibaud,
961: qsys->uuconf_ihighbaud,
962: iuport_lock, (pointer) &s,
963: &sport);
964: if (iuuconf == UUCONF_NOT_FOUND)
965: {
966: if (s.fmatched)
967: ulog (LOG_ERROR, "All matching ports in use");
968: else
969: ulog (LOG_ERROR, "No matching ports");
970: return FALSE;
971: }
972: else if (iuuconf != UUCONF_SUCCESS)
973: {
974: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
975: if (s.flocked)
976: {
977: (void) fconn_unlock (&sconn);
978: uconn_free (&sconn);
979: }
980: return FALSE;
981: }
982: }
983:
984: if (! fconn_open (&sconn, qsys->uuconf_ibaud, qsys->uuconf_ihighbaud,
985: FALSE))
986: {
987: terr = STATUS_PORT_FAILED;
988: fret = FALSE;
989: }
990: else
991: {
992: struct uuconf_dialer *qdialer;
993: struct uuconf_dialer sdialer;
994: enum tdialerfound tdialer;
995:
996: if (qsys->uuconf_zalternate == NULL)
997: ulog (LOG_NORMAL, "Calling system %s (port %s)", qsys->uuconf_zname,
998: zLdevice == NULL ? (char *) "unknown" : zLdevice);
999: else
1000: ulog (LOG_NORMAL, "Calling system %s (alternate %s, port %s)",
1001: qsys->uuconf_zname, qsys->uuconf_zalternate,
1002: zLdevice == NULL ? (char *) "unknown" : zLdevice);
1003:
1004: qdialer = NULL;
1005:
1006: if (! fconn_dial (&sconn, puuconf, qsys, qsys->uuconf_zphone,
1007: &sdialer, &tdialer))
1008: {
1009: terr = STATUS_DIAL_FAILED;
1010: fret = FALSE;
1011: }
1012: else
1013: {
1014: qdaemon->qconn = &sconn;
1015: if (tdialer == DIALERFOUND_FALSE)
1016: qdialer = NULL;
1017: else
1018: qdialer = &sdialer;
1019: fret = fdo_call (qdaemon, qstat, qdialer, pfcalled, &terr);
1020: }
1021:
1022: (void) fconn_close (&sconn, puuconf, qdialer, fret);
1023:
1024: if (tdialer == DIALERFOUND_FREE)
1025: (void) uuconf_dialer_free (puuconf, &sdialer);
1026: }
1027:
1028: if (! fret)
1029: {
1030: DEBUG_MESSAGE2 (DEBUG_HANDSHAKE, "Call failed: %d (%s)",
1031: (int) terr, azStatus[(int) terr]);
1032: qstat->ttype = terr;
1033: qstat->cretries++;
1034: qstat->ilast = ixsysdep_time ((long *) NULL);
1035: if (cretry == 0)
1036: qstat->cwait = CRETRY_WAIT (qstat->cretries);
1037: else
1038: qstat->cwait = cretry * 60;
1039: (void) fsysdep_set_status (qsys, qstat);
1040: }
1041:
1042: (void) fconn_unlock (&sconn);
1043: uconn_free (&sconn);
1044:
1045: if (qport == NULL)
1046: (void) uuconf_port_free (puuconf, &sport);
1047:
1048: return fret;
1049: }
1050:
1051: /* Do the actual work of calling another system. The qsys argument is
1052: the system to call, the qconn argument is the connection to use,
1053: the qstat argument holds the current status of the ssystem, and the
1054: qdialer argument holds the dialer being used (it may be NULL). If
1055: we log in successfully, set *pfcalled to TRUE; this is used to
1056: distinguish a failed dial from a failure during the call. If an
1057: error occurs *pterr is set to the status type to record. */
1058:
1059: static boolean
1060: fdo_call (qdaemon, qstat, qdialer, pfcalled, pterr)
1061: struct sdaemon *qdaemon;
1062: struct sstatus *qstat;
1063: const struct uuconf_dialer *qdialer;
1064: boolean *pfcalled;
1065: enum tstatus_type *pterr;
1066: {
1067: pointer puuconf;
1068: const struct uuconf_system *qsys;
1069: struct sconnection *qconn;
1070: const char *zport;
1071: int iuuconf;
1072: char *zstr;
1073: long istart_time;
1074: char *zlog;
1075:
1076: puuconf = qdaemon->puuconf;
1077: qsys = qdaemon->qsys;
1078: qconn = qdaemon->qconn;
1079:
1080: *pterr = STATUS_LOGIN_FAILED;
1081:
1082: if (qconn->qport == NULL)
1083: zport = "unknown";
1084: else
1085: zport = qconn->qport->uuconf_zname;
1086: if (! fchat (qconn, puuconf, &qsys->uuconf_schat, qsys,
1087: (const struct uuconf_dialer *) NULL,
1088: (const char *) NULL, FALSE, zport,
1089: iconn_baud (qconn)))
1090: return FALSE;
1091:
1092: *pfcalled = TRUE;
1093: istart_time = ixsysdep_time ((long *) NULL);
1094:
1095: *pterr = STATUS_HANDSHAKE_FAILED;
1096:
1097: /* We should now see "Shere" from the other system. Newer systems
1098: send "Shere=foo" where foo is the remote name. */
1099: zstr = zget_uucp_cmd (qconn, TRUE);
1100: if (zstr == NULL)
1101: return FALSE;
1102:
1103: if (strncmp (zstr, "Shere", 5) != 0)
1104: {
1105: ulog (LOG_ERROR, "Bad initialization string");
1106: ubuffree (zstr);
1107: return FALSE;
1108: }
1109:
1110: ulog (LOG_NORMAL, "Login successful");
1111:
1112: qstat->ttype = STATUS_TALKING;
1113: qstat->ilast = ixsysdep_time ((long *) NULL);
1114: qstat->cretries = 0;
1115: qstat->cwait = 0;
1116: if (! fsysdep_set_status (qsys, qstat))
1117: return FALSE;
1118:
1119: if (zstr[5] == '=')
1120: {
1121: const char *zheresys;
1122: size_t clen;
1123: int icmp;
1124:
1125: /* Some UUCP packages only provide seven characters in the Shere
1126: machine name. Others only provide fourteen. */
1127: zheresys = zstr + 6;
1128: clen = strlen (zheresys);
1129: if (clen == 7 || clen == 14)
1130: icmp = strncmp (zheresys, qsys->uuconf_zname, clen);
1131: else
1132: icmp = strcmp (zheresys, qsys->uuconf_zname);
1133: if (icmp != 0)
1134: {
1135: if (qsys->uuconf_pzalias != NULL)
1136: {
1137: char **pz;
1138:
1139: for (pz = qsys->uuconf_pzalias; *pz != NULL; pz++)
1140: {
1141: if (clen == 7 || clen == 14)
1142: icmp = strncmp (zheresys, *pz, clen);
1143: else
1144: icmp = strcmp (zheresys, *pz);
1145: if (icmp == 0)
1146: break;
1147: }
1148: }
1149: if (icmp != 0)
1150: {
1151: ulog (LOG_ERROR, "Called wrong system (%s)", zheresys);
1152: ubuffree (zstr);
1153: return FALSE;
1154: }
1155: }
1156: }
1157: #if DEBUG > 1
1158: else if (zstr[5] != '\0')
1159: DEBUG_MESSAGE1 (DEBUG_HANDSHAKE,
1160: "fdo_call: Strange Shere: %s", zstr);
1161: #endif
1162:
1163: ubuffree (zstr);
1164:
1165: /* We now send "S" name switches, where name is our UUCP name. If
1166: we are using sequence numbers with this system, we send a -Q
1167: argument with the sequence number. If the call-timegrade command
1168: was used, we send a -p argument and a -vgrade= argument with the
1169: grade to send us (we send both argument to make it more likely
1170: that one is recognized). We always send a -N (for new) switch
1171: indicating what new features we support. */
1172: {
1173: long ival;
1174: char bgrade;
1175: char *zsend;
1176: boolean fret;
1177:
1178: /* Determine the grade we should request of the other system. A
1179: '\0' means that no restrictions have been made. */
1180: if (! ftimespan_match (qsys->uuconf_qcalltimegrade, &ival,
1181: (int *) NULL))
1182: bgrade = '\0';
1183: else
1184: bgrade = (char) ival;
1185:
1186: /* Determine the name we will call ourselves. */
1187: if (qsys->uuconf_zlocalname != NULL)
1188: qdaemon->zlocalname = qsys->uuconf_zlocalname;
1189: else
1190: {
1191: iuuconf = uuconf_localname (puuconf, &qdaemon->zlocalname);
1192: if (iuuconf == UUCONF_NOT_FOUND)
1193: {
1194: qdaemon->zlocalname = zsysdep_localname ();
1195: if (qdaemon->zlocalname == NULL)
1196: return FALSE;
1197: }
1198: else if (iuuconf != UUCONF_SUCCESS)
1199: {
1200: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1201: return FALSE;
1202: }
1203: }
1204:
1205: zsend = zbufalc (strlen (qdaemon->zlocalname) + 70);
1206: if (! qsys->uuconf_fsequence)
1207: {
1208: if (bgrade == '\0')
1209: sprintf (zsend, "S%s -R -N0%o", qdaemon->zlocalname,
1210: (unsigned int) (FEATURE_SIZES
1211: | FEATURE_EXEC
1212: | FEATURE_RESTART));
1213: else
1214: sprintf (zsend, "S%s -p%c -vgrade=%c -R -N0%o",
1215: qdaemon->zlocalname, bgrade, bgrade,
1216: (unsigned int) (FEATURE_SIZES
1217: | FEATURE_EXEC
1218: | FEATURE_RESTART));
1219: }
1220: else
1221: {
1222: long iseq;
1223:
1224: iseq = ixsysdep_get_sequence (qsys);
1225: if (iseq < 0)
1226: return FALSE;
1227: if (bgrade == '\0')
1228: sprintf (zsend, "S%s -Q%ld -R -N0%o", qdaemon->zlocalname, iseq,
1229: (unsigned int) (FEATURE_SIZES
1230: | FEATURE_EXEC
1231: | FEATURE_RESTART));
1232: else
1233: sprintf (zsend, "S%s -Q%ld -p%c -vgrade=%c -R -N0%o",
1234: qdaemon->zlocalname, iseq, bgrade, bgrade,
1235: (unsigned int) (FEATURE_SIZES
1236: | FEATURE_EXEC
1237: | FEATURE_RESTART));
1238: }
1239:
1240: fret = fsend_uucp_cmd (qconn, zsend);
1241: ubuffree (zsend);
1242: if (! fret)
1243: return FALSE;
1244: }
1245:
1246: /* Now we should see ROK or Rreason where reason gives a cryptic
1247: reason for failure. If we are talking to a counterpart, we will
1248: get back ROKN, possibly with a feature bitfield attached. */
1249: zstr = zget_uucp_cmd (qconn, TRUE);
1250: if (zstr == NULL)
1251: return FALSE;
1252:
1253: if (zstr[0] != 'R')
1254: {
1255: ulog (LOG_ERROR, "Bad reponse to handshake string (%s)",
1256: zstr);
1257: ubuffree (zstr);
1258: return FALSE;
1259: }
1260:
1261: if (strncmp (zstr + 1, "OKN", sizeof "OKN" - 1) == 0)
1262: {
1263: if (zstr[sizeof "ROKN" - 1] == '\0')
1264: qdaemon->ifeatures |= FEATURE_SIZES | FEATURE_V103;
1265: else
1266: qdaemon->ifeatures |= (int) strtol (zstr + sizeof "ROKN" - 1,
1267: (char **) NULL, 0);
1268: }
1269: else if (strncmp (zstr + 1, "OK", sizeof "OK" - 1) == 0)
1270: {
1271: if (zstr[sizeof "ROK" - 1] != '\0')
1272: {
1273: char *zopt;
1274:
1275: /* SVR4 UUCP returns options following the ROK string. */
1276: zopt = zstr + sizeof "ROK" - 1;
1277: while (*zopt != '\0')
1278: {
1279: char b;
1280: long c;
1281: char *zend;
1282:
1283: b = *zopt++;
1284: if (isspace (b) || b != '-')
1285: continue;
1286: switch (*zopt)
1287: {
1288: case 'R':
1289: qdaemon->ifeatures |= (FEATURE_RESTART
1290: | FEATURE_SVR4
1291: | FEATURE_SIZES);
1292: break;
1293: case 'U':
1294: c = strtol (zopt, &zend, 0);
1295: if (c > 0 && c <= LONG_MAX / (long) 512)
1296: qdaemon->cmax_receive = c * (long) 512;
1297: zopt = zend;
1298: break;
1299: }
1300: while (*zopt != '\0' && ! isspace (*zopt))
1301: ++zopt;
1302: }
1303: }
1304: }
1305: else if (strcmp (zstr + 1, "CB") == 0)
1306: {
1307: ulog (LOG_NORMAL, "Remote system will call back");
1308: qstat->ttype = STATUS_COMPLETE;
1309: (void) fsysdep_set_status (qsys, qstat);
1310: ubuffree (zstr);
1311: return TRUE;
1312: }
1313: else
1314: {
1315: ulog (LOG_ERROR, "Handshake failed (%s)", zstr + 1);
1316: ubuffree (zstr);
1317: return FALSE;
1318: }
1319:
1320: ubuffree (zstr);
1321:
1322: /* The slave should now send \020Pprotos\0 where protos is a list of
1323: supported protocols. Each protocol is a single character. */
1324: zstr = zget_uucp_cmd (qconn, TRUE);
1325: if (zstr == NULL)
1326: return FALSE;
1327:
1328: if (zstr[0] != 'P')
1329: {
1330: ulog (LOG_ERROR, "Bad protocol handshake (%s)", zstr);
1331: ubuffree (zstr);
1332: return FALSE;
1333: }
1334:
1335: /* Determine the reliability characteristics of the connection by
1336: combining information for the port and the dialer. If we have no
1337: information, default to a reliable eight-bit full-duplex
1338: connection. */
1339: if (qconn->qport != NULL
1340: && (qconn->qport->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
1341: qdaemon->ireliable = qconn->qport->uuconf_ireliable;
1342: if (qdialer != NULL
1343: && (qdialer->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
1344: {
1345: if (qdaemon->ireliable != 0)
1346: qdaemon->ireliable &= qdialer->uuconf_ireliable;
1347: else
1348: qdaemon->ireliable = qdialer->uuconf_ireliable;
1349: }
1350: if (qdaemon->ireliable == 0)
1351: qdaemon->ireliable = (UUCONF_RELIABLE_RELIABLE
1352: | UUCONF_RELIABLE_EIGHT
1353: | UUCONF_RELIABLE_FULLDUPLEX
1354: | UUCONF_RELIABLE_SPECIFIED);
1355:
1356: /* Now decide which protocol to use. The system and the port may
1357: have their own list of protocols. */
1358: {
1359: int i;
1360: char ab[5];
1361:
1362: i = CPROTOCOLS;
1363: if (qsys->uuconf_zprotocols != NULL
1364: || (qconn->qport != NULL
1365: && qconn->qport->uuconf_zprotocols != NULL))
1366: {
1367: const char *zproto;
1368:
1369: if (qsys->uuconf_zprotocols != NULL)
1370: zproto = qsys->uuconf_zprotocols;
1371: else
1372: zproto = qconn->qport->uuconf_zprotocols;
1373: for (; *zproto != '\0'; zproto++)
1374: {
1375: if (strchr (zstr + 1, *zproto) != NULL)
1376: {
1377: for (i = 0; i < CPROTOCOLS; i++)
1378: if (asProtocols[i].bname == *zproto)
1379: break;
1380: if (i < CPROTOCOLS)
1381: break;
1382: }
1383: }
1384: }
1385: else
1386: {
1387: /* If neither the system nor the port specified a list of
1388: protocols, we want only protocols that match the known
1389: reliability of the dialer and the port. */
1390: for (i = 0; i < CPROTOCOLS; i++)
1391: {
1392: int ipr;
1393:
1394: ipr = asProtocols[i].ireliable;
1395: if ((ipr & qdaemon->ireliable) != ipr)
1396: continue;
1397: if (strchr (zstr + 1, asProtocols[i].bname) != NULL)
1398: break;
1399: }
1400: }
1401:
1402: ubuffree (zstr);
1403:
1404: if (i >= CPROTOCOLS)
1405: {
1406: (void) fsend_uucp_cmd (qconn, "UN");
1407: ulog (LOG_ERROR, "No mutually supported protocols");
1408: return FALSE;
1409: }
1410:
1411: qdaemon->qproto = &asProtocols[i];
1412:
1413: sprintf (ab, "U%c", qdaemon->qproto->bname);
1414: if (! fsend_uucp_cmd (qconn, ab))
1415: return FALSE;
1416: }
1417:
1418: /* Run any protocol parameter commands. */
1419: if (qdaemon->qproto->qcmds != NULL)
1420: {
1421: if (qsys->uuconf_qproto_params != NULL)
1422: uapply_proto_params (puuconf, qdaemon->qproto->bname,
1423: qdaemon->qproto->qcmds,
1424: qsys->uuconf_qproto_params);
1425: if (qconn->qport != NULL
1426: && qconn->qport->uuconf_qproto_params != NULL)
1427: uapply_proto_params (puuconf, qdaemon->qproto->bname,
1428: qdaemon->qproto->qcmds,
1429: qconn->qport->uuconf_qproto_params);
1430: if (qdialer != NULL
1431: && qdialer->uuconf_qproto_params != NULL)
1432: uapply_proto_params (puuconf, qdaemon->qproto->bname,
1433: qdaemon->qproto->qcmds,
1434: qdialer->uuconf_qproto_params);
1435: }
1436:
1437: /* Turn on the selected protocol. */
1438: if (! (*qdaemon->qproto->pfstart) (qdaemon, &zlog))
1439: return FALSE;
1440: if (zlog == NULL)
1441: {
1442: zlog = zbufalc (sizeof "protocol ''" + 1);
1443: sprintf (zlog, "protocol '%c'", qdaemon->qproto->bname);
1444: }
1445: ulog (LOG_NORMAL, "Handshake successful (%s)", zlog);
1446: ubuffree (zlog);
1447:
1448: *pterr = STATUS_FAILED;
1449:
1450: {
1451: boolean fret;
1452: long iend_time;
1453:
1454: fret = floop (qdaemon);
1455:
1456: /* Now send the hangup message. As the caller, we send six O's
1457: and expect to receive seven O's. We send the six O's twice to
1458: help the other side. We don't worry about errors here. */
1459: if (fsend_uucp_cmd (qconn, "OOOOOO")
1460: && fsend_uucp_cmd (qconn, "OOOOOO"))
1461: {
1462: int i, fdone;
1463:
1464: /* We look for the remote hangup string to ensure that the
1465: modem has sent out our hangup string. This is only
1466: necessary because some versions of UUCP complain if they
1467: don't get the hangup string. The remote site should send 7
1468: O's, but some versions of UUCP only send 6. We look for
1469: the string several times because supposedly some
1470: implementations send some garbage after the last packet but
1471: before the hangup string. */
1472: for (i = 0; i < 25; i++)
1473: {
1474: zstr = zget_uucp_cmd (qconn, FALSE);
1475: if (zstr == NULL)
1476: break;
1477: fdone = strstr (zstr, "OOOOOO") != NULL;
1478: ubuffree (zstr);
1479: if (fdone)
1480: break;
1481: }
1482: }
1483:
1484: iend_time = ixsysdep_time ((long *) NULL);
1485:
1486: ulog (LOG_NORMAL, "Call complete (%ld seconds)",
1487: iend_time - istart_time);
1488:
1489: if (fret)
1490: {
1491: qstat->ttype = STATUS_COMPLETE;
1492: qstat->ilast = iend_time;
1493: (void) fsysdep_set_status (qsys, qstat);
1494: }
1495:
1496: return fret;
1497: }
1498: }
1499:
1500: /* This routine is called via uuconf_find_port when a matching port is
1501: found. It tries to lock the port. If it fails, it returns
1502: UUCONF_NOT_FOUND to force uuconf_find_port to continue searching
1503: for the next matching port. */
1504:
1505: static int
1506: iuport_lock (qport, pinfo)
1507: struct uuconf_port *qport;
1508: pointer pinfo;
1509: {
1510: struct spass *q = (struct spass *) pinfo;
1511:
1512: q->fmatched = TRUE;
1513:
1514: if (! fconn_init (qport, q->qconn))
1515: return UUCONF_NOT_FOUND;
1516: else if (! fconn_lock (q->qconn, FALSE))
1517: {
1518: uconn_free (q->qconn);
1519: return UUCONF_NOT_FOUND;
1520: }
1521: else
1522: {
1523: q->flocked = TRUE;
1524: return UUCONF_SUCCESS;
1525: }
1526: }
1527:
1528: /* Prompt for a login name and a password, and run as the slave. */
1529:
1530: static boolean
1531: flogin_prompt (puuconf, qconn)
1532: pointer puuconf;
1533: struct sconnection *qconn;
1534: {
1535: char *zuser, *zpass;
1536: boolean fret;
1537: int iuuconf;
1538:
1539: DEBUG_MESSAGE0 (DEBUG_HANDSHAKE, "flogin_prompt: Waiting for login");
1540:
1541: zuser = NULL;
1542: do
1543: {
1544: ubuffree (zuser);
1545: if (! fconn_write (qconn, "login: ", sizeof "login: " - 1))
1546: return FALSE;
1547: zuser = zget_typed_line (qconn);
1548: }
1549: while (zuser != NULL && *zuser == '\0');
1550:
1551: if (zuser == NULL)
1552: return TRUE;
1553:
1554: if (! fconn_write (qconn, "Password:", sizeof "Password:" - 1))
1555: {
1556: ubuffree (zuser);
1557: return FALSE;
1558: }
1559:
1560: zpass = zget_typed_line (qconn);
1561: if (zpass == NULL)
1562: {
1563: ubuffree (zuser);
1564: return TRUE;
1565: }
1566:
1567: fret = TRUE;
1568:
1569: iuuconf = uuconf_callin (puuconf, zuser, zpass);
1570: ubuffree (zpass);
1571: if (iuuconf == UUCONF_NOT_FOUND)
1572: ulog (LOG_ERROR, "Bad login");
1573: else if (iuuconf != UUCONF_SUCCESS)
1574: {
1575: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1576: fret = FALSE;
1577: }
1578: else
1579: {
1580: #if DEBUG > 1
1581: int iholddebug;
1582: #endif
1583:
1584: /* We ignore the return value of faccept_call because we really
1585: don't care whether the call succeeded or not. We are going
1586: to reset the port anyhow. */
1587: #if DEBUG > 1
1588: iholddebug = iDebug;
1589: #endif
1590: (void) faccept_call (puuconf, zuser, qconn, (const char **) NULL);
1591: #if DEBUG > 1
1592: iDebug = iholddebug;
1593: #endif
1594: }
1595:
1596: ubuffree (zuser);
1597:
1598: return fret;
1599: }
1600:
1601: /* Accept a call from a remote system. If pqsys is not NULL, *pqsys
1602: will be set to the system that called in if known. */
1603:
1604: static boolean
1605: faccept_call (puuconf, zlogin, qconn, pzsystem)
1606: pointer puuconf;
1607: const char *zlogin;
1608: struct sconnection *qconn;
1609: const char **pzsystem;
1610: {
1611: long istart_time;
1612: const char *zport;
1613: struct uuconf_port *qport;
1614: struct uuconf_port sport;
1615: int iuuconf;
1616: struct uuconf_dialer *qdialer;
1617: struct uuconf_dialer sdialer;
1618: boolean ftcp_port;
1619: char *zsend, *zspace;
1620: boolean fret;
1621: char *zstr;
1622: struct uuconf_system ssys;
1623: const struct uuconf_system *qsys;
1624: const struct uuconf_system *qany;
1625: char *zloc;
1626: struct sstatus sstat;
1627: boolean fgotseq, fgotn;
1628: int i;
1629: char *zlog;
1630: char *zgrade;
1631:
1632: if (pzsystem != NULL)
1633: *pzsystem = NULL;
1634:
1635: ulog (LOG_NORMAL, "Incoming call (login %s port %s)", zlogin,
1636: zLdevice == NULL ? (char *) "unknown" : zLdevice);
1637:
1638: istart_time = ixsysdep_time ((long *) NULL);
1639:
1640: /* Figure out protocol parameters determined by the port. If no
1641: port was specified we're reading standard input, so try to get
1642: the port name and read information from the port file. We only
1643: use the port information to get protocol parameters; we don't
1644: want to start treating the port as though it were a modem, for
1645: example. */
1646: if (qconn->qport != NULL)
1647: {
1648: qport = qconn->qport;
1649: zport = qport->uuconf_zname;
1650: ftcp_port = FALSE;
1651: }
1652: else
1653: {
1654: zport = zsysdep_port_name (&ftcp_port);
1655: if (zport == NULL)
1656: {
1657: qport = NULL;
1658: zport = "unknown";
1659: }
1660: else
1661: {
1662: iuuconf = uuconf_find_port (puuconf, zport, (long) 0, (long) 0,
1663: (int (*) P((struct uuconf_port *,
1664: pointer pinfo))) NULL,
1665: (pointer) NULL,
1666: &sport);
1667: if (iuuconf == UUCONF_NOT_FOUND)
1668: qport = NULL;
1669: else if (iuuconf != UUCONF_SUCCESS)
1670: {
1671: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1672: return FALSE;
1673: }
1674: else
1675: qport = &sport;
1676: }
1677: }
1678:
1679: /* If we've managed to figure out that this is a modem port, now try
1680: to get protocol parameters from the dialer. */
1681: qdialer = NULL;
1682: if (qport != NULL)
1683: {
1684: if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM)
1685: {
1686: if (qport->uuconf_u.uuconf_smodem.uuconf_pzdialer != NULL)
1687: {
1688: const char *zdialer;
1689:
1690: zdialer = qport->uuconf_u.uuconf_smodem.uuconf_pzdialer[0];
1691: iuuconf = uuconf_dialer_info (puuconf, zdialer, &sdialer);
1692: if (iuuconf == UUCONF_SUCCESS)
1693: qdialer = &sdialer;
1694: }
1695: else
1696: qdialer = qport->uuconf_u.uuconf_smodem.uuconf_qdialer;
1697: }
1698: else if (qport->uuconf_ttype == UUCONF_PORTTYPE_TCP
1699: || (qport->uuconf_ttype == UUCONF_PORTTYPE_TLI
1700: && (qport->uuconf_ireliable
1701: & UUCONF_RELIABLE_SPECIFIED) == 0))
1702: ftcp_port = TRUE;
1703: }
1704:
1705: sDaemon.puuconf = puuconf;
1706: sDaemon.qsys = NULL;
1707: sDaemon.zlocalname = NULL;
1708: sDaemon.qconn = qconn;
1709: sDaemon.qproto = NULL;
1710: sDaemon.clocal_size = -1;
1711: sDaemon.cremote_size = -1;
1712: sDaemon.cmax_ever = -2;
1713: sDaemon.cmax_receive = -1;
1714: sDaemon.ifeatures = 0;
1715: sDaemon.frequest_hangup = FALSE;
1716: sDaemon.fhangup_requested = FALSE;
1717: sDaemon.fhangup = FALSE;
1718: sDaemon.fmaster = FALSE;
1719: sDaemon.fcaller = FALSE;
1720: sDaemon.ireliable = 0;
1721: sDaemon.bgrade = UUCONF_GRADE_LOW;
1722:
1723: /* Get the local name to use. If uuconf_login_localname returns a
1724: value, it is not always freed up, although it should be. */
1725: iuuconf = uuconf_login_localname (puuconf, zlogin, &zloc);
1726: if (iuuconf == UUCONF_SUCCESS)
1727: sDaemon.zlocalname = zloc;
1728: else if (iuuconf == UUCONF_NOT_FOUND)
1729: {
1730: sDaemon.zlocalname = zsysdep_localname ();
1731: if (sDaemon.zlocalname == NULL)
1732: return FALSE;
1733: }
1734: else
1735: {
1736: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1737: return FALSE;
1738: }
1739:
1740: /* Tell the remote system who we are. */
1741: zsend = zbufalc (strlen (sDaemon.zlocalname) + sizeof "Shere=");
1742: sprintf (zsend, "Shere=%s", sDaemon.zlocalname);
1743: fret = fsend_uucp_cmd (qconn, zsend);
1744: ubuffree (zsend);
1745: if (! fret)
1746: return FALSE;
1747:
1748: zstr = zget_uucp_cmd (qconn, TRUE);
1749: if (zstr == NULL)
1750: return FALSE;
1751:
1752: if (zstr[0] != 'S')
1753: {
1754: ulog (LOG_ERROR, "Bad introduction string");
1755: ubuffree (zstr);
1756: return FALSE;
1757: }
1758:
1759: zspace = strchr (zstr, ' ');
1760: if (zspace != NULL)
1761: *zspace = '\0';
1762:
1763: iuuconf = uuconf_system_info (puuconf, zstr + 1, &ssys);
1764: if (iuuconf == UUCONF_NOT_FOUND)
1765: {
1766: char *zscript;
1767:
1768: /* Run the remote.unknown script, if appropriate. */
1769: iuuconf = uuconf_remote_unknown (puuconf, &zscript);
1770: if (iuuconf == UUCONF_SUCCESS)
1771: {
1772: if (! fsysdep_unknown_caller (zscript, zstr + 1))
1773: {
1774: xfree ((pointer) zscript);
1775: (void) fsend_uucp_cmd (qconn, "RYou are unknown to me");
1776: ubuffree (zstr);
1777: return FALSE;
1778: }
1779: xfree ((pointer) zscript);
1780: }
1781: else if (iuuconf != UUCONF_NOT_FOUND)
1782: {
1783: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1784: ubuffree (zstr);
1785: return FALSE;
1786: }
1787:
1788: if (! funknown_system (puuconf, zstr + 1, &ssys))
1789: {
1790: (void) fsend_uucp_cmd (qconn, "RYou are unknown to me");
1791: ulog (LOG_ERROR, "Call from unknown system %s", zstr + 1);
1792: ubuffree (zstr);
1793: return FALSE;
1794: }
1795: }
1796: else if (iuuconf != UUCONF_SUCCESS)
1797: {
1798: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1799: ubuffree (zstr);
1800: return FALSE;
1801: }
1802:
1803: qany = NULL;
1804: for (qsys = &ssys; qsys != NULL; qsys = qsys->uuconf_qalternate)
1805: {
1806: if (! qsys->uuconf_fcalled)
1807: continue;
1808:
1809: if (qsys->uuconf_zcalled_login == NULL
1810: || strcmp (qsys->uuconf_zcalled_login, "ANY") == 0)
1811: {
1812: if (qany == NULL)
1813: qany = qsys;
1814: }
1815: else if (strcmp (qsys->uuconf_zcalled_login, zlogin) == 0)
1816: break;
1817: }
1818:
1819: if (qsys == NULL && qany != NULL)
1820: {
1821: iuuconf = uuconf_validate (puuconf, qany, zlogin);
1822: if (iuuconf == UUCONF_SUCCESS)
1823: qsys = qany;
1824: else if (iuuconf != UUCONF_NOT_FOUND)
1825: {
1826: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
1827: ubuffree (zstr);
1828: return FALSE;
1829: }
1830: }
1831:
1832: if (qsys == NULL)
1833: {
1834: (void) fsend_uucp_cmd (qconn, "RLOGIN");
1835: ulog (LOG_ERROR, "System %s used wrong login name %s",
1836: zstr + 1, zlogin);
1837: ubuffree (zstr);
1838: return FALSE;
1839: }
1840:
1841: sDaemon.qsys = qsys;
1842:
1843: if (pzsystem != NULL)
1844: *pzsystem = zbufcpy (qsys->uuconf_zname);
1845:
1846: ulog_system (qsys->uuconf_zname);
1847:
1848: #if DEBUG > 1
1849: if (qsys->uuconf_zdebug != NULL)
1850: iDebug |= idebug_parse (qsys->uuconf_zdebug);
1851: #endif
1852:
1853: /* See if we are supposed to call the system back. This will queue
1854: up an empty command. It would be better to actually call back
1855: directly at this point as well. */
1856: if (qsys->uuconf_fcallback)
1857: {
1858: (void) fsend_uucp_cmd (qconn, "RCB");
1859: ulog (LOG_NORMAL, "Will call back");
1860:
1861: /* Clear any existing status. */
1862: sstat.ttype = STATUS_COMPLETE;
1863: sstat.cretries = 0;
1864: sstat.ilast = ixsysdep_time ((long *) NULL);
1865: sstat.cwait = 0;
1866: (void) fsysdep_set_status (qsys, &sstat);
1867:
1868: ubuffree (zsysdep_spool_commands (qsys, UUCONF_GRADE_HIGH, 0,
1869: (const struct scmd *) NULL));
1870: ubuffree (zstr);
1871: return TRUE;
1872: }
1873:
1874: /* We only permit one call at a time from a remote system. Lock it. */
1875: if (! fsysdep_lock_system (qsys))
1876: {
1877: (void) fsend_uucp_cmd (qconn, "RLCK");
1878: ulog (LOG_ERROR, "System already locked");
1879: ubuffree (zstr);
1880: return FALSE;
1881: }
1882: sLocked_system = *qsys;
1883: fLocked_system = TRUE;
1884:
1885: /* Set the system status. We don't care what the status was before.
1886: We also don't want to kill the conversation just because we can't
1887: output the .Status file, so we ignore any errors. */
1888: sstat.ttype = STATUS_TALKING;
1889: sstat.cretries = 0;
1890: sstat.ilast = ixsysdep_time ((long *) NULL);
1891: sstat.cwait = 0;
1892: (void) fsysdep_set_status (qsys, &sstat);
1893:
1894: /* Check the arguments of the remote system, if any. */
1895: fgotseq = FALSE;
1896: fgotn = FALSE;
1897: if (zspace != NULL)
1898: {
1899: char **paz;
1900: char **pzset;
1901:
1902: ++zspace;
1903:
1904: /* Break the introduction line up into arguments. */
1905: paz = (char **) xmalloc ((strlen (zspace) / 2 + 2) * sizeof (char *));
1906: pzset = paz;
1907: *pzset++ = NULL;
1908: while (TRUE)
1909: {
1910: while (*zspace != '\0' && isspace (BUCHAR (*zspace)))
1911: ++zspace;
1912: if (*zspace == '\0')
1913: break;
1914: *pzset++ = zspace;
1915: ++zspace;
1916: while (*zspace != '\0' && ! isspace (BUCHAR (*zspace)))
1917: ++zspace;
1918: if (*zspace == '\0')
1919: break;
1920: *zspace++ = '\0';
1921: }
1922:
1923: if (pzset != paz + 1)
1924: {
1925: int iopt;
1926:
1927: *pzset = NULL;
1928:
1929: /* We are going to use getopt to parse the arguments. We
1930: must clear optind to force getopt to reinitialize, and
1931: clear opterr to prevent getopt from printing an error
1932: message. This approach assumes we are using the GNU
1933: getopt, which is distributed with the program anyhow. */
1934: optind = 0;
1935: opterr = 0;
1936:
1937: while ((iopt = getopt (pzset - paz, paz,
1938: "N::p:Q:RU:v:x:")) != EOF)
1939: {
1940: long iseq;
1941: long c;
1942: char b;
1943: int iwant;
1944:
1945: switch (iopt)
1946: {
1947: case 'N':
1948: /* This is used to indicate support for Taylor UUCP
1949: extensions. An plain -N mean support for size
1950: negotiation. If -N is followed by a number (with
1951: no intervening space), the number is a bit field
1952: of feature flags as defined in trans.h. Note
1953: that the argument may start with 0x for hex or 0
1954: for octal. */
1955: fgotn = TRUE;
1956: if (optarg == NULL)
1957: sDaemon.ifeatures |= FEATURE_SIZES | FEATURE_V103;
1958: else
1959: sDaemon.ifeatures |= (int) strtol (optarg,
1960: (char **) NULL,
1961: 0);
1962: break;
1963:
1964: case 'p':
1965: /* The argument is the lowest grade of work the
1966: local system should send. */
1967: if (UUCONF_GRADE_LEGAL (optarg[0]))
1968: sDaemon.bgrade = optarg[0];
1969: break;
1970:
1971: case 'Q':
1972: /* The conversation sequence number. */
1973: iseq = strtol (optarg, (char **) NULL, 10);
1974: if (qsys->uuconf_fsequence
1975: && iseq != ixsysdep_get_sequence (qsys))
1976: {
1977: (void) fsend_uucp_cmd (qconn, "RBADSEQ");
1978: ulog (LOG_ERROR, "Out of sequence call rejected");
1979: sstat.ttype = STATUS_FAILED;
1980: (void) fsysdep_set_status (qsys, &sstat);
1981: xfree ((pointer) paz);
1982: ubuffree (zstr);
1983: return FALSE;
1984: }
1985: fgotseq = TRUE;
1986: break;
1987:
1988: case 'R':
1989: /* The remote system supports file restart. */
1990: sDaemon.ifeatures |= FEATURE_RESTART;
1991: break;
1992:
1993: case 'U':
1994: /* The maximum file size the remote system is
1995: prepared to received, in blocks where each block
1996: is 512 bytes. */
1997: c = strtol (optarg, (char **) NULL, 0);
1998: if (c > 0 && c < LONG_MAX / (long) 512)
1999: sDaemon.cmax_receive = c * (long) 512;
2000: break;
2001:
2002: case 'v':
2003: /* -vgrade=X can be used to set the lowest grade of
2004: work the local system should send. */
2005: if (strncmp (optarg, "grade=", sizeof "grade=" - 1) == 0)
2006: {
2007: b = optarg[sizeof "grade=" - 1];
2008: if (UUCONF_GRADE_LEGAL (b))
2009: sDaemon.bgrade = b;
2010: }
2011: break;
2012:
2013: case 'x':
2014: iwant = (int) strtol (optarg, (char **) NULL, 10);
2015: #if DEBUG > 1
2016: if (iwant <= 9)
2017: iwant = (1 << iwant) - 1;
2018: if (qsys->uuconf_zmax_remote_debug != NULL)
2019: iwant &= idebug_parse (qsys->uuconf_zmax_remote_debug);
2020: if ((iDebug | iwant) != iDebug)
2021: {
2022: iDebug |= iwant;
2023: ulog (LOG_NORMAL, "Setting debugging mode to 0%o",
2024: iDebug);
2025: }
2026: #endif
2027: break;
2028:
2029: default:
2030: break;
2031: }
2032: }
2033: }
2034:
2035: xfree ((pointer) paz);
2036: }
2037:
2038: ubuffree (zstr);
2039:
2040: if (qsys->uuconf_fsequence && ! fgotseq)
2041: {
2042: (void) fsend_uucp_cmd (qconn, "RBADSEQ");
2043: ulog (LOG_ERROR, "No sequence number (call rejected)");
2044: sstat.ttype = STATUS_FAILED;
2045: (void) fsysdep_set_status (qsys, &sstat);
2046: return FALSE;
2047: }
2048:
2049: /* We recognized the system, and the sequence number (if any) was
2050: OK. Send an ROK, and send a list of protocols. If we got the -N
2051: switch, send ROKN to confirm it; if the -N switch was followed by
2052: a feature bitfield, return our own feature bitfield. */
2053: {
2054: char ab[20];
2055: const char *zreply;
2056:
2057: if (! fgotn)
2058: {
2059: if ((sDaemon.ifeatures & FEATURE_RESTART) == 0)
2060: zreply = "ROK";
2061: else
2062: {
2063: /* We got -R without -N, so assume that this is SVR4 UUCP.
2064: SVR4 UUCP expects ROK -R to signal support for file
2065: restart. */
2066: sDaemon.ifeatures |= FEATURE_SVR4 | FEATURE_SIZES;
2067: zreply = "ROK -R";
2068: }
2069: }
2070: else if ((sDaemon.ifeatures & FEATURE_V103) != 0)
2071: zreply = "ROKN";
2072: else
2073: {
2074: sprintf (ab, "ROKN0%o",
2075: (unsigned int) (FEATURE_SIZES
2076: | FEATURE_EXEC
2077: | FEATURE_RESTART));
2078: zreply = ab;
2079: }
2080: if (! fsend_uucp_cmd (qconn, zreply))
2081: {
2082: sstat.ttype = STATUS_FAILED;
2083: (void) fsysdep_set_status (qsys, &sstat);
2084: return FALSE;
2085: }
2086: }
2087:
2088: /* Determine the reliability of the connection based on the
2089: reliability of the port and the dialer. If we have no
2090: information, default to a reliable eight-bit full-duplex
2091: connection. */
2092: if (ftcp_port)
2093: sDaemon.ireliable = (UUCONF_RELIABLE_SPECIFIED
2094: | UUCONF_RELIABLE_ENDTOEND
2095: | UUCONF_RELIABLE_RELIABLE
2096: | UUCONF_RELIABLE_EIGHT
2097: | UUCONF_RELIABLE_FULLDUPLEX);
2098: else
2099: {
2100: if (qport != NULL
2101: && (qport->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
2102: sDaemon.ireliable = qport->uuconf_ireliable;
2103: if (qdialer != NULL
2104: && (qdialer->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
2105: {
2106: if (sDaemon.ireliable != 0)
2107: sDaemon.ireliable &= qdialer->uuconf_ireliable;
2108: else
2109: sDaemon.ireliable = qdialer->uuconf_ireliable;
2110: }
2111: if (sDaemon.ireliable == 0)
2112: sDaemon.ireliable = (UUCONF_RELIABLE_RELIABLE
2113: | UUCONF_RELIABLE_EIGHT
2114: | UUCONF_RELIABLE_FULLDUPLEX
2115: | UUCONF_RELIABLE_SPECIFIED);
2116: }
2117:
2118: if (qsys->uuconf_zprotocols != NULL ||
2119: (qport != NULL && qport->uuconf_zprotocols != NULL))
2120: {
2121: const char *zprotos;
2122:
2123: if (qsys->uuconf_zprotocols != NULL)
2124: zprotos = qsys->uuconf_zprotocols;
2125: else
2126: zprotos = qport->uuconf_zprotocols;
2127: zsend = zbufalc (strlen (zprotos) + 2);
2128: sprintf (zsend, "P%s", zprotos);
2129: }
2130: else
2131: {
2132: char *zset;
2133:
2134: zsend = zbufalc (CPROTOCOLS + 2);
2135: zset = zsend;
2136: *zset++ = 'P';
2137:
2138: /* If the system did not specify a list of protocols, we want
2139: only protocols that match the known reliability of the dialer
2140: and the port. */
2141: for (i = 0; i < CPROTOCOLS; i++)
2142: {
2143: int ipr;
2144:
2145: ipr = asProtocols[i].ireliable;
2146: if ((ipr & sDaemon.ireliable) != ipr)
2147: continue;
2148: *zset++ = asProtocols[i].bname;
2149: }
2150: *zset = '\0';
2151: }
2152:
2153: fret = fsend_uucp_cmd (qconn, zsend);
2154: ubuffree (zsend);
2155: if (! fret)
2156: {
2157: sstat.ttype = STATUS_FAILED;
2158: (void) fsysdep_set_status (qsys, &sstat);
2159: return FALSE;
2160: }
2161:
2162: /* The master will now send back the selected protocol. */
2163: zstr = zget_uucp_cmd (qconn, TRUE);
2164: if (zstr == NULL)
2165: {
2166: sstat.ttype = STATUS_FAILED;
2167: (void) fsysdep_set_status (qsys, &sstat);
2168: return FALSE;
2169: }
2170:
2171: if (zstr[0] != 'U' || zstr[2] != '\0')
2172: {
2173: ulog (LOG_ERROR, "Bad protocol response string");
2174: sstat.ttype = STATUS_FAILED;
2175: (void) fsysdep_set_status (qsys, &sstat);
2176: ubuffree (zstr);
2177: return FALSE;
2178: }
2179:
2180: if (zstr[1] == 'N')
2181: {
2182: ulog (LOG_ERROR, "No supported protocol");
2183: sstat.ttype = STATUS_FAILED;
2184: (void) fsysdep_set_status (qsys, &sstat);
2185: ubuffree (zstr);
2186: return FALSE;
2187: }
2188:
2189: for (i = 0; i < CPROTOCOLS; i++)
2190: if (asProtocols[i].bname == zstr[1])
2191: break;
2192:
2193: ubuffree (zstr);
2194:
2195: if (i >= CPROTOCOLS)
2196: {
2197: ulog (LOG_ERROR, "No supported protocol");
2198: sstat.ttype = STATUS_FAILED;
2199: (void) fsysdep_set_status (qsys, &sstat);
2200: return FALSE;
2201: }
2202:
2203: sDaemon.qproto = &asProtocols[i];
2204:
2205: /* Run the chat script for when a call is received. */
2206: if (! fchat (qconn, puuconf, &qsys->uuconf_scalled_chat, qsys,
2207: (const struct uuconf_dialer *) NULL, (const char *) NULL,
2208: FALSE, zport, iconn_baud (qconn)))
2209: {
2210: sstat.ttype = STATUS_FAILED;
2211: sstat.ilast = ixsysdep_time ((long *) NULL);
2212: (void) fsysdep_set_status (qsys, &sstat);
2213: return FALSE;
2214: }
2215:
2216: /* Run any protocol parameter commands. */
2217: if (sDaemon.qproto->qcmds != NULL)
2218: {
2219: if (qsys->uuconf_qproto_params != NULL)
2220: uapply_proto_params (puuconf, sDaemon.qproto->bname,
2221: sDaemon.qproto->qcmds,
2222: qsys->uuconf_qproto_params);
2223: if (qport != NULL
2224: && qport->uuconf_qproto_params != NULL)
2225: uapply_proto_params (puuconf, sDaemon.qproto->bname,
2226: sDaemon.qproto->qcmds,
2227: qport->uuconf_qproto_params);
2228: if (qdialer != NULL
2229: && qdialer->uuconf_qproto_params != NULL)
2230: uapply_proto_params (puuconf, sDaemon.qproto->bname,
2231: sDaemon.qproto->qcmds,
2232: qdialer->uuconf_qproto_params);
2233: }
2234:
2235: /* We don't need the dialer information any more. */
2236: if (qdialer == &sdialer)
2237: (void) uuconf_dialer_free (puuconf, &sdialer);
2238:
2239: /* Get any jobs queued for the system, and turn on the selected
2240: protocol. */
2241: if (! fqueue (&sDaemon, (boolean *) NULL)
2242: || ! (*sDaemon.qproto->pfstart) (&sDaemon, &zlog))
2243: {
2244: uclear_queue (&sDaemon);
2245: sstat.ttype = STATUS_FAILED;
2246: sstat.ilast = ixsysdep_time ((long *) NULL);
2247: (void) fsysdep_set_status (qsys, &sstat);
2248: return FALSE;
2249: }
2250:
2251: if (zlog == NULL)
2252: {
2253: zlog = zbufalc (sizeof "protocol ''" + 1);
2254: sprintf (zlog, "protocol '%c'", sDaemon.qproto->bname);
2255: }
2256:
2257: zgrade = zbufalc (sizeof "grade " + 1);
2258: if (sDaemon.bgrade == UUCONF_GRADE_LOW)
2259: *zgrade = '\0';
2260: else
2261: sprintf (zgrade, "grade %c ", sDaemon.bgrade);
2262:
2263: /* If we are using HAVE_HDB_LOGGING, then the previous ``incoming
2264: call'' message went to the general log, since we didn't know the
2265: system name at that point. In that case, we repeat the port and
2266: login names. */
2267: #if HAVE_HDB_LOGGING
2268: ulog (LOG_NORMAL, "Handshake successful (login %s port %s %s%s)",
2269: zlogin,
2270: zLdevice == NULL ? "unknown" : zLdevice,
2271: zgrade, zlog);
2272: #else /* ! HAVE_HDB_LOGGING */
2273: ulog (LOG_NORMAL, "Handshake successful (%s%s)", zgrade, zlog);
2274: #endif /* ! HAVE_HDB_LOGGING */
2275:
2276: ubuffree (zlog);
2277: ubuffree (zgrade);
2278:
2279: {
2280: long iend_time;
2281:
2282: fret = floop (&sDaemon);
2283:
2284: /* Hangup. As the answerer, we send seven O's and expect to
2285: receive six O's. We send the seven O's twice to help the other
2286: side. We don't worry about errors here. */
2287: if (fsend_uucp_cmd (qconn, "OOOOOOO")
2288: && fsend_uucp_cmd (qconn, "OOOOOOO"))
2289: {
2290: int fdone;
2291:
2292: /* We look for the remote hangup string to ensure that the
2293: modem has sent out our hangup string. This is only
2294: necessary because some versions of UUCP complain if they
2295: don't get the hangup string. We look for the string
2296: several times because supposedly some implementations send
2297: some garbage after the last packet but before the hangup
2298: string. */
2299: for (i = 0; i < 25; i++)
2300: {
2301: zstr = zget_uucp_cmd (qconn, FALSE);
2302: if (zstr == NULL)
2303: break;
2304: fdone = strstr (zstr, "OOOOOO") != NULL;
2305: ubuffree (zstr);
2306: if (fdone)
2307: break;
2308: }
2309: }
2310:
2311: iend_time = ixsysdep_time ((long *) NULL);
2312:
2313: ulog (LOG_NORMAL, "Call complete (%ld seconds)",
2314: iend_time - istart_time);
2315:
2316: uclear_queue (&sDaemon);
2317:
2318: if (fret)
2319: sstat.ttype = STATUS_COMPLETE;
2320: else
2321: sstat.ttype = STATUS_FAILED;
2322: sstat.ilast = iend_time;
2323: (void) fsysdep_set_status (qsys, &sstat);
2324:
2325: (void) uuconf_system_free (puuconf, &ssys);
2326: if (qport == &sport)
2327: (void) uuconf_port_free (puuconf, &sport);
2328: xfree ((pointer) zloc);
2329:
2330: return fret;
2331: }
2332: }
2333:
2334: /* Apply protocol parameters, once we know the protocol. */
2335:
2336: static void
2337: uapply_proto_params (puuconf, bproto, qcmds, pas)
2338: pointer puuconf;
2339: int bproto;
2340: struct uuconf_cmdtab *qcmds;
2341: struct uuconf_proto_param *pas;
2342: {
2343: struct uuconf_proto_param *qp;
2344:
2345: for (qp = pas; qp->uuconf_bproto != '\0'; qp++)
2346: {
2347: if (qp->uuconf_bproto == bproto)
2348: {
2349: struct uuconf_proto_param_entry *qe;
2350:
2351: for (qe = qp->uuconf_qentries; qe->uuconf_cargs > 0; qe++)
2352: {
2353: int iuuconf;
2354:
2355: iuuconf = uuconf_cmd_args (puuconf, qe->uuconf_cargs,
2356: qe->uuconf_pzargs, qcmds,
2357: (pointer) NULL,
2358: (uuconf_cmdtabfn) NULL, 0,
2359: (pointer) NULL);
2360: if (UUCONF_ERROR_VALUE (iuuconf) != UUCONF_SUCCESS)
2361: {
2362: ulog (LOG_ERROR, "Error in %c protocol parameters",
2363: bproto);
2364: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
2365: }
2366: }
2367:
2368: break;
2369: }
2370: }
2371: }
2372:
2373: /* Send a string to the other system beginning with a DLE
2374: character and terminated with a null byte. This is only
2375: used when no protocol is in force. */
2376:
2377: static boolean
2378: fsend_uucp_cmd (qconn, z)
2379: struct sconnection *qconn;
2380: const char *z;
2381: {
2382: size_t cwrite;
2383: char *zalc;
2384: boolean fret;
2385:
2386: DEBUG_MESSAGE1 (DEBUG_HANDSHAKE, "fsend_uucp_cmd: Sending \"%s\"", z);
2387:
2388: cwrite = strlen (z) + 2;
2389:
2390: zalc = zbufalc (cwrite);
2391: zalc[0] = '\020';
2392: memcpy (zalc + 1, z, cwrite - 1);
2393:
2394: fret = fconn_write (qconn, zalc, cwrite);
2395: ubuffree (zalc);
2396: return fret;
2397: }
2398:
2399: /* Get a UUCP command beginning with a DLE character and ending with a
2400: null byte. This is only used when no protocol is in force. This
2401: implementation has the potential of being seriously slow. It also
2402: doesn't have any real error recovery. The frequired argument is
2403: passed as TRUE if we need the string; we don't care that much if
2404: we're closing down the connection anyhow. */
2405:
2406: #define CTIMEOUT (120)
2407: #define CSHORTTIMEOUT (10)
2408: #define CINCREMENT (100)
2409:
2410: static char *
2411: zget_uucp_cmd (qconn, frequired)
2412: struct sconnection *qconn;
2413: boolean frequired;
2414: {
2415: char *zalc;
2416: size_t calc;
2417: size_t cgot;
2418: boolean fintro;
2419: long iendtime;
2420: int ctimeout;
2421: #if DEBUG > 1
2422: int cchars;
2423: int iolddebug;
2424: #endif
2425:
2426: iendtime = ixsysdep_time ((long *) NULL);
2427: if (frequired)
2428: iendtime += CTIMEOUT;
2429: else
2430: iendtime += CSHORTTIMEOUT;
2431:
2432: #if DEBUG > 1
2433: cchars = 0;
2434: iolddebug = iDebug;
2435: if (FDEBUGGING (DEBUG_HANDSHAKE))
2436: {
2437: ulog (LOG_DEBUG_START, "zget_uucp_cmd: Got \"");
2438: iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT);
2439: }
2440: #endif
2441:
2442: zalc = NULL;
2443: calc = 0;
2444: cgot = 0;
2445: fintro = FALSE;
2446: while ((ctimeout = (int) (iendtime - ixsysdep_time ((long *) NULL))) > 0)
2447: {
2448: int b;
2449:
2450: b = breceive_char (qconn, ctimeout, frequired);
2451: /* Now b == -1 on timeout, -2 on error. */
2452: if (b < 0)
2453: {
2454: #if DEBUG > 1
2455: if (FDEBUGGING (DEBUG_HANDSHAKE))
2456: {
2457: ulog (LOG_DEBUG_END, "\" (%s)",
2458: b == -1 ? "timeout" : "error");
2459: iDebug = iolddebug;
2460: }
2461: #endif
2462: if (b == -1 && frequired)
2463: ulog (LOG_ERROR, "Timeout");
2464: ubuffree (zalc);
2465: return NULL;
2466: }
2467:
2468: /* Apparently some systems use parity on these strings, so we
2469: strip the parity bit. This may need to be configurable at
2470: some point, although only if system names can have eight bit
2471: characters. */
2472: if (! isprint (BUCHAR (b)))
2473: b &= 0x7f;
2474:
2475: #if DEBUG > 1
2476: if (FDEBUGGING (DEBUG_HANDSHAKE))
2477: {
2478: char ab[5];
2479:
2480: ++cchars;
2481: if (cchars > 60)
2482: {
2483: ulog (LOG_DEBUG_END, "\"");
2484: ulog (LOG_DEBUG_START, "zget_uucp_cmd: Got \"");
2485: cchars = 0;
2486: }
2487: (void) cdebug_char (ab, b);
2488: ulog (LOG_DEBUG_CONTINUE, "%s", ab);
2489: }
2490: #endif
2491:
2492: if (! fintro)
2493: {
2494: if (b == '\020')
2495: fintro = TRUE;
2496: continue;
2497: }
2498:
2499: /* If we see another DLE, something has gone wrong; continue
2500: as though this were the first one we saw. */
2501: if (b == '\020')
2502: {
2503: cgot = 0;
2504: continue;
2505: }
2506:
2507: /* Some systems send a trailing \n on the Shere line. As far as
2508: I can tell this line can never contain a \n, so this
2509: modification should be safe enough. */
2510: if (b == '\r' || b == '\n')
2511: b = '\0';
2512:
2513: if (cgot >= calc)
2514: {
2515: char *znew;
2516:
2517: calc += CINCREMENT;
2518: znew = zbufalc (calc);
2519: memcpy (znew, zalc, cgot);
2520: ubuffree (zalc);
2521: zalc = znew;
2522: }
2523:
2524: zalc[cgot] = (char) b;
2525: ++cgot;
2526:
2527: if (b == '\0')
2528: {
2529: #if DEBUG > 1
2530: if (FDEBUGGING (DEBUG_HANDSHAKE))
2531: {
2532: ulog (LOG_DEBUG_END, "\"");
2533: iDebug = iolddebug;
2534: }
2535: #endif
2536: return zalc;
2537: }
2538: }
2539:
2540: #if DEBUG > 1
2541: if (FDEBUGGING (DEBUG_HANDSHAKE))
2542: {
2543: ulog (LOG_DEBUG_END, "\" (timeout)");
2544: iDebug = iolddebug;
2545: }
2546: #endif
2547:
2548: ubuffree (zalc);
2549:
2550: if (frequired)
2551: ulog (LOG_ERROR, "Timeout");
2552: return NULL;
2553: }
2554:
2555: /* Read a sequence of characters up to a newline or carriage return, and
2556: return the line without the line terminating character. */
2557:
2558: static char *
2559: zget_typed_line (qconn)
2560: struct sconnection *qconn;
2561: {
2562: char *zalc;
2563: size_t calc;
2564: size_t cgot;
2565:
2566: #if DEBUG > 1
2567: int cchars;
2568: int iolddebug;
2569:
2570: cchars = 0;
2571: iolddebug = iDebug;
2572: if (FDEBUGGING (DEBUG_CHAT))
2573: {
2574: ulog (LOG_DEBUG_START, "zget_typed_line: Got \"");
2575: iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT);
2576: }
2577: #endif
2578:
2579: zalc = NULL;
2580: calc = 0;
2581: cgot = 0;
2582: while (TRUE)
2583: {
2584: int b;
2585:
2586: b = breceive_char (qconn, CTIMEOUT, FALSE);
2587:
2588: /* Now b == -1 on timeout, -2 on error. */
2589:
2590: if (b == -2 || FGOT_SIGNAL ())
2591: {
2592: #if DEBUG > 1
2593: if (FDEBUGGING (DEBUG_CHAT))
2594: {
2595: ulog (LOG_DEBUG_END, "\" (error)");
2596: iDebug = iolddebug;
2597: }
2598: #endif
2599: ubuffree (zalc);
2600: return NULL;
2601: }
2602:
2603: if (b == -1)
2604: continue;
2605:
2606: #if DEBUG > 1
2607: if (FDEBUGGING (DEBUG_CHAT))
2608: {
2609: char ab[5];
2610:
2611: ++cchars;
2612: if (cchars > 60)
2613: {
2614: ulog (LOG_DEBUG_END, "\"");
2615: ulog (LOG_DEBUG_START, "zget_typed_line: Got \"");
2616: cchars = 0;
2617: }
2618: (void) cdebug_char (ab, b);
2619: ulog (LOG_DEBUG_CONTINUE, "%s", ab);
2620: }
2621: #endif
2622:
2623: if (cgot >= calc)
2624: {
2625: char *znew;
2626:
2627: calc += CINCREMENT;
2628: znew = zbufalc (calc);
2629: memcpy (znew, zalc, cgot);
2630: ubuffree (zalc);
2631: zalc = znew;
2632: }
2633:
2634: if (b == '\r' || b == '\n')
2635: b = '\0';
2636:
2637: zalc[cgot] = (char) b;
2638: ++cgot;
2639:
2640: if (b == '\0')
2641: {
2642: #if DEBUG > 1
2643: if (FDEBUGGING (DEBUG_CHAT))
2644: {
2645: ulog (LOG_DEBUG_END, "\"");
2646: iDebug = iolddebug;
2647: }
2648: #endif
2649: return zalc;
2650: }
2651: }
2652: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.