Commit | Line | Data |
---|---|---|
ce5db1eb | 1 | #ifndef lint |
7ebaa22e | 2 | static char sccsid[] = "@(#)cico.c 5.10 (Berkeley) %G%"; |
ce5db1eb SL |
3 | #endif |
4 | ||
ce5db1eb | 5 | #include <signal.h> |
4b31fbb4 | 6 | #include "uucp.h" |
ce5db1eb | 7 | #include <setjmp.h> |
88db71e9 | 8 | #ifdef USG |
ce5db1eb SL |
9 | #include <termio.h> |
10 | #endif | |
88db71e9 | 11 | #ifndef USG |
ce5db1eb SL |
12 | #include <sgtty.h> |
13 | #endif | |
88db71e9 RC |
14 | #ifdef BSDTCP |
15 | #include <netdb.h> | |
16 | #include <netinet/in.h> | |
17 | #include <sys/socket.h> | |
18 | #endif BSDTCP | |
19 | #include <sys/stat.h> | |
20 | #include "uust.h" | |
21 | #include "uusub.h" | |
ce5db1eb | 22 | |
4b31fbb4 JB |
23 | #if defined(VMS) && defined(BSDTCP) |
24 | #define NOGETPEER | |
25 | #endif | |
26 | ||
27 | #ifdef BSD2_9 | |
28 | #define NOGETPEER | |
29 | #endif | |
30 | ||
ce5db1eb | 31 | jmp_buf Sjbuf; |
88db71e9 RC |
32 | jmp_buf Pipebuf; |
33 | ||
34 | /* call fail text */ | |
ce5db1eb SL |
35 | char *Stattext[] = { |
36 | "", | |
37 | "BAD SYSTEM", | |
88db71e9 | 38 | "WRONG TIME TO CALL", |
ce5db1eb SL |
39 | "SYSTEM LOCKED", |
40 | "NO DEVICE", | |
41 | "DIAL FAILED", | |
42 | "LOGIN FAILED", | |
43 | "BAD SEQUENCE" | |
88db71e9 | 44 | }; |
ce5db1eb | 45 | |
88db71e9 RC |
46 | /* call fail codes */ |
47 | int Stattype[] = { | |
48 | 0, | |
49 | 0, | |
50 | SS_WRONGTIME, | |
51 | 0, | |
52 | SS_NODEVICE, | |
53 | SS_FAIL, | |
54 | SS_FAIL, | |
55 | SS_BADSEQ | |
56 | }; | |
ce5db1eb SL |
57 | |
58 | ||
88db71e9 RC |
59 | int ReverseRole = 0; |
60 | int StdErrIsTty = 0; | |
61 | int Role = SLAVE; | |
62 | int onesys = 0; | |
1a85e9d2 | 63 | int turntime = 30 * 60; /* 30 minutes expressed in seconds */ |
88db71e9 | 64 | extern int LocalOnly; |
1a85e9d2 RC |
65 | extern char MaxGrade, DefMaxGrade; |
66 | extern char Myfullname[]; | |
88db71e9 RC |
67 | |
68 | #ifdef USG | |
ce5db1eb SL |
69 | struct termio Savettyb; |
70 | #endif | |
88db71e9 | 71 | #ifndef USG |
ce5db1eb SL |
72 | struct sgttyb Savettyb; |
73 | #endif | |
74 | ||
75 | /******* | |
76 | * cico - this program is used to place a call to a | |
77 | * remote machine, login, and copy files between the two machines. | |
78 | */ | |
79 | ||
80 | main(argc, argv) | |
81 | register char *argv[]; | |
82 | { | |
83 | register int ret; | |
84 | int seq; | |
ce5db1eb | 85 | char wkpre[NAMESIZE], file[NAMESIZE]; |
88db71e9 | 86 | char msg[MAXFULLNAME], *q, **alias; |
ce5db1eb SL |
87 | register char *p; |
88 | extern onintr(), timeout(), setdebug(); | |
ce5db1eb | 89 | extern char *pskip(); |
a534f0fb | 90 | char rflags[MAXFULLNAME]; |
ce5db1eb | 91 | char *ttyn; |
4b31fbb4 | 92 | #ifdef NOGETPEER |
88db71e9 | 93 | u_long Hostnumber = 0; |
4b31fbb4 | 94 | #endif NOGETPEER |
ce5db1eb SL |
95 | |
96 | strcpy(Progname, "uucico"); | |
ce5db1eb | 97 | |
ce5db1eb SL |
98 | signal(SIGINT, onintr); |
99 | signal(SIGHUP, onintr); | |
100 | signal(SIGQUIT, onintr); | |
101 | signal(SIGTERM, onintr); | |
102 | signal(SIGPIPE, onintr); /* 4.1a tcp-ip stupidity */ | |
103 | signal(SIGFPE, setdebug); | |
104 | ret = guinfo(getuid(), User, msg); | |
105 | strcpy(Loginuser, User); | |
4b31fbb4 | 106 | uucpname(Myname); |
88db71e9 | 107 | ASSERT(ret == 0, "BAD UID", CNULL, ret); |
ce5db1eb | 108 | |
88db71e9 RC |
109 | #ifdef BSD4_2 |
110 | setlinebuf(stderr); | |
111 | #endif | |
ce5db1eb SL |
112 | umask(WFMASK); |
113 | strcpy(Rmtname, Myname); | |
114 | Ifn = Ofn = -1; | |
115 | while(argc>1 && argv[1][0] == '-'){ | |
116 | switch(argv[1][1]){ | |
117 | case 'd': | |
118 | Spool = &argv[1][2]; | |
119 | break; | |
ce5db1eb | 120 | case 'g': |
1a85e9d2 RC |
121 | case 'p': |
122 | MaxGrade = DefMaxGrade = argv[1][2]; | |
ce5db1eb | 123 | break; |
ce5db1eb SL |
124 | case 'r': |
125 | Role = atoi(&argv[1][2]); | |
126 | break; | |
88db71e9 RC |
127 | case 'R': |
128 | ReverseRole++; | |
129 | Role = MASTER; | |
130 | break; | |
ce5db1eb | 131 | case 's': |
4b31fbb4 JB |
132 | strncpy(Rmtname, &argv[1][2], MAXBASENAME); |
133 | Rmtname[MAXBASENAME] = '\0'; | |
ce5db1eb SL |
134 | if (Rmtname[0] != '\0') |
135 | onesys = 1; | |
136 | break; | |
137 | case 'x': | |
88db71e9 | 138 | chkdebug(); |
ce5db1eb SL |
139 | Debug = atoi(&argv[1][2]); |
140 | if (Debug <= 0) | |
141 | Debug = 1; | |
ce5db1eb SL |
142 | logent("ENABLED", "DEBUG"); |
143 | break; | |
1a85e9d2 RC |
144 | case 't': |
145 | turntime = atoi(&argv[1][2])*60;/* minutes to seconds */ | |
146 | break; | |
88db71e9 RC |
147 | case 'L': /* local calls only */ |
148 | LocalOnly++; | |
149 | break; | |
4b31fbb4 | 150 | #ifdef NOGETPEER |
88db71e9 RC |
151 | case 'h': |
152 | Hostnumber = inet_addr(&argv[1][2]); | |
153 | break; | |
4b31fbb4 | 154 | #endif NOGETPEER |
ce5db1eb | 155 | default: |
88db71e9 | 156 | printf("unknown flag %s (ignored)\n", argv[1]); |
ce5db1eb SL |
157 | break; |
158 | } | |
159 | --argc; argv++; | |
160 | } | |
161 | ||
88db71e9 RC |
162 | while (argc > 1) { |
163 | printf("unknown argument %s (ignored)\n", argv[1]); | |
164 | --argc; argv++; | |
165 | } | |
ce5db1eb | 166 | |
01af9d69 | 167 | /* Try to run as uucp */ |
88db71e9 RC |
168 | setgid(getegid()); |
169 | setuid(geteuid()); | |
170 | #ifdef TIOCNOTTY | |
171 | /* | |
172 | * detach uucico from controlling terminal | |
173 | * to defend against rlogind sending us a SIGKILL (!!!) | |
174 | */ | |
175 | if (Role == MASTER && (ret = open("/dev/tty", 2)) >= 0) { | |
176 | ioctl(ret, TIOCNOTTY, STBNULL); | |
177 | close(ret); | |
ce5db1eb | 178 | } |
88db71e9 RC |
179 | #endif TIOCNOTTY |
180 | #ifdef BSD4_2 | |
7ebaa22e | 181 | if (getpgrp(0) == 0) { /* We have no controlling terminal */ |
88db71e9 RC |
182 | setpgrp(0, getpid()); |
183 | } | |
184 | #endif BSD4_2 | |
185 | ||
186 | ret = subchdir(Spool); | |
187 | ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret); | |
188 | strcpy(Wrkdir, Spool); | |
189 | ||
ce5db1eb | 190 | if (Role == SLAVE) { |
88db71e9 | 191 | /* check for /etc/nologin */ |
01af9d69 | 192 | if (access(NOLOGIN, 0) == 0) { |
88db71e9 | 193 | logent(NOLOGIN, "UUCICO SHUTDOWN"); |
4b31fbb4 | 194 | if (Debug > 4) |
88db71e9 RC |
195 | logent("DEBUGGING", "continuing anyway"); |
196 | else | |
197 | cleanup(1); | |
198 | } | |
199 | #ifdef TCPIP | |
200 | /* | |
201 | * Determine if we are on TCPIP | |
202 | */ | |
203 | if (isatty(0) == 0) { | |
204 | IsTcpIp = 1; | |
205 | DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL); | |
4b31fbb4 JB |
206 | } else |
207 | IsTcpIp = 0; | |
88db71e9 | 208 | #endif TCPIP |
ce5db1eb SL |
209 | /* initial handshake */ |
210 | onesys = 1; | |
88db71e9 RC |
211 | if (!IsTcpIp) { |
212 | #ifdef USG | |
ce5db1eb SL |
213 | ret = ioctl(0, TCGETA, &Savettyb); |
214 | Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7; | |
215 | Savettyb.c_oflag |= OPOST; | |
216 | Savettyb.c_lflag |= (ISIG|ICANON|ECHO); | |
88db71e9 | 217 | #else !USG |
ce5db1eb SL |
218 | ret = ioctl(0, TIOCGETP, &Savettyb); |
219 | Savettyb.sg_flags |= ECHO; | |
220 | Savettyb.sg_flags &= ~RAW; | |
88db71e9 | 221 | #endif !USG |
ce5db1eb SL |
222 | } |
223 | Ifn = 0; | |
224 | Ofn = 1; | |
225 | fixmode(Ifn); | |
7ebaa22e | 226 | getbaud(Ifn); |
88db71e9 RC |
227 | sprintf(file,"%s/%d", RMTDEBUG, getpid()); |
228 | #ifdef VMS | |
229 | /* hold the version number down */ | |
230 | unlink(file); | |
4b31fbb4 | 231 | #endif VMS |
88db71e9 RC |
232 | freopen(file, "w", stderr); |
233 | #ifdef BSD4_2 | |
234 | setlinebuf(stderr); | |
235 | #else !BSD4_2 | |
236 | setbuf(stderr, NULL); | |
237 | #endif !BSD4_2 | |
1a85e9d2 | 238 | sprintf(msg, "here=%s", Myfullname); |
88db71e9 | 239 | omsg('S', msg, Ofn); |
ce5db1eb SL |
240 | signal(SIGALRM, timeout); |
241 | alarm(MAXMSGTIME); | |
242 | if (setjmp(Sjbuf)) { | |
243 | /* timed out */ | |
88db71e9 RC |
244 | if (!IsTcpIp) { |
245 | #ifdef USG | |
ce5db1eb | 246 | ret = ioctl(0, TCSETA, &Savettyb); |
4b31fbb4 | 247 | #else !USG |
ce5db1eb | 248 | ret = ioctl(0, TIOCSETP, &Savettyb); |
4b31fbb4 | 249 | #endif !USG |
ce5db1eb | 250 | } |
88db71e9 | 251 | cleanup(0); |
ce5db1eb SL |
252 | } |
253 | for (;;) { | |
254 | ret = imsg(msg, Ifn); | |
255 | if (ret != 0) { | |
256 | alarm(0); | |
88db71e9 RC |
257 | if (!IsTcpIp) { |
258 | #ifdef USG | |
ce5db1eb | 259 | ret = ioctl(0, TCSETA, &Savettyb); |
4b31fbb4 | 260 | #else !USG |
ce5db1eb | 261 | ret = ioctl(0, TIOCSETP, &Savettyb); |
4b31fbb4 | 262 | #endif !USG |
ce5db1eb | 263 | } |
88db71e9 | 264 | cleanup(0); |
ce5db1eb SL |
265 | } |
266 | if (msg[0] == 'S') | |
267 | break; | |
268 | } | |
269 | alarm(0); | |
270 | q = &msg[1]; | |
271 | p = pskip(q); | |
4b31fbb4 JB |
272 | strncpy(Rmtname, q, MAXBASENAME); |
273 | Rmtname[MAXBASENAME] = '\0'; | |
88db71e9 RC |
274 | sprintf(wkpre,"%s/%s", RMTDEBUG, Rmtname); |
275 | unlink(wkpre); | |
276 | if (link(file, wkpre) == 0) | |
277 | unlink(file); | |
ce5db1eb | 278 | DEBUG(4, "sys-%s\n", Rmtname); |
a534f0fb | 279 | /* The versys will also do an alias on the incoming name */ |
4b31fbb4 | 280 | if (versys(&Rmtname)) { |
a534f0fb JB |
281 | /* If we don't know them, we won't talk to them... */ |
282 | #ifdef NOSTRANGERS | |
4b31fbb4 JB |
283 | logent(Rmtname, "UNKNOWN HOST"); |
284 | omsg('R', "You are unknown to me", Ofn); | |
285 | cleanup(0); | |
4b31fbb4 | 286 | #endif NOSTRANGERS |
a534f0fb | 287 | } |
88db71e9 RC |
288 | #ifdef BSDTCP |
289 | /* we must make sure they are really who they say they | |
290 | * are. We compare the hostnumber with the number in the hosts | |
291 | * table for the site they claim to be. | |
292 | */ | |
293 | if (IsTcpIp) { | |
294 | struct hostent *hp; | |
295 | char *cpnt, *inet_ntoa(); | |
01af9d69 | 296 | int len; |
88db71e9 | 297 | struct sockaddr_in from; |
01af9d69 | 298 | extern char PhoneNumber[]; |
88db71e9 | 299 | |
4b31fbb4 JB |
300 | #ifdef NOGETPEER |
301 | from.sin_addr.s_addr = Hostnumber; | |
302 | from.sin_family = AF_INET; | |
303 | #else !NOGETPEER | |
01af9d69 JB |
304 | len = sizeof(from); |
305 | if (getpeername(0, &from, &len) < 0) { | |
88db71e9 RC |
306 | logent(Rmtname, "NOT A TCP CONNECTION"); |
307 | omsg('R', "NOT TCP", Ofn); | |
308 | cleanup(0); | |
309 | } | |
4b31fbb4 | 310 | #endif !NOGETPEER |
88db71e9 RC |
311 | hp = gethostbyaddr(&from.sin_addr, |
312 | sizeof (struct in_addr), from.sin_family); | |
313 | if (hp == 0) { | |
314 | /* security break or just old host table? */ | |
315 | logent(Rmtname, "UNKNOWN IP-HOST Name ="); | |
316 | cpnt = inet_ntoa(from.sin_addr), | |
317 | logent(cpnt, "UNKNOWN IP-HOST Number ="); | |
318 | sprintf(wkpre, "%s/%s isn't in my host table", | |
319 | Rmtname, cpnt); | |
320 | omsg('R' ,wkpre ,Ofn); | |
321 | cleanup(0); | |
322 | } | |
323 | if (Debug>99) | |
324 | logent(Rmtname,"Request from IP-Host name ="); | |
01af9d69 JB |
325 | /* |
326 | * The following is to determine if the name given us by | |
327 | * the Remote uucico matches any of the names | |
88db71e9 RC |
328 | * given its network number (remote machine) in our |
329 | * host table. | |
01af9d69 JB |
330 | * We could check the aliases, but that won't work in |
331 | * all cases (like if you are running the domain | |
332 | * server, where you don't get any aliases). The only | |
333 | * reliable way I can think of that works in ALL cases | |
334 | * is too look up the site in L.sys and see if the | |
335 | * sitename matches what we would call him if we | |
336 | * originated the call. | |
88db71e9 | 337 | */ |
01af9d69 JB |
338 | /* PhoneNumber contains the official network name of the host we are checking. (set in versys.c) */ |
339 | if (sncncmp(PhoneNumber, hp->h_name, SYSNSIZE) == 0) { | |
88db71e9 RC |
340 | if (Debug > 99) |
341 | logent(q,"Found in host Tables"); | |
01af9d69 JB |
342 | } else { |
343 | logent(hp->h_name, "FORGED HOSTNAME"); | |
344 | logent(inet_ntoa(from.sin_addr), "ORIGINATED AT"); | |
345 | logent(PhoneNumber, "SHOULD BE"); | |
346 | sprintf(wkpre, "You're not who you claim to be: %s != %s", hp->h_name, PhoneNumber); | |
347 | omsg('R', wkpre, Ofn); | |
348 | cleanup(0); | |
88db71e9 RC |
349 | } |
350 | } | |
351 | #endif BSDTCP | |
352 | ||
01af9d69 | 353 | if (mlock(Rmtname) == FAIL) { |
ce5db1eb SL |
354 | omsg('R', "LCK", Ofn); |
355 | cleanup(0); | |
356 | } | |
357 | else if (callback(Loginuser)) { | |
358 | signal(SIGINT, SIG_IGN); | |
359 | signal(SIGHUP, SIG_IGN); | |
360 | omsg('R', "CB", Ofn); | |
361 | logent("CALLBACK", "REQUIRED"); | |
362 | /* set up for call back */ | |
88db71e9 | 363 | systat(Rmtname, SS_CALLBACK, "CALLING BACK"); |
ce5db1eb SL |
364 | gename(CMDPRE, Rmtname, 'C', file); |
365 | close(creat(subfile(file), 0666)); | |
366 | xuucico(Rmtname); | |
367 | cleanup(0); | |
368 | } | |
369 | seq = 0; | |
370 | while (*p == '-') { | |
371 | q = pskip(p); | |
372 | switch(*(++p)) { | |
ce5db1eb SL |
373 | case 'x': |
374 | Debug = atoi(++p); | |
375 | if (Debug <= 0) | |
376 | Debug = 1; | |
377 | break; | |
378 | case 'Q': | |
379 | seq = atoi(++p); | |
380 | break; | |
1a85e9d2 RC |
381 | case 'p': |
382 | MaxGrade = DefMaxGrade = *++p; | |
383 | DEBUG(4, "MaxGrade set to %c\n", MaxGrade); | |
384 | break; | |
4b31fbb4 JB |
385 | case 'v': |
386 | if (strncmp(p, "grade", 5) == 0) { | |
387 | p += 6; | |
388 | MaxGrade = DefMaxGrade = *p++; | |
389 | DEBUG(4, "MaxGrade set to %c\n", MaxGrade); | |
390 | } | |
391 | break; | |
ce5db1eb SL |
392 | default: |
393 | break; | |
394 | } | |
395 | p = q; | |
396 | } | |
397 | if (callok(Rmtname) == SS_BADSEQ) { | |
398 | logent("BADSEQ", "PREVIOUS"); | |
399 | omsg('R', "BADSEQ", Ofn); | |
400 | cleanup(0); | |
401 | } | |
88db71e9 | 402 | #ifdef GNXSEQ |
ce5db1eb SL |
403 | if ((ret = gnxseq(Rmtname)) == seq) { |
404 | omsg('R', "OK", Ofn); | |
405 | cmtseq(); | |
88db71e9 RC |
406 | } else { |
407 | #else !GNXSEQ | |
408 | if (seq == 0) | |
409 | omsg('R', "OK", Ofn); | |
ce5db1eb | 410 | else { |
88db71e9 | 411 | #endif !GNXSEQ |
ce5db1eb | 412 | systat(Rmtname, Stattype[7], Stattext[7]); |
4b31fbb4 | 413 | logent("BAD SEQ", "FAILED HANDSHAKE"); |
88db71e9 | 414 | #ifdef GNXSEQ |
ce5db1eb | 415 | ulkseq(); |
88db71e9 | 416 | #endif GNXSEQ |
ce5db1eb SL |
417 | omsg('R', "BADSEQ", Ofn); |
418 | cleanup(0); | |
419 | } | |
420 | ttyn = ttyname(Ifn); | |
421 | if (ttyn != NULL) | |
422 | chmod(ttyn, 0600); | |
88db71e9 RC |
423 | } else { /* Role == MASTER */ |
424 | struct stat stbuf; | |
425 | if (isatty(fileno(stderr)) || (fstat(fileno(stderr),&stbuf) == 0 | |
426 | && stbuf.st_mode&S_IFREG) ) | |
427 | StdErrIsTty = 1; | |
428 | setdebug(0); | |
ce5db1eb | 429 | } |
88db71e9 | 430 | |
ce5db1eb | 431 | loop: |
88db71e9 RC |
432 | if(setjmp(Pipebuf)) { /* come here on SIGPIPE */ |
433 | clsacu(); | |
434 | close(Ofn); | |
435 | close(Ifn); | |
436 | Ifn = Ofn = -1; | |
437 | rmlock(CNULL); | |
438 | sleep(3); | |
439 | } | |
ce5db1eb | 440 | if (!onesys) { |
88db71e9 RC |
441 | struct stat sbuf; |
442 | ||
443 | if (!StdErrIsTty) { | |
444 | sprintf(file, "%s/%s", RMTDEBUG, Rmtname); | |
445 | if (stat(file, &sbuf) == 0 && sbuf.st_size == 0) | |
446 | unlink(file); | |
447 | } | |
ce5db1eb | 448 | ret = gnsys(Rmtname, Spool, CMDPRE); |
88db71e9 | 449 | setdebug(0); |
ce5db1eb SL |
450 | if (ret == FAIL) |
451 | cleanup(100); | |
4b31fbb4 | 452 | if (ret == SUCCESS) |
ce5db1eb | 453 | cleanup(0); |
88db71e9 | 454 | } else if (Role == MASTER && callok(Rmtname) != 0) { |
ce5db1eb SL |
455 | logent("SYSTEM STATUS", "CAN NOT CALL"); |
456 | cleanup(0); | |
457 | } | |
458 | ||
4b31fbb4 | 459 | sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname); |
ce5db1eb | 460 | |
88db71e9 RC |
461 | signal(SIGINT, SIG_IGN); |
462 | signal(SIGQUIT, SIG_IGN); | |
ce5db1eb | 463 | if (Role == MASTER) { |
88db71e9 | 464 | /* check for /etc/nologin */ |
01af9d69 | 465 | if (access(NOLOGIN, 0) == 0) { |
88db71e9 | 466 | logent(NOLOGIN, "UUCICO SHUTDOWN"); |
4b31fbb4 | 467 | if (Debug > 4) |
88db71e9 RC |
468 | logent("DEBUGGING", "continuing anyway"); |
469 | else | |
470 | cleanup(1); | |
471 | } | |
ce5db1eb | 472 | /* master part */ |
ce5db1eb | 473 | signal(SIGHUP, SIG_IGN); |
ce5db1eb SL |
474 | if (Ifn != -1 && Role == MASTER) { |
475 | write(Ofn, EOTMSG, strlen(EOTMSG)); | |
476 | clsacu(); | |
477 | close(Ofn); | |
478 | close(Ifn); | |
479 | Ifn = Ofn = -1; | |
480 | rmlock(CNULL); | |
481 | sleep(3); | |
482 | } | |
483 | sprintf(msg, "call to %s ", Rmtname); | |
01af9d69 | 484 | if (mlock(Rmtname) != SUCCESS) { |
ce5db1eb | 485 | logent(msg, "LOCKED"); |
88db71e9 | 486 | US_SST(us_s_lock); |
ce5db1eb SL |
487 | goto next; |
488 | } | |
489 | Ofn = Ifn = conn(Rmtname); | |
490 | if (Ofn < 0) { | |
88db71e9 RC |
491 | if (Ofn != CF_TIME) |
492 | logent(msg, _FAILED); | |
493 | /* avoid excessive 'wrong time' info */ | |
4b31fbb4 | 494 | if (Stattype[-Ofn] != SS_WRONGTIME){ |
88db71e9 RC |
495 | systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]); |
496 | US_SST(-Ofn); | |
497 | UB_SST(-Ofn); | |
498 | } | |
ce5db1eb | 499 | goto next; |
88db71e9 | 500 | } else { |
ce5db1eb | 501 | logent(msg, "SUCCEEDED"); |
88db71e9 RC |
502 | US_SST(us_s_cok); |
503 | UB_SST(ub_ok); | |
504 | } | |
505 | #ifdef TCPIP | |
506 | /* | |
507 | * Determine if we are on TCPIP | |
508 | */ | |
509 | if (isatty(Ifn) == 0) { | |
510 | IsTcpIp = 1; | |
511 | DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL); | |
4b31fbb4 JB |
512 | } else |
513 | IsTcpIp = 0; | |
88db71e9 RC |
514 | #endif |
515 | ||
ce5db1eb SL |
516 | if (setjmp(Sjbuf)) |
517 | goto next; | |
518 | signal(SIGALRM, timeout); | |
519 | alarm(2 * MAXMSGTIME); | |
520 | for (;;) { | |
521 | ret = imsg(msg, Ifn); | |
522 | if (ret != 0) { | |
523 | alarm(0); | |
88db71e9 RC |
524 | logent("imsg 1", _FAILED); |
525 | goto Failure; | |
ce5db1eb SL |
526 | } |
527 | if (msg[0] == 'S') | |
528 | break; | |
529 | } | |
530 | alarm(MAXMSGTIME); | |
88db71e9 | 531 | #ifdef GNXSEQ |
ce5db1eb | 532 | seq = gnxseq(Rmtname); |
88db71e9 RC |
533 | #else !GNXSEQ |
534 | seq = 0; | |
535 | #endif !GNXSEQ | |
01af9d69 JB |
536 | if (Debug) |
537 | sprintf(rflags, "-x%d", Debug); | |
538 | else | |
539 | rflags[0] = '\0'; | |
540 | ||
1a85e9d2 | 541 | if (MaxGrade != '\177') { |
a534f0fb | 542 | char buf[MAXFULLNAME]; |
4b31fbb4 | 543 | sprintf(buf, " -p%c -vgrade=%c", MaxGrade, MaxGrade); |
1a85e9d2 RC |
544 | strcat(rflags, buf); |
545 | } | |
546 | ||
4b31fbb4 JB |
547 | sprintf(msg, "%s -Q%d %s", Myname, seq, rflags); |
548 | if (MaxGrade != '\177') | |
549 | DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade); | |
ce5db1eb SL |
550 | omsg('S', msg, Ofn); |
551 | for (;;) { | |
552 | ret = imsg(msg, Ifn); | |
553 | DEBUG(4, "msg-%s\n", msg); | |
88db71e9 | 554 | if (ret != SUCCESS) { |
ce5db1eb | 555 | alarm(0); |
88db71e9 | 556 | #ifdef GNXSEQ |
ce5db1eb | 557 | ulkseq(); |
88db71e9 RC |
558 | #endif GNXSEQ |
559 | logent("imsg 2", _FAILED); | |
560 | goto Failure; | |
ce5db1eb SL |
561 | } |
562 | if (msg[0] == 'R') | |
563 | break; | |
564 | } | |
565 | alarm(0); | |
566 | if (msg[1] == 'B') { | |
567 | /* bad sequence */ | |
4b31fbb4 | 568 | logent("BAD SEQ", "FAILED HANDSHAKE"); |
88db71e9 RC |
569 | US_SST(us_s_hand); |
570 | systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]); | |
571 | #ifdef GNXSEQ | |
ce5db1eb | 572 | ulkseq(); |
88db71e9 | 573 | #endif GNXSEQ |
ce5db1eb SL |
574 | goto next; |
575 | } | |
576 | if (strcmp(&msg[1], "OK") != SAME) { | |
4b31fbb4 | 577 | logent(&msg[1], "FAILED HANDSHAKE"); |
88db71e9 RC |
578 | US_SST(us_s_hand); |
579 | #ifdef GNXSEQ | |
ce5db1eb | 580 | ulkseq(); |
88db71e9 RC |
581 | #endif GNXSEQ |
582 | systat(Rmtname, SS_INPROGRESS, | |
583 | strcmp(&msg[1], "CB") == SAME? | |
4b31fbb4 | 584 | "AWAITING CALLBACK": "FAILED HANDSHAKE"); |
ce5db1eb SL |
585 | goto next; |
586 | } | |
88db71e9 | 587 | #ifdef GNXSEQ |
ce5db1eb | 588 | cmtseq(); |
88db71e9 | 589 | #endif GNXSEQ |
ce5db1eb | 590 | } |
88db71e9 | 591 | DEBUG(1, "Rmtname %s, ", Rmtname); |
ce5db1eb SL |
592 | DEBUG(1, "Role %s, ", Role ? "MASTER" : "SLAVE"); |
593 | DEBUG(1, "Ifn - %d, ", Ifn); | |
594 | DEBUG(1, "Loginuser - %s\n", Loginuser); | |
595 | ||
596 | alarm(MAXMSGTIME); | |
1a85e9d2 | 597 | if (ret=setjmp(Sjbuf)) |
ce5db1eb SL |
598 | goto Failure; |
599 | ret = startup(Role); | |
600 | alarm(0); | |
601 | if (ret != SUCCESS) { | |
88db71e9 | 602 | logent("startup", _FAILED); |
ce5db1eb | 603 | Failure: |
88db71e9 | 604 | US_SST(us_s_start); |
1a85e9d2 RC |
605 | systat(Rmtname, SS_FAIL, ret > 0 ? "CONVERSATION FAILED" : |
606 | "STARTUP FAILED"); | |
ce5db1eb | 607 | goto next; |
88db71e9 | 608 | } else { |
ce5db1eb | 609 | logent("startup", "OK"); |
88db71e9 | 610 | US_SST(us_s_gress); |
ce5db1eb SL |
611 | systat(Rmtname, SS_INPROGRESS, "TALKING"); |
612 | ret = cntrl(Role, wkpre); | |
613 | DEBUG(1, "cntrl - %d\n", ret); | |
614 | signal(SIGINT, SIG_IGN); | |
615 | signal(SIGHUP, SIG_IGN); | |
616 | signal(SIGALRM, timeout); | |
88db71e9 | 617 | if (ret == SUCCESS) { |
ce5db1eb | 618 | logent("conversation complete", "OK"); |
88db71e9 | 619 | US_SST(us_s_ok); |
ce5db1eb SL |
620 | rmstat(Rmtname); |
621 | ||
88db71e9 RC |
622 | } else { |
623 | logent("conversation complete", _FAILED); | |
624 | US_SST(us_s_cf); | |
625 | systat(Rmtname, SS_FAIL, "CONVERSATION FAILED"); | |
ce5db1eb SL |
626 | } |
627 | alarm(MAXMSGTIME); | |
ce5db1eb SL |
628 | DEBUG(4, "send OO %d,", ret); |
629 | if (!setjmp(Sjbuf)) { | |
630 | for (;;) { | |
631 | omsg('O', "OOOOO", Ofn); | |
632 | ret = imsg(msg, Ifn); | |
633 | if (ret != 0) | |
634 | break; | |
635 | if (msg[0] == 'O') | |
636 | break; | |
637 | } | |
638 | } | |
639 | alarm(0); | |
88db71e9 RC |
640 | clsacu(); |
641 | rmlock(CNULL); | |
ce5db1eb SL |
642 | } |
643 | next: | |
644 | if (!onesys) { | |
645 | goto loop; | |
646 | } | |
647 | cleanup(0); | |
648 | } | |
649 | ||
88db71e9 | 650 | #ifndef USG |
ce5db1eb SL |
651 | struct sgttyb Hupvec; |
652 | #endif | |
653 | ||
654 | /*** | |
655 | * cleanup(code) cleanup and exit with "code" status | |
656 | * int code; | |
657 | */ | |
658 | ||
659 | cleanup(code) | |
660 | register int code; | |
661 | { | |
ce5db1eb | 662 | register char *ttyn; |
88db71e9 RC |
663 | char bfr[BUFSIZ]; |
664 | struct stat sbuf; | |
ce5db1eb SL |
665 | |
666 | signal(SIGINT, SIG_IGN); | |
667 | signal(SIGHUP, SIG_IGN); | |
668 | rmlock(CNULL); | |
669 | clsacu(); | |
670 | logcls(); | |
671 | if (Role == SLAVE) { | |
88db71e9 RC |
672 | if (!IsTcpIp) { |
673 | #ifdef USG | |
ce5db1eb | 674 | Savettyb.c_cflag |= HUPCL; |
4b31fbb4 | 675 | (void) ioctl(0, TCSETA, &Savettyb); |
88db71e9 | 676 | #else !USG |
4b31fbb4 | 677 | (void) ioctl(0, TIOCHPCL, STBNULL); |
1a85e9d2 | 678 | #ifdef TIOCSDTR |
4b31fbb4 | 679 | (void) ioctl(0, TIOCCDTR, STBNULL); |
1a85e9d2 | 680 | sleep(2); |
4b31fbb4 | 681 | (void) ioctl(0, TIOCSDTR, STBNULL); |
1a85e9d2 | 682 | #else !TIOCSDTR |
4b31fbb4 | 683 | (void) ioctl(0, TIOCGETP, &Hupvec); |
1a85e9d2 | 684 | #endif !TIOCSDTR |
ce5db1eb SL |
685 | Hupvec.sg_ispeed = B0; |
686 | Hupvec.sg_ospeed = B0; | |
4b31fbb4 | 687 | (void) ioctl(0, TIOCSETP, &Hupvec); |
ce5db1eb | 688 | sleep(2); |
4b31fbb4 | 689 | (void) ioctl(0, TIOCSETP, &Savettyb); |
88db71e9 | 690 | /* make *sure* exclusive access is off */ |
4b31fbb4 | 691 | (void) ioctl(0, TIOCNXCL, STBNULL); |
88db71e9 | 692 | #endif !USG |
ce5db1eb SL |
693 | } |
694 | ttyn = ttyname(Ifn); | |
695 | if (ttyn != NULL) | |
696 | chmod(ttyn, 0600); | |
697 | } | |
698 | if (Ofn != -1) { | |
699 | if (Role == MASTER) | |
700 | write(Ofn, EOTMSG, strlen(EOTMSG)); | |
701 | close(Ifn); | |
702 | close(Ofn); | |
703 | } | |
1a85e9d2 RC |
704 | #ifdef DIALINOUT |
705 | /* reenable logins on dialout */ | |
706 | reenable(); | |
707 | #endif DIALINOUT | |
ce5db1eb SL |
708 | if (code == 0) |
709 | xuuxqt(); | |
88db71e9 RC |
710 | else |
711 | DEBUG(1, "exit code %d\n", code); | |
712 | sprintf(bfr, "%s/%s", RMTDEBUG, Rmtname); | |
713 | if (stat(bfr, &sbuf) == 0 && sbuf.st_size == 0) | |
714 | unlink(bfr); | |
715 | sprintf(bfr, "%s/%d", RMTDEBUG, getpid()); | |
716 | unlink(bfr); | |
ce5db1eb SL |
717 | exit(code); |
718 | } | |
719 | ||
720 | /*** | |
721 | * onintr(inter) interrupt - remove locks and exit | |
722 | */ | |
723 | ||
724 | onintr(inter) | |
725 | register int inter; | |
726 | { | |
727 | char str[30]; | |
728 | signal(inter, SIG_IGN); | |
729 | sprintf(str, "SIGNAL %d", inter); | |
730 | logent(str, "CAUGHT"); | |
88db71e9 | 731 | US_SST(us_s_intr); |
4b31fbb4 | 732 | if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) |
88db71e9 RC |
733 | systat(Rmtname, SS_FAIL, str); |
734 | if (inter == SIGPIPE && !onesys) | |
735 | longjmp(Pipebuf, 1); | |
ce5db1eb SL |
736 | cleanup(inter); |
737 | } | |
738 | ||
ce5db1eb SL |
739 | /* |
740 | * Catch a special signal | |
741 | * (SIGFPE, ugh), and toggle debugging between 0 and 30. | |
742 | * Handy for looking in on long running uucicos. | |
743 | */ | |
88db71e9 RC |
744 | setdebug(code) |
745 | int code; | |
ce5db1eb | 746 | { |
88db71e9 RC |
747 | char buf[BUFSIZ]; |
748 | ||
4b31fbb4 JB |
749 | if (code) { |
750 | if (Debug == 0) | |
751 | Debug = 30; | |
752 | else | |
753 | Debug = 0; | |
754 | } | |
755 | if (Debug && !StdErrIsTty) { | |
88db71e9 RC |
756 | sprintf(buf,"%s/%s", RMTDEBUG, Rmtname); |
757 | unlink(buf); | |
758 | freopen(buf, "w", stderr); | |
759 | #ifdef BSD4_2 | |
760 | setlinebuf(stderr); | |
761 | #else !BSD4_2 | |
762 | setbuf(stderr, NULL); | |
763 | #endif !BSD4_2 | |
764 | } | |
ce5db1eb SL |
765 | } |
766 | ||
767 | ||
768 | /*** | |
769 | * fixmode(tty) fix kill/echo/raw on line | |
770 | * | |
771 | * return codes: none | |
772 | */ | |
773 | ||
774 | fixmode(tty) | |
775 | register int tty; | |
776 | { | |
88db71e9 | 777 | #ifdef USG |
ce5db1eb SL |
778 | struct termio ttbuf; |
779 | #endif | |
88db71e9 | 780 | #ifndef USG |
ce5db1eb SL |
781 | struct sgttyb ttbuf; |
782 | #endif | |
ce5db1eb | 783 | |
88db71e9 | 784 | if (IsTcpIp) |
ce5db1eb | 785 | return; |
88db71e9 | 786 | #ifdef USG |
4b31fbb4 | 787 | ioctl(tty, TCGETA, &ttbuf); |
ce5db1eb SL |
788 | ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0; |
789 | ttbuf.c_cflag &= (CBAUD); | |
790 | ttbuf.c_cflag |= (CS8|CREAD); | |
791 | ttbuf.c_cc[VMIN] = 6; | |
792 | ttbuf.c_cc[VTIME] = 1; | |
4b31fbb4 | 793 | ioctl(tty, TCSETA, &ttbuf); |
ce5db1eb | 794 | #endif |
88db71e9 | 795 | #ifndef USG |
ce5db1eb SL |
796 | ioctl(tty, TIOCGETP, &ttbuf); |
797 | ttbuf.sg_flags = (ANYP | RAW); | |
4b31fbb4 | 798 | ioctl(tty, TIOCSETP, &ttbuf); |
ce5db1eb | 799 | #endif |
88db71e9 | 800 | #ifndef USG |
4b31fbb4 | 801 | ioctl(tty, TIOCEXCL, STBNULL); |
ce5db1eb SL |
802 | #endif |
803 | } | |
804 | ||
805 | ||
4b31fbb4 | 806 | /* |
ce5db1eb SL |
807 | * timeout() catch SIGALRM routine |
808 | */ | |
809 | ||
810 | timeout() | |
811 | { | |
4b31fbb4 JB |
812 | extern int HaveSentHup; |
813 | if (!HaveSentHup) { | |
814 | logent(Rmtname, "TIMEOUT"); | |
815 | if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) { | |
816 | US_SST(us_s_tmot); | |
817 | systat(Rmtname, SS_FAIL, "TIMEOUT"); | |
818 | } | |
88db71e9 | 819 | } |
ce5db1eb SL |
820 | longjmp(Sjbuf, 1); |
821 | } | |
822 | ||
823 | static char * | |
824 | pskip(p) | |
825 | register char *p; | |
826 | { | |
88db71e9 | 827 | while(*p && *p != ' ') |
ce5db1eb | 828 | ++p; |
4b31fbb4 | 829 | while(*p && *p == ' ') |
88db71e9 RC |
830 | *p++ = 0; |
831 | return p; | |
ce5db1eb | 832 | } |