xref: /csrg-svn/usr.bin/uucp/uucico/cntrl.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 
813640Ssam #ifndef lint
9*62391Sbostic static char sccsid[] = "@(#)cntrl.c	8.1 (Berkeley) 06/06/93";
1048664Sbostic #endif /* not lint */
1113640Ssam 
1213640Ssam #include "uucp.h"
1313640Ssam #include <sys/stat.h>
1417832Sralph #include "uust.h"
1513640Ssam 
1617832Sralph extern int errno;
1718617Sralph extern int turntime;
1818617Sralph int willturn;
1923591Sbloom int HaveSentHup = 0;
2013640Ssam 
2113640Ssam struct Proto {
2213640Ssam 	char P_id;
2313640Ssam 	int (*P_turnon)();
2413640Ssam 	int (*P_rdmsg)();
2513640Ssam 	int (*P_wrmsg)();
2613640Ssam 	int (*P_rddata)();
2713640Ssam 	int (*P_wrdata)();
2813640Ssam 	int (*P_turnoff)();
2913640Ssam };
3013640Ssam 
3113640Ssam extern int gturnon(), gturnoff();
3213640Ssam extern int grdmsg(), grddata();
3313640Ssam extern int gwrmsg(), gwrdata();
3423591Sbloom extern int imsg(), omsg(), nullf();
3523591Sbloom #ifdef TCPIP
3617832Sralph extern int twrmsg(), trdmsg();
3717832Sralph extern int twrdata(), trddata();
3823591Sbloom #endif TCPIP
3917832Sralph #ifdef PAD
4017832Sralph extern int fturnon(), fturnoff();
4117832Sralph extern int frdmsg(), frddata();
4217832Sralph extern int fwrmsg(), fwrdata();
4317832Sralph #endif PAD
4413640Ssam 
4513640Ssam struct Proto Ptbl[]={
4623591Sbloom #ifdef TCPIP
4723591Sbloom 	't', nullf, trdmsg, twrmsg, trddata, twrdata, nullf,
4823591Sbloom #endif TCPIP
4917832Sralph #ifdef PAD
5017832Sralph 	'f', fturnon, frdmsg, fwrmsg, frddata, fwrdata, fturnoff,
5117832Sralph #endif PAD
5213640Ssam 	'g', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff,
5313640Ssam 	'\0'
5413640Ssam };
5513640Ssam 
5617832Sralph int (*Imsg)() = imsg, (*Omsg)() = omsg;
5713640Ssam 
5813640Ssam int (*Rdmsg)()=imsg, (*Rddata)();
5913640Ssam int (*Wrmsg)()=omsg, (*Wrdata)();
6023591Sbloom int (*Turnon)()=nullf, (*Turnoff)() = nullf;
6113640Ssam 
6225125Sbloom struct timeb Now, LastTurned, LastCheckedNoLogin;
6313640Ssam 
6417832Sralph static char *YES = "Y";
6517832Sralph static char *NO = "N";
6613640Ssam 
6718617Sralph int TransferSucceeded = 1;
6818617Sralph 
6913640Ssam /*  failure messages  */
7013640Ssam #define EM_MAX		6
7113640Ssam #define EM_LOCACC	"N1"	/* local access to file denied */
7213640Ssam #define EM_RMTACC	"N2"	/* remote access to file/path denied */
7313640Ssam #define EM_BADUUCP	"N3"	/* a bad uucp command was generated */
7413640Ssam #define EM_NOTMP	"N4"	/* remote error - can't create temp */
7513640Ssam #define EM_RMTCP	"N5"	/* can't copy to remote directory - file in public */
7613640Ssam #define EM_LOCCP	"N6"	/* can't copy on local system */
7713640Ssam 
7813640Ssam char *Em_msg[] = {
7913640Ssam 	"COPY FAILED (reason not given by remote)",
8013640Ssam 	"local access to file denied",
8113640Ssam 	"remote access to path/file denied",
8213640Ssam 	"system error - bad uucp command generated",
8313640Ssam 	"remote system can't create temp file",
8413640Ssam 	"can't copy to file/directory - file left in PUBDIR/user/file",
8517832Sralph 	"can't copy to file/directory on local system  - file left in PUBDIR/user/file"
8613640Ssam };
8713640Ssam 
8813640Ssam 
8913640Ssam #define XUUCP 'X'	/* execute uucp (string) */
9013640Ssam #define SLTPTCL 'P'	/* select protocol  (string)  */
9113640Ssam #define USEPTCL 'U'	/* use protocol (character) */
9213640Ssam #define RCVFILE 'R'	/* receive file (string) */
9313640Ssam #define SNDFILE 'S'	/* send file (string) */
9413640Ssam #define RQSTCMPT 'C'	/* request complete (string - yes | no) */
9513640Ssam #define HUP     'H'	/* ready to hangup (string - yes | no) */
9613640Ssam #define RESET	'X'	/* reset line modes */
9713640Ssam 
9813640Ssam #define W_TYPE		wrkvec[0]
9913640Ssam #define W_FILE1		wrkvec[1]
10013640Ssam #define W_FILE2		wrkvec[2]
10113640Ssam #define W_USER		wrkvec[3]
10213640Ssam #define W_OPTNS		wrkvec[4]
10313640Ssam #define W_DFILE		wrkvec[5]
10413640Ssam #define W_MODE		wrkvec[6]
10513640Ssam #define W_NUSER		wrkvec[7]
10613640Ssam 
10717832Sralph #define	XFRRATE	35000L
10817832Sralph #define RMESG(m, s, n) if (rmesg(m, s, n) != 0) {(*Turnoff)(); return FAIL;} else
10917832Sralph #define RAMESG(s, n) if (rmesg('\0', s, n) != 0) {(*Turnoff)(); return FAIL;} else
11017832Sralph #define WMESG(m, s) if(wmesg(m, s) != 0) {(*Turnoff)(); return FAIL;} else
11113640Ssam 
11213640Ssam char Wfile[MAXFULLNAME] = {'\0'};
11313640Ssam char Dfile[MAXFULLNAME];
11413640Ssam 
11513640Ssam /*
11613640Ssam  * To avoid a huge backlog of X. files, start uuxqt every so often.
11713640Ssam  */
11813640Ssam static int nXfiles = 0;	/* number of X files since last uuxqt start */
11917832Sralph static char send_or_receive;
12017832Sralph struct stat stbuf;
12113640Ssam 
12217832Sralph /*
12313640Ssam  *	cntrl  -  this routine will execute the conversation
12413640Ssam  *	between the two machines after both programs are
12513640Ssam  *	running.
12613640Ssam  *
12713640Ssam  *	return codes
12813640Ssam  *		SUCCESS - ok
12913640Ssam  *		FAIL - failed
13013640Ssam  */
13113640Ssam 
cntrl(role,wkpre)13213640Ssam cntrl(role, wkpre)
13313640Ssam int role;
13413640Ssam char *wkpre;
13513640Ssam {
13613640Ssam 	char msg[BUFSIZ], rqstr[BUFSIZ];
13713640Ssam 	register FILE *fp;
13813640Ssam 	int filemode;
13913640Ssam 	char filename[MAXFULLNAME], wrktype, *wrkvec[20];
14013640Ssam 	extern (*Rdmsg)(), (*Wrmsg)();
14113640Ssam 	extern char *index(), *lastpart();
14213640Ssam 	int status = 1;
14313640Ssam 	register int i, narg;
14413640Ssam 	int mailopt, ntfyopt;
14513640Ssam 	int ret;
14613640Ssam 	static int pnum, tmpnum = 0;
14717832Sralph 	extern int ReverseRole;
14813640Ssam 
14913640Ssam 	pnum = getpid();
15013640Ssam 	Wfile[0] = '\0';
15118617Sralph 	willturn = turntime > 0;
15218617Sralph remaster:
15318617Sralph #ifdef USG
15418617Sralph 	time(&LastTurned.time);
15518617Sralph 	LastTurned.millitm = 0;
15618617Sralph #else !USG
15718617Sralph 	ftime(&LastTurned);
15818617Sralph #endif !USG
15918617Sralph 	send_or_receive = RESET;
16023591Sbloom 	HaveSentHup = 0;
16113640Ssam top:
16213640Ssam 	for (i = 0; i < sizeof wrkvec / sizeof wrkvec[0]; i++)
16313640Ssam 		wrkvec[i] = 0;
16417832Sralph 	DEBUG(4, "*** TOP ***  -  role=%s\n", role ? "MASTER" : "SLAVE");
16534165Srick 	setproctitle("%s: %s", Rmtname, role ? "MASTER" : "SLAVE");
16623591Sbloom 	setupline(RESET);
16725125Sbloom 	if (Now.time > (LastCheckedNoLogin.time+60)) {
16825125Sbloom 		LastCheckedNoLogin = Now;
16925125Sbloom 		if (access(NOLOGIN, 0) == 0) {
17025125Sbloom 			logent(NOLOGIN, "UUCICO SHUTDOWN");
17125125Sbloom 			if (Debug > 4)
17225125Sbloom 				logent("DEBUGGING", "continuing anyway");
17325125Sbloom 			else {
17425125Sbloom 				WMESG(HUP, YES);
17525125Sbloom 				RMESG(HUP, msg, 1);
17625125Sbloom 				goto process;
17725125Sbloom 			}
17818617Sralph 		}
17918617Sralph 	}
18013640Ssam 	if (role == MASTER) {
18113640Ssam 		/* get work */
18217832Sralph 		if (ReverseRole || (narg = gtwvec(Wfile, Spool, wkpre, wrkvec)) == 0) {
18317832Sralph 			ReverseRole = 0;
18413640Ssam 			WMESG(HUP, "");
18513640Ssam 			RMESG(HUP, msg, 1);
18613640Ssam 			goto process;
18713640Ssam 		}
18813640Ssam 		wrktype = W_TYPE[0];
18913640Ssam 
19013640Ssam 		msg[0] = '\0';
19113640Ssam 		for (i = 1; i < narg; i++) {
19213640Ssam 			strcat(msg, " ");
19313640Ssam 			strcat(msg, wrkvec[i]);
19413640Ssam 		}
19513640Ssam 
19613640Ssam 		if (wrktype == XUUCP) {
19713640Ssam 			sprintf(rqstr, "X %s", msg);
19813640Ssam 			logent(rqstr, "REQUEST");
19913640Ssam 			goto sendmsg;
20013640Ssam 		}
20117832Sralph 		mailopt = index(W_OPTNS, 'm') != NULL;
20217832Sralph 		ntfyopt = index(W_OPTNS, 'n') != NULL;
20313640Ssam 
20433560Srick 		if (narg < 5 || W_TYPE[1] != '\0') {
20517832Sralph 			char *bnp;
20617832Sralph 			bnp = rindex(Wfile, '/');
20717832Sralph 			sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile);
20817832Sralph 			xmv(Wfile, rqstr);
20933946Srick 			syslog(LOG_WARNING, "%s CORRUPTED: %d args", Wfile,
21033946Srick 				narg);
21117832Sralph 			Wfile[0] = '\0';
21217832Sralph 			goto top;
21317832Sralph 		}
21413640Ssam 		sprintf(User, "%.9s", W_USER);
21534165Srick 		sprintf(rqstr, "(%s %s %s %s)", W_TYPE, W_FILE1,
21613640Ssam 		  W_FILE2, W_USER);
21713640Ssam 		logent(rqstr, "REQUEST");
21813640Ssam 		if (wrktype == SNDFILE ) {
21913640Ssam 			strcpy(filename, W_FILE1);
22013640Ssam 			i = expfile(filename);
22117832Sralph 			DEBUG(4, "expfile type - %d, ", i);
22213640Ssam 			if (i != 0 && chkpth(User, "", filename))
22313640Ssam 				goto e_access;
22413640Ssam 			strcpy(Dfile, W_DFILE);
22513640Ssam 			fp = NULL;
22613640Ssam 			if (index(W_OPTNS, 'c') == NULL) {
22713640Ssam 				fp = fopen(subfile(Dfile), "r");
22813640Ssam 				if (fp != NULL)
22913640Ssam 					i = 0;
23013640Ssam 			}
23113640Ssam 			if (fp == NULL &&
23213640Ssam 			   (fp = fopen(subfile(filename), "r")) == NULL) {
23313640Ssam 				/*  can not read data file  */
23417832Sralph 				logent("CAN'T READ DATA", _FAILED);
23523591Sbloom 				TransferSucceeded = 1; /* else will keep sending */
23617832Sralph 				USRF(USR_LOCACC);
23713640Ssam 				unlinkdf(Dfile);
23813640Ssam 				lnotify(User, filename, "can't access");
23913640Ssam 				goto top;
24013640Ssam 			}
24113640Ssam 			/* if file exists but is not generally readable... */
24213640Ssam 			if (i != 0 && fstat(fileno(fp), &stbuf) == 0
24313640Ssam 			&&  (stbuf.st_mode & ANYREAD) == 0) {
24413640Ssam 		e_access:;
24513640Ssam 				/*  access denied  */
24633946Srick 				if (fp != NULL) {
24733946Srick 					fclose(fp);
24833946Srick 					fp = NULL;
24933946Srick 				}
25023591Sbloom 				TransferSucceeded = 1; /* else will keep sending */
25113640Ssam 				logent("DENIED", "ACCESS");
25217832Sralph 				USRF(USR_LOCACC);
25313640Ssam 				unlinkdf(W_DFILE);
25413640Ssam 				lnotify(User, filename, "access denied");
25513640Ssam 				goto top;
25613640Ssam 			}
25713640Ssam 
25823591Sbloom 			setupline(SNDFILE);
25913640Ssam 		}
26013640Ssam 
26113640Ssam 		if (wrktype == RCVFILE) {
26213640Ssam 			strcpy(filename, W_FILE2);
26313640Ssam 			expfile(filename);
26413640Ssam 			if (chkpth(User, "", filename)
26513640Ssam 			 || chkperm(filename, index(W_OPTNS, 'd'))) {
26613640Ssam 				/*  access denied  */
26713640Ssam 				logent("DENIED", "ACCESS");
26823591Sbloom 				TransferSucceeded = 1; /* else will keep trying */
26917832Sralph 				USRF(USR_LOCACC);
27013640Ssam 				lnotify(User, filename, "access denied");
27113640Ssam 				goto top;
27213640Ssam 			}
27313640Ssam 			sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++);
27413640Ssam 			if ((fp = fopen(subfile(Dfile), "w")) == NULL) {
27513640Ssam 				/*  can not create temp  */
27617832Sralph 				logent("CAN'T CREATE TM", _FAILED);
27717832Sralph 				USRF(USR_LNOTMP);
27813640Ssam 				unlinkdf(Dfile);
27913640Ssam 				goto top;
28013640Ssam 			}
28123591Sbloom 			setupline(RCVFILE);
28213640Ssam 		}
28313640Ssam sendmsg:
28417832Sralph 		DEBUG(4, "wrktype - %c\n", wrktype);
28513640Ssam 		WMESG(wrktype, msg);
28613640Ssam 		RMESG(wrktype, msg, 1);
28713640Ssam 		goto process;
28813640Ssam 	}
28913640Ssam 
29013640Ssam 	/* role is slave */
29113640Ssam 	RAMESG(msg, 1);
29218617Sralph 	if (willturn < 0)
29318617Sralph 		willturn = msg[0] == HUP;
29418617Sralph 
29513640Ssam process:
29617832Sralph 	DEBUG(4, "PROCESS: msg - %s\n", msg);
29713640Ssam 	switch (msg[0]) {
29813640Ssam 
29913640Ssam 	case RQSTCMPT:
30017832Sralph 		DEBUG(4, "RQSTCMPT:\n", CNULL);
30113640Ssam 		if (msg[1] == 'N') {
30213640Ssam 			i = atoi(&msg[2]);
30323591Sbloom 			if (i<0 || i>EM_MAX)
30423591Sbloom 				i = 0;
30517832Sralph 			USRF( 1 << i );
30617832Sralph 			logent(Em_msg[i], "REQUEST FAILED");
30725125Sbloom 			TransferSucceeded = 1; /* He had his chance */
30813640Ssam 		}
30923591Sbloom 		if (msg[1] == 'Y') {
31017832Sralph 			USRF(USR_COK);
31123591Sbloom 			TransferSucceeded = 1;
31223591Sbloom 		}
31333946Srick 		if (role == MASTER)
31433591Srick 			notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
31533946Srick 
31633946Srick 		if (msg[2] == 'M' && role == MASTER) {
31718617Sralph 			extern int Nfiles;
31818617Sralph 			WMESG(HUP, "");
31918617Sralph 			RMESG(HUP, msg, 1);
32018617Sralph 			logent(Rmtname, "TURNAROUND");
32118617Sralph #ifdef USG
32218617Sralph 				time(&LastTurned.time);
32318617Sralph 				LastTurned.millitm = 0;
32418617Sralph #else !USG
32518617Sralph 				ftime(&LastTurned);
32618617Sralph #endif !USG
32718617Sralph 			Nfiles = 0; /* force rescan of queue for work */
32818617Sralph 			goto process;
32918617Sralph 		}
33013640Ssam 		goto top;
33113640Ssam 
33213640Ssam 	case HUP:
33317832Sralph 		DEBUG(4, "HUP:\n", CNULL);
33423591Sbloom 		HaveSentHup = 1;
33513640Ssam 		if (msg[1] == 'Y') {
33617832Sralph 			if (role == MASTER)
33717832Sralph 				WMESG(HUP, YES);
33813640Ssam 			(*Turnoff)();
33913640Ssam 			Rdmsg = Imsg;
34013640Ssam 			Wrmsg = Omsg;
34117832Sralph 			return SUCCESS;
34213640Ssam 		}
34313640Ssam 
34413640Ssam 		if (msg[1] == 'N') {
34533946Srick 			if (role != MASTER) {
34633946Srick 				syslog(LOG_ERR, "Wrong Role - HUP");
34733946Srick 				cleanup(FAIL);
34833946Srick 			}
34913640Ssam 			role = SLAVE;
35018617Sralph 			goto remaster;
35113640Ssam 		}
35213640Ssam 
35313640Ssam 		/* get work */
35413640Ssam 		if (!iswrk(Wfile, "chk", Spool, wkpre)) {
35513640Ssam 			WMESG(HUP, YES);
35613640Ssam 			RMESG(HUP, msg, 1);
35713640Ssam 			goto process;
35813640Ssam 		}
35913640Ssam 
36013640Ssam 		WMESG(HUP, NO);
36133946Srick 		/*
36233946Srick 		 * want to create an orphan uuxqt,
36333946Srick 		 * so a double-fork is needed.
36433946Srick 		 */
36533946Srick 		if (fork() == 0) {
36633946Srick 			xuuxqt();
36733946Srick 			_exit(0);
36833946Srick 		}
36933946Srick 		wait((int *)0);
37013640Ssam 		role = MASTER;
37118617Sralph 		goto remaster;
37213640Ssam 
37313640Ssam 	case XUUCP:
37413640Ssam 		if (role == MASTER) {
37513640Ssam 			goto top;
37613640Ssam 		}
37713640Ssam 
37813640Ssam 		/*  slave part  */
37917832Sralph 		i = getargs(msg, wrkvec, 20);
38013640Ssam 		strcpy(filename, W_FILE1);
38117832Sralph 		if (index(filename, ';') != NULL || index(W_FILE2, ';') != NULL
38217832Sralph 		    || i < 3) {
38313640Ssam 			WMESG(XUUCP, NO);
38413640Ssam 			goto top;
38513640Ssam 		}
38613640Ssam 		expfile(filename);
38713640Ssam 		if (chkpth("", Rmtname, filename)) {
38813640Ssam 			WMESG(XUUCP, NO);
38913640Ssam 			logent("XUUCP DENIED", filename);
39017832Sralph 				USRF(USR_XUUCP);
39113640Ssam 			goto top;
39213640Ssam 		}
39313640Ssam 		sprintf(rqstr, "%s %s", filename, W_FILE2);
39413640Ssam 		xuucp(rqstr);
39513640Ssam 		WMESG(XUUCP, YES);
39613640Ssam 		goto top;
39713640Ssam 
39813640Ssam 	case SNDFILE:
39913640Ssam 		/*  MASTER section of SNDFILE  */
40013640Ssam 
40113640Ssam 		DEBUG(4, "%s\n", "SNDFILE:");
40213640Ssam 		if (msg[1] == 'N') {
40313640Ssam 			i = atoi(&msg[2]);
40413640Ssam 			if (i < 0 || i > EM_MAX)
40513640Ssam 				i = 0;
40617832Sralph 			logent(Em_msg[i], "REQUEST FAILED");
40717832Sralph 			USRF( 1 << i );
40813640Ssam 			fclose(fp);
40913640Ssam 			fp = NULL;
41025125Sbloom 			/* dont send him files he can't save */
41117832Sralph 			if (strcmp(&msg[1], EM_NOTMP) == 0) {
41217832Sralph 				WMESG(HUP, "");
41317832Sralph 				RMESG(HUP, msg, 1);
41417832Sralph 				goto process;
41517832Sralph 			}
41633591Srick 			notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
41733946Srick 			if (role != MASTER) {
41833946Srick 				syslog(LOG_ERR, "Wrong Role - SN");
41933946Srick 				cleanup(FAIL);
42033946Srick 			}
42133560Srick 			unlinkdf(W_DFILE);
42213640Ssam 			goto top;
42313640Ssam 		}
42413640Ssam 
42513640Ssam 		if (msg[1] == 'Y') {
42613640Ssam 			/* send file */
42733946Srick 			if (role != MASTER) {
42833946Srick 				syslog(LOG_ERR, "Wrong Role - SY");
42933946Srick 				cleanup(FAIL);
43033946Srick 			}
43133946Srick 			if (fstat(fileno(fp), &stbuf) < 0) {
43233946Srick 				syslog(LOG_ERR, "stat(%s) failed: %m",filename);
43333946Srick 				cleanup(FAIL);
43433946Srick 			}
43513640Ssam 			i = 1 + (int)(stbuf.st_size / XFRRATE);
43617832Sralph 			if (send_or_receive != SNDFILE) {
43717832Sralph 				send_or_receive = SNDFILE;
43817832Sralph 				systat(Rmtname, SS_INPROGRESS, "SENDING");
43917832Sralph 			}
44013640Ssam 			ret = (*Wrdata)(fp, Ofn);
44113640Ssam 			fclose(fp);
44213640Ssam 			fp = NULL;
44317832Sralph 			if (ret != SUCCESS) {
44413640Ssam 				(*Turnoff)();
44517832Sralph 				USRF(USR_CFAIL);
44617832Sralph 				return FAIL;
44713640Ssam 			}
44813640Ssam 			RMESG(RQSTCMPT, msg, i);
44913640Ssam 			unlinkdf(W_DFILE);
45013640Ssam 			goto process;
45113640Ssam 		}
45213640Ssam 
45313640Ssam 		/*  SLAVE section of SNDFILE  */
45433946Srick 		if (role != SLAVE) {
45533946Srick 			syslog(LOG_ERR, "Wrong Role - SLAVE");
45633946Srick 			cleanup(FAIL);
45733946Srick 		}
45813640Ssam 
45913640Ssam 		/* request to receive file */
46013640Ssam 		/* check permissions */
46117832Sralph 		i = getargs(msg, wrkvec, 20);
46217832Sralph 		if (i < 5) {
46317832Sralph 			char *bnp;
46417832Sralph 			bnp = rindex(Wfile, '/');
46517832Sralph 			sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile);
46617832Sralph 			xmv(Wfile, rqstr);
46733946Srick 			syslog(LOG_WARNING, "%s CORRUPTED: %d args", Wfile, i);
46817832Sralph 			Wfile[0] = '\0';
46917832Sralph 			goto top;
47017832Sralph 		}
47134165Srick 		sprintf(rqstr, "(%s %s %s %s)", W_TYPE, W_FILE1, W_FILE2,
47234165Srick 			W_USER);
47313640Ssam 		logent(rqstr, "REQUESTED");
47413640Ssam 		DEBUG(4, "msg - %s\n", msg);
47513640Ssam 		strcpy(filename, W_FILE2);
47613640Ssam 		/* Run uuxqt occasionally */
47713640Ssam 		if (filename[0] == XQTPRE) {
47813640Ssam 			if (++nXfiles > 10) {
47913640Ssam 				nXfiles = 0;
48017832Sralph 				/*
48117832Sralph 				 * want to create an orphan uuxqt,
48217832Sralph 				 * so a double-fork is needed.
48313640Ssam 				 */
48417832Sralph 				if (fork() == 0) {
48517832Sralph 					xuuxqt();
48617832Sralph 					_exit(0);
48717832Sralph 				}
48817832Sralph 				wait((int *)0);
48913640Ssam 			}
49013640Ssam 		}
49117832Sralph 		/* expand filename, i is set to 0 if this is
49213640Ssam 		 * is a vanilla spool file, so no stat(II)s are needed */
49313640Ssam 		i = expfile(filename);
49413640Ssam 		DEBUG(4, "expfile type - %d\n", i);
49513640Ssam 		if (i != 0) {
49613640Ssam 			if (chkpth("", Rmtname, filename)
49713640Ssam 			 || chkperm(filename, index(W_OPTNS, 'd'))) {
49813640Ssam 				WMESG(SNDFILE, EM_RMTACC);
49913640Ssam 				logent("DENIED", "PERMISSION");
50013640Ssam 				goto top;
50113640Ssam 			}
50213640Ssam 			if (isdir(filename)) {
50313640Ssam 				strcat(filename, "/");
50413640Ssam 				strcat(filename, lastpart(W_FILE1));
50513640Ssam 			}
50613640Ssam 		}
50713640Ssam 		sprintf(User, "%.9s", W_USER);
50813640Ssam 
50913640Ssam 		DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
51017832Sralph 		/* speed things up by OKing file before
51117832Sralph 		 * creating TM file.  If the TM file cannot be created,
51217832Sralph 		 * then the conversation bombs, but that seems reasonable,
51317832Sralph 		 * as there are probably serious problems then.
51417832Sralph 		 */
51517832Sralph 		WMESG(SNDFILE, YES);
51613640Ssam 		sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++);
51713640Ssam 		if((fp = fopen(subfile(Dfile), "w")) == NULL) {
51817832Sralph /*			WMESG(SNDFILE, EM_NOTMP);*/
51917832Sralph 			logent("CAN'T OPEN", "TM FILE");
52013640Ssam 			unlinkdf(Dfile);
52117832Sralph 			(*Turnoff)();
52217832Sralph 			return FAIL;
52313640Ssam 		}
52413640Ssam 
52517832Sralph 		if (send_or_receive != RCVFILE) {
52617832Sralph 			send_or_receive = RCVFILE;
52717832Sralph 			systat(Rmtname, SS_INPROGRESS, "RECEIVING");
52817832Sralph 		}
52913640Ssam 		ret = (*Rddata)(Ifn, fp);
53013640Ssam 		fflush(fp);
53113640Ssam 		if (ferror(fp) || fclose(fp))
53213640Ssam 			ret = FAIL;
53323591Sbloom 
53417832Sralph 		if (ret != SUCCESS) {
53517832Sralph 			(void) unlinkdf(Dfile);
53613640Ssam 			(*Turnoff)();
53717832Sralph 			return FAIL;
53813640Ssam 		}
53913640Ssam 		/* copy to user directory */
54013640Ssam 		ntfyopt = index(W_OPTNS, 'n') != NULL;
54113640Ssam 		status = xmv(Dfile, filename);
54218617Sralph 
54318617Sralph 		if (willturn && Now.time > (LastTurned.time+turntime)
54418617Sralph 			&& iswrk(Wfile, "chk", Spool, wkpre)) {
54518617Sralph 				WMESG(RQSTCMPT, status ? EM_RMTCP : "YM");
54618617Sralph 				willturn = -1;
54718617Sralph 		} else
54818617Sralph 			WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
54917832Sralph 		if (i == 0)
55017832Sralph 			;	/* vanilla file, nothing to do */
55117832Sralph 		else if (status == 0) {
55217832Sralph 			if (W_MODE == 0 || sscanf(W_MODE, "%o", &filemode) != 1)
55313640Ssam 				filemode = BASEMODE;
55417832Sralph 			chmod(subfile(filename), (filemode|BASEMODE)&0777);
55513640Ssam 			arrived(ntfyopt, filename, W_NUSER, Rmtname, User);
55617832Sralph 		} else {
55717832Sralph 			logent(_FAILED, "COPY");
55813640Ssam 			status = putinpub(filename, Dfile, W_USER);
55913640Ssam 			DEBUG(4, "->PUBDIR %d\n", status);
56013640Ssam 			if (status == 0)
56117832Sralph 				arrived(ntfyopt, filename, W_NUSER, Rmtname, User);
56213640Ssam 		}
56313640Ssam 
56413640Ssam 		goto top;
56513640Ssam 
56613640Ssam 	case RCVFILE:
56713640Ssam 		/*  MASTER section of RCVFILE  */
56813640Ssam 
56913640Ssam 		DEBUG(4, "%s\n", "RCVFILE:");
57013640Ssam 		if (msg[1] == 'N') {
57113640Ssam 			i = atoi(&msg[2]);
57213640Ssam 			if (i < 0 || i > EM_MAX)
57313640Ssam 				i = 0;
57417832Sralph 			logent(Em_msg[i], "REQUEST FAILED");
57517832Sralph 			USRF( 1 << i );
57617832Sralph 			fclose(fp);
57717832Sralph 			fp = NULL;
57833591Srick 			notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
57933946Srick 			if (role != MASTER) {
58033946Srick 				syslog(LOG_ERR, "Wrong Role - RN");
58133946Srick 				cleanup(FAIL);
58233946Srick 			}
58313640Ssam 			unlinkdf(Dfile);
58413640Ssam 			goto top;
58513640Ssam 		}
58613640Ssam 
58713640Ssam 		if (msg[1] == 'Y') {
58813640Ssam 			/* receive file */
58933946Srick 			if (role != MASTER) {
59033946Srick 				syslog(LOG_ERR, "Wrong Role - RY");
59133946Srick 				cleanup(FAIL);
59233946Srick 			}
59317832Sralph 			if (send_or_receive != RCVFILE) {
59417832Sralph 				send_or_receive = RCVFILE;
59517832Sralph 				systat(Rmtname, SS_INPROGRESS, "RECEIVING");
59617832Sralph 			}
59713640Ssam 			ret = (*Rddata)(Ifn, fp);
59813640Ssam 			fflush(fp);
59913640Ssam 			if (ferror(fp) || fclose(fp))
60013640Ssam 				ret = FAIL;
60117832Sralph 			if (ret != SUCCESS) {
60217832Sralph 				unlinkdf(Dfile);
60313640Ssam 				(*Turnoff)();
60417832Sralph 				USRF(USR_CFAIL);
60517832Sralph 				return FAIL;
60613640Ssam 			}
60713640Ssam 			/* copy to user directory */
60813640Ssam 			if (isdir(filename)) {
60913640Ssam 				strcat(filename, "/");
61013640Ssam 				strcat(filename, lastpart(W_FILE1));
61113640Ssam 			}
61213640Ssam 			status = xmv(Dfile, filename);
61333946Srick 			WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
61413640Ssam 			notify(mailopt, W_USER, filename, Rmtname,
61525964Sbloom 				status ? EM_LOCCP : YES);
61613640Ssam 			if (status == 0) {
61713640Ssam 				sscanf(&msg[2], "%o", &filemode);
61813640Ssam 				if (filemode <= 0)
61913640Ssam 					filemode = BASEMODE;
62017832Sralph 				chmod(subfile(filename), (filemode|BASEMODE)&0777);
62117832Sralph 				USRF(USR_COK);
62225964Sbloom 			} else {
62317832Sralph 				logent(_FAILED, "COPY");
62413640Ssam 				putinpub(filename, Dfile, W_USER);
62517832Sralph 				USRF(USR_LOCCP);
62613640Ssam 			}
62733946Srick 			if (msg[strlen(msg)-1] == 'M') {
62833946Srick 				extern int Nfiles;
62933946Srick 				WMESG(HUP, "");
63033946Srick 				RMESG(HUP, msg, 1);
63133946Srick 				logent(Rmtname, "TURNAROUND");
63233946Srick #ifdef USG
63333946Srick 				time(&LastTurned.time);
63433946Srick 				LastTurned.millitm = 0;
63533946Srick #else !USG
63633946Srick 				ftime(&LastTurned);
63733946Srick #endif !USG
63833946Srick 				Nfiles = 0; /* force rescan of queue for work */
63933946Srick 				goto process;
64033946Srick 			}
64113640Ssam 			goto top;
64213640Ssam 		}
64313640Ssam 
64413640Ssam 		/*  SLAVE section of RCVFILE  */
64533946Srick 		if (role != SLAVE) {
64633946Srick 			syslog(LOG_ERR, "Wrong Role - SLAVE RCV");
64733946Srick 			cleanup(FAIL);
64833946Srick 		}
64913640Ssam 
65013640Ssam 		/* request to send file */
65134165Srick 		sprintf(rqstr,"(%s)", msg);
65213640Ssam 		logent(rqstr, "REQUESTED");
65313640Ssam 
65413640Ssam 		/* check permissions */
65517832Sralph 		i = getargs(msg, wrkvec, 20);
65617832Sralph 		if (i < 4) {
65717832Sralph 			char *bnp;
65817832Sralph 			bnp = rindex(Wfile, '/');
65917832Sralph 			sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile);
66017832Sralph 			xmv(Wfile, rqstr);
66133946Srick 			syslog(LOG_WARNING, "%s CORRUPTED: %d args", Wfile, i);
66217832Sralph 			Wfile[0] = '\0';
66317832Sralph 			goto top;
66417832Sralph 		}
66513640Ssam 		DEBUG(4, "msg - %s\n", msg);
66613640Ssam 		DEBUG(4, "W_FILE1 - %s\n", W_FILE1);
66713640Ssam 		strcpy(filename, W_FILE1);
66813640Ssam 		expfile(filename);
66913640Ssam 		if (isdir(filename)) {
67013640Ssam 			strcat(filename, "/");
67113640Ssam 			strcat(filename, lastpart(W_FILE2));
67213640Ssam 		}
67313640Ssam 		sprintf(User, "%.9s", W_USER);
67413640Ssam 		if (chkpth("", Rmtname, filename) || anyread(filename)) {
67513640Ssam 			WMESG(RCVFILE, EM_RMTACC);
67613640Ssam 			logent("DENIED", "PERMISSION");
67713640Ssam 			goto top;
67813640Ssam 		}
67913640Ssam 		DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
68013640Ssam 
68113640Ssam 		if ((fp = fopen(subfile(filename), "r")) == NULL) {
68213640Ssam 			WMESG(RCVFILE, EM_RMTACC);
68313640Ssam 			logent("CAN'T OPEN", "DENIED");
68413640Ssam 			goto top;
68513640Ssam 		}
68613640Ssam 
68713640Ssam 		/*  ok to send file */
68833946Srick 		if (fstat(fileno(fp), &stbuf) < 0) {
68933946Srick 			syslog(LOG_ERR, "stat(%s) failed: %m", filename);
69033946Srick 			cleanup(FAIL);
69133946Srick 		}
69233946Srick 
69313640Ssam 		i = 1 + (int)(stbuf.st_size / XFRRATE);
69433946Srick 		if (willturn && Now.time > (LastTurned.time+turntime)
69533946Srick 			&& iswrk(Wfile, "chk", Spool, wkpre)) {
69633946Srick 				willturn = -1;
69733946Srick 		}
69833946Srick 		sprintf(msg, "%s %o%s", YES, (int)stbuf.st_mode & 0777,
69933946Srick 			willturn < 0 ? " M" : "");
70013640Ssam 		WMESG(RCVFILE, msg);
70117832Sralph 		if (send_or_receive != SNDFILE) {
70217832Sralph 			send_or_receive = SNDFILE;
70317832Sralph 			systat(Rmtname, SS_INPROGRESS, "SENDING");
70417832Sralph 		}
70513640Ssam 		ret = (*Wrdata)(fp, Ofn);
70613640Ssam 		fclose(fp);
70717832Sralph 		if (ret != SUCCESS) {
70813640Ssam 			(*Turnoff)();
70917832Sralph 			return FAIL;
71013640Ssam 		}
71113640Ssam 		RMESG(RQSTCMPT, msg, i);
71213640Ssam 		goto process;
71313640Ssam 	}
71413640Ssam 	(*Turnoff)();
71517832Sralph 	return FAIL;
71613640Ssam }
71713640Ssam 
71813640Ssam 
71925964Sbloom /*
72025964Sbloom  *	read message 'c'. try 'n' times
72113640Ssam  *
72225964Sbloom  *	return code:  SUCCESS  |  FAIL
72313640Ssam  */
rmesg(c,msg,n)72413640Ssam rmesg(c, msg, n)
72513640Ssam register char *msg, c;
72613640Ssam register int n;
72713640Ssam {
72825964Sbloom 	char str[MAXFULLNAME];
72913640Ssam 
73013640Ssam 	DEBUG(4, "rmesg - '%c' ", c);
73117832Sralph 	while ((*Rdmsg)(msg, Ifn) != SUCCESS) {
73217832Sralph 		if (--n > 0) {
73317832Sralph 			sprintf(str, "%d", n);
73417832Sralph 			logent(str, "PATIENCE");
73513640Ssam 			continue;
73617832Sralph 		}
73717832Sralph 		DEBUG(4, "got FAIL\n", CNULL);
73817832Sralph 		if (c != '\0')
73917832Sralph 			sprintf(str, "expected '%c' got FAIL (%d)", c, errno);
74017832Sralph 		else
74117832Sralph 			sprintf(str, "expected ANY got FAIL (%d)", errno);
74213640Ssam 		logent(str, "BAD READ");
74317832Sralph 		return FAIL;
74413640Ssam 	}
74513640Ssam 	if (c != '\0' && msg[0] != c) {
74613640Ssam 		DEBUG(4, "got %s\n", msg);
74717832Sralph 		sprintf(str, "expected '%c' got %s", c, msg);
74813640Ssam 		logent(str, "BAD READ");
74917832Sralph 		return FAIL;
75013640Ssam 	}
75117832Sralph 	DEBUG(4, "got %s\n", msg);
75217832Sralph 	return SUCCESS;
75313640Ssam }
75413640Ssam 
75513640Ssam 
75625964Sbloom /*
75725964Sbloom  *	write a message (type m)
75813640Ssam  *
75925964Sbloom  *	return codes: SUCCESS - ok | FAIL - ng
76013640Ssam  */
wmesg(m,s)76113640Ssam wmesg(m, s)
76213640Ssam register char *s, m;
76313640Ssam {
76417832Sralph 	DEBUG(4, "wmesg '%c' ", m);
76517832Sralph 	DEBUG(4, "%s\n", s);
76617832Sralph 	return (*Wrmsg)(m, s, Ofn);
76713640Ssam }
76813640Ssam 
76925964Sbloom /*
77025964Sbloom  *	mail results of command
77113640Ssam  *
77213640Ssam  *	return codes:  none
77313640Ssam  */
notify(mailopt,user,file,sys,msgcode)77413640Ssam notify(mailopt, user, file, sys, msgcode)
77513640Ssam char *user, *file, *sys, *msgcode;
77613640Ssam {
77725964Sbloom 	char str[BUFSIZ];
77813640Ssam 	int i;
77913640Ssam 	char *msg;
78013640Ssam 
78113640Ssam 	if (!mailopt && *msgcode == 'Y')
78213640Ssam 		return;
78313640Ssam 	if (*msgcode == 'Y')
78413640Ssam 		msg = "copy succeeded";
78513640Ssam 	else {
78613640Ssam 		i = atoi(msgcode + 1);
78713640Ssam 		if (i < 1 || i > EM_MAX)
78813640Ssam 			i = 0;
78913640Ssam 		msg = Em_msg[i];
79013640Ssam 	}
79117832Sralph 	sprintf(str, "file %s!%s -- %s\n",
79217832Sralph 		sys,file, msg);
79317832Sralph 	mailst(user, str, CNULL);
79413640Ssam 	return;
79513640Ssam }
79613640Ssam 
79725964Sbloom /*
79825964Sbloom  *	local notify
79913640Ssam  *
80013640Ssam  *	return code - none
80113640Ssam  */
lnotify(user,file,mesg)80213640Ssam lnotify(user, file, mesg)
80313640Ssam char *user, *file, *mesg;
80413640Ssam {
80513640Ssam 	char mbuf[200];
80617832Sralph 	sprintf(mbuf, "file %s!%s -- %s\n", Myname, file, mesg);
80717832Sralph 	mailst(user, mbuf, CNULL);
80813640Ssam 	return;
80913640Ssam }
81013640Ssam 
81133591Srick char UsingProtocol;
81233591Srick 
81325964Sbloom /*
81425964Sbloom  *	converse with the remote machine, agree upon a protocol (if possible)
81525964Sbloom  *	and start the protocol.
81613640Ssam  *
81713640Ssam  *	return codes:
81813640Ssam  *		SUCCESS - successful protocol selection
81913640Ssam  *		FAIL - can't find common or open failed
82013640Ssam  */
startup(role)82113640Ssam startup(role)
82213640Ssam int role;
82313640Ssam {
82413640Ssam 	extern (*Rdmsg)(), (*Wrmsg)();
82513640Ssam 	extern char *blptcl(), fptcl();
82617832Sralph 	char msg[BUFSIZ], str[MAXFULLNAME];
82713640Ssam 
82813640Ssam 	Rdmsg = Imsg;
82913640Ssam 	Wrmsg = Omsg;
83013640Ssam 	if (role == MASTER) {
83113640Ssam 		RMESG(SLTPTCL, msg, 1);
83213640Ssam 		if ((str[0] = fptcl(&msg[1])) == NULL) {
83313640Ssam 			/* no protocol match */
83413640Ssam 			WMESG(USEPTCL, NO);
83517832Sralph 			return FAIL;
83613640Ssam 		}
83713640Ssam 		str[1] = '\0';
83813640Ssam 		WMESG(USEPTCL, str);
83913640Ssam 		if (stptcl(str) != 0)
84017832Sralph 			return FAIL;
84113640Ssam 		DEBUG(4, "protocol %s\n", str);
84233591Srick 		UsingProtocol = str[0];
84317832Sralph 		return SUCCESS;
84413640Ssam 	}
84513640Ssam 	else {
84613640Ssam 		WMESG(SLTPTCL, blptcl(str));
84713640Ssam 		RMESG(USEPTCL, msg, 1);
84813640Ssam 		if (msg[1] == 'N') {
84917832Sralph 			return FAIL;
85013640Ssam 		}
85113640Ssam 
85213640Ssam 		if (stptcl(&msg[1]) != 0)
85317832Sralph 			return FAIL;
85413640Ssam 		DEBUG(4, "Protocol %s\n", msg);
85533591Srick 		UsingProtocol = msg[1];
85617832Sralph 		return SUCCESS;
85713640Ssam 	}
85813640Ssam }
85913640Ssam 
86025964Sbloom /*
86125964Sbloom  *	choose a protocol from the input string (str) and return the it
86213640Ssam  *
86313640Ssam  *	return codes:
86413640Ssam  *		'\0'  -  no acceptable protocol
86513640Ssam  *		any character  -  the chosen protocol
86613640Ssam  */
86713640Ssam char
fptcl(str)86813640Ssam fptcl(str)
86913640Ssam register char *str;
87013640Ssam {
87113640Ssam 	register struct Proto *p;
87225964Sbloom 	extern char LineType[];
87313640Ssam 
87413640Ssam 	for (p = Ptbl; p->P_id != '\0'; p++) {
87523591Sbloom #ifdef TCPIP
87623591Sbloom 		/* Only use 't' on TCP/IP */
87725964Sbloom 		if (p->P_id == 't' && strcmp("TCP", LineType))
87817662Sralph 			continue;
87923591Sbloom #endif TCPIP
88023591Sbloom #ifdef PAD
88117832Sralph 		/* only use 'f' protocol on PAD */
88225964Sbloom 		if (p->P_id == 'f' && strcmp("PAD", LineType))
88317832Sralph 			continue;
88423591Sbloom #endif PAD
88513640Ssam 		if (index(str, p->P_id) != NULL) {
88617832Sralph 			return p->P_id;
88713640Ssam 		}
88813640Ssam 	}
88913640Ssam 
89017832Sralph 	return '\0';
89113640Ssam }
89213640Ssam 
89325964Sbloom /*
89425964Sbloom  *	build a string of the letters of the available protocols
89513640Ssam  */
89613640Ssam char *
blptcl(str)89713640Ssam blptcl(str)
89813640Ssam register char *str;
89913640Ssam {
90013640Ssam 	register struct Proto *p;
90113640Ssam 	register char *s;
90213640Ssam 
90317832Sralph 	for (p = Ptbl, s = str; (*s++ = p->P_id) != '\0'; p++)
90417832Sralph 		;
90517662Sralph 	*s = '\0';
90617832Sralph 	return str;
90713640Ssam }
90813640Ssam 
90925964Sbloom /*
91025964Sbloom  *	this routine will set up the six routines
91113640Ssam  *	(Rdmsg, Wrmsg, Rddata, Wrdata, Turnon, Turnoff) for the
91213640Ssam  *	desired protocol.
91313640Ssam  *
91413640Ssam  *	return codes:
91513640Ssam  *		SUCCESS - ok
91613640Ssam  *		FAIL - no find or failed to open
91713640Ssam  *
91813640Ssam  */
stptcl(c)91913640Ssam stptcl(c)
92013640Ssam register char *c;
92113640Ssam {
92213640Ssam 	register struct Proto *p;
92313640Ssam 
92413640Ssam 	for (p = Ptbl; p->P_id != '\0'; p++) {
92513640Ssam 		if (*c == p->P_id) {
92613640Ssam 			/* found protocol - set routines */
92713640Ssam 			Rdmsg = p->P_rdmsg;
92813640Ssam 			Wrmsg = p->P_wrmsg;
92913640Ssam 			Rddata = p->P_rddata;
93013640Ssam 			Wrdata = p->P_wrdata;
93113640Ssam 			Turnon = p->P_turnon;
93213640Ssam 			Turnoff = p->P_turnoff;
93317832Sralph 			if ((*Turnon)() != SUCCESS)
93417832Sralph 				return FAIL;
93513640Ssam 			DEBUG(4, "Proto started %c\n", *c);
93617832Sralph 			return SUCCESS;
93713640Ssam 		}
93813640Ssam 	}
93913640Ssam 	DEBUG(4, "Proto start-fail %c\n", *c);
94017832Sralph 	return FAIL;
94113640Ssam }
94213640Ssam 
94325964Sbloom /*
94425964Sbloom  *	put file in public place. if successful, filename is modified
94513640Ssam  *
94625964Sbloom  *	return code  SUCCESS | FAIL
94713640Ssam  */
94813640Ssam 
putinpub(file,tmp,user)94913640Ssam putinpub(file, tmp, user)
95025964Sbloom register char *file, *tmp, *user;
95113640Ssam {
95213640Ssam 	char fullname[MAXFULLNAME];
95313640Ssam 	char *lastpart();
95413640Ssam 	int status;
95513640Ssam 
95613640Ssam 	sprintf(fullname, "%s/%s/", PUBDIR, user);
95713640Ssam 	if (mkdirs(fullname) != 0) {
95813640Ssam 		/* can not make directories */
95925964Sbloom 		DEBUG(1, "Cannot mkdirs(%s)\n", fullname);
96017832Sralph 		return FAIL;
96113640Ssam 	}
96213640Ssam 	strcat(fullname, lastpart(file));
96313640Ssam 	status = xmv(tmp, fullname);
96413640Ssam 	if (status == 0) {
96513640Ssam 		strcpy(file, fullname);
96613640Ssam 		chmod(subfile(fullname), BASEMODE);
96713640Ssam 	}
96817832Sralph 	return status;
96913640Ssam }
97013640Ssam 
97125964Sbloom /*
97225964Sbloom  *	unlink D. file
97313640Ssam  *
97413640Ssam  *	return code - none
97513640Ssam  */
97613640Ssam 
unlinkdf(file)97713640Ssam unlinkdf(file)
97813640Ssam register char *file;
97913640Ssam {
98013640Ssam 	if (strlen(file) > 6)
98113640Ssam 		unlink(subfile(file));
98213640Ssam 	return;
98313640Ssam }
98413640Ssam 
98525964Sbloom /*
98625964Sbloom  *	notify receiver of arrived file
98713640Ssam  *
98813640Ssam  *	return code - none
98913640Ssam  */
arrived(opt,file,nuser,rmtsys,rmtuser)99013640Ssam arrived(opt, file, nuser, rmtsys, rmtuser)
99113640Ssam char *file, *nuser, *rmtsys, *rmtuser;
99213640Ssam {
99313640Ssam 	char mbuf[200];
99413640Ssam 
99513640Ssam 	if (!opt)
99613640Ssam 		return;
99713640Ssam 	sprintf(mbuf, "%s from %s!%s arrived\n", file, rmtsys, rmtuser);
99817832Sralph 	mailst(nuser, mbuf, CNULL);
99913640Ssam 	return;
100013640Ssam }
100123591Sbloom 
nullf()100223591Sbloom nullf()
100323591Sbloom {
100423591Sbloom 	return SUCCESS;
100523591Sbloom }
1006