xref: /csrg-svn/usr.bin/uucp/uucico/cico.c (revision 46879)
113639Ssam #ifndef lint
2*46879Sbostic static char sccsid[] = "@(#)cico.c	5.20	(Berkeley) 03/02/91";
313639Ssam #endif
413639Ssam 
523590Sbloom #include <signal.h>
613639Ssam #include "uucp.h"
713639Ssam #include <setjmp.h>
817767Sralph #ifdef	USG
913639Ssam #include <termio.h>
1033559Srick #include <fcntl.h>
1113639Ssam #endif
1217767Sralph #ifndef	USG
1313639Ssam #include <sgtty.h>
1413639Ssam #endif
1517767Sralph #ifdef BSDTCP
1617767Sralph #include <netdb.h>
1717767Sralph #include <netinet/in.h>
1817767Sralph #include <sys/socket.h>
1917767Sralph #endif BSDTCP
2017767Sralph #include <sys/stat.h>
2133559Srick #ifdef BSD4_2
2233559Srick #include <sys/time.h>
2333559Srick #include <fcntl.h>
2433559Srick #else
2533559Srick #include <time.h>
2633559Srick #endif
2717767Sralph #include "uust.h"
2817767Sralph #include "uusub.h"
2937930Sbostic #include "pathnames.h"
3013639Ssam 
3123590Sbloom #if defined(VMS) && defined(BSDTCP)
3223590Sbloom #define NOGETPEER
3323590Sbloom #endif
3423590Sbloom 
3517767Sralph jmp_buf Sjbuf;
3617767Sralph jmp_buf Pipebuf;
3713639Ssam 
3817767Sralph /*  call fail text  */
3913639Ssam char *Stattext[] = {
4013639Ssam 	"",
4113639Ssam 	"BAD SYSTEM",
4217767Sralph 	"WRONG TIME TO CALL",
4313639Ssam 	"SYSTEM LOCKED",
4413639Ssam 	"NO DEVICE",
4525703Sbloom 	"CALL FAILED",
4613639Ssam 	"LOGIN FAILED",
4713639Ssam 	"BAD SEQUENCE"
4817767Sralph };
4913639Ssam 
5017767Sralph /*  call fail codes  */
5117767Sralph int Stattype[] = {
5217767Sralph 	0,
5317767Sralph 	0,
5417767Sralph 	SS_WRONGTIME,
5517767Sralph 	0,
5617767Sralph 	SS_NODEVICE,
5717767Sralph 	SS_FAIL,
5817767Sralph 	SS_FAIL,
5917767Sralph 	SS_BADSEQ
6017767Sralph };
6113639Ssam 
6225703Sbloom 				/* Arguments to setdebug():		     */
6325703Sbloom #define DBG_TEMP  0		/*   Create a temporary audit file	     */
6425703Sbloom #define DBG_PERM  1		/*   Create a permanent audit file	     */
6525703Sbloom #define DBG_CLEAN 2		/*   Cleanup, discard temp file		     */
6613639Ssam 
6717767Sralph int ReverseRole = 0;
6817767Sralph int Role = SLAVE;
6933559Srick int InitialRole = SLAVE;
7033559Srick long StartTime;
7117767Sralph int onesys = 0;
7218616Sralph int turntime = 30 * 60;	/* 30 minutes expressed in seconds */
7325703Sbloom char *ttyn = NULL;
7417767Sralph extern int LocalOnly;
7525703Sbloom extern int errno;
7618616Sralph extern char MaxGrade, DefMaxGrade;
7718616Sralph extern char Myfullname[];
7817767Sralph 
7933559Srick long Bytes_Sent, Bytes_Received;
8033559Srick 
8117767Sralph #ifdef	USG
8213639Ssam struct termio Savettyb;
8313639Ssam #endif
8417767Sralph #ifndef	USG
8513639Ssam struct sgttyb Savettyb;
8613639Ssam #endif
8713639Ssam 
8834164Srick #define SETPROCTITLE
8934164Srick #ifdef SETPROCTITLE
9034164Srick char	**Argv = NULL;		/* pointer to argument vector */
9134164Srick char	*LastArgv = NULL;	/* end of argv */
9234164Srick #endif SETPROCTITLE
9334164Srick 
9425703Sbloom /*
9525703Sbloom  *	this program is used  to place a call to a
9613639Ssam  *	remote machine, login, and copy files between the two machines.
9713639Ssam  */
9834164Srick main(argc, argv, envp)
9925703Sbloom int argc;
10033945Srick char **argv;
10134164Srick char **envp;
10213639Ssam {
10313639Ssam 	register int ret;
10413639Ssam 	int seq;
10513639Ssam 	char wkpre[NAMESIZE], file[NAMESIZE];
10625703Sbloom 	char msg[MAXFULLNAME], *q;
10713639Ssam 	register char *p;
108*46879Sbostic 	static void onintr(), timeout(), dbg_signal();
109*46879Sbostic 	static char *pskip();
11033945Srick 	extern char *optarg;
11133945Srick 	extern int optind;
11223725Sbloom 	char rflags[MAXFULLNAME];
11323590Sbloom #ifdef NOGETPEER
11417767Sralph 	u_long Hostnumber = 0;
11523590Sbloom #endif NOGETPEER
11613639Ssam 
11713639Ssam 	strcpy(Progname, "uucico");
11813639Ssam 
11926149Sbloom #ifdef BSD4_2
12033945Srick 	sigsetmask(0L);	/* in case we inherit blocked signals */
12126149Sbloom #endif BSD4_2
12213639Ssam 	signal(SIGINT, onintr);
12313639Ssam 	signal(SIGHUP, onintr);
12413639Ssam 	signal(SIGQUIT, onintr);
12513639Ssam 	signal(SIGTERM, onintr);
12613639Ssam 	signal(SIGPIPE, onintr);	/* 4.1a tcp-ip stupidity */
12736449Smarc 	signal(SIGUSR1, dbg_signal);
12813639Ssam 	ret = guinfo(getuid(), User, msg);
12913639Ssam 	strcpy(Loginuser, User);
13023590Sbloom 	uucpname(Myname);
13133945Srick 	if (ret == FAIL) {
13233945Srick 		syslog(LOG_ERR, "can't get uid");
13333945Srick 		cleanup(FAIL);
13433945Srick 	}
13513639Ssam 
13625703Sbloom 	setbuf (stderr, CNULL);
13725703Sbloom 
13825703Sbloom 	rflags[0] = '\0';
13913639Ssam 	umask(WFMASK);
14013639Ssam 	strcpy(Rmtname, Myname);
14113639Ssam 	Ifn = Ofn = -1;
14233945Srick 	while ((ret = getopt(argc, argv, "RLd:g:p:r:s:x:t:")) != EOF)
14333945Srick 		switch(ret){
14413639Ssam 		case 'd':
14533945Srick 			Spool = optarg;
14613639Ssam 			break;
14713639Ssam 		case 'g':
14818616Sralph 		case 'p':
14933945Srick 			MaxGrade = DefMaxGrade = *optarg;
15013639Ssam 			break;
15113639Ssam 		case 'r':
15233945Srick 			Role = atoi(optarg);
15313639Ssam 			break;
15417767Sralph 		case 'R':
15517767Sralph 			ReverseRole++;
15617767Sralph 			Role = MASTER;
15717767Sralph 			break;
15813639Ssam 		case 's':
15933945Srick 			strncpy(Rmtname, optarg, MAXBASENAME);
16023590Sbloom 			Rmtname[MAXBASENAME] = '\0';
16113639Ssam 			if (Rmtname[0] != '\0')
16213639Ssam 				onesys = 1;
16313639Ssam 			break;
16413639Ssam 		case 'x':
16533945Srick 			Debug = atoi(optarg);
16613639Ssam 			if (Debug <= 0)
16713639Ssam 				Debug = 1;
16833945Srick 			strcat(rflags, argv[optind-1]);
16913639Ssam 			break;
17018616Sralph 		case 't':
17133945Srick 			turntime = atoi(optarg)*60;/* minutes to seconds */
17218616Sralph 			break;
17317767Sralph 		case 'L':	/* local calls only */
17417767Sralph 			LocalOnly++;
17517767Sralph 			break;
17623590Sbloom #ifdef NOGETPEER
17717767Sralph 		case 'h':
17817767Sralph 			Hostnumber = inet_addr(&argv[1][2]);
17917767Sralph 			break;
18023590Sbloom #endif NOGETPEER
18133945Srick 		case '?':
18213639Ssam 		default:
18333945Srick 			fprintf(stderr, "unknown flag %s (ignored)\n",
18433945Srick 				argv[optind-1]);
18513639Ssam 			break;
18613639Ssam 		}
18713639Ssam 
18833945Srick 	while (optind < argc)
18933945Srick 		fprintf(stderr, "unknown argument %s (ignored)\n",
19033945Srick 			argv[optind++]);
19117767Sralph 
19227069Sbloom 	if (Debug && Role == MASTER)
19327069Sbloom 		chkdebug();
19427069Sbloom 
19534164Srick #ifdef SETPROCTITLE
19634164Srick 	/*
19734164Srick 	 *  Save start and extent of argv for setproctitle.
19834164Srick 	 */
19934164Srick 
20034164Srick 	Argv = argv;
20134164Srick 	LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
20234164Srick #endif SETPROCTITLE
20334164Srick 
20425124Sbloom 	/* Try to run as uucp */
20517767Sralph 	setgid(getegid());
20617767Sralph 	setuid(geteuid());
20717767Sralph #ifdef	TIOCNOTTY
20817767Sralph 	/*
20917767Sralph 	 * detach uucico from controlling terminal
21017767Sralph 	 * to defend against rlogind sending us a SIGKILL (!!!)
21117767Sralph 	 */
21237930Sbostic 	if (Role == MASTER && (ret = open(_PATH_TTY, 2)) >= 0) {
21317767Sralph 		ioctl(ret, TIOCNOTTY, STBNULL);
21417767Sralph 		close(ret);
21517767Sralph 	}
21617767Sralph #endif TIOCNOTTY
21717767Sralph #ifdef BSD4_2
21825517Stef 	if (getpgrp(0) == 0) { /* We have no controlling terminal */
21917767Sralph 		setpgrp(0, getpid());
22017767Sralph 	}
22133945Srick #ifdef USE_SYSLOG
22233945Srick #ifdef BSD4_3
22333945Srick 	openlog("uucico", LOG_PID, LOG_UUCP);
22433945Srick #else /* !BSD4_3 */
22533945Srick 	openlog("uucico", LOG_PID);
22633945Srick #endif /* !BSD4_3 */
22733945Srick #endif /* USE_SYSLOG */
22817767Sralph #endif BSD4_2
22917767Sralph 
23033945Srick #ifdef BSD4_3
23133945Srick 	unsetenv("TZ");		/* We don't want him resetting our time zone */
23233945Srick #endif /* !BSD4_3 */
23333945Srick 
23433945Srick 	if (subchdir(Spool) < 0) {
23533945Srick 		syslog(LOG_ERR, "chdir(%s) failed: %m", Spool);
23633945Srick 		cleanup(FAIL);
23733945Srick 	}
23833945Srick 
23913639Ssam 	strcpy(Wrkdir, Spool);
24013639Ssam 
24125703Sbloom 	if (Debug) {
24225703Sbloom 		setdebug ((Role == SLAVE) ? DBG_TEMP : DBG_PERM);
24325703Sbloom 		if (Debug > 0)
24425703Sbloom 			logent ("Local Enabled", "DEBUG");
24525703Sbloom 	}
24625703Sbloom 
24725703Sbloom 	/*
24825703Sbloom 	 * First time through: If we're the slave, do initial checking.
24925703Sbloom 	 */
25013639Ssam 	if (Role == SLAVE) {
25117767Sralph 		/* check for /etc/nologin */
25225124Sbloom 		if (access(NOLOGIN, 0) == 0) {
25317767Sralph 			logent(NOLOGIN, "UUCICO SHUTDOWN");
25423590Sbloom 			if (Debug > 4)
25517767Sralph 				logent("DEBUGGING", "continuing anyway");
25617767Sralph 			else
25717767Sralph 				cleanup(1);
25817767Sralph 		}
25925703Sbloom 		Ifn = 0;
26025703Sbloom 		Ofn = 1;
26117767Sralph #ifdef	TCPIP
26217767Sralph 		/*
26317767Sralph 		 * Determine if we are on TCPIP
26417767Sralph 		 */
26533559Srick 		if (isatty(Ifn) == 0) {
26617767Sralph 			IsTcpIp = 1;
26717767Sralph 			DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
26823590Sbloom 		} else
26923590Sbloom 			IsTcpIp = 0;
27017767Sralph #endif TCPIP
27113639Ssam 		/* initial handshake */
27213639Ssam 		onesys = 1;
27317767Sralph 		if (!IsTcpIp) {
27417767Sralph #ifdef	USG
27525703Sbloom 			ret = ioctl(Ifn, TCGETA, &Savettyb);
27613639Ssam 			Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7;
27713639Ssam 			Savettyb.c_oflag |= OPOST;
27813639Ssam 			Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
27917767Sralph #else !USG
28025703Sbloom 			ret = ioctl(Ifn, TIOCGETP, &Savettyb);
28113639Ssam 			Savettyb.sg_flags |= ECHO;
28213639Ssam 			Savettyb.sg_flags &= ~RAW;
28317767Sralph #endif !USG
28425703Sbloom 			ttyn = ttyname(Ifn);
28513639Ssam 		}
28613639Ssam 		fixmode(Ifn);
28725703Sbloom 
28825703Sbloom 		/*
28925703Sbloom 		 * Initial Message -- tell them we're here, and who we are.
29025703Sbloom 		 */
29118616Sralph 		sprintf(msg, "here=%s", Myfullname);
29217767Sralph 		omsg('S', msg, Ofn);
29313639Ssam 		signal(SIGALRM, timeout);
29433559Srick 		alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME);
29513639Ssam 		if (setjmp(Sjbuf)) {
29613639Ssam 			/* timed out */
29717767Sralph 			if (!IsTcpIp) {
29817767Sralph #ifdef	USG
29925703Sbloom 				ret = ioctl(Ifn, TCSETA, &Savettyb);
30025703Sbloom 
30123590Sbloom #else	!USG
30225703Sbloom 				ret = ioctl(Ifn, TIOCSETP, &Savettyb);
30323590Sbloom #endif !USG
30413639Ssam 			}
30517767Sralph 			cleanup(0);
30613639Ssam 		}
30713639Ssam 		for (;;) {
30813639Ssam 			ret = imsg(msg, Ifn);
30925703Sbloom 			if (ret != SUCCESS) {
31013639Ssam 				alarm(0);
31117767Sralph 				if (!IsTcpIp) {
31217767Sralph #ifdef	USG
31325703Sbloom 					ret = ioctl(Ifn, TCSETA, &Savettyb);
31423590Sbloom #else	!USG
31525703Sbloom 					ret = ioctl(Ifn, TIOCSETP, &Savettyb);
31623590Sbloom #endif !USG
31713639Ssam 				}
31817767Sralph 				cleanup(0);
31913639Ssam 			}
32013639Ssam 			if (msg[0] == 'S')
32113639Ssam 				break;
32213639Ssam 		}
32313639Ssam 		alarm(0);
32413639Ssam 		q = &msg[1];
32513639Ssam 		p = pskip(q);
32623590Sbloom 		strncpy(Rmtname, q, MAXBASENAME);
32723590Sbloom 		Rmtname[MAXBASENAME] = '\0';
32825703Sbloom 
32925703Sbloom 		/*
33025703Sbloom 		 * Now that we know who they are, give the audit file the right
33125703Sbloom 		 * name.
33225703Sbloom 		 */
33325703Sbloom 		setdebug (DBG_PERM);
33413639Ssam 		DEBUG(4, "sys-%s\n", Rmtname);
33523725Sbloom 		/* The versys will also do an alias on the incoming name */
33623725Sbloom 		if (versys(&Rmtname)) {
33733559Srick #ifdef	NOSTRANGERS
33823725Sbloom 			/* If we don't know them, we won't talk to them... */
33933945Srick 			syslog(LOG_WARNING, "Unknown host: %s", Rmtname);
34023590Sbloom 			omsg('R', "You are unknown to me", Ofn);
34123590Sbloom 			cleanup(0);
34223725Sbloom #endif	NOSTRANGERS
34323590Sbloom 		}
34417767Sralph #ifdef BSDTCP
34517767Sralph 		/* we must make sure they are really who they say they
34617767Sralph 		 * are. We compare the hostnumber with the number in the hosts
34717767Sralph 		 * table for the site they claim to be.
34817767Sralph 		 */
34917767Sralph 		if (IsTcpIp) {
35017767Sralph 			struct hostent *hp;
35117767Sralph 			char *cpnt, *inet_ntoa();
35225703Sbloom 			int fromlen;
35317767Sralph 			struct sockaddr_in from;
35425124Sbloom 			extern char PhoneNumber[];
35517767Sralph 
35623590Sbloom #ifdef	NOGETPEER
35723590Sbloom 			from.sin_addr.s_addr = Hostnumber;
35823590Sbloom 			from.sin_family = AF_INET;
35923590Sbloom #else	!NOGETPEER
36025703Sbloom 			fromlen = sizeof(from);
361*46879Sbostic 			if (getpeername(Ifn,
362*46879Sbostic 			    (struct sockaddr *)&from, &fromlen) < 0) {
36317767Sralph 				logent(Rmtname, "NOT A TCP CONNECTION");
36417767Sralph 				omsg('R', "NOT TCP", Ofn);
36517767Sralph 				cleanup(0);
36617767Sralph 			}
36723590Sbloom #endif	!NOGETPEER
368*46879Sbostic 			hp = gethostbyaddr((char *)&from.sin_addr,
36917767Sralph 				sizeof (struct in_addr), from.sin_family);
37025703Sbloom 			if (hp == NULL) {
37117767Sralph 				/* security break or just old host table? */
37217767Sralph 				logent(Rmtname, "UNKNOWN IP-HOST Name =");
37317767Sralph 				cpnt = inet_ntoa(from.sin_addr),
37417767Sralph 				logent(cpnt, "UNKNOWN IP-HOST Number =");
37517767Sralph 				sprintf(wkpre, "%s/%s isn't in my host table",
37617767Sralph 					Rmtname, cpnt);
37717767Sralph 				omsg('R' ,wkpre ,Ofn);
37817767Sralph 				cleanup(0);
37917767Sralph 			}
38025703Sbloom 			if (Debug > 99)
38117767Sralph 				logent(Rmtname,"Request from IP-Host name =");
38225124Sbloom 			/*
38325124Sbloom 			 * The following is to determine if the name given us by
38425124Sbloom 			 * the Remote uucico matches any of the names
38517767Sralph 			 * given its network number (remote machine) in our
38617767Sralph 			 * host table.
38725124Sbloom 			 * We could check the aliases, but that won't work in
38825124Sbloom 			 * all cases (like if you are running the domain
38925124Sbloom 			 * server, where you don't get any aliases). The only
39025124Sbloom 			 * reliable way I can think of that works in ALL cases
39125124Sbloom 			 * is too look up the site in L.sys and see if the
39225124Sbloom 			 * sitename matches what we would call him if we
39325124Sbloom 			 * originated the call.
39417767Sralph 			 */
39525124Sbloom 			/* PhoneNumber contains the official network name of the 			   host we are checking. (set in versys.c) */
39625124Sbloom 			if (sncncmp(PhoneNumber, hp->h_name, SYSNSIZE) == 0) {
39717767Sralph 				if (Debug > 99)
39817767Sralph 					logent(q,"Found in host Tables");
39925124Sbloom 			} else {
40025124Sbloom 				logent(hp->h_name, "FORGED HOSTNAME");
40125124Sbloom 				logent(inet_ntoa(from.sin_addr), "ORIGINATED AT");
40225124Sbloom 				logent(PhoneNumber, "SHOULD BE");
40325124Sbloom 				sprintf(wkpre, "You're not who you claim to be: %s !=  %s", hp->h_name, PhoneNumber);
40425124Sbloom 				omsg('R', wkpre, Ofn);
40525124Sbloom 				cleanup(0);
40617767Sralph 			}
40717767Sralph 		}
40817767Sralph #endif	BSDTCP
40917767Sralph 
41025703Sbloom 		if (mlock(Rmtname)) {
41113639Ssam 			omsg('R', "LCK", Ofn);
41213639Ssam 			cleanup(0);
41313639Ssam 		}
41413639Ssam 		else if (callback(Loginuser)) {
41513639Ssam 			signal(SIGINT, SIG_IGN);
41613639Ssam 			signal(SIGHUP, SIG_IGN);
41713639Ssam 			omsg('R', "CB", Ofn);
41813639Ssam 			logent("CALLBACK", "REQUIRED");
41913639Ssam 			/*  set up for call back  */
42017767Sralph 			systat(Rmtname, SS_CALLBACK, "CALLING BACK");
42113639Ssam 			gename(CMDPRE, Rmtname, 'C', file);
42213639Ssam 			close(creat(subfile(file), 0666));
42313639Ssam 			xuucico(Rmtname);
42413639Ssam 			cleanup(0);
42513639Ssam 		}
42613639Ssam 		seq = 0;
42713639Ssam 		while (*p == '-') {
42813639Ssam 			q = pskip(p);
42913639Ssam 			switch(*(++p)) {
43013639Ssam 			case 'x':
43125703Sbloom 				if (Debug == 0) {
43225703Sbloom 					Debug = atoi(++p);
43325703Sbloom 					if (Debug <= 0)
43425703Sbloom 						Debug = 1;
43525703Sbloom 					setdebug(DBG_PERM);
43625703Sbloom 					if (Debug > 0)
43725703Sbloom 						logent("Remote Enabled", "DEBUG");
43825703Sbloom 				} else {
43925703Sbloom 					DEBUG(1, "Remote debug request ignored\n",
44025703Sbloom 					   CNULL);
44125703Sbloom 				}
44213639Ssam 				break;
44313639Ssam 			case 'Q':
44413639Ssam 				seq = atoi(++p);
44513639Ssam 				break;
44618616Sralph 			case 'p':
44718616Sralph 				MaxGrade = DefMaxGrade = *++p;
44818616Sralph 				DEBUG(4, "MaxGrade set to %c\n", MaxGrade);
44918616Sralph 				break;
45023590Sbloom 			case 'v':
45123590Sbloom 				if (strncmp(p, "grade", 5) == 0) {
45223590Sbloom 					p += 6;
45323590Sbloom 					MaxGrade = DefMaxGrade = *p++;
45423590Sbloom 					DEBUG(4, "MaxGrade set to %c\n", MaxGrade);
45523590Sbloom 				}
45623590Sbloom 				break;
45713639Ssam 			default:
45813639Ssam 				break;
45913639Ssam 			}
46013639Ssam 			p = q;
46113639Ssam 		}
46234164Srick 		setproctitle("%s: startup", Rmtname);
46313639Ssam 		if (callok(Rmtname) == SS_BADSEQ) {
46413639Ssam 			logent("BADSEQ", "PREVIOUS");
46513639Ssam 			omsg('R', "BADSEQ", Ofn);
46613639Ssam 			cleanup(0);
46713639Ssam 		}
46817767Sralph #ifdef GNXSEQ
46913639Ssam 		if ((ret = gnxseq(Rmtname)) == seq) {
47013639Ssam 			omsg('R', "OK", Ofn);
47113639Ssam 			cmtseq();
47217767Sralph 		} else {
47317767Sralph #else !GNXSEQ
47417767Sralph 		if (seq == 0)
47517767Sralph 			omsg('R', "OK", Ofn);
47613639Ssam 		else {
47717767Sralph #endif !GNXSEQ
47813639Ssam 			systat(Rmtname, Stattype[7], Stattext[7]);
47923590Sbloom 			logent("BAD SEQ", "FAILED HANDSHAKE");
48017767Sralph #ifdef GNXSEQ
48113639Ssam 			ulkseq();
48217767Sralph #endif GNXSEQ
48313639Ssam 			omsg('R', "BADSEQ", Ofn);
48413639Ssam 			cleanup(0);
48513639Ssam 		}
48613639Ssam 		if (ttyn != NULL)
48713639Ssam 			chmod(ttyn, 0600);
48813639Ssam 	}
48917767Sralph 
49013639Ssam loop:
49117767Sralph 	if(setjmp(Pipebuf)) {	/* come here on SIGPIPE	*/
49217767Sralph 		clsacu();
49334164Srick 		logcls();
49417767Sralph 		close(Ofn);
49517767Sralph 		close(Ifn);
49617767Sralph 		Ifn = Ofn = -1;
49717767Sralph 		rmlock(CNULL);
49817767Sralph 		sleep(3);
49917767Sralph 	}
50013639Ssam 	if (!onesys) {
50133559Srick 		do_connect_accounting();
50233945Srick #ifdef DIALINOUT
50333945Srick 		/* reenable logins on dialout */
50433945Srick 		reenable();
50533945Srick #endif DIALINOUT
50633559Srick 		StartTime = 0;
50734164Srick 		setproctitle("looking for work");
50813639Ssam 		ret = gnsys(Rmtname, Spool, CMDPRE);
50934164Srick 		setproctitle("%s: startup", Rmtname);
51025703Sbloom 		setdebug(DBG_PERM);
51113639Ssam 		if (ret == FAIL)
51213639Ssam 			cleanup(100);
51333559Srick 		else if (ret == SUCCESS)
51413639Ssam 			cleanup(0);
51534164Srick 		logcls();
51617767Sralph 	} else if (Role == MASTER && callok(Rmtname) != 0) {
51713639Ssam 		logent("SYSTEM STATUS", "CAN NOT CALL");
51813639Ssam 		cleanup(0);
51913639Ssam 	}
52013639Ssam 
52123590Sbloom 	sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
52233559Srick 	StartTime = 0;
52333559Srick 	Bytes_Sent = Bytes_Received = 0L;
52413639Ssam 
52517767Sralph 	signal(SIGINT, SIG_IGN);
52617767Sralph 	signal(SIGQUIT, SIG_IGN);
52713639Ssam 	if (Role == MASTER) {
52833559Srick 		extern char LineType[];
52917767Sralph 		/* check for /etc/nologin */
53025124Sbloom 		if (access(NOLOGIN, 0) == 0) {
53117767Sralph 			logent(NOLOGIN, "UUCICO SHUTDOWN");
53223590Sbloom 			if (Debug > 4)
53317767Sralph 				logent("DEBUGGING", "continuing anyway");
53417767Sralph 			else
53517767Sralph 				cleanup(1);
53617767Sralph 		}
53713639Ssam 		/*  master part */
53813639Ssam 		signal(SIGHUP, SIG_IGN);
53913639Ssam 		if (Ifn != -1 && Role == MASTER) {
54013639Ssam 			write(Ofn, EOTMSG, strlen(EOTMSG));
54113639Ssam 			clsacu();
54213639Ssam 			close(Ofn);
54313639Ssam 			close(Ifn);
54413639Ssam 			Ifn = Ofn = -1;
54513639Ssam 			rmlock(CNULL);
54613639Ssam 			sleep(3);
54713639Ssam 		}
54825124Sbloom 		if (mlock(Rmtname) != SUCCESS) {
54933559Srick 			DEBUG(1, "LOCKED: call to %s\n", Rmtname);
55017767Sralph 			US_SST(us_s_lock);
55113639Ssam 			goto next;
55213639Ssam 		}
55334164Srick 		setproctitle("%s: starting call", Rmtname);
55413639Ssam 		Ofn = Ifn = conn(Rmtname);
55534164Srick 		sprintf(msg, "(call to %s via %s)", Rmtname, LineType);
55613639Ssam 		if (Ofn < 0) {
55717767Sralph 			if (Ofn != CF_TIME)
55817767Sralph 				logent(msg, _FAILED);
55917767Sralph 			/* avoid excessive 'wrong time' info */
56023590Sbloom 			if (Stattype[-Ofn] != SS_WRONGTIME){
56117767Sralph 				systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]);
56217767Sralph 				US_SST(-Ofn);
56317767Sralph 				UB_SST(-Ofn);
56417767Sralph 			}
56513639Ssam 			goto next;
56617767Sralph 		} else {
56713639Ssam 			logent(msg, "SUCCEEDED");
56817767Sralph 			US_SST(us_s_cok);
56917767Sralph 			UB_SST(ub_ok);
57013639Ssam 		}
57133559Srick 		InitialRole = MASTER;
57217767Sralph #ifdef	TCPIP
57317767Sralph 		/*
57417767Sralph 		 * Determine if we are on TCPIP
57517767Sralph 		 */
57625703Sbloom 		if (isatty(Ifn) == 0) {
57717767Sralph 			IsTcpIp = 1;
57817767Sralph 			DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
57923590Sbloom 		} else
58023590Sbloom 			IsTcpIp = 0;
58117767Sralph #endif
58217767Sralph 
58313639Ssam 		if (setjmp(Sjbuf))
58413639Ssam 			goto next;
58513639Ssam 		signal(SIGALRM, timeout);
58633559Srick 		alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME*2);
58713639Ssam 		for (;;) {
58813639Ssam 			ret = imsg(msg, Ifn);
58933559Srick 			if (ret != SUCCESS) {
59013639Ssam 				alarm(0);
59133559Srick 				DEBUG(4,"\nimsg failed: errno %d\n", errno);
59217767Sralph 				logent("imsg 1", _FAILED);
59317767Sralph 				goto Failure;
59413639Ssam 			}
59513639Ssam 			if (msg[0] == 'S')
59613639Ssam 				break;
59713639Ssam 		}
59833559Srick 		alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME);
59917767Sralph #ifdef GNXSEQ
60013639Ssam 		seq = gnxseq(Rmtname);
60117767Sralph #else !GNXSEQ
60217767Sralph 		seq = 0;
60317767Sralph #endif !GNXSEQ
60418616Sralph 		if (MaxGrade != '\177') {
60523590Sbloom 			DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade);
60625963Sbloom 			sprintf(msg, "%s -Q%d -p%c -vgrade=%c %s",
60725963Sbloom 				Myname, seq, MaxGrade, MaxGrade, rflags);
60825963Sbloom 		} else
60925963Sbloom 			sprintf(msg, "%s -Q%d %s", Myname, seq, rflags);
61013639Ssam 		omsg('S', msg, Ofn);
61113639Ssam 		for (;;) {
61213639Ssam 			ret = imsg(msg, Ifn);
61313639Ssam 			DEBUG(4, "msg-%s\n", msg);
61417767Sralph 			if (ret != SUCCESS) {
61513639Ssam 				alarm(0);
61617767Sralph #ifdef GNXSEQ
61713639Ssam 				ulkseq();
61817767Sralph #endif GNXSEQ
61917767Sralph 				logent("imsg 2", _FAILED);
62017767Sralph 				goto Failure;
62113639Ssam 			}
62213639Ssam 			if (msg[0] == 'R')
62313639Ssam 				break;
62413639Ssam 		}
62513639Ssam 		alarm(0);
62613639Ssam 		if (msg[1] == 'B') {
62713639Ssam 			/* bad sequence */
62823590Sbloom 			logent("BAD SEQ", "FAILED HANDSHAKE");
62917767Sralph 			US_SST(us_s_hand);
63017767Sralph 			systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]);
63117767Sralph #ifdef GNXSEQ
63213639Ssam 			ulkseq();
63317767Sralph #endif GNXSEQ
63413639Ssam 			goto next;
63513639Ssam 		}
63613639Ssam 		if (strcmp(&msg[1], "OK") != SAME)  {
63723590Sbloom 			logent(&msg[1], "FAILED HANDSHAKE");
63817767Sralph 			US_SST(us_s_hand);
63917767Sralph #ifdef GNXSEQ
64013639Ssam 			ulkseq();
64117767Sralph #endif GNXSEQ
64217767Sralph 			systat(Rmtname, SS_INPROGRESS,
64317767Sralph 				strcmp(&msg[1], "CB") == SAME?
64423590Sbloom 				"AWAITING CALLBACK": "FAILED HANDSHAKE");
64513639Ssam 			goto next;
64613639Ssam 		}
64717767Sralph #ifdef GNXSEQ
64813639Ssam 		cmtseq();
64917767Sralph #endif GNXSEQ
65013639Ssam 	}
65117767Sralph 	DEBUG(1, "Rmtname %s, ", Rmtname);
65213639Ssam 	DEBUG(1, "Role %s,  ", Role ? "MASTER" : "SLAVE");
65313639Ssam 	DEBUG(1, "Ifn - %d, ", Ifn);
65413639Ssam 	DEBUG(1, "Loginuser - %s\n", Loginuser);
65534164Srick 	setproctitle("%s: %s", Rmtname, Role ? "MASTER" : "SLAVE");
65613639Ssam 
65725703Sbloom 	ttyn = ttyname(Ifn);
65825703Sbloom 
65933559Srick 	alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME);
66018616Sralph 	if (ret=setjmp(Sjbuf))
66113639Ssam 		goto Failure;
66213639Ssam 	ret = startup(Role);
66313639Ssam 	alarm(0);
66413639Ssam 	if (ret != SUCCESS) {
66534164Srick 		logent("(startup)", _FAILED);
66613639Ssam Failure:
66717767Sralph 		US_SST(us_s_start);
66818616Sralph 		systat(Rmtname, SS_FAIL, ret > 0 ? "CONVERSATION FAILED" :
66918616Sralph 			"STARTUP FAILED");
67013639Ssam 		goto next;
67117767Sralph 	} else {
67233559Srick 		char smsg[BUFSIZ], gmsg[10], pmsg[20], bpsmsg[20];
67333559Srick 		extern char UsingProtocol;
67433559Srick 		extern int linebaudrate;
67533559Srick 		if (ttyn != NULL)
67633559Srick 			sprintf(bpsmsg, " %s %d bps", &ttyn[5], linebaudrate);
67733559Srick 		else
67833559Srick 			bpsmsg[0] = '\0';
67933559Srick 		if (UsingProtocol != 'g')
68033559Srick 			sprintf(pmsg, " %c protocol", UsingProtocol);
68133559Srick 		else
68233559Srick 			pmsg[0] = '\0';
68333559Srick 		if (MaxGrade != '\177')
68433559Srick 			sprintf(gmsg, " grade %c", MaxGrade);
68533559Srick 		else
68633559Srick 			gmsg[0] = '\0';
68734164Srick 		sprintf(smsg, "(startup%s%s%s)", bpsmsg, pmsg, gmsg);
68833559Srick 		logent(smsg, "OK");
68917767Sralph 		US_SST(us_s_gress);
69033559Srick 		StartTime = Now.time;
69113639Ssam 		systat(Rmtname, SS_INPROGRESS, "TALKING");
69213639Ssam 		ret = cntrl(Role, wkpre);
69313639Ssam 		DEBUG(1, "cntrl - %d\n", ret);
69413639Ssam 		signal(SIGINT, SIG_IGN);
69513639Ssam 		signal(SIGHUP, SIG_IGN);
69613639Ssam 		signal(SIGALRM, timeout);
69734164Srick 		sprintf(smsg, "(conversation complete %ld sent %ld received)",
69833559Srick 			Bytes_Sent, Bytes_Received);
69917767Sralph 		if (ret == SUCCESS) {
70033559Srick 			logent(smsg, "OK");
70117767Sralph 			US_SST(us_s_ok);
70213639Ssam 			rmstat(Rmtname);
70313639Ssam 
70417767Sralph 		} else {
70533559Srick 			logent(smsg, _FAILED);
70617767Sralph 			US_SST(us_s_cf);
70717767Sralph 			systat(Rmtname, SS_FAIL, "CONVERSATION FAILED");
70813639Ssam 		}
70933559Srick 		alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME);
71013639Ssam 		DEBUG(4, "send OO %d,", ret);
71113639Ssam 		if (!setjmp(Sjbuf)) {
71213639Ssam 			for (;;) {
71313639Ssam 				omsg('O', "OOOOO", Ofn);
71413639Ssam 				ret = imsg(msg, Ifn);
71513639Ssam 				if (ret != 0)
71613639Ssam 					break;
71713639Ssam 				if (msg[0] == 'O')
71813639Ssam 					break;
71913639Ssam 			}
72013639Ssam 		}
72113639Ssam 		alarm(0);
72217767Sralph 		clsacu();
72317767Sralph 		rmlock(CNULL);
72433559Srick 
72513639Ssam 	}
72613639Ssam next:
72713639Ssam 	if (!onesys) {
72813639Ssam 		goto loop;
72913639Ssam 	}
73013639Ssam 	cleanup(0);
73113639Ssam }
73213639Ssam 
73317767Sralph #ifndef	USG
73413639Ssam struct sgttyb Hupvec;
73513639Ssam #endif
73613639Ssam 
73725703Sbloom /*
73825703Sbloom  *	cleanup and exit with "code" status
73913639Ssam  */
74013639Ssam cleanup(code)
74113639Ssam register int code;
74213639Ssam {
74313639Ssam 	signal(SIGINT, SIG_IGN);
74413639Ssam 	signal(SIGHUP, SIG_IGN);
74513639Ssam 	rmlock(CNULL);
74625703Sbloom 	sleep(5);			/* Wait for any pending output	  */
74713639Ssam 	clsacu();
74813639Ssam 	logcls();
74913639Ssam 	if (Role == SLAVE) {
75017767Sralph 		if (!IsTcpIp) {
75117767Sralph #ifdef USG
75213639Ssam 			Savettyb.c_cflag |= HUPCL;
75323590Sbloom 			(void) ioctl(0, TCSETA, &Savettyb);
75417767Sralph #else !USG
75523590Sbloom 			(void) ioctl(0, TIOCHPCL, STBNULL);
75618616Sralph #ifdef TIOCSDTR
75723590Sbloom 			(void) ioctl(0, TIOCCDTR, STBNULL);
75818616Sralph 			sleep(2);
75923590Sbloom 			(void) ioctl(0, TIOCSDTR, STBNULL);
76018616Sralph #else !TIOCSDTR
76123590Sbloom 			(void) ioctl(0, TIOCGETP, &Hupvec);
76213639Ssam 			Hupvec.sg_ispeed = B0;
76313639Ssam 			Hupvec.sg_ospeed = B0;
76423590Sbloom 			(void) ioctl(0, TIOCSETP, &Hupvec);
76525703Sbloom #endif !TIOCSDTR
76613639Ssam 			sleep(2);
76723590Sbloom 			(void) ioctl(0, TIOCSETP, &Savettyb);
76817767Sralph 			/* make *sure* exclusive access is off */
76923590Sbloom 			(void) ioctl(0, TIOCNXCL, STBNULL);
77017767Sralph #endif !USG
77113639Ssam 		}
77213639Ssam 		if (ttyn != NULL)
77313639Ssam 			chmod(ttyn, 0600);
77413639Ssam 	}
77513639Ssam 	if (Ofn != -1) {
77613639Ssam 		if (Role == MASTER)
77713639Ssam 			write(Ofn, EOTMSG, strlen(EOTMSG));
77813639Ssam 		close(Ifn);
77913639Ssam 		close(Ofn);
78013639Ssam 	}
78118616Sralph #ifdef DIALINOUT
78218616Sralph 	/* reenable logins on dialout */
78318616Sralph 	reenable();
78418616Sralph #endif DIALINOUT
78513639Ssam 	if (code == 0)
78613639Ssam 		xuuxqt();
78717767Sralph 	else
78817767Sralph 		DEBUG(1, "exit code %d\n", code);
78925703Sbloom 	setdebug (DBG_CLEAN);
79033559Srick 	do_connect_accounting();
79113639Ssam 	exit(code);
79213639Ssam }
79313639Ssam 
79433559Srick do_connect_accounting()
79533559Srick {
79633945Srick #ifdef DO_CONNECT_ACCOUNTING
79733559Srick 	register FILE *fp;
79833559Srick 	struct tm *localtime();
79933559Srick 	register struct tm *tm;
80033559Srick 	int flags;
80133559Srick 
80233559Srick 	if (StartTime == 0)
80333559Srick 		return;
80433559Srick 
80533945Srick 	fp = fopen(DO_CONNECT_ACCOUNTING, "a");
80633945Srick 	if (fp == NULL) {
80733945Srick 		syslog(LOG_ALERT, "fopen(%s) failed: %m",DO_CONNECT_ACCOUNTING);
80833945Srick 		cleanup(FAIL);
80933945Srick 	}
81033559Srick 
81133559Srick 	tm = localtime(&StartTime);
81233559Srick #ifdef F_SETFL
81333559Srick 	flags = fcntl(fileno(fp), F_GETFL, 0);
81433559Srick 	fcntl(fileno(fp), F_SETFL, flags|O_APPEND);
81533559Srick #endif
81633559Srick #ifdef USG
81733559Srick 	fprintf(fp,"%s %d %d%.2d%.2d %.2d%.2d %d %ld %s %ld %ld\n",
81833559Srick #else /* V7 */
81933559Srick 	fprintf(fp,"%s %d %d%02d%02d %02d%02d %d %ld %s %ld %ld\n",
82033559Srick #endif /* V7 */
82133559Srick 		Rmtname, InitialRole, tm->tm_year, tm->tm_mon + 1,
82233559Srick 		tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_wday,
82333559Srick 		(Now.time - StartTime + 59) / 60,
82433559Srick 		ttyn == NULL ? "ttyp0" : &ttyn[5],
82533559Srick 			Bytes_Sent, Bytes_Received);
82633559Srick 	fclose(fp);
82733559Srick #endif /* DO_CONNECT_ACCOUNTING */
82833559Srick }
82933559Srick 
83025703Sbloom /*
83125703Sbloom  *	on interrupt - remove locks and exit
83213639Ssam  */
83313639Ssam 
834*46879Sbostic static void
83513639Ssam onintr(inter)
83613639Ssam register int inter;
83713639Ssam {
83833559Srick 	char str[BUFSIZ];
83913639Ssam 	signal(inter, SIG_IGN);
84034164Srick 	sprintf(str, "(SIGNAL %d)", inter);
84113639Ssam 	logent(str, "CAUGHT");
84217767Sralph 	US_SST(us_s_intr);
84323590Sbloom 	if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME))
84417767Sralph 		systat(Rmtname, SS_FAIL, str);
84534164Srick 	sprintf(str, "(conversation complete %ld sent %ld received)",
84633559Srick 		Bytes_Sent, Bytes_Received);
84733559Srick 	logent(str, _FAILED);
84817767Sralph 	if (inter == SIGPIPE && !onesys)
84917767Sralph 		longjmp(Pipebuf, 1);
85013639Ssam 	cleanup(inter);
85113639Ssam }
85213639Ssam 
85313639Ssam /*
85413639Ssam  * Catch a special signal
85536449Smarc  * (SIGUSR1), and toggle debugging between 0 and 30.
85613639Ssam  * Handy for looking in on long running uucicos.
85713639Ssam  */
858*46879Sbostic static void
85925703Sbloom dbg_signal()
86013639Ssam {
86125703Sbloom 	Debug = (Debug == 0) ? 30 : 0;
86225703Sbloom 	setdebug(DBG_PERM);
86325703Sbloom 	if (Debug > 0)
86425703Sbloom 		logent("Signal Enabled", "DEBUG");
86525703Sbloom }
86617767Sralph 
86725703Sbloom 
86825703Sbloom /*
86925703Sbloom  * Check debugging requests, and open RMTDEBUG audit file if necessary. If an
87025703Sbloom  * audit file is needed, the parm argument indicates how to create the file:
87125703Sbloom  *
87225703Sbloom  *	DBG_TEMP  - Open a temporary file, with filename = RMTDEBUG/pid.
87325703Sbloom  *	DBG_PERM  - Open a permanent audit file, filename = RMTDEBUG/Rmtname.
87425703Sbloom  *		    If a temp file already exists, it is mv'ed to be permanent.
87525703Sbloom  *	DBG_CLEAN - Cleanup; unlink temp files.
87625703Sbloom  *
87725703Sbloom  * Restrictions - this code can only cope with one open debug file at a time.
87825703Sbloom  * Each call creates a new file; if an old one of the same name exists it will
87925703Sbloom  * be overwritten.
88025703Sbloom  */
88125703Sbloom setdebug(parm)
88225703Sbloom int parm;
88325703Sbloom {
88425703Sbloom 	char buf[BUFSIZ];		/* Buffer for building filenames     */
88525703Sbloom 	static char *temp = NULL;	/* Ptr to temporary file name	     */
88625703Sbloom 	static int auditopen = 0;	/* Set to 1 when we open a file	     */
88725703Sbloom 	struct stat stbuf;		/* File status buffer		     */
88825703Sbloom 
88925703Sbloom 	/*
89025703Sbloom 	 * If movement or cleanup of a temp file is indicated, we do it no
89125703Sbloom 	 * matter what.
89225703Sbloom 	 */
89325703Sbloom 	if (temp != CNULL && parm == DBG_PERM) {
89425703Sbloom 		sprintf(buf, "%s/%s", RMTDEBUG, Rmtname);
89525703Sbloom 		unlink(buf);
89625703Sbloom 		if (link(temp, buf) != 0) {
89723590Sbloom 			Debug = 0;
89833945Srick 			syslog(LOG_ERR, "RMTDEBUG link(%s,%s) failed: %m",
89933945Srick 				temp, buf);
90033945Srick 			cleanup(FAIL);
90125703Sbloom 		}
90225703Sbloom 		parm = DBG_CLEAN;
90323590Sbloom 	}
90425703Sbloom 	if (parm == DBG_CLEAN) {
90525703Sbloom 		if (temp != CNULL) {
90625703Sbloom 			unlink(temp);
90725703Sbloom 			free(temp);
90825703Sbloom 			temp = CNULL;
90925703Sbloom 		}
91025703Sbloom 		return;
91125703Sbloom 	}
91225703Sbloom 
91325703Sbloom 	if (Debug == 0)
91425703Sbloom 		return;		/* Gotta be in debug to come here.   */
91525703Sbloom 
91625703Sbloom 	/*
91725703Sbloom 	 * If we haven't opened a file already, we can just return if it's
91825703Sbloom 	 * alright to use the stderr we came in with. We can if:
91925703Sbloom 	 *
92025703Sbloom 	 *	Role == MASTER, and Stderr is a regular file, a TTY or a pipe.
92125703Sbloom 	 *
92225703Sbloom 	 * Caution: Detecting when stderr is a pipe is tricky, because the 4.2
92325703Sbloom 	 * man page for fstat(2) disagrees with reality, and System V leaves it
92425703Sbloom 	 * undefined, which means different implementations act differently.
92525703Sbloom 	 */
92625703Sbloom 	if (!auditopen && Role == MASTER) {
92725703Sbloom 		if (isatty(fileno(stderr)))
92825703Sbloom 			return;
92925703Sbloom 		else if (fstat(fileno(stderr), &stbuf) == 0) {
93025703Sbloom #ifdef USG
93125703Sbloom 			/* Is Regular File or Fifo   */
93225703Sbloom 			if ((stbuf.st_mode & 0060000) == 0)
93325703Sbloom 				return;
93425703Sbloom #else !USG
93517767Sralph #ifdef BSD4_2
93625703Sbloom 					/* Is Regular File */
93725703Sbloom 			if ((stbuf.st_mode & S_IFMT) == S_IFREG ||
93825703Sbloom 			    stbuf.st_mode == 0)		/* Is a pipe */
93925703Sbloom 				return;
94025703Sbloom #else !BSD4_2
94125703Sbloom 					 /* Is Regular File or Pipe  */
94225703Sbloom 			if ((stbuf.st_mode & S_IFMT) == S_IFREG)
94325703Sbloom 				return;
94425703Sbloom #endif BSD4_2
94525703Sbloom #endif USG
94625703Sbloom 		}
94717767Sralph 	}
94813639Ssam 
94925703Sbloom 	/*
95025703Sbloom 	 * We need RMTDEBUG directory to do auditing. If the file doesn't exist,
95125703Sbloom 	 * then we forget about debugging; if it exists but has improper owner-
95225703Sbloom 	 * ship or modes, we gripe about it in ERRLOG.
95325703Sbloom 	 */
95425703Sbloom 	if (stat(RMTDEBUG, &stbuf) != SUCCESS) {
95525703Sbloom 		Debug = 0;
95625703Sbloom 		return;
95725703Sbloom 	}
95825703Sbloom 	if ((geteuid() != stbuf.st_uid) ||	  	/* We must own it    */
95925703Sbloom 	    ((stbuf.st_mode & 0170700) != 040700)) {	/* Directory, rwx    */
96025703Sbloom 		Debug = 0;
96133945Srick 		syslog(LOG_ERR, "%s: invalid directory mode: %o", RMTDEBUG,
96233945Srick 			stbuf.st_mode);
96325703Sbloom 		return;
96425703Sbloom 	}
96513639Ssam 
96625703Sbloom 	if (parm == DBG_TEMP) {
96725703Sbloom 		sprintf(buf, "%s/%d", RMTDEBUG, getpid());
96825703Sbloom 		temp = malloc(strlen (buf) + 1);
96925703Sbloom 		if (temp == CNULL) {
97025703Sbloom 			Debug = 0;
97133945Srick 			syslog(LOG_ERR, "RMTDEBUG malloc failed: %m");
97233945Srick 			cleanup(FAIL);
97325703Sbloom 		}
97425703Sbloom 		strcpy(temp, buf);
97525703Sbloom 	} else
97625703Sbloom 		sprintf(buf, "%s/%s", RMTDEBUG, Rmtname);
97713639Ssam 
97825703Sbloom 	unlink(buf);
97925703Sbloom 	if (freopen(buf, "w", stderr) != stderr) {
98025703Sbloom 		Debug = 0;
98133945Srick 		syslog(LOG_ERR, "RMTDEBUG freopen(%s) failed: %m", buf);
98233945Srick 		cleanup(FAIL);
98325703Sbloom 	}
98425703Sbloom 	setbuf(stderr, CNULL);
98525703Sbloom 	auditopen = 1;
98613639Ssam }
98713639Ssam 
98823590Sbloom /*
98925703Sbloom  *	catch SIGALRM routine
99013639Ssam  */
991*46879Sbostic static void
99213639Ssam timeout()
99313639Ssam {
99423590Sbloom 	extern int HaveSentHup;
99523590Sbloom 	if (!HaveSentHup) {
99623590Sbloom 		logent(Rmtname, "TIMEOUT");
99723590Sbloom 		if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) {
99823590Sbloom 			US_SST(us_s_tmot);
99923590Sbloom 			systat(Rmtname, SS_FAIL, "TIMEOUT");
100023590Sbloom 		}
100117767Sralph 	}
100213639Ssam 	longjmp(Sjbuf, 1);
100313639Ssam }
100413639Ssam 
100513639Ssam static char *
100613639Ssam pskip(p)
100713639Ssam register char *p;
100813639Ssam {
100917767Sralph 	while(*p && *p != ' ')
101013639Ssam 		++p;
101123590Sbloom 	while(*p && *p == ' ')
101217767Sralph 		*p++ = 0;
101317767Sralph 	return p;
101413639Ssam }
101534164Srick 
101634164Srick /*
101734164Srick  * clobber argv so ps will show what we're doing.
101834164Srick  * stolen from sendmail
101934164Srick  */
102034164Srick /*VARARGS1*/
102134164Srick setproctitle(fmt, a, b, c)
102234164Srick char *fmt;
102334164Srick {
102434164Srick #ifdef SETPROCTITLE
102534164Srick 	register char *p;
102634164Srick 	register int i;
102734164Srick 	extern char **Argv;
102834164Srick 	extern char *LastArgv;
102934164Srick 	char buf[BUFSIZ];
103034164Srick 
103134164Srick 	(void) sprintf(buf, fmt, a, b, c);
103234164Srick 
103334164Srick 	/* make ps print "(sendmail)" */
103434164Srick 	p = Argv[0];
103534164Srick 	*p++ = '-';
103634164Srick 
103734164Srick 	i = strlen(buf);
103834164Srick 	if (i > LastArgv - p - 2) {
103934164Srick 		i = LastArgv - p - 2;
104034164Srick 		buf[i] = '\0';
104134164Srick 	}
104234164Srick 	(void) strcpy(p, buf);
104334164Srick 	p += i;
104434164Srick 	while (p < LastArgv)
104534164Srick 		*p++ = ' ';
104634164Srick #endif SETPROCTITLE
104734164Srick }
1048