xref: /csrg-svn/usr.bin/uucp/uux/uux.c (revision 17845)
113695Ssam #ifndef lint
2*17845Sralph static char sccsid[] = "@(#)uux.c	5.2 (Berkeley) 01/22/85";
313695Ssam #endif
413695Ssam 
513695Ssam #include "uucp.h"
613695Ssam 
713695Ssam #define NOSYSPART 0
813695Ssam #define HASSYSPART 1
913695Ssam 
1013695Ssam #define APPCMD(d) {\
11*17845Sralph char *p; for (p = d; *p != '\0';) *cmdp++ = *p++; *cmdp++ = ' '; *cmdp = '\0';}
1213695Ssam 
1313695Ssam #define GENSEND(f, a, b, c, d, e) {\
14*17845Sralph fprintf(f, "S %s %s %s -%s %s 0666\n", a, b, c, d, e); }
15*17845Sralph #define GENRCV(f, a, b, c) {fprintf(f, "R %s %s %s - \n", a, b, c);}
1613695Ssam 
1713695Ssam main(argc, argv)
1813695Ssam char *argv[];
1913695Ssam {
2013695Ssam 	char cfile[NAMESIZE];	/* send commands for files from here */
2113695Ssam 	char dfile[NAMESIZE];	/* used for all data files from here */
2213695Ssam 	char rxfile[NAMESIZE];	/* to be sent to xqt file (X. ...) */
2313695Ssam 	char tfile[NAMESIZE];	/* temporary file name */
2413695Ssam 	char tcfile[NAMESIZE];	/* temporary file name */
2513695Ssam 	char t2file[NAMESIZE];	/* temporary file name */
2613695Ssam 	int cflag = 0;		/*  commands in C. file flag  */
2713695Ssam 	int rflag = 0;		/*  C. files for receiving flag  */
28*17845Sralph #ifdef DONTCOPY
29*17845Sralph 	int Copy = 0;		/* Don't Copy spool files */
30*17845Sralph #else !DONTCOPY
3113695Ssam 	int Copy = 1;		/* Copy spool files */
32*17845Sralph #endif !DONTCOPY
33*17845Sralph 	int Linkit = 0;		/* Try link before copy */
3413695Ssam 	char buf[BUFSIZ];
3513695Ssam 	char inargs[BUFSIZ];
3613695Ssam 	int pipein = 0;
3713695Ssam 	int startjob = 1;
3813695Ssam 	char Grade = 'A';
3913695Ssam 	char path[MAXFULLNAME];
4013695Ssam 	char cmd[BUFSIZ];
4113695Ssam 	char *ap, *cmdp;
4213695Ssam 	char prm[BUFSIZ];
4313695Ssam 	char syspart[8], rest[MAXFULLNAME];
4413695Ssam 	char xsys[8], local[8];
4513695Ssam 	FILE *fprx, *fpc, *fpd, *fp;
4613695Ssam 	extern char *getprm(), *lastpart();
4713695Ssam 	extern FILE *ufopen();
4813695Ssam 	int uid, ret;
4913695Ssam 	char redir = '\0';
5013695Ssam 	int nonoti = 0;
5113695Ssam 	int nonzero = 0;
52*17845Sralph 	int link_failed;
53*17845Sralph 	char *ReturnTo = NULL;
54*17845Sralph 	extern int LocalOnly;
5513695Ssam 
5613695Ssam 	strcpy(Progname, "uux");
5713695Ssam 	uucpname(Myname);
5813695Ssam 	umask(WFMASK);
5913695Ssam 	Ofn = 1;
6013695Ssam 	Ifn = 0;
61*17845Sralph #ifdef	VMS
62*17845Sralph 	arg_fix(argc, argv);
63*17845Sralph #endif
6413695Ssam 	while (argc>1 && argv[1][0] == '-') {
6513695Ssam 		switch(argv[1][1]){
6613695Ssam 		case 'p':
6713695Ssam 		case '\0':
6813695Ssam 			pipein = 1;
6913695Ssam 			break;
7013695Ssam 		case 'r':
7113695Ssam 			startjob = 0;
7213695Ssam 			break;
7313695Ssam 		case 'c':
74*17845Sralph 			Copy = 0;
75*17845Sralph 			Linkit = 0;
76*17845Sralph 			break;
7713695Ssam 		case 'l':
7813695Ssam 			Copy = 0;
79*17845Sralph 			Linkit = 1;
8013695Ssam 			break;
81*17845Sralph 		case 'C':
82*17845Sralph 			Copy = 1;
83*17845Sralph 			Linkit = 0;
84*17845Sralph 			break;
8513695Ssam 		case 'g':
8613695Ssam 			Grade = argv[1][2];
8713695Ssam 			break;
8813695Ssam 		case 'x':
89*17845Sralph 			chkdebug();
9013695Ssam 			Debug = atoi(&argv[1][2]);
9113695Ssam 			if (Debug <= 0)
9213695Ssam 				Debug = 1;
9313695Ssam 			break;
9413695Ssam 		case 'n':
9513695Ssam 			nonoti = 1;
9613695Ssam 			break;
9713695Ssam 		case 'z':
9813695Ssam 			nonzero = 1;
9913695Ssam 			break;
100*17845Sralph 		case 'L':
101*17845Sralph 			LocalOnly++;
102*17845Sralph 			break;
103*17845Sralph 		case 'a':
104*17845Sralph 			ReturnTo = &argv[1][2];
105*17845Sralph 			break;
10613695Ssam 		default:
10713695Ssam 			fprintf(stderr, "unknown flag %s\n", argv[1]);
10813695Ssam 				break;
10913695Ssam 		}
11013695Ssam 		--argc;  argv++;
11113695Ssam 	}
112*17845Sralph 	if (argc > 2) {
113*17845Sralph 		ret = gwd(Wrkdir);
114*17845Sralph 		if (ret != 0) {
115*17845Sralph 			fprintf(stderr, "can't get working directory; will try to continue\n");
116*17845Sralph 			strcpy(Wrkdir, "/UNKNOWN");
117*17845Sralph 		}
118*17845Sralph 	}
11913695Ssam 
12013695Ssam 	DEBUG(4, "\n\n** %s **\n", "START");
12113695Ssam 
12213695Ssam 	inargs[0] = '\0';
12313695Ssam 	for (argv++; argc > 1; argc--) {
12413695Ssam 		DEBUG(4, "arg - %s:", *argv);
12513695Ssam 		strcat(inargs, " ");
12613695Ssam 		strcat(inargs, *argv++);
12713695Ssam 	}
12813695Ssam 	DEBUG(4, "arg - %s\n", inargs);
129*17845Sralph 	ret = subchdir(Spool);
130*17845Sralph 	ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret);
13113695Ssam 	uid = getuid();
13213695Ssam 	guinfo(uid, User, path);
13313695Ssam 
13413695Ssam 	sprintf(local, "%.7s", Myname);
13513695Ssam 	cmdp = cmd;
13613695Ssam 	*cmdp = '\0';
13713695Ssam 	gename(DATAPRE, local, 'X', rxfile);
13813695Ssam 	fprx = ufopen(rxfile, "w");
13913695Ssam 	ASSERT(fprx != NULL, "CAN'T OPEN", rxfile, 0);
14013695Ssam 	gename(DATAPRE, local, 'T', tcfile);
14113695Ssam 	fpc = ufopen(tcfile, "w");
14213695Ssam 	ASSERT(fpc != NULL, "CAN'T OPEN", tcfile, 0);
14313695Ssam 	fprintf(fprx, "%c %s %s\n", X_USER, User, local);
14413695Ssam 	if (nonoti)
14513695Ssam 		fprintf(fprx, "%c\n", X_NONOTI);
14613695Ssam 	if (nonzero)
14713695Ssam 		fprintf(fprx, "%c\n", X_NONZERO);
148*17845Sralph 	if (ReturnTo == NULL || *ReturnTo == '\0')
149*17845Sralph 		ReturnTo = User;
150*17845Sralph 	fprintf(fprx, "%c %s\n", X_RETURNTO, ReturnTo);
15113695Ssam 
15213695Ssam 	/* find remote system name */
15313695Ssam 	ap = inargs;
15413695Ssam 	xsys[0] = '\0';
15513695Ssam 	while ((ap = getprm(ap, prm)) != NULL) {
15613695Ssam 		if (prm[0] == '>' || prm[0] == '<') {
15713695Ssam 			ap = getprm(ap, prm);
15813695Ssam 			continue;
15913695Ssam 		}
16013695Ssam 
16113695Ssam 
16213695Ssam 		split(prm, xsys, rest);
16313695Ssam 		break;
16413695Ssam 	}
16513695Ssam 	if (xsys[0] == '\0')
16613695Ssam 		strcpy(xsys, local);
16713695Ssam 	sprintf(Rmtname, "%.7s", xsys);
16813695Ssam 	DEBUG(4, "xsys %s\n", xsys);
16913695Ssam 	if (versys(xsys) != 0) {
17013695Ssam 		/*  bad system name  */
17113695Ssam 		fprintf(stderr, "bad system name: %s\n", xsys);
17213695Ssam 		fclose(fprx);
17313695Ssam 		fclose(fpc);
17413695Ssam 		cleanup(EX_NOHOST);
17513695Ssam 	}
17613695Ssam 
17713695Ssam 	if (pipein) {
17813695Ssam 		gename(DATAPRE, local, 'B', dfile);
17913695Ssam 		fpd = ufopen(dfile, "w");
18013695Ssam 		ASSERT(fpd != NULL, "CAN'T OPEN", dfile, 0);
18113695Ssam 		while (!feof(stdin)) {
18213695Ssam 			ret = fread(buf, 1, BUFSIZ, stdin);
18313695Ssam 			fwrite(buf, 1, ret, fpd);
18413695Ssam 		}
18513695Ssam 		fclose(fpd);
186*17845Sralph 		strcpy(tfile, dfile);
18713695Ssam 		if (strcmp(local, xsys) != SAME) {
188*17845Sralph 			tfile[strlen(local) + 2] = 'S';
189*17845Sralph 			GENSEND(fpc, dfile, tfile, User, "", dfile);
19013695Ssam 			cflag++;
19113695Ssam 		}
192*17845Sralph 		fprintf(fprx, "%c %s\n", X_RQDFILE, tfile);
193*17845Sralph 		fprintf(fprx, "%c %s\n", X_STDIN, tfile);
19413695Ssam 	}
19513695Ssam 	/* parse command */
19613695Ssam 	ap = inargs;
19713695Ssam 	while ((ap = getprm(ap, prm)) != NULL) {
19813695Ssam 		DEBUG(4, "prm - %s\n", prm);
19913695Ssam 		if (prm[0] == '>' || prm[0] == '<') {
20013695Ssam 			redir = prm[0];
20113695Ssam 			continue;
20213695Ssam 		}
20313695Ssam 
20413695Ssam 		if (prm[0] == ';') {
20513695Ssam 			APPCMD(prm);
20613695Ssam 			continue;
20713695Ssam 		}
20813695Ssam 
20913695Ssam 		if (prm[0] == '|' || prm[0] == '^') {
21013695Ssam 			if (cmdp != cmd)
21113695Ssam 				APPCMD(prm);
21213695Ssam 			continue;
21313695Ssam 		}
21413695Ssam 
21513695Ssam 		/* process command or file or option */
21613695Ssam 		ret = split(prm, syspart, rest);
21713695Ssam 		DEBUG(4, "s - %s, ", syspart);
21813695Ssam 		DEBUG(4, "r - %s, ", rest);
21913695Ssam 		DEBUG(4, "ret - %d\n", ret);
22013695Ssam 		if (syspart[0] == '\0')
22113695Ssam 			strcpy(syspart, local);
22213695Ssam 
22313695Ssam 		if (cmdp == cmd && redir == '\0') {
22413695Ssam 			/* command */
22513695Ssam 			APPCMD(rest);
22613695Ssam 			continue;
22713695Ssam 		}
22813695Ssam 
22913695Ssam 		/* process file or option */
23013695Ssam 		DEBUG(4, "file s- %s, ", syspart);
23113695Ssam 		DEBUG(4, "local - %s\n", local);
23213695Ssam 		/* process file */
23313695Ssam 		if (redir == '>') {
23413695Ssam 			if (rest[0] != '~')
23513695Ssam 				if (ckexpf(rest))
23613695Ssam 					cleanup(EX_CANTCREAT);
23713695Ssam 			fprintf(fprx, "%c %s %s\n", X_STDOUT, rest,
23813695Ssam 			 syspart);
23913695Ssam 			redir = '\0';
24013695Ssam 			continue;
24113695Ssam 		}
24213695Ssam 
24313695Ssam 		if (ret == NOSYSPART && redir == '\0') {
24413695Ssam 			/* option */
24513695Ssam 			APPCMD(rest);
24613695Ssam 			continue;
24713695Ssam 		}
24813695Ssam 
24913695Ssam 		if (strcmp(xsys, local) == SAME
25013695Ssam 		 && strcmp(xsys, syspart) == SAME) {
25113695Ssam 			if (ckexpf(rest))
25213695Ssam 				cleanup(EX_CANTCREAT);
25313695Ssam 			if (redir == '<')
25413695Ssam 				fprintf(fprx, "%c %s\n", X_STDIN, rest);
25513695Ssam 			else
25613695Ssam 				APPCMD(rest);
25713695Ssam 			redir = '\0';
25813695Ssam 			continue;
25913695Ssam 		}
26013695Ssam 
26113695Ssam 		if (strcmp(syspart, local) == SAME) {
26213695Ssam 			/*  generate send file */
26313695Ssam 			if (ckexpf(rest))
26413695Ssam 				cleanup(EX_CANTCREAT);
26513695Ssam 			gename(DATAPRE, local, 'A', dfile);
26613695Ssam 			DEBUG(4, "rest %s\n", rest);
26713695Ssam 			if ((chkpth(User, "", rest) || anyread(rest)) != 0) {
26813695Ssam 				fprintf(stderr, "permission denied %s\n", rest);
26913695Ssam 				cleanup(EX_NOINPUT);
27013695Ssam 			}
271*17845Sralph 			link_failed = 0;
272*17845Sralph 			if (Linkit) {
273*17845Sralph 				if (link(subfile(rest), subfile(dfile)) != 0)
274*17845Sralph 					link_failed++;
275*17845Sralph 				else
276*17845Sralph 					GENSEND(fpc, rest, dfile, User, "", dfile);
277*17845Sralph 			}
278*17845Sralph 			if (Copy || link_failed) {
27913695Ssam 				if (xcp(rest, dfile) != 0) {
28013695Ssam 					fprintf(stderr, "can't copy %s to %s\n", rest, dfile);
28113695Ssam 					cleanup(EX_NOINPUT);
28213695Ssam 				}
28313695Ssam 				GENSEND(fpc, rest, dfile, User, "", dfile);
28413695Ssam 			}
285*17845Sralph 			if (!Copy && !Linkit) {
28613695Ssam 				GENSEND(fpc, rest, dfile, User, "c", "D.0");
28713695Ssam 			}
28813695Ssam 			cflag++;
28913695Ssam 			if (redir == '<') {
29013695Ssam 				fprintf(fprx, "%c %s\n", X_STDIN, dfile);
29113695Ssam 				fprintf(fprx, "%c %s\n", X_RQDFILE, dfile);
29213695Ssam 			}
29313695Ssam 			else {
29413695Ssam 				APPCMD(lastpart(rest));
29513695Ssam 				fprintf(fprx, "%c %s %s\n", X_RQDFILE,
29613695Ssam 				 dfile, lastpart(rest));
29713695Ssam 			}
29813695Ssam 			redir = '\0';
29913695Ssam 			continue;
30013695Ssam 		}
30113695Ssam 
30213695Ssam 		if (strcmp(local, xsys) == SAME) {
30313695Ssam 			/*  generate local receive  */
30413695Ssam 			gename(CMDPRE, syspart, 'R', tfile);
30513695Ssam 			strcpy(dfile, tfile);
30613695Ssam 			dfile[0] = DATAPRE;
30713695Ssam 			fp = ufopen(tfile, "w");
30813695Ssam 			ASSERT(fp != NULL, "CAN'T OPEN", tfile, 0);
30913695Ssam 			if (ckexpf(rest))
31013695Ssam 				cleanup(EX_CANTCREAT);
31113695Ssam 			GENRCV(fp, rest, dfile, User);
31213695Ssam 			fclose(fp);
31313695Ssam 			rflag++;
31413695Ssam 			if (rest[0] != '~')
31513695Ssam 				if (ckexpf(rest))
31613695Ssam 					cleanup(EX_CANTCREAT);
31713695Ssam 			if (redir == '<') {
31813695Ssam 				fprintf(fprx, "%c %s\n", X_RQDFILE, dfile);
31913695Ssam 				fprintf(fprx, "%c %s\n", X_STDIN, dfile);
32013695Ssam 			}
32113695Ssam 			else {
32213695Ssam 				fprintf(fprx, "%c %s %s\n", X_RQDFILE, dfile,
32313695Ssam 				  lastpart(rest));
32413695Ssam 				APPCMD(lastpart(rest));
32513695Ssam 			}
32613695Ssam 
32713695Ssam 			redir = '\0';
32813695Ssam 			continue;
32913695Ssam 		}
33013695Ssam 
33113695Ssam 		if (strcmp(syspart, xsys) != SAME) {
33213695Ssam 			/* generate remote receives */
33313695Ssam 			gename(DATAPRE, syspart, 'R', dfile);
33413695Ssam 			strcpy(tfile, dfile);
33513695Ssam 			tfile[0] = CMDPRE;
33613695Ssam 			fpd = ufopen(dfile, "w");
33713695Ssam 			ASSERT(fpd != NULL, "CAN'T OPEN", dfile, 0);
33813695Ssam 			gename(DATAPRE, local, 'T', t2file);
33913695Ssam 			GENRCV(fpd, rest, t2file, User);
34013695Ssam 			fclose(fpd);
34113695Ssam 			GENSEND(fpc, dfile, tfile, User, "", dfile);
34213695Ssam 			cflag++;
34313695Ssam 			if (redir == '<') {
34413695Ssam 				fprintf(fprx, "%c %s\n", X_RQDFILE, t2file);
34513695Ssam 				fprintf(fprx, "%c %s\n", X_STDIN, t2file);
34613695Ssam 			}
34713695Ssam 			else {
34813695Ssam 				fprintf(fprx, "%c %s %s\n", X_RQDFILE, t2file,
34913695Ssam 				  lastpart(rest));
35013695Ssam 				APPCMD(lastpart(rest));
35113695Ssam 			}
35213695Ssam 			redir = '\0';
35313695Ssam 			continue;
35413695Ssam 		}
35513695Ssam 
35613695Ssam 		/* file on remote system */
35713695Ssam 		if (rest[0] != '~')
35813695Ssam 			if (ckexpf(rest))
35913695Ssam 				cleanup(EX_CANTCREAT);
36013695Ssam 		if (redir == '<')
36113695Ssam 			fprintf(fprx, "%c %s\n", X_STDIN, rest);
36213695Ssam 		else
36313695Ssam 			APPCMD(rest);
36413695Ssam 		redir = '\0';
36513695Ssam 		continue;
36613695Ssam 
36713695Ssam 	}
368*17845Sralph 	/*
369*17845Sralph 	 * clean up trailing ' ' in command.
370*17845Sralph 	 */
371*17845Sralph 	if (cmdp > cmd && cmdp[0] == '\0' && cmdp[-1] == ' ')
372*17845Sralph 		*--cmdp = '\0';
373*17845Sralph 	/* block multi-hop uux, which doesn't work */
374*17845Sralph 	for (ap = cmd; *ap && *ap != ' '; ap++)
375*17845Sralph 		if (*ap == '!') {
376*17845Sralph 			fprintf(stderr, "uux handles only adjacent sites.\n");
377*17845Sralph 			fprintf(stderr, "Try uusend for multi-hop delivery.\n");
378*17845Sralph 			cleanup(1);
379*17845Sralph 		}
38013695Ssam 
38113695Ssam 	fprintf(fprx, "%c %s\n", X_CMD, cmd);
38213695Ssam 	logent(cmd, "XQT QUE'D");
38313695Ssam 	fclose(fprx);
38413695Ssam 
385*17845Sralph 	gename(XQTPRE, local, Grade, tfile);
38613695Ssam 	if (strcmp(xsys, local) == SAME) {
38713695Ssam 		/* rti!trt: xmv() works across filesystems, link(II) doesnt */
38813695Ssam 		xmv(rxfile, tfile);
38913695Ssam 		if (startjob)
39013695Ssam 			if (rflag)
39113695Ssam 				xuucico(xsys);
39213695Ssam 			else
39313695Ssam 				xuuxqt();
39413695Ssam 	}
39513695Ssam 	else {
39613695Ssam 		GENSEND(fpc, rxfile, tfile, User, "", rxfile);
39713695Ssam 		cflag++;
39813695Ssam 	}
39913695Ssam 
40013695Ssam 	fclose(fpc);
40113695Ssam 	if (cflag) {
40213695Ssam 		gename(CMDPRE, xsys, Grade, cfile);
40313695Ssam 		/* rti!trt: use xmv() rather than link(II) */
40413695Ssam 		xmv(tcfile, cfile);
40513695Ssam 		if (startjob)
40613695Ssam 			xuucico(xsys);
40713695Ssam 		cleanup(0);
40813695Ssam 	}
40913695Ssam 	else
41013695Ssam 		unlink(subfile(tcfile));
41113695Ssam }
41213695Ssam 
41313695Ssam #define FTABSIZE 30
41413695Ssam char Fname[FTABSIZE][NAMESIZE];
41513695Ssam int Fnamect = 0;
41613695Ssam 
417*17845Sralph /*
418*17845Sralph  *	cleanup and unlink if error
41913695Ssam  *
42013695Ssam  *	return - none - do exit()
42113695Ssam  */
42213695Ssam 
42313695Ssam cleanup(code)
42413695Ssam int code;
42513695Ssam {
42613695Ssam 	int i;
42713695Ssam 
42813695Ssam 	logcls();
42913695Ssam 	rmlock(CNULL);
43013695Ssam 	if (code) {
43113695Ssam 		for (i = 0; i < Fnamect; i++)
43213695Ssam 			unlink(subfile(Fname[i]));
43313695Ssam 		fprintf(stderr, "uux failed. code %d\n", code);
43413695Ssam 	}
43513695Ssam 	DEBUG(1, "exit code %d\n", code);
43613695Ssam 	exit(code);
43713695Ssam }
43813695Ssam 
439*17845Sralph /*
440*17845Sralph  *	open file and record name
44113695Ssam  *
44213695Ssam  *	return file pointer.
44313695Ssam  */
44413695Ssam 
44513695Ssam FILE *ufopen(file, mode)
44613695Ssam char *file, *mode;
44713695Ssam {
44813695Ssam 	if (Fnamect < FTABSIZE)
44913695Ssam 		strcpy(Fname[Fnamect++], file);
45013695Ssam 	else
45113695Ssam 		logent("Fname", "TABLE OVERFLOW");
452*17845Sralph 	return fopen(subfile(file), mode);
45313695Ssam }
454*17845Sralph #ifdef	VMS
455*17845Sralph /*
456*17845Sralph  * EUNICE bug:
457*17845Sralph  *	quotes are not stripped from DCL.  Do it here.
458*17845Sralph  *	Note if we are running under Unix shell we don't
459*17845Sralph  *	do the right thing.
460*17845Sralph  */
461*17845Sralph arg_fix(argc, argv)
462*17845Sralph char **argv;
463*17845Sralph {
464*17845Sralph 	register char *cp, *tp;
465*17845Sralph 
466*17845Sralph 	for (; argc > 0; --argc, argv++) {
467*17845Sralph 		cp = *argv;
468*17845Sralph 		if (cp == (char *)0 || *cp++ != '"')
469*17845Sralph 			continue;
470*17845Sralph 		tp = cp;
471*17845Sralph 		while (*tp++) ;
472*17845Sralph 		tp -= 2;
473*17845Sralph 		if (*tp == '"') {
474*17845Sralph 			*tp = '\0';
475*17845Sralph 			*argv = cp;
476*17845Sralph 		}
477*17845Sralph 	}
478*17845Sralph }
479*17845Sralph #endif VMS
480