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