Commit | Line | Data |
---|---|---|
d34dfbc0 KB |
1 | /*- |
2 | * Copyright (c) 1985 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.proprietary.c% | |
6 | */ | |
7 | ||
ce5db1eb | 8 | #ifndef lint |
d34dfbc0 KB |
9 | static char sccsid[] = "@(#)cico.c 5.21 (Berkeley) %G%"; |
10 | #endif /* not lint */ | |
ce5db1eb | 11 | |
ce5db1eb | 12 | #include <signal.h> |
4b31fbb4 | 13 | #include "uucp.h" |
ce5db1eb | 14 | #include <setjmp.h> |
88db71e9 | 15 | #ifdef USG |
ce5db1eb | 16 | #include <termio.h> |
9c672c90 | 17 | #include <fcntl.h> |
ce5db1eb | 18 | #endif |
88db71e9 | 19 | #ifndef USG |
ce5db1eb SL |
20 | #include <sgtty.h> |
21 | #endif | |
88db71e9 RC |
22 | #ifdef BSDTCP |
23 | #include <netdb.h> | |
24 | #include <netinet/in.h> | |
25 | #include <sys/socket.h> | |
26 | #endif BSDTCP | |
27 | #include <sys/stat.h> | |
9c672c90 RA |
28 | #ifdef BSD4_2 |
29 | #include <sys/time.h> | |
30 | #include <fcntl.h> | |
31 | #else | |
32 | #include <time.h> | |
33 | #endif | |
88db71e9 RC |
34 | #include "uust.h" |
35 | #include "uusub.h" | |
c861cac9 | 36 | #include "pathnames.h" |
ce5db1eb | 37 | |
4b31fbb4 JB |
38 | #if defined(VMS) && defined(BSDTCP) |
39 | #define NOGETPEER | |
40 | #endif | |
41 | ||
ce5db1eb | 42 | jmp_buf Sjbuf; |
88db71e9 RC |
43 | jmp_buf Pipebuf; |
44 | ||
45 | /* call fail text */ | |
ce5db1eb SL |
46 | char *Stattext[] = { |
47 | "", | |
48 | "BAD SYSTEM", | |
88db71e9 | 49 | "WRONG TIME TO CALL", |
ce5db1eb SL |
50 | "SYSTEM LOCKED", |
51 | "NO DEVICE", | |
2af814a5 | 52 | "CALL FAILED", |
ce5db1eb SL |
53 | "LOGIN FAILED", |
54 | "BAD SEQUENCE" | |
88db71e9 | 55 | }; |
ce5db1eb | 56 | |
88db71e9 RC |
57 | /* call fail codes */ |
58 | int Stattype[] = { | |
59 | 0, | |
60 | 0, | |
61 | SS_WRONGTIME, | |
62 | 0, | |
63 | SS_NODEVICE, | |
64 | SS_FAIL, | |
65 | SS_FAIL, | |
66 | SS_BADSEQ | |
67 | }; | |
ce5db1eb | 68 | |
2af814a5 JB |
69 | /* Arguments to setdebug(): */ |
70 | #define DBG_TEMP 0 /* Create a temporary audit file */ | |
71 | #define DBG_PERM 1 /* Create a permanent audit file */ | |
72 | #define DBG_CLEAN 2 /* Cleanup, discard temp file */ | |
ce5db1eb | 73 | |
88db71e9 | 74 | int ReverseRole = 0; |
88db71e9 | 75 | int Role = SLAVE; |
9c672c90 RA |
76 | int InitialRole = SLAVE; |
77 | long StartTime; | |
88db71e9 | 78 | int onesys = 0; |
1a85e9d2 | 79 | int turntime = 30 * 60; /* 30 minutes expressed in seconds */ |
2af814a5 | 80 | char *ttyn = NULL; |
88db71e9 | 81 | extern int LocalOnly; |
2af814a5 | 82 | extern int errno; |
1a85e9d2 RC |
83 | extern char MaxGrade, DefMaxGrade; |
84 | extern char Myfullname[]; | |
88db71e9 | 85 | |
9c672c90 RA |
86 | long Bytes_Sent, Bytes_Received; |
87 | ||
88db71e9 | 88 | #ifdef USG |
ce5db1eb SL |
89 | struct termio Savettyb; |
90 | #endif | |
88db71e9 | 91 | #ifndef USG |
ce5db1eb SL |
92 | struct sgttyb Savettyb; |
93 | #endif | |
94 | ||
274cf361 RA |
95 | #define SETPROCTITLE |
96 | #ifdef SETPROCTITLE | |
97 | char **Argv = NULL; /* pointer to argument vector */ | |
98 | char *LastArgv = NULL; /* end of argv */ | |
99 | #endif SETPROCTITLE | |
100 | ||
2af814a5 JB |
101 | /* |
102 | * this program is used to place a call to a | |
ce5db1eb SL |
103 | * remote machine, login, and copy files between the two machines. |
104 | */ | |
274cf361 | 105 | main(argc, argv, envp) |
2af814a5 | 106 | int argc; |
a5c64120 | 107 | char **argv; |
274cf361 | 108 | char **envp; |
ce5db1eb SL |
109 | { |
110 | register int ret; | |
111 | int seq; | |
ce5db1eb | 112 | char wkpre[NAMESIZE], file[NAMESIZE]; |
2af814a5 | 113 | char msg[MAXFULLNAME], *q; |
ce5db1eb | 114 | register char *p; |
41654125 KB |
115 | static void onintr(), timeout(), dbg_signal(); |
116 | static char *pskip(); | |
a5c64120 RA |
117 | extern char *optarg; |
118 | extern int optind; | |
a534f0fb | 119 | char rflags[MAXFULLNAME]; |
4b31fbb4 | 120 | #ifdef NOGETPEER |
88db71e9 | 121 | u_long Hostnumber = 0; |
4b31fbb4 | 122 | #endif NOGETPEER |
ce5db1eb SL |
123 | |
124 | strcpy(Progname, "uucico"); | |
ce5db1eb | 125 | |
2ae50b97 | 126 | #ifdef BSD4_2 |
a5c64120 | 127 | sigsetmask(0L); /* in case we inherit blocked signals */ |
2ae50b97 | 128 | #endif BSD4_2 |
ce5db1eb SL |
129 | signal(SIGINT, onintr); |
130 | signal(SIGHUP, onintr); | |
131 | signal(SIGQUIT, onintr); | |
132 | signal(SIGTERM, onintr); | |
133 | signal(SIGPIPE, onintr); /* 4.1a tcp-ip stupidity */ | |
3d98b35e | 134 | signal(SIGUSR1, dbg_signal); |
ce5db1eb SL |
135 | ret = guinfo(getuid(), User, msg); |
136 | strcpy(Loginuser, User); | |
4b31fbb4 | 137 | uucpname(Myname); |
a5c64120 RA |
138 | if (ret == FAIL) { |
139 | syslog(LOG_ERR, "can't get uid"); | |
140 | cleanup(FAIL); | |
141 | } | |
ce5db1eb | 142 | |
2af814a5 JB |
143 | setbuf (stderr, CNULL); |
144 | ||
145 | rflags[0] = '\0'; | |
ce5db1eb SL |
146 | umask(WFMASK); |
147 | strcpy(Rmtname, Myname); | |
148 | Ifn = Ofn = -1; | |
a5c64120 RA |
149 | while ((ret = getopt(argc, argv, "RLd:g:p:r:s:x:t:")) != EOF) |
150 | switch(ret){ | |
ce5db1eb | 151 | case 'd': |
a5c64120 | 152 | Spool = optarg; |
ce5db1eb | 153 | break; |
ce5db1eb | 154 | case 'g': |
1a85e9d2 | 155 | case 'p': |
a5c64120 | 156 | MaxGrade = DefMaxGrade = *optarg; |
ce5db1eb | 157 | break; |
ce5db1eb | 158 | case 'r': |
a5c64120 | 159 | Role = atoi(optarg); |
ce5db1eb | 160 | break; |
88db71e9 RC |
161 | case 'R': |
162 | ReverseRole++; | |
163 | Role = MASTER; | |
164 | break; | |
ce5db1eb | 165 | case 's': |
a5c64120 | 166 | strncpy(Rmtname, optarg, MAXBASENAME); |
4b31fbb4 | 167 | Rmtname[MAXBASENAME] = '\0'; |
ce5db1eb SL |
168 | if (Rmtname[0] != '\0') |
169 | onesys = 1; | |
170 | break; | |
171 | case 'x': | |
a5c64120 | 172 | Debug = atoi(optarg); |
ce5db1eb SL |
173 | if (Debug <= 0) |
174 | Debug = 1; | |
a5c64120 | 175 | strcat(rflags, argv[optind-1]); |
ce5db1eb | 176 | break; |
1a85e9d2 | 177 | case 't': |
a5c64120 | 178 | turntime = atoi(optarg)*60;/* minutes to seconds */ |
1a85e9d2 | 179 | break; |
88db71e9 RC |
180 | case 'L': /* local calls only */ |
181 | LocalOnly++; | |
182 | break; | |
4b31fbb4 | 183 | #ifdef NOGETPEER |
88db71e9 RC |
184 | case 'h': |
185 | Hostnumber = inet_addr(&argv[1][2]); | |
186 | break; | |
4b31fbb4 | 187 | #endif NOGETPEER |
a5c64120 | 188 | case '?': |
ce5db1eb | 189 | default: |
a5c64120 RA |
190 | fprintf(stderr, "unknown flag %s (ignored)\n", |
191 | argv[optind-1]); | |
ce5db1eb SL |
192 | break; |
193 | } | |
ce5db1eb | 194 | |
a5c64120 RA |
195 | while (optind < argc) |
196 | fprintf(stderr, "unknown argument %s (ignored)\n", | |
197 | argv[optind++]); | |
ce5db1eb | 198 | |
f18f4128 JB |
199 | if (Debug && Role == MASTER) |
200 | chkdebug(); | |
201 | ||
274cf361 RA |
202 | #ifdef SETPROCTITLE |
203 | /* | |
204 | * Save start and extent of argv for setproctitle. | |
205 | */ | |
206 | ||
207 | Argv = argv; | |
208 | LastArgv = argv[argc - 1] + strlen(argv[argc - 1]); | |
209 | #endif SETPROCTITLE | |
210 | ||
01af9d69 | 211 | /* Try to run as uucp */ |
88db71e9 RC |
212 | setgid(getegid()); |
213 | setuid(geteuid()); | |
214 | #ifdef TIOCNOTTY | |
215 | /* | |
216 | * detach uucico from controlling terminal | |
217 | * to defend against rlogind sending us a SIGKILL (!!!) | |
218 | */ | |
c861cac9 | 219 | if (Role == MASTER && (ret = open(_PATH_TTY, 2)) >= 0) { |
88db71e9 RC |
220 | ioctl(ret, TIOCNOTTY, STBNULL); |
221 | close(ret); | |
ce5db1eb | 222 | } |
88db71e9 RC |
223 | #endif TIOCNOTTY |
224 | #ifdef BSD4_2 | |
7ebaa22e | 225 | if (getpgrp(0) == 0) { /* We have no controlling terminal */ |
88db71e9 RC |
226 | setpgrp(0, getpid()); |
227 | } | |
a5c64120 RA |
228 | #ifdef USE_SYSLOG |
229 | #ifdef BSD4_3 | |
230 | openlog("uucico", LOG_PID, LOG_UUCP); | |
231 | #else /* !BSD4_3 */ | |
232 | openlog("uucico", LOG_PID); | |
233 | #endif /* !BSD4_3 */ | |
234 | #endif /* USE_SYSLOG */ | |
88db71e9 RC |
235 | #endif BSD4_2 |
236 | ||
a5c64120 RA |
237 | #ifdef BSD4_3 |
238 | unsetenv("TZ"); /* We don't want him resetting our time zone */ | |
239 | #endif /* !BSD4_3 */ | |
240 | ||
241 | if (subchdir(Spool) < 0) { | |
242 | syslog(LOG_ERR, "chdir(%s) failed: %m", Spool); | |
243 | cleanup(FAIL); | |
244 | } | |
245 | ||
88db71e9 RC |
246 | strcpy(Wrkdir, Spool); |
247 | ||
2af814a5 | 248 | if (Debug) { |
2af814a5 JB |
249 | setdebug ((Role == SLAVE) ? DBG_TEMP : DBG_PERM); |
250 | if (Debug > 0) | |
251 | logent ("Local Enabled", "DEBUG"); | |
252 | } | |
253 | ||
254 | /* | |
255 | * First time through: If we're the slave, do initial checking. | |
256 | */ | |
ce5db1eb | 257 | if (Role == SLAVE) { |
88db71e9 | 258 | /* check for /etc/nologin */ |
01af9d69 | 259 | if (access(NOLOGIN, 0) == 0) { |
88db71e9 | 260 | logent(NOLOGIN, "UUCICO SHUTDOWN"); |
4b31fbb4 | 261 | if (Debug > 4) |
88db71e9 RC |
262 | logent("DEBUGGING", "continuing anyway"); |
263 | else | |
264 | cleanup(1); | |
265 | } | |
2af814a5 JB |
266 | Ifn = 0; |
267 | Ofn = 1; | |
88db71e9 RC |
268 | #ifdef TCPIP |
269 | /* | |
270 | * Determine if we are on TCPIP | |
271 | */ | |
9c672c90 | 272 | if (isatty(Ifn) == 0) { |
88db71e9 RC |
273 | IsTcpIp = 1; |
274 | DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL); | |
4b31fbb4 JB |
275 | } else |
276 | IsTcpIp = 0; | |
88db71e9 | 277 | #endif TCPIP |
ce5db1eb SL |
278 | /* initial handshake */ |
279 | onesys = 1; | |
88db71e9 RC |
280 | if (!IsTcpIp) { |
281 | #ifdef USG | |
2af814a5 | 282 | ret = ioctl(Ifn, TCGETA, &Savettyb); |
ce5db1eb SL |
283 | Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7; |
284 | Savettyb.c_oflag |= OPOST; | |
285 | Savettyb.c_lflag |= (ISIG|ICANON|ECHO); | |
88db71e9 | 286 | #else !USG |
2af814a5 | 287 | ret = ioctl(Ifn, TIOCGETP, &Savettyb); |
ce5db1eb SL |
288 | Savettyb.sg_flags |= ECHO; |
289 | Savettyb.sg_flags &= ~RAW; | |
88db71e9 | 290 | #endif !USG |
2af814a5 | 291 | ttyn = ttyname(Ifn); |
ce5db1eb | 292 | } |
ce5db1eb | 293 | fixmode(Ifn); |
2af814a5 JB |
294 | |
295 | /* | |
296 | * Initial Message -- tell them we're here, and who we are. | |
297 | */ | |
1a85e9d2 | 298 | sprintf(msg, "here=%s", Myfullname); |
88db71e9 | 299 | omsg('S', msg, Ofn); |
ce5db1eb | 300 | signal(SIGALRM, timeout); |
9c672c90 | 301 | alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME); |
ce5db1eb SL |
302 | if (setjmp(Sjbuf)) { |
303 | /* timed out */ | |
88db71e9 RC |
304 | if (!IsTcpIp) { |
305 | #ifdef USG | |
2af814a5 JB |
306 | ret = ioctl(Ifn, TCSETA, &Savettyb); |
307 | ||
4b31fbb4 | 308 | #else !USG |
2af814a5 | 309 | ret = ioctl(Ifn, TIOCSETP, &Savettyb); |
4b31fbb4 | 310 | #endif !USG |
ce5db1eb | 311 | } |
88db71e9 | 312 | cleanup(0); |
ce5db1eb SL |
313 | } |
314 | for (;;) { | |
315 | ret = imsg(msg, Ifn); | |
2af814a5 | 316 | if (ret != SUCCESS) { |
ce5db1eb | 317 | alarm(0); |
88db71e9 RC |
318 | if (!IsTcpIp) { |
319 | #ifdef USG | |
2af814a5 | 320 | ret = ioctl(Ifn, TCSETA, &Savettyb); |
4b31fbb4 | 321 | #else !USG |
2af814a5 | 322 | ret = ioctl(Ifn, TIOCSETP, &Savettyb); |
4b31fbb4 | 323 | #endif !USG |
ce5db1eb | 324 | } |
88db71e9 | 325 | cleanup(0); |
ce5db1eb SL |
326 | } |
327 | if (msg[0] == 'S') | |
328 | break; | |
329 | } | |
330 | alarm(0); | |
331 | q = &msg[1]; | |
332 | p = pskip(q); | |
4b31fbb4 JB |
333 | strncpy(Rmtname, q, MAXBASENAME); |
334 | Rmtname[MAXBASENAME] = '\0'; | |
2af814a5 JB |
335 | |
336 | /* | |
337 | * Now that we know who they are, give the audit file the right | |
338 | * name. | |
339 | */ | |
340 | setdebug (DBG_PERM); | |
ce5db1eb | 341 | DEBUG(4, "sys-%s\n", Rmtname); |
a534f0fb | 342 | /* The versys will also do an alias on the incoming name */ |
4b31fbb4 | 343 | if (versys(&Rmtname)) { |
a534f0fb | 344 | #ifdef NOSTRANGERS |
9c672c90 | 345 | /* If we don't know them, we won't talk to them... */ |
a5c64120 | 346 | syslog(LOG_WARNING, "Unknown host: %s", Rmtname); |
4b31fbb4 JB |
347 | omsg('R', "You are unknown to me", Ofn); |
348 | cleanup(0); | |
4b31fbb4 | 349 | #endif NOSTRANGERS |
a534f0fb | 350 | } |
88db71e9 RC |
351 | #ifdef BSDTCP |
352 | /* we must make sure they are really who they say they | |
353 | * are. We compare the hostnumber with the number in the hosts | |
354 | * table for the site they claim to be. | |
355 | */ | |
356 | if (IsTcpIp) { | |
357 | struct hostent *hp; | |
358 | char *cpnt, *inet_ntoa(); | |
2af814a5 | 359 | int fromlen; |
88db71e9 | 360 | struct sockaddr_in from; |
01af9d69 | 361 | extern char PhoneNumber[]; |
88db71e9 | 362 | |
4b31fbb4 JB |
363 | #ifdef NOGETPEER |
364 | from.sin_addr.s_addr = Hostnumber; | |
365 | from.sin_family = AF_INET; | |
366 | #else !NOGETPEER | |
2af814a5 | 367 | fromlen = sizeof(from); |
41654125 KB |
368 | if (getpeername(Ifn, |
369 | (struct sockaddr *)&from, &fromlen) < 0) { | |
88db71e9 RC |
370 | logent(Rmtname, "NOT A TCP CONNECTION"); |
371 | omsg('R', "NOT TCP", Ofn); | |
372 | cleanup(0); | |
373 | } | |
4b31fbb4 | 374 | #endif !NOGETPEER |
41654125 | 375 | hp = gethostbyaddr((char *)&from.sin_addr, |
88db71e9 | 376 | sizeof (struct in_addr), from.sin_family); |
2af814a5 | 377 | if (hp == NULL) { |
88db71e9 RC |
378 | /* security break or just old host table? */ |
379 | logent(Rmtname, "UNKNOWN IP-HOST Name ="); | |
380 | cpnt = inet_ntoa(from.sin_addr), | |
381 | logent(cpnt, "UNKNOWN IP-HOST Number ="); | |
382 | sprintf(wkpre, "%s/%s isn't in my host table", | |
383 | Rmtname, cpnt); | |
384 | omsg('R' ,wkpre ,Ofn); | |
385 | cleanup(0); | |
386 | } | |
2af814a5 | 387 | if (Debug > 99) |
88db71e9 | 388 | logent(Rmtname,"Request from IP-Host name ="); |
01af9d69 JB |
389 | /* |
390 | * The following is to determine if the name given us by | |
391 | * the Remote uucico matches any of the names | |
88db71e9 RC |
392 | * given its network number (remote machine) in our |
393 | * host table. | |
01af9d69 JB |
394 | * We could check the aliases, but that won't work in |
395 | * all cases (like if you are running the domain | |
396 | * server, where you don't get any aliases). The only | |
397 | * reliable way I can think of that works in ALL cases | |
398 | * is too look up the site in L.sys and see if the | |
399 | * sitename matches what we would call him if we | |
400 | * originated the call. | |
88db71e9 | 401 | */ |
01af9d69 JB |
402 | /* PhoneNumber contains the official network name of the host we are checking. (set in versys.c) */ |
403 | if (sncncmp(PhoneNumber, hp->h_name, SYSNSIZE) == 0) { | |
88db71e9 RC |
404 | if (Debug > 99) |
405 | logent(q,"Found in host Tables"); | |
01af9d69 JB |
406 | } else { |
407 | logent(hp->h_name, "FORGED HOSTNAME"); | |
408 | logent(inet_ntoa(from.sin_addr), "ORIGINATED AT"); | |
409 | logent(PhoneNumber, "SHOULD BE"); | |
410 | sprintf(wkpre, "You're not who you claim to be: %s != %s", hp->h_name, PhoneNumber); | |
411 | omsg('R', wkpre, Ofn); | |
412 | cleanup(0); | |
88db71e9 RC |
413 | } |
414 | } | |
415 | #endif BSDTCP | |
416 | ||
2af814a5 | 417 | if (mlock(Rmtname)) { |
ce5db1eb SL |
418 | omsg('R', "LCK", Ofn); |
419 | cleanup(0); | |
420 | } | |
421 | else if (callback(Loginuser)) { | |
422 | signal(SIGINT, SIG_IGN); | |
423 | signal(SIGHUP, SIG_IGN); | |
424 | omsg('R', "CB", Ofn); | |
425 | logent("CALLBACK", "REQUIRED"); | |
426 | /* set up for call back */ | |
88db71e9 | 427 | systat(Rmtname, SS_CALLBACK, "CALLING BACK"); |
ce5db1eb SL |
428 | gename(CMDPRE, Rmtname, 'C', file); |
429 | close(creat(subfile(file), 0666)); | |
430 | xuucico(Rmtname); | |
431 | cleanup(0); | |
432 | } | |
433 | seq = 0; | |
434 | while (*p == '-') { | |
435 | q = pskip(p); | |
436 | switch(*(++p)) { | |
ce5db1eb | 437 | case 'x': |
2af814a5 JB |
438 | if (Debug == 0) { |
439 | Debug = atoi(++p); | |
440 | if (Debug <= 0) | |
441 | Debug = 1; | |
442 | setdebug(DBG_PERM); | |
443 | if (Debug > 0) | |
444 | logent("Remote Enabled", "DEBUG"); | |
445 | } else { | |
446 | DEBUG(1, "Remote debug request ignored\n", | |
447 | CNULL); | |
448 | } | |
ce5db1eb SL |
449 | break; |
450 | case 'Q': | |
451 | seq = atoi(++p); | |
452 | break; | |
1a85e9d2 RC |
453 | case 'p': |
454 | MaxGrade = DefMaxGrade = *++p; | |
455 | DEBUG(4, "MaxGrade set to %c\n", MaxGrade); | |
456 | break; | |
4b31fbb4 JB |
457 | case 'v': |
458 | if (strncmp(p, "grade", 5) == 0) { | |
459 | p += 6; | |
460 | MaxGrade = DefMaxGrade = *p++; | |
461 | DEBUG(4, "MaxGrade set to %c\n", MaxGrade); | |
462 | } | |
463 | break; | |
ce5db1eb SL |
464 | default: |
465 | break; | |
466 | } | |
467 | p = q; | |
468 | } | |
274cf361 | 469 | setproctitle("%s: startup", Rmtname); |
ce5db1eb SL |
470 | if (callok(Rmtname) == SS_BADSEQ) { |
471 | logent("BADSEQ", "PREVIOUS"); | |
472 | omsg('R', "BADSEQ", Ofn); | |
473 | cleanup(0); | |
474 | } | |
88db71e9 | 475 | #ifdef GNXSEQ |
ce5db1eb SL |
476 | if ((ret = gnxseq(Rmtname)) == seq) { |
477 | omsg('R', "OK", Ofn); | |
478 | cmtseq(); | |
88db71e9 RC |
479 | } else { |
480 | #else !GNXSEQ | |
481 | if (seq == 0) | |
482 | omsg('R', "OK", Ofn); | |
ce5db1eb | 483 | else { |
88db71e9 | 484 | #endif !GNXSEQ |
ce5db1eb | 485 | systat(Rmtname, Stattype[7], Stattext[7]); |
4b31fbb4 | 486 | logent("BAD SEQ", "FAILED HANDSHAKE"); |
88db71e9 | 487 | #ifdef GNXSEQ |
ce5db1eb | 488 | ulkseq(); |
88db71e9 | 489 | #endif GNXSEQ |
ce5db1eb SL |
490 | omsg('R', "BADSEQ", Ofn); |
491 | cleanup(0); | |
492 | } | |
ce5db1eb SL |
493 | if (ttyn != NULL) |
494 | chmod(ttyn, 0600); | |
495 | } | |
88db71e9 | 496 | |
ce5db1eb | 497 | loop: |
88db71e9 RC |
498 | if(setjmp(Pipebuf)) { /* come here on SIGPIPE */ |
499 | clsacu(); | |
274cf361 | 500 | logcls(); |
88db71e9 RC |
501 | close(Ofn); |
502 | close(Ifn); | |
503 | Ifn = Ofn = -1; | |
504 | rmlock(CNULL); | |
505 | sleep(3); | |
506 | } | |
ce5db1eb | 507 | if (!onesys) { |
9c672c90 | 508 | do_connect_accounting(); |
a5c64120 RA |
509 | #ifdef DIALINOUT |
510 | /* reenable logins on dialout */ | |
511 | reenable(); | |
512 | #endif DIALINOUT | |
9c672c90 | 513 | StartTime = 0; |
274cf361 | 514 | setproctitle("looking for work"); |
ce5db1eb | 515 | ret = gnsys(Rmtname, Spool, CMDPRE); |
274cf361 | 516 | setproctitle("%s: startup", Rmtname); |
2af814a5 | 517 | setdebug(DBG_PERM); |
ce5db1eb SL |
518 | if (ret == FAIL) |
519 | cleanup(100); | |
9c672c90 | 520 | else if (ret == SUCCESS) |
ce5db1eb | 521 | cleanup(0); |
274cf361 | 522 | logcls(); |
88db71e9 | 523 | } else if (Role == MASTER && callok(Rmtname) != 0) { |
ce5db1eb SL |
524 | logent("SYSTEM STATUS", "CAN NOT CALL"); |
525 | cleanup(0); | |
526 | } | |
527 | ||
4b31fbb4 | 528 | sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname); |
9c672c90 RA |
529 | StartTime = 0; |
530 | Bytes_Sent = Bytes_Received = 0L; | |
ce5db1eb | 531 | |
88db71e9 RC |
532 | signal(SIGINT, SIG_IGN); |
533 | signal(SIGQUIT, SIG_IGN); | |
ce5db1eb | 534 | if (Role == MASTER) { |
9c672c90 | 535 | extern char LineType[]; |
88db71e9 | 536 | /* check for /etc/nologin */ |
01af9d69 | 537 | if (access(NOLOGIN, 0) == 0) { |
88db71e9 | 538 | logent(NOLOGIN, "UUCICO SHUTDOWN"); |
4b31fbb4 | 539 | if (Debug > 4) |
88db71e9 RC |
540 | logent("DEBUGGING", "continuing anyway"); |
541 | else | |
542 | cleanup(1); | |
543 | } | |
ce5db1eb | 544 | /* master part */ |
ce5db1eb | 545 | signal(SIGHUP, SIG_IGN); |
ce5db1eb SL |
546 | if (Ifn != -1 && Role == MASTER) { |
547 | write(Ofn, EOTMSG, strlen(EOTMSG)); | |
548 | clsacu(); | |
549 | close(Ofn); | |
550 | close(Ifn); | |
551 | Ifn = Ofn = -1; | |
552 | rmlock(CNULL); | |
553 | sleep(3); | |
554 | } | |
01af9d69 | 555 | if (mlock(Rmtname) != SUCCESS) { |
9c672c90 | 556 | DEBUG(1, "LOCKED: call to %s\n", Rmtname); |
88db71e9 | 557 | US_SST(us_s_lock); |
ce5db1eb SL |
558 | goto next; |
559 | } | |
274cf361 | 560 | setproctitle("%s: starting call", Rmtname); |
ce5db1eb | 561 | Ofn = Ifn = conn(Rmtname); |
274cf361 | 562 | sprintf(msg, "(call to %s via %s)", Rmtname, LineType); |
ce5db1eb | 563 | if (Ofn < 0) { |
88db71e9 RC |
564 | if (Ofn != CF_TIME) |
565 | logent(msg, _FAILED); | |
566 | /* avoid excessive 'wrong time' info */ | |
4b31fbb4 | 567 | if (Stattype[-Ofn] != SS_WRONGTIME){ |
88db71e9 RC |
568 | systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]); |
569 | US_SST(-Ofn); | |
570 | UB_SST(-Ofn); | |
571 | } | |
ce5db1eb | 572 | goto next; |
88db71e9 | 573 | } else { |
ce5db1eb | 574 | logent(msg, "SUCCEEDED"); |
88db71e9 RC |
575 | US_SST(us_s_cok); |
576 | UB_SST(ub_ok); | |
577 | } | |
9c672c90 | 578 | InitialRole = MASTER; |
88db71e9 RC |
579 | #ifdef TCPIP |
580 | /* | |
581 | * Determine if we are on TCPIP | |
582 | */ | |
2af814a5 | 583 | if (isatty(Ifn) == 0) { |
88db71e9 RC |
584 | IsTcpIp = 1; |
585 | DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL); | |
4b31fbb4 JB |
586 | } else |
587 | IsTcpIp = 0; | |
88db71e9 RC |
588 | #endif |
589 | ||
ce5db1eb SL |
590 | if (setjmp(Sjbuf)) |
591 | goto next; | |
592 | signal(SIGALRM, timeout); | |
9c672c90 | 593 | alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME*2); |
ce5db1eb SL |
594 | for (;;) { |
595 | ret = imsg(msg, Ifn); | |
9c672c90 | 596 | if (ret != SUCCESS) { |
ce5db1eb | 597 | alarm(0); |
9c672c90 | 598 | DEBUG(4,"\nimsg failed: errno %d\n", errno); |
88db71e9 RC |
599 | logent("imsg 1", _FAILED); |
600 | goto Failure; | |
ce5db1eb SL |
601 | } |
602 | if (msg[0] == 'S') | |
603 | break; | |
604 | } | |
9c672c90 | 605 | alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME); |
88db71e9 | 606 | #ifdef GNXSEQ |
ce5db1eb | 607 | seq = gnxseq(Rmtname); |
88db71e9 RC |
608 | #else !GNXSEQ |
609 | seq = 0; | |
610 | #endif !GNXSEQ | |
1a85e9d2 | 611 | if (MaxGrade != '\177') { |
4b31fbb4 | 612 | DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade); |
9313cec6 JB |
613 | sprintf(msg, "%s -Q%d -p%c -vgrade=%c %s", |
614 | Myname, seq, MaxGrade, MaxGrade, rflags); | |
615 | } else | |
616 | sprintf(msg, "%s -Q%d %s", Myname, seq, rflags); | |
ce5db1eb SL |
617 | omsg('S', msg, Ofn); |
618 | for (;;) { | |
619 | ret = imsg(msg, Ifn); | |
620 | DEBUG(4, "msg-%s\n", msg); | |
88db71e9 | 621 | if (ret != SUCCESS) { |
ce5db1eb | 622 | alarm(0); |
88db71e9 | 623 | #ifdef GNXSEQ |
ce5db1eb | 624 | ulkseq(); |
88db71e9 RC |
625 | #endif GNXSEQ |
626 | logent("imsg 2", _FAILED); | |
627 | goto Failure; | |
ce5db1eb SL |
628 | } |
629 | if (msg[0] == 'R') | |
630 | break; | |
631 | } | |
632 | alarm(0); | |
633 | if (msg[1] == 'B') { | |
634 | /* bad sequence */ | |
4b31fbb4 | 635 | logent("BAD SEQ", "FAILED HANDSHAKE"); |
88db71e9 RC |
636 | US_SST(us_s_hand); |
637 | systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]); | |
638 | #ifdef GNXSEQ | |
ce5db1eb | 639 | ulkseq(); |
88db71e9 | 640 | #endif GNXSEQ |
ce5db1eb SL |
641 | goto next; |
642 | } | |
643 | if (strcmp(&msg[1], "OK") != SAME) { | |
4b31fbb4 | 644 | logent(&msg[1], "FAILED HANDSHAKE"); |
88db71e9 RC |
645 | US_SST(us_s_hand); |
646 | #ifdef GNXSEQ | |
ce5db1eb | 647 | ulkseq(); |
88db71e9 RC |
648 | #endif GNXSEQ |
649 | systat(Rmtname, SS_INPROGRESS, | |
650 | strcmp(&msg[1], "CB") == SAME? | |
4b31fbb4 | 651 | "AWAITING CALLBACK": "FAILED HANDSHAKE"); |
ce5db1eb SL |
652 | goto next; |
653 | } | |
88db71e9 | 654 | #ifdef GNXSEQ |
ce5db1eb | 655 | cmtseq(); |
88db71e9 | 656 | #endif GNXSEQ |
ce5db1eb | 657 | } |
88db71e9 | 658 | DEBUG(1, "Rmtname %s, ", Rmtname); |
ce5db1eb SL |
659 | DEBUG(1, "Role %s, ", Role ? "MASTER" : "SLAVE"); |
660 | DEBUG(1, "Ifn - %d, ", Ifn); | |
661 | DEBUG(1, "Loginuser - %s\n", Loginuser); | |
274cf361 | 662 | setproctitle("%s: %s", Rmtname, Role ? "MASTER" : "SLAVE"); |
ce5db1eb | 663 | |
2af814a5 JB |
664 | ttyn = ttyname(Ifn); |
665 | ||
9c672c90 | 666 | alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME); |
1a85e9d2 | 667 | if (ret=setjmp(Sjbuf)) |
ce5db1eb SL |
668 | goto Failure; |
669 | ret = startup(Role); | |
670 | alarm(0); | |
671 | if (ret != SUCCESS) { | |
274cf361 | 672 | logent("(startup)", _FAILED); |
ce5db1eb | 673 | Failure: |
88db71e9 | 674 | US_SST(us_s_start); |
1a85e9d2 RC |
675 | systat(Rmtname, SS_FAIL, ret > 0 ? "CONVERSATION FAILED" : |
676 | "STARTUP FAILED"); | |
ce5db1eb | 677 | goto next; |
88db71e9 | 678 | } else { |
9c672c90 RA |
679 | char smsg[BUFSIZ], gmsg[10], pmsg[20], bpsmsg[20]; |
680 | extern char UsingProtocol; | |
681 | extern int linebaudrate; | |
682 | if (ttyn != NULL) | |
683 | sprintf(bpsmsg, " %s %d bps", &ttyn[5], linebaudrate); | |
684 | else | |
685 | bpsmsg[0] = '\0'; | |
686 | if (UsingProtocol != 'g') | |
687 | sprintf(pmsg, " %c protocol", UsingProtocol); | |
688 | else | |
689 | pmsg[0] = '\0'; | |
690 | if (MaxGrade != '\177') | |
691 | sprintf(gmsg, " grade %c", MaxGrade); | |
692 | else | |
693 | gmsg[0] = '\0'; | |
274cf361 | 694 | sprintf(smsg, "(startup%s%s%s)", bpsmsg, pmsg, gmsg); |
9c672c90 | 695 | logent(smsg, "OK"); |
88db71e9 | 696 | US_SST(us_s_gress); |
9c672c90 | 697 | StartTime = Now.time; |
ce5db1eb SL |
698 | systat(Rmtname, SS_INPROGRESS, "TALKING"); |
699 | ret = cntrl(Role, wkpre); | |
700 | DEBUG(1, "cntrl - %d\n", ret); | |
701 | signal(SIGINT, SIG_IGN); | |
702 | signal(SIGHUP, SIG_IGN); | |
703 | signal(SIGALRM, timeout); | |
274cf361 | 704 | sprintf(smsg, "(conversation complete %ld sent %ld received)", |
9c672c90 | 705 | Bytes_Sent, Bytes_Received); |
88db71e9 | 706 | if (ret == SUCCESS) { |
9c672c90 | 707 | logent(smsg, "OK"); |
88db71e9 | 708 | US_SST(us_s_ok); |
ce5db1eb SL |
709 | rmstat(Rmtname); |
710 | ||
88db71e9 | 711 | } else { |
9c672c90 | 712 | logent(smsg, _FAILED); |
88db71e9 RC |
713 | US_SST(us_s_cf); |
714 | systat(Rmtname, SS_FAIL, "CONVERSATION FAILED"); | |
ce5db1eb | 715 | } |
9c672c90 | 716 | alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME); |
ce5db1eb SL |
717 | DEBUG(4, "send OO %d,", ret); |
718 | if (!setjmp(Sjbuf)) { | |
719 | for (;;) { | |
720 | omsg('O', "OOOOO", Ofn); | |
721 | ret = imsg(msg, Ifn); | |
722 | if (ret != 0) | |
723 | break; | |
724 | if (msg[0] == 'O') | |
725 | break; | |
726 | } | |
727 | } | |
728 | alarm(0); | |
88db71e9 RC |
729 | clsacu(); |
730 | rmlock(CNULL); | |
9c672c90 | 731 | |
ce5db1eb SL |
732 | } |
733 | next: | |
734 | if (!onesys) { | |
735 | goto loop; | |
736 | } | |
737 | cleanup(0); | |
738 | } | |
739 | ||
88db71e9 | 740 | #ifndef USG |
ce5db1eb SL |
741 | struct sgttyb Hupvec; |
742 | #endif | |
743 | ||
2af814a5 JB |
744 | /* |
745 | * cleanup and exit with "code" status | |
ce5db1eb | 746 | */ |
ce5db1eb SL |
747 | cleanup(code) |
748 | register int code; | |
749 | { | |
ce5db1eb SL |
750 | signal(SIGINT, SIG_IGN); |
751 | signal(SIGHUP, SIG_IGN); | |
752 | rmlock(CNULL); | |
2af814a5 | 753 | sleep(5); /* Wait for any pending output */ |
ce5db1eb SL |
754 | clsacu(); |
755 | logcls(); | |
756 | if (Role == SLAVE) { | |
88db71e9 RC |
757 | if (!IsTcpIp) { |
758 | #ifdef USG | |
ce5db1eb | 759 | Savettyb.c_cflag |= HUPCL; |
4b31fbb4 | 760 | (void) ioctl(0, TCSETA, &Savettyb); |
88db71e9 | 761 | #else !USG |
4b31fbb4 | 762 | (void) ioctl(0, TIOCHPCL, STBNULL); |
1a85e9d2 | 763 | #ifdef TIOCSDTR |
4b31fbb4 | 764 | (void) ioctl(0, TIOCCDTR, STBNULL); |
1a85e9d2 | 765 | sleep(2); |
4b31fbb4 | 766 | (void) ioctl(0, TIOCSDTR, STBNULL); |
1a85e9d2 | 767 | #else !TIOCSDTR |
4b31fbb4 | 768 | (void) ioctl(0, TIOCGETP, &Hupvec); |
ce5db1eb SL |
769 | Hupvec.sg_ispeed = B0; |
770 | Hupvec.sg_ospeed = B0; | |
4b31fbb4 | 771 | (void) ioctl(0, TIOCSETP, &Hupvec); |
2af814a5 | 772 | #endif !TIOCSDTR |
ce5db1eb | 773 | sleep(2); |
4b31fbb4 | 774 | (void) ioctl(0, TIOCSETP, &Savettyb); |
88db71e9 | 775 | /* make *sure* exclusive access is off */ |
4b31fbb4 | 776 | (void) ioctl(0, TIOCNXCL, STBNULL); |
88db71e9 | 777 | #endif !USG |
ce5db1eb | 778 | } |
ce5db1eb SL |
779 | if (ttyn != NULL) |
780 | chmod(ttyn, 0600); | |
781 | } | |
782 | if (Ofn != -1) { | |
783 | if (Role == MASTER) | |
784 | write(Ofn, EOTMSG, strlen(EOTMSG)); | |
785 | close(Ifn); | |
786 | close(Ofn); | |
787 | } | |
1a85e9d2 RC |
788 | #ifdef DIALINOUT |
789 | /* reenable logins on dialout */ | |
790 | reenable(); | |
791 | #endif DIALINOUT | |
ce5db1eb SL |
792 | if (code == 0) |
793 | xuuxqt(); | |
88db71e9 RC |
794 | else |
795 | DEBUG(1, "exit code %d\n", code); | |
2af814a5 | 796 | setdebug (DBG_CLEAN); |
9c672c90 | 797 | do_connect_accounting(); |
ce5db1eb SL |
798 | exit(code); |
799 | } | |
800 | ||
9c672c90 RA |
801 | do_connect_accounting() |
802 | { | |
a5c64120 | 803 | #ifdef DO_CONNECT_ACCOUNTING |
9c672c90 RA |
804 | register FILE *fp; |
805 | struct tm *localtime(); | |
806 | register struct tm *tm; | |
807 | int flags; | |
808 | ||
809 | if (StartTime == 0) | |
810 | return; | |
811 | ||
a5c64120 RA |
812 | fp = fopen(DO_CONNECT_ACCOUNTING, "a"); |
813 | if (fp == NULL) { | |
814 | syslog(LOG_ALERT, "fopen(%s) failed: %m",DO_CONNECT_ACCOUNTING); | |
815 | cleanup(FAIL); | |
816 | } | |
9c672c90 RA |
817 | |
818 | tm = localtime(&StartTime); | |
819 | #ifdef F_SETFL | |
820 | flags = fcntl(fileno(fp), F_GETFL, 0); | |
821 | fcntl(fileno(fp), F_SETFL, flags|O_APPEND); | |
822 | #endif | |
823 | #ifdef USG | |
824 | fprintf(fp,"%s %d %d%.2d%.2d %.2d%.2d %d %ld %s %ld %ld\n", | |
825 | #else /* V7 */ | |
826 | fprintf(fp,"%s %d %d%02d%02d %02d%02d %d %ld %s %ld %ld\n", | |
827 | #endif /* V7 */ | |
828 | Rmtname, InitialRole, tm->tm_year, tm->tm_mon + 1, | |
829 | tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_wday, | |
830 | (Now.time - StartTime + 59) / 60, | |
831 | ttyn == NULL ? "ttyp0" : &ttyn[5], | |
832 | Bytes_Sent, Bytes_Received); | |
833 | fclose(fp); | |
834 | #endif /* DO_CONNECT_ACCOUNTING */ | |
835 | } | |
836 | ||
2af814a5 JB |
837 | /* |
838 | * on interrupt - remove locks and exit | |
ce5db1eb SL |
839 | */ |
840 | ||
41654125 | 841 | static void |
ce5db1eb SL |
842 | onintr(inter) |
843 | register int inter; | |
844 | { | |
9c672c90 | 845 | char str[BUFSIZ]; |
ce5db1eb | 846 | signal(inter, SIG_IGN); |
274cf361 | 847 | sprintf(str, "(SIGNAL %d)", inter); |
ce5db1eb | 848 | logent(str, "CAUGHT"); |
88db71e9 | 849 | US_SST(us_s_intr); |
4b31fbb4 | 850 | if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) |
88db71e9 | 851 | systat(Rmtname, SS_FAIL, str); |
274cf361 | 852 | sprintf(str, "(conversation complete %ld sent %ld received)", |
9c672c90 RA |
853 | Bytes_Sent, Bytes_Received); |
854 | logent(str, _FAILED); | |
88db71e9 RC |
855 | if (inter == SIGPIPE && !onesys) |
856 | longjmp(Pipebuf, 1); | |
ce5db1eb SL |
857 | cleanup(inter); |
858 | } | |
859 | ||
ce5db1eb SL |
860 | /* |
861 | * Catch a special signal | |
3d98b35e | 862 | * (SIGUSR1), and toggle debugging between 0 and 30. |
ce5db1eb SL |
863 | * Handy for looking in on long running uucicos. |
864 | */ | |
41654125 | 865 | static void |
2af814a5 | 866 | dbg_signal() |
ce5db1eb | 867 | { |
2af814a5 JB |
868 | Debug = (Debug == 0) ? 30 : 0; |
869 | setdebug(DBG_PERM); | |
870 | if (Debug > 0) | |
871 | logent("Signal Enabled", "DEBUG"); | |
ce5db1eb SL |
872 | } |
873 | ||
874 | ||
2af814a5 JB |
875 | /* |
876 | * Check debugging requests, and open RMTDEBUG audit file if necessary. If an | |
877 | * audit file is needed, the parm argument indicates how to create the file: | |
878 | * | |
879 | * DBG_TEMP - Open a temporary file, with filename = RMTDEBUG/pid. | |
880 | * DBG_PERM - Open a permanent audit file, filename = RMTDEBUG/Rmtname. | |
881 | * If a temp file already exists, it is mv'ed to be permanent. | |
882 | * DBG_CLEAN - Cleanup; unlink temp files. | |
ce5db1eb | 883 | * |
2af814a5 JB |
884 | * Restrictions - this code can only cope with one open debug file at a time. |
885 | * Each call creates a new file; if an old one of the same name exists it will | |
886 | * be overwritten. | |
ce5db1eb | 887 | */ |
2af814a5 JB |
888 | setdebug(parm) |
889 | int parm; | |
ce5db1eb | 890 | { |
2af814a5 JB |
891 | char buf[BUFSIZ]; /* Buffer for building filenames */ |
892 | static char *temp = NULL; /* Ptr to temporary file name */ | |
893 | static int auditopen = 0; /* Set to 1 when we open a file */ | |
894 | struct stat stbuf; /* File status buffer */ | |
ce5db1eb | 895 | |
2af814a5 JB |
896 | /* |
897 | * If movement or cleanup of a temp file is indicated, we do it no | |
898 | * matter what. | |
899 | */ | |
900 | if (temp != CNULL && parm == DBG_PERM) { | |
901 | sprintf(buf, "%s/%s", RMTDEBUG, Rmtname); | |
902 | unlink(buf); | |
903 | if (link(temp, buf) != 0) { | |
904 | Debug = 0; | |
a5c64120 RA |
905 | syslog(LOG_ERR, "RMTDEBUG link(%s,%s) failed: %m", |
906 | temp, buf); | |
907 | cleanup(FAIL); | |
2af814a5 JB |
908 | } |
909 | parm = DBG_CLEAN; | |
910 | } | |
911 | if (parm == DBG_CLEAN) { | |
912 | if (temp != CNULL) { | |
913 | unlink(temp); | |
914 | free(temp); | |
915 | temp = CNULL; | |
916 | } | |
ce5db1eb | 917 | return; |
2af814a5 | 918 | } |
ce5db1eb | 919 | |
2af814a5 JB |
920 | if (Debug == 0) |
921 | return; /* Gotta be in debug to come here. */ | |
922 | ||
923 | /* | |
924 | * If we haven't opened a file already, we can just return if it's | |
925 | * alright to use the stderr we came in with. We can if: | |
926 | * | |
927 | * Role == MASTER, and Stderr is a regular file, a TTY or a pipe. | |
928 | * | |
929 | * Caution: Detecting when stderr is a pipe is tricky, because the 4.2 | |
930 | * man page for fstat(2) disagrees with reality, and System V leaves it | |
931 | * undefined, which means different implementations act differently. | |
932 | */ | |
933 | if (!auditopen && Role == MASTER) { | |
934 | if (isatty(fileno(stderr))) | |
935 | return; | |
936 | else if (fstat(fileno(stderr), &stbuf) == 0) { | |
937 | #ifdef USG | |
938 | /* Is Regular File or Fifo */ | |
939 | if ((stbuf.st_mode & 0060000) == 0) | |
940 | return; | |
941 | #else !USG | |
942 | #ifdef BSD4_2 | |
943 | /* Is Regular File */ | |
944 | if ((stbuf.st_mode & S_IFMT) == S_IFREG || | |
945 | stbuf.st_mode == 0) /* Is a pipe */ | |
946 | return; | |
947 | #else !BSD4_2 | |
948 | /* Is Regular File or Pipe */ | |
949 | if ((stbuf.st_mode & S_IFMT) == S_IFREG) | |
950 | return; | |
951 | #endif BSD4_2 | |
952 | #endif USG | |
953 | } | |
954 | } | |
955 | ||
956 | /* | |
957 | * We need RMTDEBUG directory to do auditing. If the file doesn't exist, | |
958 | * then we forget about debugging; if it exists but has improper owner- | |
959 | * ship or modes, we gripe about it in ERRLOG. | |
960 | */ | |
961 | if (stat(RMTDEBUG, &stbuf) != SUCCESS) { | |
962 | Debug = 0; | |
963 | return; | |
964 | } | |
965 | if ((geteuid() != stbuf.st_uid) || /* We must own it */ | |
966 | ((stbuf.st_mode & 0170700) != 040700)) { /* Directory, rwx */ | |
967 | Debug = 0; | |
a5c64120 RA |
968 | syslog(LOG_ERR, "%s: invalid directory mode: %o", RMTDEBUG, |
969 | stbuf.st_mode); | |
2af814a5 JB |
970 | return; |
971 | } | |
972 | ||
973 | if (parm == DBG_TEMP) { | |
974 | sprintf(buf, "%s/%d", RMTDEBUG, getpid()); | |
975 | temp = malloc(strlen (buf) + 1); | |
976 | if (temp == CNULL) { | |
977 | Debug = 0; | |
a5c64120 RA |
978 | syslog(LOG_ERR, "RMTDEBUG malloc failed: %m"); |
979 | cleanup(FAIL); | |
2af814a5 JB |
980 | } |
981 | strcpy(temp, buf); | |
982 | } else | |
983 | sprintf(buf, "%s/%s", RMTDEBUG, Rmtname); | |
984 | ||
985 | unlink(buf); | |
986 | if (freopen(buf, "w", stderr) != stderr) { | |
987 | Debug = 0; | |
a5c64120 RA |
988 | syslog(LOG_ERR, "RMTDEBUG freopen(%s) failed: %m", buf); |
989 | cleanup(FAIL); | |
2af814a5 JB |
990 | } |
991 | setbuf(stderr, CNULL); | |
992 | auditopen = 1; | |
993 | } | |
ce5db1eb | 994 | |
4b31fbb4 | 995 | /* |
2af814a5 | 996 | * catch SIGALRM routine |
ce5db1eb | 997 | */ |
41654125 | 998 | static void |
ce5db1eb SL |
999 | timeout() |
1000 | { | |
4b31fbb4 JB |
1001 | extern int HaveSentHup; |
1002 | if (!HaveSentHup) { | |
1003 | logent(Rmtname, "TIMEOUT"); | |
1004 | if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) { | |
1005 | US_SST(us_s_tmot); | |
1006 | systat(Rmtname, SS_FAIL, "TIMEOUT"); | |
1007 | } | |
88db71e9 | 1008 | } |
ce5db1eb SL |
1009 | longjmp(Sjbuf, 1); |
1010 | } | |
1011 | ||
1012 | static char * | |
1013 | pskip(p) | |
1014 | register char *p; | |
1015 | { | |
88db71e9 | 1016 | while(*p && *p != ' ') |
ce5db1eb | 1017 | ++p; |
4b31fbb4 | 1018 | while(*p && *p == ' ') |
88db71e9 RC |
1019 | *p++ = 0; |
1020 | return p; | |
ce5db1eb | 1021 | } |
274cf361 RA |
1022 | |
1023 | /* | |
1024 | * clobber argv so ps will show what we're doing. | |
1025 | * stolen from sendmail | |
1026 | */ | |
1027 | /*VARARGS1*/ | |
1028 | setproctitle(fmt, a, b, c) | |
1029 | char *fmt; | |
1030 | { | |
1031 | #ifdef SETPROCTITLE | |
1032 | register char *p; | |
1033 | register int i; | |
1034 | extern char **Argv; | |
1035 | extern char *LastArgv; | |
1036 | char buf[BUFSIZ]; | |
1037 | ||
1038 | (void) sprintf(buf, fmt, a, b, c); | |
1039 | ||
1040 | /* make ps print "(sendmail)" */ | |
1041 | p = Argv[0]; | |
1042 | *p++ = '-'; | |
1043 | ||
1044 | i = strlen(buf); | |
1045 | if (i > LastArgv - p - 2) { | |
1046 | i = LastArgv - p - 2; | |
1047 | buf[i] = '\0'; | |
1048 | } | |
1049 | (void) strcpy(p, buf); | |
1050 | p += i; | |
1051 | while (p < LastArgv) | |
1052 | *p++ = ' '; | |
1053 | #endif SETPROCTITLE | |
1054 | } |