|
|
1.1 root 1: /*
2: * dcpsys.c
3: *
4: * System File Parsing and Initial Login Negotiation Routines for uucico
5: */
6:
7: /* #include <sys/dir.h> */
8: #include "dirent.h"
9: #include <ctype.h>
10: #include "dcp.h"
11: #include "lsys.h"
12:
13: /*
14: * Communication Protocol Declarations and Definitions
15: */
16:
17: #define PROTOS "g"
18: int (*getpkt)(), (*sendpkt)(), (*openpk)(), (*closepk)();
19:
20: extern int ggetpkt(), gsendpkt(), gopenpk(), gclosepk();
21: #if 0
22: extern int kgetpkt(), ksendpkt(), kopenpk(), kclosepk();
23: extern int rgetpkt(), rsendpkt(), ropenpk(), rclosepk();
24: extern int tgetpkt(), tsendpkt(), topenpk(), tclosepk();
25: #endif
26:
27: typedef struct proto {
28: char type; /* One character Protocol Type */
29: int (*getpkt)(); /* Get Packet Function */
30: int (*sendpkt)(); /* Send Packet Function */
31: int (*openpk)(); /* Open Packet Function */
32: int (*closepk)(); /* Close Packet Function */
33: } PROTO;
34:
35: PROTO protolst[] =
36: {
37: { 'g', ggetpkt, gsendpkt, gopenpk, gclosepk },
38: #if 0
39: { 'k', kgetpkt, ksendpkt, kopenpk, kclosepk },
40: { 'r', rgetpkt, rsendpkt, ropenpk, rclosepk },
41: { 't', tgetpkt, tsendpkt, topenpk, tclosepk },
42: #endif
43: { '\0' }
44: };
45:
46: int leavelock = 0; /* Leave the rmtname lock file */
47:
48: /*
49: * getsystem()
50: * Retrieve and Process an "L.sys" file entry.
51: */
52:
53: getsystem()
54: {
55: if ( lsys_next() == 0 )
56: return('A');
57:
58: rmtname = lsys_value(sys_e);
59: if ( strcmp(rmtname, sysname) ) {
60: if ( strcmp(sysname, "all") && strcmp(sysname, "any") )
61: return('I');
62: if ( scandir() != 'S' )
63: return('I');
64: }
65: printmsg(M_CALL, "Thinking of calling system: %s", rmtname);
66: if ( !checktime(lsys_value(sched_e)) )
67: return('I');
68:
69: open_the_logfile("uucico");
70: if (cfp != NULL)
71: fclose(cfp); /* in case matched scandir */
72: if ( lockit(rmtname) < 0 ) {
73: plog(M_CALL, "Site Locked: %s", rmtname);
74: close_logfile();
75: return('I');
76: }
77: return('S');
78: }
79:
80: /*
81: * checkrmt()
82: * Scan through L.sys file to verify that we know about the given
83: * remote system name.
84: * Returns: (1) if we found match, (0) if rmtname unknown.
85: */
86:
87: checkrmt()
88: {
89: lsys_open();
90: while ( lsys_next() ) {
91: if ( strcmp(rmtname, lsys_value(sys_e)) == 0 )
92: return(1);
93: }
94: lsys_close();
95: return(0);
96: }
97:
98: /*
99: * rmsg(msg, maxlen) char *msg; int maxlen;
100: * Read a ^P (DLE) type msg from the remote uucp. (startup negotiation).
101: *
102: * wmsg(msg) char *msg;
103: * Write a ^P (DLE) type msg to the remote uucp. (startup negotiation).
104: */
105:
106: #define MAXDROP 2048 /* Maximum characters to drop waiting for ^P */
107:
108: rmsg(msg, maxlen)
109: char *msg;
110: int maxlen;
111: {
112: char ch;
113: register char *cp;
114: int i;
115:
116: for (i=0; i<MAXDROP; i++) {
117: if ( sread(&ch, 1, MSGTIME) != 1 ){
118: goto badrmsg;
119: }
120: if ( ch == DLE )
121: break;
122: }
123:
124:
125: if ( ch != DLE ){
126: goto nodle;
127: }
128:
129: for (cp=msg,i=1; i<maxlen; i++) {
130: if ( sread(&ch, 1, MSGTIME) != 1 )
131: goto badrmsg;
132: if ( (ch == '\0') || (ch == '\r') || (ch == '\n') )
133: break;
134: *cp++ = ch;
135: }
136: *cp = '\0';
137: printmsg(M_DEBUG, "rmsg {%s}", visib(msg));
138: return( strlen(msg) );
139:
140: badrmsg:
141: /* *cp = '\0'; this is a NONO, cp never has valid characters here
142: * when we've determined that we were missing DLE
143: */
144: printmsg(M_CALL, "Bad received message {%s}", visib(msg));
145: return(-1);
146: nodle:
147: /* *cp = '\0'; this is a NONO, cp never has valid characters here */
148: printmsg(M_CALL, "Remote machine not sending DLE startup (uucico)");
149: return(-1);
150: }
151:
152: wmsg(msg)
153: char *msg;
154: {
155: char buf[2] = {'\0', DLE};
156:
157: printmsg(M_DEBUG, "wmsg {%s}", visib(msg));
158: swrite(&buf[0], 2);
159: swrite(msg, strlen(msg));
160: swrite(&buf[0], 1);
161: }
162:
163: /*
164: * startup()
165: *
166: * Initiate communication with a remote uucp.
167: */
168:
169: #define FAIL1(x) {errmsg=(x); errarg=NULL; goto failure;}
170: #define FAIL2(x, y) {errmsg=(x); errarg=(y); goto failure;}
171:
172: startup()
173: {
174: char msg[BUFSIZ];
175: char *errmsg, *errarg, *cp, ch;
176: static char locbuf[SITELEN+1];
177: static char *readymsg = "Ready for transactions";
178:
179: sysended = 0;
180: leavelock = 0;
181: if (role == MASTER) {
182: if ( rmsg(msg, BUFSIZ) < 0 ){
183: FAIL1("Logon failed: 1st msg (broken communication?)");
184: }
185: printmsg(M_CALLMSG, "1st msg = {%s}", visib(msg));
186: if ( strncmp(msg, "Shere", 5) ){
187: FAIL1("Bad format for 1st msg");
188: }
189: if ( (msg[5] == '\0') || (msg[5] == '\n') ||
190: (msg[6] == '\0') || (msg[6] == '\n') )
191: plog(M_CALL, "Warning: Null sitename contacted");
192: else if ( strncmp(&msg[6], rmtname, SITESIG) )
193: FAIL2("Incorrect sitename contacted: %s", &msg[6]);
194:
195: sprintf(msg, "S%.*s -Q0 -x%d", SITESIG, nodename, debuglevel);
196: printmsg(M_CALLMSG, "Reply to 1st msg = {%s}", msg);
197: wmsg(msg);
198:
199: if ( rmsg(msg, BUFSIZ) < 0 )
200: FAIL1("Logon failed: 2nd msg (remote site stale LCK?)");
201:
202: printmsg(M_CALLMSG, "2nd msg = {%s}", visib(msg));
203: if ( strncmp(msg, "ROK", 2) )
204: FAIL1("Bad format for 2nd msg");
205:
206: if ( rmsg(msg, BUFSIZ) < 0 )
207: FAIL1("Logon failed: 3rd msg (broken communication?)");
208: printmsg(M_CALLMSG, "3rd msg = {%s}", visib(msg));
209: if ( *msg != 'P' )
210: FAIL1("Bad format for 3rd msg");
211: ch = 'N';
212: for (cp=PROTOS; *cp; cp++)
213: if ( index(&msg[1], *cp) != NULL ) {
214: ch = *cp;
215: break;
216: }
217: sprintf(msg, "U%c", ch);
218: printmsg(M_CALLMSG, "Reply to 3rd msg = {%s}", msg);
219: wmsg(msg);
220: if ( ch == 'N' )
221: FAIL1("No common protocol");
222: setproto(ch);
223: plog(M_CALL, readymsg);
224: return('D');
225: } else {
226: sprintf(msg, "Shere=%s", nodename);
227: printmsg(M_CALLMSG, "1st msg = {%s}", msg);
228: wmsg(msg);
229:
230: if ( rmsg(msg, BUFSIZ) < 0 )
231: FAIL1("Logon failed: 1st reply (wrong sitename?)");
232: printmsg(M_CALLMSG, "Reply to 1st msg = {%s}", visib(msg));
233: if ( *msg != 'S' )
234: FAIL1("Bad format for reply to 1st msg");
235: if ( (cp=index(msg+1, ' ')) != NULL )
236: *cp = '\0';
237: if ( strlen(msg) > (SITELEN+1) )
238: FAIL1("Received sitename to long");
239: strcpy(locbuf, msg+1);
240: rmtname = &locbuf[0];
241: #ifdef BBS
242: #define BBSUSER "bbsuser"
243:
244: /*
245: * For BBS, anonymous caller's sitename is replaced by the
246: * device name, notice we skip over "/dev/".
247: */
248: {
249: char *tmp;
250:
251: if ( (strcmp(rmtname, BBSUSER) == 0) &&
252: ((tmp=ttyname(fileno(stdin))) != NULL) )
253: sprintf(locbuf, "U%s", tmp+5);
254: printmsg(M_DEBUG, "BBS replaced new rmtname: <%s>",
255: rmtname);
256: }
257: #endif
258: open_the_logfile("uucico");
259: plog(M_CALL, "Call received from %s {%d} (V%s)",
260: rmtname, processid, version);
261: plog(M_CALL,"Locking remote site %s",rmtname);
262: if ( lockit(rmtname) < 0 ) {
263: leavelock = 1;
264: FAIL2("Incoming site %s already locked", rmtname);
265: }
266:
267: if ( !checkrmt() )
268: FAIL2("Unknown host %s", rmtname);
269:
270: if ( (rdevname=ttyname(fileno(stdin))) == NULL )
271: FAIL1("No attached tty device.");
272: rdevname += 5;
273:
274: /* The incoming device will already have been locked by login. */
275: if (MASTER == role) {
276: if ( locktty(rdevname) < 0 ) {
277: cp = rdevname;
278: rdevname = NULL;
279: FAIL2("Incoming device locked: %s", cp);
280: }
281: }
282:
283: sprintf(msg, "ROK");
284: printmsg(M_CALLMSG, "2nd msg = {%s}", msg);
285: wmsg(msg);
286: sprintf(msg, "P%s", PROTOS);
287: printmsg(M_CALLMSG, "3rd msg = {%s}", msg);
288: wmsg(msg);
289: if ( rmsg(msg, BUFSIZ) < 0 )
290: FAIL1("Logon failure: 3rd reply (lost communication?)");
291: printmsg(M_CALLMSG, "Reply to 3rd msg = {%s}", visib(msg));
292: if ( (msg[0] != 'U') || (index(PROTOS, msg[1]) == NULL) )
293: FAIL1("No common communications protocol");
294: setproto(msg[1]);
295: plog(M_CALL, readymsg);
296: return('R');
297: }
298:
299: failure:
300: plog(M_CALL, errmsg, errarg);
301: terminatelevel++;
302: return('Y');
303: }
304:
305: /*
306: * Assign the global protocol function variables to the specified
307: * protocol type.
308: */
309:
310: setproto(type)
311: char type;
312: {
313: register PROTO *p;
314:
315: for(p=&protolst[0]; (p->type!='\0') && (p->type!=type); p++) ;
316:
317: if (p->type == '\0')
318: fatal("setproto('%c'): Unknown protocol type", type);
319: printmsg(M_CALL, "Agreed protocol: %c", type);
320: getpkt = p->getpkt;
321: sendpkt = p->sendpkt;
322: openpk = p->openpk;
323: closepk = p->closepk;
324:
325: }
326:
327: /*
328: * expectstr(str, timeout) char *str; int timeout;
329: *
330: * Wait to receive the specified "str" from the serial connection.
331: * Returns: (1) if string received,
332: * (0) for timeout occurred before string received.
333: */
334:
335: expectstr(str, timeout)
336: char *str;
337: int timeout;
338: {
339: register char *cp;
340: char buf[BUFSIZ], ch;
341: int retval = 0;
342: int len;
343:
344: printmsg(M_DEBUG, "waiting for {%s}", str);
345:
346: if ( strcmp(str, "\"\"") == 0 )
347: retval = 1;
348: len = strlen(str);
349:
350: cp = &buf[0];
351: while ( !retval && (sread(&ch, 1, timeout) == 1) ) {
352: *cp++ = ch;
353: if ( (cp-buf) < len )
354: continue;
355: *cp = '\0';
356: if ( strncmp(str, cp-len, len) == 0 )
357: retval = 1;
358: if ( cp == &buf[BUFSIZ-1] )
359: break;
360: }
361: printmsg(M_CALL, "actually received {%s}", visbuf(buf, cp-buf));
362: if ( retval )
363: printmsg(M_CALL, "got that");
364: return(retval);
365: }
366:
367: /*
368: * sendstr(str) char *str;
369: * Send string of chat script out the communications line.
370: */
371:
372: sendstr(str)
373: char *str;
374: {
375: register char *cp = str;
376: char ch;
377: int slash, nocr;
378:
379: sleep(1);
380: if ( strncmp(str, "\"\"", 2) == 0 )
381: str = "";
382:
383: nocr = slash = 0;
384: while ( (ch=*cp++) ) {
385: if ( !slash ) {
386: if ( strncmp(cp-1, "EOT", 3) == 0 ) {
387: swrite("\004", 1);
388: cp += 2;
389: } else if ( strncmp(cp-1, "BREAK", 4) == 0 ) {
390: sendbrk();
391: cp += 4;
392: } else if ( ch == '\\' ) {
393: slash = 1;
394: } else {
395: swrite(&ch, 1);
396: }
397: continue;
398: }
399: switch( ch ) {
400: case 'b':
401: swrite("\b", 1);
402: break;
403: case 'c':
404: nocr = 1;
405: break;
406: case 'd':
407: sleep(2);
408: break;
409: case 'K':
410: sendbrk();
411: break;
412: case 'n':
413: swrite("\n", 1);
414: break;
415: case 'N':
416: swrite("\0", 1);
417: break;
418: case 'p':
419: sleep(1);
420: break;
421: case 'r':
422: swrite("\r", 1);
423: break;
424: case 's':
425: swrite(" ", 1);
426: break;
427: case 't':
428: swrite("\t", 1);
429: break;
430: case '\\':
431: swrite("\\", 1);
432: break;
433: default:
434: if ( !isdigit(ch) ||
435: !isdigit(*cp) ||
436: !isdigit(*(cp+1)) )
437: fatal("Can't parse chat script: {%s}", str);
438: ch = ((ch-'0')<<6) | ((*cp-'0')<<3) | (*(cp+1));
439: swrite(&ch, 1);
440: break;
441: }
442: slash = 0;
443: }
444: if ( !nocr ){
445: swrite("\r", 1);
446: }
447: }
448:
449: /*
450: * callup()
451: * Initiate the call, and walk through the chat script.
452: */
453:
454: callup()
455: {
456: char *device, *speed, *phone;
457: char *expect, *send, *dsh;
458: int i;
459:
460: plog(M_CALL, "Calling site %s {%d} (V%s)", rmtname, processid, version);
461:
462: device = lsys_value(device_e);
463: speed = lsys_value(speed_e);
464: phone = lsys_value(phone_e);
465:
466: if ( strcmp(device, "ACU") == 0 ) {
467: if ( !dcpdial(NULL, speed, phone) )
468: goto calluperr;
469: } else if ( !dcpdial(device, speed, NULL) )
470: goto calluperr;
471:
472: for (i=0; (expect=lsys_expect(i)) != NULL; i++) {
473: for (;;) {
474: printmsg(M_CALL, "callup: expecting {%s}", expect);
475: if ( (dsh=index(expect, '-')) != NULL )
476: *dsh++ = '\0';
477: if ( expectstr(expect, MSGTIME) )
478: break;
479: if ( dsh == NULL ) {
480: plog(M_CALL, "Login failed.");
481: goto calluperr;
482: }
483: if ( (expect=index(dsh, '-')) == NULL )
484: fatal("Chat script syntax error: %s", dsh);
485: *expect++ = '\0';
486: printmsg(M_CALL, "callup: send alternate {%s}", dsh);
487: sendstr(dsh);
488: }
489: send = lsys_send(i);
490: printmsg(M_CALL, "callup: sending {%s}", send);
491: sendstr(send);
492: }
493: return('P');
494:
495: calluperr:
496: terminatelevel++;
497: return('Y');
498: }
499:
500: /*
501: * sysend()
502: * End UUCP session.
503: */
504:
505: sysend()
506: {
507:
508: /* We may have a problem here. Someone else may be removing the remote
509: * device lock file before we call unlocktty. Tests have shown this to
510: * be unimportant because the lock file IS being removed. A warning
511: * will be printed to the log files for users to check for locks.
512: * Hopefully, this isn't going to be a bug. Bob H. 11/22/91.
513: */
514:
515: /* December 4, 1991: Problem solved(?). When we are in master mode,
516: * we call dcpundial, which calls the hangup, which, in turn, calls
517: * undial. Undial removes the locks on the device. Thie following
518: * code USED to call dcpundial if in master mode, and THEN continued
519: * to call the unlocktty function, which had previously been called
520: * by dcpundial. I snuck in an 'else' statement to get around this.
521: * Tests show that this solves the problem described above, but who
522: * knows if this will cause problems when we are NOT in master mode.
523: */
524:
525: if ( role == MASTER ){
526: printmsg(M_DEBUG,"Sysend: calling undial and hangup routines.");
527: dcpundial();
528: }else{
529: plog(M_CALL,"Sysend: Removing remote device lock file.");
530: if(unlocktty(rdevname) != 0){
531: plog(M_CALL,"sysend: Possible lock file removal failure.");
532: }
533: }
534:
535:
536: /* May 05, 1992 (Bob H.) problems communicating with a 386 based bbs
537: * and a customer complaint from Germany lead to the discovery of a
538: * condition where undial() was never called, which meant that cicio
539: * NEVER hung up the phone! Adding the dcpundial() in the following
540: * if... resolves this.
541: */
542: if ( !leavelock && lockexist(rmtname) ){
543: dcpundial();
544: plog(M_CALL,"Removing remote site lock");
545: if (lockexist(rmtname)){
546: #ifndef _I386
547: if (lockrm(rmtname)!= 0) {
548: #else
549: if (!lockrm(rmtname)) {
550: #endif
551: printmsg(M_LOG,"sysend: Remote site Lock file removal failed!");
552: plog(M_CALL,"sysend: Remote site lock file removal failed!");
553: }
554: }
555: }
556: plog(M_CALL, terminatelevel ?
557: "Abnormal completion {%d}" :
558: "Call completing normally {%d}", processid);
559: close_logfile();
560: sysended = 1;
561: return( (role == MASTER) ? 'I': 'A' );
562: }
563:
564: /*
565: * scandir()
566: *
567: * scan work dir for "C." files matching current remote host (rmtname)
568: * return:
569: * Y - can't open file
570: * S - ok
571: * Q - no files
572: */
573:
574: extern DIR *opendir();
575: extern struct direct *readdir();
576:
577: scandir()
578: {
579: char fn[DIRSIZ+1];
580: char dirname[CTLFLEN];
581: DIR *dirp;
582: struct dirent *dp;
583:
584: sprintf(dirname, "%s/%s", SPOOLDIR, rmtname); /* build spool dir name */
585: printmsg(M_INFO, "Scandir: %s", dirname);
586:
587: if ((dirp=opendir(dirname)) == NULL) /* open spool dir */
588: return('Q');
589:
590: fn[0] = fn[DIRSIZ] = '\0';
591: while ( (dp=readdir(dirp)) != NULL ) {
592: printmsg(M_DEBUG, "Scandir: %s", dp->d_name);
593: if ( strncmp("C.", dp->d_name, 2) ) /* is this a C. file? */
594: continue;
595: if ( (fn[0] == '\0') || (strncmp(dp->d_name, fn, DIRSIZ) < 0) )
596: strncpy(fn, dp->d_name, DIRSIZ);
597: }
598: closedir(dirp);
599:
600: if (fn[0] != '\0') {
601: sprintf(cfile, "%s/%s/%s", SPOOLDIR, rmtname, fn);
602: printmsg(M_DEBUG, "Scandir: cfile: %s", cfile);
603: if ((cfp = fopen(cfile, "r")) == NULL) {
604: plog(M_DEBUG, "Unable to open control file %s", cfile);
605: terminatelevel++;
606: return('Y');
607: }
608: return('S');
609: }
610: return('Q');
611: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.