xref: /csrg-svn/usr.bin/uucp/uucico/cico.c (revision 62391)
148664Sbostic /*-
2*62391Sbostic  * Copyright (c) 1985, 1993
3*62391Sbostic  *	The Regents of the University of California.  All rights reserved.
448664Sbostic  *
548664Sbostic  * %sccs.include.proprietary.c%
648664Sbostic  */
748664Sbostic 
813639Ssam #ifndef lint
9*62391Sbostic static char sccsid[] = "@(#)cico.c	8.1 (Berkeley) 06/06/93";
1048664Sbostic #endif /* not lint */
1113639Ssam 
1223590Sbloom #include <signal.h>
1313639Ssam #include "uucp.h"
1413639Ssam #include <setjmp.h>
1517767Sralph #ifdef	USG
1613639Ssam #include <termio.h>
1733559Srick #include <fcntl.h>
1813639Ssam #endif
1917767Sralph #ifndef	USG
2013639Ssam #include <sgtty.h>
2113639Ssam #endif
2217767Sralph #ifdef BSDTCP
2317767Sralph #include <netdb.h>
2417767Sralph #include <netinet/in.h>
2517767Sralph #include <sys/socket.h>
2617767Sralph #endif BSDTCP
2717767Sralph #include <sys/stat.h>
2833559Srick #ifdef BSD4_2
2933559Srick #include <sys/time.h>
3033559Srick #include <fcntl.h>
3133559Srick #else
3233559Srick #include <time.h>
3333559Srick #endif
3417767Sralph #include "uust.h"
3517767Sralph #include "uusub.h"
3637930Sbostic #include "pathnames.h"
3713639Ssam 
3823590Sbloom #if defined(VMS) && defined(BSDTCP)
3923590Sbloom #define NOGETPEER
4023590Sbloom #endif
4123590Sbloom 
4217767Sralph jmp_buf Sjbuf;
4317767Sralph jmp_buf Pipebuf;
4413639Ssam 
4517767Sralph /*  call fail text  */
4613639Ssam char *Stattext[] = {
4713639Ssam 	"",
4813639Ssam 	"BAD SYSTEM",
4917767Sralph 	"WRONG TIME TO CALL",
5013639Ssam 	"SYSTEM LOCKED",
5113639Ssam 	"NO DEVICE",
5225703Sbloom 	"CALL FAILED",
5313639Ssam 	"LOGIN FAILED",
5413639Ssam 	"BAD SEQUENCE"
5517767Sralph };
5613639Ssam 
5717767Sralph /*  call fail codes  */
5817767Sralph int Stattype[] = {
5917767Sralph 	0,
6017767Sralph 	0,
6117767Sralph 	SS_WRONGTIME,
6217767Sralph 	0,
6317767Sralph 	SS_NODEVICE,
6417767Sralph 	SS_FAIL,
6517767Sralph 	SS_FAIL,
6617767Sralph 	SS_BADSEQ
6717767Sralph };
6813639Ssam 
6925703Sbloom 				/* Arguments to setdebug():		     */
7025703Sbloom #define DBG_TEMP  0		/*   Create a temporary audit file	     */
7125703Sbloom #define DBG_PERM  1		/*   Create a permanent audit file	     */
7225703Sbloom #define DBG_CLEAN 2		/*   Cleanup, discard temp file		     */
7313639Ssam 
7417767Sralph int ReverseRole = 0;
7517767Sralph int Role = SLAVE;
7633559Srick int InitialRole = SLAVE;
7733559Srick long StartTime;
7817767Sralph int onesys = 0;
7918616Sralph int turntime = 30 * 60;	/* 30 minutes expressed in seconds */
8025703Sbloom char *ttyn = NULL;
8117767Sralph extern int LocalOnly;
8225703Sbloom extern int errno;
8318616Sralph extern char MaxGrade, DefMaxGrade;
8418616Sralph extern char Myfullname[];
8517767Sralph 
8633559Srick long Bytes_Sent, Bytes_Received;
8733559Srick 
8817767Sralph #ifdef	USG
8913639Ssam struct termio Savettyb;
9013639Ssam #endif
9117767Sralph #ifndef	USG
9213639Ssam struct sgttyb Savettyb;
9313639Ssam #endif
9413639Ssam 
9534164Srick #define SETPROCTITLE
9634164Srick #ifdef SETPROCTITLE
9734164Srick char	**Argv = NULL;		/* pointer to argument vector */
9834164Srick char	*LastArgv = NULL;	/* end of argv */
9934164Srick #endif SETPROCTITLE
10034164Srick 
10125703Sbloom /*
10225703Sbloom  *	this program is used  to place a call to a
10313639Ssam  *	remote machine, login, and copy files between the two machines.
10413639Ssam  */
main(argc,argv,envp)10534164Srick main(argc, argv, envp)
10625703Sbloom int argc;
10733945Srick char **argv;
10834164Srick char **envp;
10913639Ssam {
11013639Ssam 	register int ret;
11113639Ssam 	int seq;
11213639Ssam 	char wkpre[NAMESIZE], file[NAMESIZE];
11325703Sbloom 	char msg[MAXFULLNAME], *q;
11413639Ssam 	register char *p;
11546879Sbostic 	static void onintr(), timeout(), dbg_signal();
11646879Sbostic 	static char *pskip();
11733945Srick 	extern char *optarg;
11833945Srick 	extern int optind;
11923725Sbloom 	char rflags[MAXFULLNAME];
12023590Sbloom #ifdef NOGETPEER
12117767Sralph 	u_long Hostnumber = 0;
12223590Sbloom #endif NOGETPEER
12313639Ssam 
12413639Ssam 	strcpy(Progname, "uucico");
12513639Ssam 
12626149Sbloom #ifdef BSD4_2
12733945Srick 	sigsetmask(0L);	/* in case we inherit blocked signals */
12826149Sbloom #endif BSD4_2
12913639Ssam 	signal(SIGINT, onintr);
13013639Ssam 	signal(SIGHUP, onintr);
13113639Ssam 	signal(SIGQUIT, onintr);
13213639Ssam 	signal(SIGTERM, onintr);
13313639Ssam 	signal(SIGPIPE, onintr);	/* 4.1a tcp-ip stupidity */
13436449Smarc 	signal(SIGUSR1, dbg_signal);
13513639Ssam 	ret = guinfo(getuid(), User, msg);
13613639Ssam 	strcpy(Loginuser, User);
13723590Sbloom 	uucpname(Myname);
13833945Srick 	if (ret == FAIL) {
13933945Srick 		syslog(LOG_ERR, "can't get uid");
14033945Srick 		cleanup(FAIL);
14133945Srick 	}
14213639Ssam 
14325703Sbloom 	setbuf (stderr, CNULL);
14425703Sbloom 
14525703Sbloom 	rflags[0] = '\0';
14613639Ssam 	umask(WFMASK);
14713639Ssam 	strcpy(Rmtname, Myname);
14813639Ssam 	Ifn = Ofn = -1;
14933945Srick 	while ((ret = getopt(argc, argv, "RLd:g:p:r:s:x:t:")) != EOF)
15033945Srick 		switch(ret){
15113639Ssam 		case 'd':
15233945Srick 			Spool = optarg;
15313639Ssam 			break;
15413639Ssam 		case 'g':
15518616Sralph 		case 'p':
15633945Srick 			MaxGrade = DefMaxGrade = *optarg;
15713639Ssam 			break;
15813639Ssam 		case 'r':
15933945Srick 			Role = atoi(optarg);
16013639Ssam 			break;
16117767Sralph 		case 'R':
16217767Sralph 			ReverseRole++;
16317767Sralph 			Role = MASTER;
16417767Sralph 			break;
16513639Ssam 		case 's':
16633945Srick 			strncpy(Rmtname, optarg, MAXBASENAME);
16723590Sbloom 			Rmtname[MAXBASENAME] = '\0';
16813639Ssam 			if (Rmtname[0] != '\0')
16913639Ssam 				onesys = 1;
17013639Ssam 			break;
17113639Ssam 		case 'x':
17233945Srick 			Debug = atoi(optarg);
17313639Ssam 			if (Debug <= 0)
17413639Ssam 				Debug = 1;
17533945Srick 			strcat(rflags, argv[optind-1]);
17613639Ssam 			break;
17718616Sralph 		case 't':
17833945Srick 			turntime = atoi(optarg)*60;/* minutes to seconds */
17918616Sralph 			break;
18017767Sralph 		case 'L':	/* local calls only */
18117767Sralph 			LocalOnly++;
18217767Sralph 			break;
18323590Sbloom #ifdef NOGETPEER
18417767Sralph 		case 'h':
18517767Sralph 			Hostnumber = inet_addr(&argv[1][2]);
18617767Sralph 			break;
18723590Sbloom #endif NOGETPEER
18833945Srick 		case '?':
18913639Ssam 		default:
19033945Srick 			fprintf(stderr, "unknown flag %s (ignored)\n",
19133945Srick 				argv[optind-1]);
19213639Ssam 			break;
19313639Ssam 		}
19413639Ssam 
19533945Srick 	while (optind < argc)
19633945Srick 		fprintf(stderr, "unknown argument %s (ignored)\n",
19733945Srick 			argv[optind++]);
19817767Sralph 
19927069Sbloom 	if (Debug && Role == MASTER)
20027069Sbloom 		chkdebug();
20127069Sbloom 
20234164Srick #ifdef SETPROCTITLE
20334164Srick 	/*
20434164Srick 	 *  Save start and extent of argv for setproctitle.
20534164Srick 	 */
20634164Srick 
20734164Srick 	Argv = argv;
20834164Srick 	LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
20934164Srick #endif SETPROCTITLE
21034164Srick 
21125124Sbloom 	/* Try to run as uucp */
21217767Sralph 	setgid(getegid());
21317767Sralph 	setuid(geteuid());
21417767Sralph #ifdef	TIOCNOTTY
21517767Sralph 	/*
21617767Sralph 	 * detach uucico from controlling terminal
21717767Sralph 	 * to defend against rlogind sending us a SIGKILL (!!!)
21817767Sralph 	 */
21937930Sbostic 	if (Role == MASTER && (ret = open(_PATH_TTY, 2)) >= 0) {
22017767Sralph 		ioctl(ret, TIOCNOTTY, STBNULL);
22117767Sralph 		close(ret);
22217767Sralph 	}
22317767Sralph #endif TIOCNOTTY
22417767Sralph #ifdef BSD4_2
22525517Stef 	if (getpgrp(0) == 0) { /* We have no controlling terminal */
22617767Sralph 		setpgrp(0, getpid());
22717767Sralph 	}
22833945Srick #ifdef USE_SYSLOG
22933945Srick #ifdef BSD4_3
23033945Srick 	openlog("uucico", LOG_PID, LOG_UUCP);
23133945Srick #else /* !BSD4_3 */
23233945Srick 	openlog("uucico", LOG_PID);
23333945Srick #endif /* !BSD4_3 */
23433945Srick #endif /* USE_SYSLOG */
23517767Sralph #endif BSD4_2
23617767Sralph 
23733945Srick #ifdef BSD4_3
23833945Srick 	unsetenv("TZ");		/* We don't want him resetting our time zone */
23933945Srick #endif /* !BSD4_3 */
24033945Srick 
24133945Srick 	if (subchdir(Spool) < 0) {
24233945Srick 		syslog(LOG_ERR, "chdir(%s) failed: %m", Spool);
24333945Srick 		cleanup(FAIL);
24433945Srick 	}
24533945Srick 
24613639Ssam 	strcpy(Wrkdir, Spool);
24713639Ssam 
24825703Sbloom 	if (Debug) {
24925703Sbloom 		setdebug ((Role == SLAVE) ? DBG_TEMP : DBG_PERM);
25025703Sbloom 		if (Debug > 0)
25125703Sbloom 			logent ("Local Enabled", "DEBUG");
25225703Sbloom 	}
25325703Sbloom 
25425703Sbloom 	/*
25525703Sbloom 	 * First time through: If we're the slave, do initial checking.
25625703Sbloom 	 */
25713639Ssam 	if (Role == SLAVE) {
25817767Sralph 		/* check for /etc/nologin */
25925124Sbloom 		if (access(NOLOGIN, 0) == 0) {
26017767Sralph 			logent(NOLOGIN, "UUCICO SHUTDOWN");
26123590Sbloom 			if (Debug > 4)
26217767Sralph 				logent("DEBUGGING", "continuing anyway");
26317767Sralph 			else
26417767Sralph 				cleanup(1);
26517767Sralph 		}
26625703Sbloom 		Ifn = 0;
26725703Sbloom 		Ofn = 1;
26817767Sralph #ifdef	TCPIP
26917767Sralph 		/*
27017767Sralph 		 * Determine if we are on TCPIP
27117767Sralph 		 */
27233559Srick 		if (isatty(Ifn) == 0) {
27317767Sralph 			IsTcpIp = 1;
27417767Sralph 			DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
27523590Sbloom 		} else
27623590Sbloom 			IsTcpIp = 0;
27717767Sralph #endif TCPIP
27813639Ssam 		/* initial handshake */
27913639Ssam 		onesys = 1;
28017767Sralph 		if (!IsTcpIp) {
28117767Sralph #ifdef	USG
28225703Sbloom 			ret = ioctl(Ifn, TCGETA, &Savettyb);
28313639Ssam 			Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7;
28413639Ssam 			Savettyb.c_oflag |= OPOST;
28513639Ssam 			Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
28617767Sralph #else !USG
28725703Sbloom 			ret = ioctl(Ifn, TIOCGETP, &Savettyb);
28813639Ssam 			Savettyb.sg_flags |= ECHO;
28913639Ssam 			Savettyb.sg_flags &= ~RAW;
29017767Sralph #endif !USG
29125703Sbloom 			ttyn = ttyname(Ifn);
29213639Ssam 		}
29313639Ssam 		fixmode(Ifn);
29425703Sbloom 
29525703Sbloom 		/*
29625703Sbloom 		 * Initial Message -- tell them we're here, and who we are.
29725703Sbloom 		 */
29818616Sralph 		sprintf(msg, "here=%s", Myfullname);
29917767Sralph 		omsg('S', msg, Ofn);
30013639Ssam 		signal(SIGALRM, timeout);
30133559Srick 		alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME);
30213639Ssam 		if (setjmp(Sjbuf)) {
30313639Ssam 			/* timed out */
30417767Sralph 			if (!IsTcpIp) {
30517767Sralph #ifdef	USG
30625703Sbloom 				ret = ioctl(Ifn, TCSETA, &Savettyb);
30725703Sbloom 
30823590Sbloom #else	!USG
30925703Sbloom 				ret = ioctl(Ifn, TIOCSETP, &Savettyb);
31023590Sbloom #endif !USG
31113639Ssam 			}
31217767Sralph 			cleanup(0);
31313639Ssam 		}
31413639Ssam 		for (;;) {
31513639Ssam 			ret = imsg(msg, Ifn);
31625703Sbloom 			if (ret != SUCCESS) {
31713639Ssam 				alarm(0);
31817767Sralph 				if (!IsTcpIp) {
31917767Sralph #ifdef	USG
32025703Sbloom 					ret = ioctl(Ifn, TCSETA, &Savettyb);
32123590Sbloom #else	!USG
32225703Sbloom 					ret = ioctl(Ifn, TIOCSETP, &Savettyb);
32323590Sbloom #endif !USG
32413639Ssam 				}
32517767Sralph 				cleanup(0);
32613639Ssam 			}
32713639Ssam 			if (msg[0] == 'S')
32813639Ssam 				break;
32913639Ssam 		}
33013639Ssam 		alarm(0);
33113639Ssam 		q = &msg[1];
33213639Ssam 		p = pskip(q);
33323590Sbloom 		strncpy(Rmtname, q, MAXBASENAME);
33423590Sbloom 		Rmtname[MAXBASENAME] = '\0';
33525703Sbloom 
33625703Sbloom 		/*
33725703Sbloom 		 * Now that we know who they are, give the audit file the right
33825703Sbloom 		 * name.
33925703Sbloom 		 */
34025703Sbloom 		setdebug (DBG_PERM);
34113639Ssam 		DEBUG(4, "sys-%s\n", Rmtname);
34223725Sbloom 		/* The versys will also do an alias on the incoming name */
34323725Sbloom 		if (versys(&Rmtname)) {
34433559Srick #ifdef	NOSTRANGERS
34523725Sbloom 			/* If we don't know them, we won't talk to them... */
34633945Srick 			syslog(LOG_WARNING, "Unknown host: %s", Rmtname);
34723590Sbloom 			omsg('R', "You are unknown to me", Ofn);
34823590Sbloom 			cleanup(0);
34923725Sbloom #endif	NOSTRANGERS
35023590Sbloom 		}
35117767Sralph #ifdef BSDTCP
35217767Sralph 		/* we must make sure they are really who they say they
35317767Sralph 		 * are. We compare the hostnumber with the number in the hosts
35417767Sralph 		 * table for the site they claim to be.
35517767Sralph 		 */
35617767Sralph 		if (IsTcpIp) {
35717767Sralph 			struct hostent *hp;
35817767Sralph 			char *cpnt, *inet_ntoa();
35925703Sbloom 			int fromlen;
36017767Sralph 			struct sockaddr_in from;
36125124Sbloom 			extern char PhoneNumber[];
36217767Sralph 
36323590Sbloom #ifdef	NOGETPEER
36423590Sbloom 			from.sin_addr.s_addr = Hostnumber;
36523590Sbloom 			from.sin_family = AF_INET;
36623590Sbloom #else	!NOGETPEER
36725703Sbloom 			fromlen = sizeof(from);
36846879Sbostic 			if (getpeername(Ifn,
36946879Sbostic 			    (struct sockaddr *)&from, &fromlen) < 0) {
37017767Sralph 				logent(Rmtname, "NOT A TCP CONNECTION");
37117767Sralph 				omsg('R', "NOT TCP", Ofn);
37217767Sralph 				cleanup(0);
37317767Sralph 			}
37423590Sbloom #endif	!NOGETPEER
37546879Sbostic 			hp = gethostbyaddr((char *)&from.sin_addr,
37617767Sralph 				sizeof (struct in_addr), from.sin_family);
37725703Sbloom 			if (hp == NULL) {
37817767Sralph 				/* security break or just old host table? */
37917767Sralph 				logent(Rmtname, "UNKNOWN IP-HOST Name =");
38017767Sralph 				cpnt = inet_ntoa(from.sin_addr),
38117767Sralph 				logent(cpnt, "UNKNOWN IP-HOST Number =");
38217767Sralph 				sprintf(wkpre, "%s/%s isn't in my host table",
38317767Sralph 					Rmtname, cpnt);
38417767Sralph 				omsg('R' ,wkpre ,Ofn);
38517767Sralph 				cleanup(0);
38617767Sralph 			}
38725703Sbloom 			if (Debug > 99)
38817767Sralph 				logent(Rmtname,"Request from IP-Host name =");
38925124Sbloom 			/*
39025124Sbloom 			 * The following is to determine if the name given us by
39125124Sbloom 			 * the Remote uucico matches any of the names
39217767Sralph 			 * given its network number (remote machine) in our
39317767Sralph 			 * host table.
39425124Sbloom 			 * We could check the aliases, but that won't work in
39525124Sbloom 			 * all cases (like if you are running the domain
39625124Sbloom 			 * server, where you don't get any aliases). The only
39725124Sbloom 			 * reliable way I can think of that works in ALL cases
39825124Sbloom 			 * is too look up the site in L.sys and see if the
39925124Sbloom 			 * sitename matches what we would call him if we
40025124Sbloom 			 * originated the call.
40117767Sralph 			 */
40225124Sbloom 			/* PhoneNumber contains the official network name of the 			   host we are checking. (set in versys.c) */
40325124Sbloom 			if (sncncmp(PhoneNumber, hp->h_name, SYSNSIZE) == 0) {
40417767Sralph 				if (Debug > 99)
40517767Sralph 					logent(q,"Found in host Tables");
40625124Sbloom 			} else {
40725124Sbloom 				logent(hp->h_name, "FORGED HOSTNAME");
40825124Sbloom 				logent(inet_ntoa(from.sin_addr), "ORIGINATED AT");
40925124Sbloom 				logent(PhoneNumber, "SHOULD BE");
41025124Sbloom 				sprintf(wkpre, "You're not who you claim to be: %s !=  %s", hp->h_name, PhoneNumber);
41125124Sbloom 				omsg('R', wkpre, Ofn);
41225124Sbloom 				cleanup(0);
41317767Sralph 			}
41417767Sralph 		}
41517767Sralph #endif	BSDTCP
41617767Sralph 
41725703Sbloom 		if (mlock(Rmtname)) {
41813639Ssam 			omsg('R', "LCK", Ofn);
41913639Ssam 			cleanup(0);
42013639Ssam 		}
42113639Ssam 		else if (callback(Loginuser)) {
42213639Ssam 			signal(SIGINT, SIG_IGN);
42313639Ssam 			signal(SIGHUP, SIG_IGN);
42413639Ssam 			omsg('R', "CB", Ofn);
42513639Ssam 			logent("CALLBACK", "REQUIRED");
42613639Ssam 			/*  set up for call back  */
42717767Sralph 			systat(Rmtname, SS_CALLBACK, "CALLING BACK");
42813639Ssam 			gename(CMDPRE, Rmtname, 'C', file);
42913639Ssam 			close(creat(subfile(file), 0666));
43013639Ssam 			xuucico(Rmtname);
43113639Ssam 			cleanup(0);
43213639Ssam 		}
43313639Ssam 		seq = 0;
43413639Ssam 		while (*p == '-') {
43513639Ssam 			q = pskip(p);
43613639Ssam 			switch(*(++p)) {
43713639Ssam 			case 'x':
43825703Sbloom 				if (Debug == 0) {
43925703Sbloom 					Debug = atoi(++p);
44025703Sbloom 					if (Debug <= 0)
44125703Sbloom 						Debug = 1;
44225703Sbloom 					setdebug(DBG_PERM);
44325703Sbloom 					if (Debug > 0)
44425703Sbloom 						logent("Remote Enabled", "DEBUG");
44525703Sbloom 				} else {
44625703Sbloom 					DEBUG(1, "Remote debug request ignored\n",
44725703Sbloom 					   CNULL);
44825703Sbloom 				}
44913639Ssam 				break;
45013639Ssam 			case 'Q':
45113639Ssam 				seq = atoi(++p);
45213639Ssam 				break;
45318616Sralph 			case 'p':
45418616Sralph 				MaxGrade = DefMaxGrade = *++p;
45518616Sralph 				DEBUG(4, "MaxGrade set to %c\n", MaxGrade);
45618616Sralph 				break;
45723590Sbloom 			case 'v':
45823590Sbloom 				if (strncmp(p, "grade", 5) == 0) {
45923590Sbloom 					p += 6;
46023590Sbloom 					MaxGrade = DefMaxGrade = *p++;
46123590Sbloom 					DEBUG(4, "MaxGrade set to %c\n", MaxGrade);
46223590Sbloom 				}
46323590Sbloom 				break;
46413639Ssam 			default:
46513639Ssam 				break;
46613639Ssam 			}
46713639Ssam 			p = q;
46813639Ssam 		}
46934164Srick 		setproctitle("%s: startup", Rmtname);
47013639Ssam 		if (callok(Rmtname) == SS_BADSEQ) {
47113639Ssam 			logent("BADSEQ", "PREVIOUS");
47213639Ssam 			omsg('R', "BADSEQ", Ofn);
47313639Ssam 			cleanup(0);
47413639Ssam 		}
47517767Sralph #ifdef GNXSEQ
47613639Ssam 		if ((ret = gnxseq(Rmtname)) == seq) {
47713639Ssam 			omsg('R', "OK", Ofn);
47813639Ssam 			cmtseq();
47917767Sralph 		} else {
48017767Sralph #else !GNXSEQ
48117767Sralph 		if (seq == 0)
48217767Sralph 			omsg('R', "OK", Ofn);
48313639Ssam 		else {
48417767Sralph #endif !GNXSEQ
48513639Ssam 			systat(Rmtname, Stattype[7], Stattext[7]);
48623590Sbloom 			logent("BAD SEQ", "FAILED HANDSHAKE");
48717767Sralph #ifdef GNXSEQ
48813639Ssam 			ulkseq();
48917767Sralph #endif GNXSEQ
49013639Ssam 			omsg('R', "BADSEQ", Ofn);
49113639Ssam 			cleanup(0);
49213639Ssam 		}
49313639Ssam 		if (ttyn != NULL)
49413639Ssam 			chmod(ttyn, 0600);
49513639Ssam 	}
49617767Sralph 
49713639Ssam loop:
49817767Sralph 	if(setjmp(Pipebuf)) {	/* come here on SIGPIPE	*/
49917767Sralph 		clsacu();
50034164Srick 		logcls();
50117767Sralph 		close(Ofn);
50217767Sralph 		close(Ifn);
50317767Sralph 		Ifn = Ofn = -1;
50417767Sralph 		rmlock(CNULL);
50517767Sralph 		sleep(3);
50617767Sralph 	}
50713639Ssam 	if (!onesys) {
50833559Srick 		do_connect_accounting();
50933945Srick #ifdef DIALINOUT
51033945Srick 		/* reenable logins on dialout */
51133945Srick 		reenable();
51233945Srick #endif DIALINOUT
51333559Srick 		StartTime = 0;
51434164Srick 		setproctitle("looking for work");
51513639Ssam 		ret = gnsys(Rmtname, Spool, CMDPRE);
51634164Srick 		setproctitle("%s: startup", Rmtname);
51725703Sbloom 		setdebug(DBG_PERM);
51813639Ssam 		if (ret == FAIL)
51913639Ssam 			cleanup(100);
52033559Srick 		else if (ret == SUCCESS)
52113639Ssam 			cleanup(0);
52234164Srick 		logcls();
52317767Sralph 	} else if (Role == MASTER && callok(Rmtname) != 0) {
52413639Ssam 		logent("SYSTEM STATUS", "CAN NOT CALL");
52513639Ssam 		cleanup(0);
52613639Ssam 	}
52713639Ssam 
52823590Sbloom 	sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
52933559Srick 	StartTime = 0;
53033559Srick 	Bytes_Sent = Bytes_Received = 0L;
53113639Ssam 
53217767Sralph 	signal(SIGINT, SIG_IGN);
53317767Sralph 	signal(SIGQUIT, SIG_IGN);
53413639Ssam 	if (Role == MASTER) {
53533559Srick 		extern char LineType[];
53617767Sralph 		/* check for /etc/nologin */
53725124Sbloom 		if (access(NOLOGIN, 0) == 0) {
53817767Sralph 			logent(NOLOGIN, "UUCICO SHUTDOWN");
53923590Sbloom 			if (Debug > 4)
54017767Sralph 				logent("DEBUGGING", "continuing anyway");
54117767Sralph 			else
54217767Sralph 				cleanup(1);
54317767Sralph 		}
54413639Ssam 		/*  master part */
54513639Ssam 		signal(SIGHUP, SIG_IGN);
54613639Ssam 		if (Ifn != -1 && Role == MASTER) {
54713639Ssam 			write(Ofn, EOTMSG, strlen(EOTMSG));
54813639Ssam 			clsacu();
54913639Ssam 			close(Ofn);
55013639Ssam 			close(Ifn);
55113639Ssam 			Ifn = Ofn = -1;
55213639Ssam 			rmlock(CNULL);
55313639Ssam 			sleep(3);
55413639Ssam 		}
55525124Sbloom 		if (mlock(Rmtname) != SUCCESS) {
55633559Srick 			DEBUG(1, "LOCKED: call to %s\n", Rmtname);
55717767Sralph 			US_SST(us_s_lock);
55813639Ssam 			goto next;
55913639Ssam 		}
56034164Srick 		setproctitle("%s: starting call", Rmtname);
56113639Ssam 		Ofn = Ifn = conn(Rmtname);
56234164Srick 		sprintf(msg, "(call to %s via %s)", Rmtname, LineType);
56313639Ssam 		if (Ofn < 0) {
56417767Sralph 			if (Ofn != CF_TIME)
56517767Sralph 				logent(msg, _FAILED);
56617767Sralph 			/* avoid excessive 'wrong time' info */
56723590Sbloom 			if (Stattype[-Ofn] != SS_WRONGTIME){
56817767Sralph 				systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]);
56917767Sralph 				US_SST(-Ofn);
57017767Sralph 				UB_SST(-Ofn);
57117767Sralph 			}
57213639Ssam 			goto next;
57317767Sralph 		} else {
57413639Ssam 			logent(msg, "SUCCEEDED");
57517767Sralph 			US_SST(us_s_cok);
57617767Sralph 			UB_SST(ub_ok);
57713639Ssam 		}
57833559Srick 		InitialRole = MASTER;
57917767Sralph #ifdef	TCPIP
58017767Sralph 		/*
58117767Sralph 		 * Determine if we are on TCPIP
58217767Sralph 		 */
58325703Sbloom 		if (isatty(Ifn) == 0) {
58417767Sralph 			IsTcpIp = 1;
58517767Sralph 			DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL);
58623590Sbloom 		} else
58723590Sbloom 			IsTcpIp = 0;
58817767Sralph #endif
58917767Sralph 
59013639Ssam 		if (setjmp(Sjbuf))
59113639Ssam 			goto next;
59213639Ssam 		signal(SIGALRM, timeout);
59333559Srick 		alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME*2);
59413639Ssam 		for (;;) {
59513639Ssam 			ret = imsg(msg, Ifn);
59633559Srick 			if (ret != SUCCESS) {
59713639Ssam 				alarm(0);
59833559Srick 				DEBUG(4,"\nimsg failed: errno %d\n", errno);
59917767Sralph 				logent("imsg 1", _FAILED);
60017767Sralph 				goto Failure;
60113639Ssam 			}
60213639Ssam 			if (msg[0] == 'S')
60313639Ssam 				break;
60413639Ssam 		}
60533559Srick 		alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME);
60617767Sralph #ifdef GNXSEQ
60713639Ssam 		seq = gnxseq(Rmtname);
60817767Sralph #else !GNXSEQ
60917767Sralph 		seq = 0;
61017767Sralph #endif !GNXSEQ
61118616Sralph 		if (MaxGrade != '\177') {
61223590Sbloom 			DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade);
61325963Sbloom 			sprintf(msg, "%s -Q%d -p%c -vgrade=%c %s",
61425963Sbloom 				Myname, seq, MaxGrade, MaxGrade, rflags);
61525963Sbloom 		} else
61625963Sbloom 			sprintf(msg, "%s -Q%d %s", Myname, seq, rflags);
61713639Ssam 		omsg('S', msg, Ofn);
61813639Ssam 		for (;;) {
61913639Ssam 			ret = imsg(msg, Ifn);
62013639Ssam 			DEBUG(4, "msg-%s\n", msg);
62117767Sralph 			if (ret != SUCCESS) {
62213639Ssam 				alarm(0);
62317767Sralph #ifdef GNXSEQ
62413639Ssam 				ulkseq();
62517767Sralph #endif GNXSEQ
62617767Sralph 				logent("imsg 2", _FAILED);
62717767Sralph 				goto Failure;
62813639Ssam 			}
62913639Ssam 			if (msg[0] == 'R')
63013639Ssam 				break;
63113639Ssam 		}
63213639Ssam 		alarm(0);
63313639Ssam 		if (msg[1] == 'B') {
63413639Ssam 			/* bad sequence */
63523590Sbloom 			logent("BAD SEQ", "FAILED HANDSHAKE");
63617767Sralph 			US_SST(us_s_hand);
63717767Sralph 			systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]);
63817767Sralph #ifdef GNXSEQ
63913639Ssam 			ulkseq();
64017767Sralph #endif GNXSEQ
64113639Ssam 			goto next;
64213639Ssam 		}
64313639Ssam 		if (strcmp(&msg[1], "OK") != SAME)  {
64423590Sbloom 			logent(&msg[1], "FAILED HANDSHAKE");
64517767Sralph 			US_SST(us_s_hand);
64617767Sralph #ifdef GNXSEQ
64713639Ssam 			ulkseq();
64817767Sralph #endif GNXSEQ
64917767Sralph 			systat(Rmtname, SS_INPROGRESS,
65017767Sralph 				strcmp(&msg[1], "CB") == SAME?
65123590Sbloom 				"AWAITING CALLBACK": "FAILED HANDSHAKE");
65213639Ssam 			goto next;
65313639Ssam 		}
65417767Sralph #ifdef GNXSEQ
65513639Ssam 		cmtseq();
65617767Sralph #endif GNXSEQ
65713639Ssam 	}
65817767Sralph 	DEBUG(1, "Rmtname %s, ", Rmtname);
65913639Ssam 	DEBUG(1, "Role %s,  ", Role ? "MASTER" : "SLAVE");
66013639Ssam 	DEBUG(1, "Ifn - %d, ", Ifn);
66113639Ssam 	DEBUG(1, "Loginuser - %s\n", Loginuser);
66234164Srick 	setproctitle("%s: %s", Rmtname, Role ? "MASTER" : "SLAVE");
66313639Ssam 
66425703Sbloom 	ttyn = ttyname(Ifn);
66525703Sbloom 
66633559Srick 	alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME);
66718616Sralph 	if (ret=setjmp(Sjbuf))
66813639Ssam 		goto Failure;
66913639Ssam 	ret = startup(Role);
67013639Ssam 	alarm(0);
67113639Ssam 	if (ret != SUCCESS) {
67234164Srick 		logent("(startup)", _FAILED);
67313639Ssam Failure:
67417767Sralph 		US_SST(us_s_start);
67518616Sralph 		systat(Rmtname, SS_FAIL, ret > 0 ? "CONVERSATION FAILED" :
67618616Sralph 			"STARTUP FAILED");
67713639Ssam 		goto next;
67817767Sralph 	} else {
67933559Srick 		char smsg[BUFSIZ], gmsg[10], pmsg[20], bpsmsg[20];
68033559Srick 		extern char UsingProtocol;
68133559Srick 		extern int linebaudrate;
68233559Srick 		if (ttyn != NULL)
68333559Srick 			sprintf(bpsmsg, " %s %d bps", &ttyn[5], linebaudrate);
68433559Srick 		else
68533559Srick 			bpsmsg[0] = '\0';
68633559Srick 		if (UsingProtocol != 'g')
68733559Srick 			sprintf(pmsg, " %c protocol", UsingProtocol);
68833559Srick 		else
68933559Srick 			pmsg[0] = '\0';
69033559Srick 		if (MaxGrade != '\177')
69133559Srick 			sprintf(gmsg, " grade %c", MaxGrade);
69233559Srick 		else
69333559Srick 			gmsg[0] = '\0';
69434164Srick 		sprintf(smsg, "(startup%s%s%s)", bpsmsg, pmsg, gmsg);
69533559Srick 		logent(smsg, "OK");
69617767Sralph 		US_SST(us_s_gress);
69733559Srick 		StartTime = Now.time;
69813639Ssam 		systat(Rmtname, SS_INPROGRESS, "TALKING");
69913639Ssam 		ret = cntrl(Role, wkpre);
70013639Ssam 		DEBUG(1, "cntrl - %d\n", ret);
70113639Ssam 		signal(SIGINT, SIG_IGN);
70213639Ssam 		signal(SIGHUP, SIG_IGN);
70313639Ssam 		signal(SIGALRM, timeout);
70434164Srick 		sprintf(smsg, "(conversation complete %ld sent %ld received)",
70533559Srick 			Bytes_Sent, Bytes_Received);
70617767Sralph 		if (ret == SUCCESS) {
70733559Srick 			logent(smsg, "OK");
70817767Sralph 			US_SST(us_s_ok);
70913639Ssam 			rmstat(Rmtname);
71013639Ssam 
71117767Sralph 		} else {
71233559Srick 			logent(smsg, _FAILED);
71317767Sralph 			US_SST(us_s_cf);
71417767Sralph 			systat(Rmtname, SS_FAIL, "CONVERSATION FAILED");
71513639Ssam 		}
71633559Srick 		alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME);
71713639Ssam 		DEBUG(4, "send OO %d,", ret);
71813639Ssam 		if (!setjmp(Sjbuf)) {
71913639Ssam 			for (;;) {
72013639Ssam 				omsg('O', "OOOOO", Ofn);
72113639Ssam 				ret = imsg(msg, Ifn);
72213639Ssam 				if (ret != 0)
72313639Ssam 					break;
72413639Ssam 				if (msg[0] == 'O')
72513639Ssam 					break;
72613639Ssam 			}
72713639Ssam 		}
72813639Ssam 		alarm(0);
72917767Sralph 		clsacu();
73017767Sralph 		rmlock(CNULL);
73133559Srick 
73213639Ssam 	}
73313639Ssam next:
73413639Ssam 	if (!onesys) {
73513639Ssam 		goto loop;
73613639Ssam 	}
73713639Ssam 	cleanup(0);
73813639Ssam }
73913639Ssam 
74017767Sralph #ifndef	USG
74113639Ssam struct sgttyb Hupvec;
74213639Ssam #endif
74313639Ssam 
74425703Sbloom /*
74525703Sbloom  *	cleanup and exit with "code" status
74613639Ssam  */
cleanup(code)74713639Ssam cleanup(code)
74813639Ssam register int code;
74913639Ssam {
75013639Ssam 	signal(SIGINT, SIG_IGN);
75113639Ssam 	signal(SIGHUP, SIG_IGN);
75213639Ssam 	rmlock(CNULL);
75325703Sbloom 	sleep(5);			/* Wait for any pending output	  */
75413639Ssam 	clsacu();
75513639Ssam 	logcls();
75613639Ssam 	if (Role == SLAVE) {
75717767Sralph 		if (!IsTcpIp) {
75817767Sralph #ifdef USG
75913639Ssam 			Savettyb.c_cflag |= HUPCL;
76023590Sbloom 			(void) ioctl(0, TCSETA, &Savettyb);
76117767Sralph #else !USG
76223590Sbloom 			(void) ioctl(0, TIOCHPCL, STBNULL);
76318616Sralph #ifdef TIOCSDTR
76423590Sbloom 			(void) ioctl(0, TIOCCDTR, STBNULL);
76518616Sralph 			sleep(2);
76623590Sbloom 			(void) ioctl(0, TIOCSDTR, STBNULL);
76718616Sralph #else !TIOCSDTR
76823590Sbloom 			(void) ioctl(0, TIOCGETP, &Hupvec);
76913639Ssam 			Hupvec.sg_ispeed = B0;
77013639Ssam 			Hupvec.sg_ospeed = B0;
77123590Sbloom 			(void) ioctl(0, TIOCSETP, &Hupvec);
77225703Sbloom #endif !TIOCSDTR
77313639Ssam 			sleep(2);
77423590Sbloom 			(void) ioctl(0, TIOCSETP, &Savettyb);
77517767Sralph 			/* make *sure* exclusive access is off */
77623590Sbloom 			(void) ioctl(0, TIOCNXCL, STBNULL);
77717767Sralph #endif !USG
77813639Ssam 		}
77913639Ssam 		if (ttyn != NULL)
78013639Ssam 			chmod(ttyn, 0600);
78113639Ssam 	}
78213639Ssam 	if (Ofn != -1) {
78313639Ssam 		if (Role == MASTER)
78413639Ssam 			write(Ofn, EOTMSG, strlen(EOTMSG));
78513639Ssam 		close(Ifn);
78613639Ssam 		close(Ofn);
78713639Ssam 	}
78818616Sralph #ifdef DIALINOUT
78918616Sralph 	/* reenable logins on dialout */
79018616Sralph 	reenable();
79118616Sralph #endif DIALINOUT
79213639Ssam 	if (code == 0)
79313639Ssam 		xuuxqt();
79417767Sralph 	else
79517767Sralph 		DEBUG(1, "exit code %d\n", code);
79625703Sbloom 	setdebug (DBG_CLEAN);
79733559Srick 	do_connect_accounting();
79813639Ssam 	exit(code);
79913639Ssam }
80013639Ssam 
do_connect_accounting()80133559Srick do_connect_accounting()
80233559Srick {
80333945Srick #ifdef DO_CONNECT_ACCOUNTING
80433559Srick 	register FILE *fp;
80533559Srick 	struct tm *localtime();
80633559Srick 	register struct tm *tm;
80733559Srick 	int flags;
80833559Srick 
80933559Srick 	if (StartTime == 0)
81033559Srick 		return;
81133559Srick 
81233945Srick 	fp = fopen(DO_CONNECT_ACCOUNTING, "a");
81333945Srick 	if (fp == NULL) {
81433945Srick 		syslog(LOG_ALERT, "fopen(%s) failed: %m",DO_CONNECT_ACCOUNTING);
81533945Srick 		cleanup(FAIL);
81633945Srick 	}
81733559Srick 
81833559Srick 	tm = localtime(&StartTime);
81933559Srick #ifdef F_SETFL
82033559Srick 	flags = fcntl(fileno(fp), F_GETFL, 0);
82133559Srick 	fcntl(fileno(fp), F_SETFL, flags|O_APPEND);
82233559Srick #endif
82333559Srick #ifdef USG
82433559Srick 	fprintf(fp,"%s %d %d%.2d%.2d %.2d%.2d %d %ld %s %ld %ld\n",
82533559Srick #else /* V7 */
82633559Srick 	fprintf(fp,"%s %d %d%02d%02d %02d%02d %d %ld %s %ld %ld\n",
82733559Srick #endif /* V7 */
82833559Srick 		Rmtname, InitialRole, tm->tm_year, tm->tm_mon + 1,
82933559Srick 		tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_wday,
83033559Srick 		(Now.time - StartTime + 59) / 60,
83133559Srick 		ttyn == NULL ? "ttyp0" : &ttyn[5],
83233559Srick 			Bytes_Sent, Bytes_Received);
83333559Srick 	fclose(fp);
83433559Srick #endif /* DO_CONNECT_ACCOUNTING */
83533559Srick }
83633559Srick 
83725703Sbloom /*
83825703Sbloom  *	on interrupt - remove locks and exit
83913639Ssam  */
84013639Ssam 
84146879Sbostic static void
onintr(inter)84213639Ssam onintr(inter)
84313639Ssam register int inter;
84413639Ssam {
84533559Srick 	char str[BUFSIZ];
84613639Ssam 	signal(inter, SIG_IGN);
84734164Srick 	sprintf(str, "(SIGNAL %d)", inter);
84813639Ssam 	logent(str, "CAUGHT");
84917767Sralph 	US_SST(us_s_intr);
85023590Sbloom 	if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME))
85117767Sralph 		systat(Rmtname, SS_FAIL, str);
85234164Srick 	sprintf(str, "(conversation complete %ld sent %ld received)",
85333559Srick 		Bytes_Sent, Bytes_Received);
85433559Srick 	logent(str, _FAILED);
85517767Sralph 	if (inter == SIGPIPE && !onesys)
85617767Sralph 		longjmp(Pipebuf, 1);
85713639Ssam 	cleanup(inter);
85813639Ssam }
85913639Ssam 
86013639Ssam /*
86113639Ssam  * Catch a special signal
86236449Smarc  * (SIGUSR1), and toggle debugging between 0 and 30.
86313639Ssam  * Handy for looking in on long running uucicos.
86413639Ssam  */
86546879Sbostic static void
dbg_signal()86625703Sbloom dbg_signal()
86713639Ssam {
86825703Sbloom 	Debug = (Debug == 0) ? 30 : 0;
86925703Sbloom 	setdebug(DBG_PERM);
87025703Sbloom 	if (Debug > 0)
87125703Sbloom 		logent("Signal Enabled", "DEBUG");
87225703Sbloom }
87317767Sralph 
87425703Sbloom 
87525703Sbloom /*
87625703Sbloom  * Check debugging requests, and open RMTDEBUG audit file if necessary. If an
87725703Sbloom  * audit file is needed, the parm argument indicates how to create the file:
87825703Sbloom  *
87925703Sbloom  *	DBG_TEMP  - Open a temporary file, with filename = RMTDEBUG/pid.
88025703Sbloom  *	DBG_PERM  - Open a permanent audit file, filename = RMTDEBUG/Rmtname.
88125703Sbloom  *		    If a temp file already exists, it is mv'ed to be permanent.
88225703Sbloom  *	DBG_CLEAN - Cleanup; unlink temp files.
88325703Sbloom  *
88425703Sbloom  * Restrictions - this code can only cope with one open debug file at a time.
88525703Sbloom  * Each call creates a new file; if an old one of the same name exists it will
88625703Sbloom  * be overwritten.
88725703Sbloom  */
setdebug(parm)88825703Sbloom setdebug(parm)
88925703Sbloom int parm;
89025703Sbloom {
89125703Sbloom 	char buf[BUFSIZ];		/* Buffer for building filenames     */
89225703Sbloom 	static char *temp = NULL;	/* Ptr to temporary file name	     */
89325703Sbloom 	static int auditopen = 0;	/* Set to 1 when we open a file	     */
89425703Sbloom 	struct stat stbuf;		/* File status buffer		     */
89525703Sbloom 
89625703Sbloom 	/*
89725703Sbloom 	 * If movement or cleanup of a temp file is indicated, we do it no
89825703Sbloom 	 * matter what.
89925703Sbloom 	 */
90025703Sbloom 	if (temp != CNULL && parm == DBG_PERM) {
90125703Sbloom 		sprintf(buf, "%s/%s", RMTDEBUG, Rmtname);
90225703Sbloom 		unlink(buf);
90325703Sbloom 		if (link(temp, buf) != 0) {
90423590Sbloom 			Debug = 0;
90533945Srick 			syslog(LOG_ERR, "RMTDEBUG link(%s,%s) failed: %m",
90633945Srick 				temp, buf);
90733945Srick 			cleanup(FAIL);
90825703Sbloom 		}
90925703Sbloom 		parm = DBG_CLEAN;
91023590Sbloom 	}
91125703Sbloom 	if (parm == DBG_CLEAN) {
91225703Sbloom 		if (temp != CNULL) {
91325703Sbloom 			unlink(temp);
91425703Sbloom 			free(temp);
91525703Sbloom 			temp = CNULL;
91625703Sbloom 		}
91725703Sbloom 		return;
91825703Sbloom 	}
91925703Sbloom 
92025703Sbloom 	if (Debug == 0)
92125703Sbloom 		return;		/* Gotta be in debug to come here.   */
92225703Sbloom 
92325703Sbloom 	/*
92425703Sbloom 	 * If we haven't opened a file already, we can just return if it's
92525703Sbloom 	 * alright to use the stderr we came in with. We can if:
92625703Sbloom 	 *
92725703Sbloom 	 *	Role == MASTER, and Stderr is a regular file, a TTY or a pipe.
92825703Sbloom 	 *
92925703Sbloom 	 * Caution: Detecting when stderr is a pipe is tricky, because the 4.2
93025703Sbloom 	 * man page for fstat(2) disagrees with reality, and System V leaves it
93125703Sbloom 	 * undefined, which means different implementations act differently.
93225703Sbloom 	 */
93325703Sbloom 	if (!auditopen && Role == MASTER) {
93425703Sbloom 		if (isatty(fileno(stderr)))
93525703Sbloom 			return;
93625703Sbloom 		else if (fstat(fileno(stderr), &stbuf) == 0) {
93725703Sbloom #ifdef USG
93825703Sbloom 			/* Is Regular File or Fifo   */
93925703Sbloom 			if ((stbuf.st_mode & 0060000) == 0)
94025703Sbloom 				return;
94125703Sbloom #else !USG
94217767Sralph #ifdef BSD4_2
94325703Sbloom 					/* Is Regular File */
94425703Sbloom 			if ((stbuf.st_mode & S_IFMT) == S_IFREG ||
94525703Sbloom 			    stbuf.st_mode == 0)		/* Is a pipe */
94625703Sbloom 				return;
94725703Sbloom #else !BSD4_2
94825703Sbloom 					 /* Is Regular File or Pipe  */
94925703Sbloom 			if ((stbuf.st_mode & S_IFMT) == S_IFREG)
95025703Sbloom 				return;
95125703Sbloom #endif BSD4_2
95225703Sbloom #endif USG
95325703Sbloom 		}
95417767Sralph 	}
95513639Ssam 
95625703Sbloom 	/*
95725703Sbloom 	 * We need RMTDEBUG directory to do auditing. If the file doesn't exist,
95825703Sbloom 	 * then we forget about debugging; if it exists but has improper owner-
95925703Sbloom 	 * ship or modes, we gripe about it in ERRLOG.
96025703Sbloom 	 */
96125703Sbloom 	if (stat(RMTDEBUG, &stbuf) != SUCCESS) {
96225703Sbloom 		Debug = 0;
96325703Sbloom 		return;
96425703Sbloom 	}
96525703Sbloom 	if ((geteuid() != stbuf.st_uid) ||	  	/* We must own it    */
96625703Sbloom 	    ((stbuf.st_mode & 0170700) != 040700)) {	/* Directory, rwx    */
96725703Sbloom 		Debug = 0;
96833945Srick 		syslog(LOG_ERR, "%s: invalid directory mode: %o", RMTDEBUG,
96933945Srick 			stbuf.st_mode);
97025703Sbloom 		return;
97125703Sbloom 	}
97213639Ssam 
97325703Sbloom 	if (parm == DBG_TEMP) {
97425703Sbloom 		sprintf(buf, "%s/%d", RMTDEBUG, getpid());
97525703Sbloom 		temp = malloc(strlen (buf) + 1);
97625703Sbloom 		if (temp == CNULL) {
97725703Sbloom 			Debug = 0;
97833945Srick 			syslog(LOG_ERR, "RMTDEBUG malloc failed: %m");
97933945Srick 			cleanup(FAIL);
98025703Sbloom 		}
98125703Sbloom 		strcpy(temp, buf);
98225703Sbloom 	} else
98325703Sbloom 		sprintf(buf, "%s/%s", RMTDEBUG, Rmtname);
98413639Ssam 
98525703Sbloom 	unlink(buf);
98625703Sbloom 	if (freopen(buf, "w", stderr) != stderr) {
98725703Sbloom 		Debug = 0;
98833945Srick 		syslog(LOG_ERR, "RMTDEBUG freopen(%s) failed: %m", buf);
98933945Srick 		cleanup(FAIL);
99025703Sbloom 	}
99125703Sbloom 	setbuf(stderr, CNULL);
99225703Sbloom 	auditopen = 1;
99313639Ssam }
99413639Ssam 
99523590Sbloom /*
99625703Sbloom  *	catch SIGALRM routine
99713639Ssam  */
99846879Sbostic static void
timeout()99913639Ssam timeout()
100013639Ssam {
100123590Sbloom 	extern int HaveSentHup;
100223590Sbloom 	if (!HaveSentHup) {
100323590Sbloom 		logent(Rmtname, "TIMEOUT");
100423590Sbloom 		if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) {
100523590Sbloom 			US_SST(us_s_tmot);
100623590Sbloom 			systat(Rmtname, SS_FAIL, "TIMEOUT");
100723590Sbloom 		}
100817767Sralph 	}
100913639Ssam 	longjmp(Sjbuf, 1);
101013639Ssam }
101113639Ssam 
101213639Ssam static char *
pskip(p)101313639Ssam pskip(p)
101413639Ssam register char *p;
101513639Ssam {
101617767Sralph 	while(*p && *p != ' ')
101713639Ssam 		++p;
101823590Sbloom 	while(*p && *p == ' ')
101917767Sralph 		*p++ = 0;
102017767Sralph 	return p;
102113639Ssam }
102234164Srick 
102334164Srick /*
102434164Srick  * clobber argv so ps will show what we're doing.
102534164Srick  * stolen from sendmail
102634164Srick  */
102734164Srick /*VARARGS1*/
setproctitle(fmt,a,b,c)102834164Srick setproctitle(fmt, a, b, c)
102934164Srick char *fmt;
103034164Srick {
103134164Srick #ifdef SETPROCTITLE
103234164Srick 	register char *p;
103334164Srick 	register int i;
103434164Srick 	extern char **Argv;
103534164Srick 	extern char *LastArgv;
103634164Srick 	char buf[BUFSIZ];
103734164Srick 
103834164Srick 	(void) sprintf(buf, fmt, a, b, c);
103934164Srick 
104034164Srick 	/* make ps print "(sendmail)" */
104134164Srick 	p = Argv[0];
104234164Srick 	*p++ = '-';
104334164Srick 
104434164Srick 	i = strlen(buf);
104534164Srick 	if (i > LastArgv - p - 2) {
104634164Srick 		i = LastArgv - p - 2;
104734164Srick 		buf[i] = '\0';
104834164Srick 	}
104934164Srick 	(void) strcpy(p, buf);
105034164Srick 	p += i;
105134164Srick 	while (p < LastArgv)
105234164Srick 		*p++ = ' ';
105334164Srick #endif SETPROCTITLE
105434164Srick }
1055