xref: /original-bsd/usr.bin/uucp/uux/uux.c (revision 9087ff44)
1 #ifndef lint
2 static char sccsid[] = "@(#)uux.c	5.4 (Berkeley) 06/23/85";
3 #endif
4 
5 #include "uucp.h"
6 
7 #define NOSYSPART 0
8 #define HASSYSPART 1
9 
10 #define APPCMD(d) {\
11 char *p; for (p = d; *p != '\0';) *cmdp++ = *p++; *cmdp++ = ' '; *cmdp = '\0';}
12 
13 #define GENSEND(f, a, b, c, d, e) {\
14 fprintf(f, "S %s %s %s -%s %s 0666\n", a, b, c, d, e); }
15 #define GENRCV(f, a, b, c) {fprintf(f, "R %s %s %s - \n", a, b, c);}
16 
17 main(argc, argv)
18 char *argv[];
19 {
20 	char cfile[NAMESIZE];	/* send commands for files from here */
21 	char dfile[NAMESIZE];	/* used for all data files from here */
22 	char rxfile[NAMESIZE];	/* to be sent to xqt file (X. ...) */
23 	char tfile[NAMESIZE];	/* temporary file name */
24 	char tcfile[NAMESIZE];	/* temporary file name */
25 	char t2file[NAMESIZE];	/* temporary file name */
26 	int cflag = 0;		/*  commands in C. file flag  */
27 	int rflag = 0;		/*  C. files for receiving flag  */
28 #ifdef DONTCOPY
29 	int Copy = 0;		/* Don't Copy spool files */
30 #else !DONTCOPY
31 	int Copy = 1;		/* Copy spool files */
32 #endif !DONTCOPY
33 	int Linkit = 0;		/* Try link before copy */
34 	char buf[BUFSIZ];
35 	char inargs[BUFSIZ];
36 	int pipein = 0;
37 	int startjob = 1;
38 	char Grade = 'A';
39 	char path[MAXFULLNAME];
40 	char cmd[BUFSIZ];
41 	char *ap, *cmdp;
42 	char prm[BUFSIZ];
43 	char syspart[MAXBASENAME+1], rest[MAXFULLNAME];
44 	char Xsys[MAXBASENAME+1], local[MAXBASENAME+1];
45 	char *xsys = Xsys;
46 	FILE *fprx, *fpc, *fpd, *fp;
47 	extern char *getprm(), *lastpart();
48 	extern FILE *ufopen();
49 	int uid, ret;
50 	char redir = '\0';
51 	int nonoti = 0;
52 	int nonzero = 0;
53 	int link_failed;
54 	char *ReturnTo = NULL;
55 	extern int LocalOnly;
56 
57 	strcpy(Progname, "uux");
58 	uucpname(Myname);
59 	umask(WFMASK);
60 	Ofn = 1;
61 	Ifn = 0;
62 #ifdef	VMS
63 	arg_fix(argc, argv);
64 #endif
65 	while (argc>1 && argv[1][0] == '-') {
66 		switch(argv[1][1]){
67 		case 'p':
68 		case '\0':
69 			pipein = 1;
70 			break;
71 		case 'r':
72 			startjob = 0;
73 			break;
74 		case 'c':
75 			Copy = 0;
76 			Linkit = 0;
77 			break;
78 		case 'l':
79 			Copy = 0;
80 			Linkit = 1;
81 			break;
82 		case 'C':
83 			Copy = 1;
84 			Linkit = 0;
85 			break;
86 		case 'g':
87 			Grade = argv[1][2];
88 			break;
89 		case 'x':
90 			chkdebug();
91 			Debug = atoi(&argv[1][2]);
92 			if (Debug <= 0)
93 				Debug = 1;
94 			break;
95 		case 'n':
96 			nonoti = 1;
97 			break;
98 		case 'z':
99 			nonzero = 1;
100 			break;
101 		case 'L':
102 			LocalOnly++;
103 			break;
104 		case 'a':
105 			ReturnTo = &argv[1][2];
106 			if (prefix(Myname, ReturnTo) && ReturnTo[strlen(Myname)]				== '!')
107 				ReturnTo = index(ReturnTo, '!') + 1;
108 			break;
109 		default:
110 			fprintf(stderr, "unknown flag %s\n", argv[1]);
111 				break;
112 		}
113 		--argc;  argv++;
114 	}
115 	if (argc > 2) {
116 		ap = getwd(Wrkdir);
117 		if (ap == 0) {
118 			fprintf(stderr, "can't get working directory; will try to continue\n");
119 			strcpy(Wrkdir, "/UNKNOWN");
120 		}
121 	}
122 
123 	DEBUG(4, "\n\n** %s **\n", "START");
124 
125 	inargs[0] = '\0';
126 	for (argv++; argc > 1; argc--) {
127 		DEBUG(4, "arg - %s:", *argv);
128 		strcat(inargs, " ");
129 		strcat(inargs, *argv++);
130 	}
131 	DEBUG(4, "arg - %s\n", inargs);
132 	ret = subchdir(Spool);
133 	ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret);
134 	uid = getuid();
135 	guinfo(uid, User, path);
136 
137 	strncpy(local, Myname, MAXBASENAME);
138 	cmdp = cmd;
139 	*cmdp = '\0';
140 	gename(DATAPRE, local, 'X', rxfile);
141 	fprx = ufopen(rxfile, "w");
142 	ASSERT(fprx != NULL, "CAN'T OPEN", rxfile, 0);
143 	gename(DATAPRE, local, 'T', tcfile);
144 	fpc = ufopen(tcfile, "w");
145 	ASSERT(fpc != NULL, "CAN'T OPEN", tcfile, 0);
146 	fprintf(fprx, "%c %s %s\n", X_USER, User, local);
147 	if (nonoti)
148 		fprintf(fprx, "%c\n", X_NONOTI);
149 	if (nonzero)
150 		fprintf(fprx, "%c\n", X_NONZERO);
151 	if (ReturnTo == NULL || *ReturnTo == '\0')
152 		ReturnTo = User;
153 	fprintf(fprx, "%c %s\n", X_RETURNTO, ReturnTo);
154 
155 	/* find remote system name */
156 	ap = inargs;
157 	xsys[0] = '\0';
158 	while ((ap = getprm(ap, prm)) != NULL) {
159 		if (prm[0] == '>' || prm[0] == '<') {
160 			ap = getprm(ap, prm);
161 			continue;
162 		}
163 
164 
165 		split(prm, xsys, rest);
166 		break;
167 	}
168 	if (xsys[0] == '\0')
169 		strcpy(xsys, local);
170 	strncpy(Rmtname, xsys, MAXBASENAME);
171 	DEBUG(4, "xsys %s\n", xsys);
172 	if (versys(&xsys) != 0) {
173 		/*  bad system name  */
174 		fprintf(stderr, "bad system name: %s\n", xsys);
175 		fclose(fprx);
176 		fclose(fpc);
177 		cleanup(EX_NOHOST);
178 	}
179 
180 	if (pipein) {
181 		gename(DATAPRE, local, 'B', dfile);
182 		fpd = ufopen(dfile, "w");
183 		ASSERT(fpd != NULL, "CAN'T OPEN", dfile, 0);
184 		while (!feof(stdin)) {
185 			ret = fread(buf, 1, BUFSIZ, stdin);
186 			fwrite(buf, 1, ret, fpd);
187 		}
188 		fclose(fpd);
189 		strcpy(tfile, dfile);
190 		if (strcmp(local, xsys) != SAME) {
191 			tfile[strlen(local) + 2] = 'S';
192 			GENSEND(fpc, dfile, tfile, User, "", dfile);
193 			cflag++;
194 		}
195 		fprintf(fprx, "%c %s\n", X_RQDFILE, tfile);
196 		fprintf(fprx, "%c %s\n", X_STDIN, tfile);
197 	}
198 	/* parse command */
199 	ap = inargs;
200 	while ((ap = getprm(ap, prm)) != NULL) {
201 		DEBUG(4, "prm - %s\n", prm);
202 		if (prm[0] == '>' || prm[0] == '<') {
203 			redir = prm[0];
204 			continue;
205 		}
206 
207 		if (prm[0] == ';') {
208 			APPCMD(prm);
209 			continue;
210 		}
211 
212 		if (prm[0] == '|' || prm[0] == '^') {
213 			if (cmdp != cmd)
214 				APPCMD(prm);
215 			continue;
216 		}
217 
218 		/* process command or file or option */
219 		ret = split(prm, syspart, rest);
220 		DEBUG(4, "s - %s, ", syspart);
221 		DEBUG(4, "r - %s, ", rest);
222 		DEBUG(4, "ret - %d\n", ret);
223 		if (syspart[0] == '\0')
224 			strcpy(syspart, local);
225 
226 		if (cmdp == cmd && redir == '\0') {
227 			/* command */
228 			APPCMD(rest);
229 			continue;
230 		}
231 
232 		/* process file or option */
233 		DEBUG(4, "file s- %s, ", syspart);
234 		DEBUG(4, "local - %s\n", local);
235 		/* process file */
236 		if (redir == '>') {
237 			if (rest[0] != '~')
238 				if (ckexpf(rest))
239 					cleanup(EX_CANTCREAT);
240 			fprintf(fprx, "%c %s %s\n", X_STDOUT, rest,
241 			 syspart);
242 			redir = '\0';
243 			continue;
244 		}
245 
246 		if (ret == NOSYSPART && redir == '\0') {
247 			/* option */
248 			APPCMD(rest);
249 			continue;
250 		}
251 
252 		if (strcmp(xsys, local) == SAME
253 		 && strcmp(xsys, syspart) == SAME) {
254 			if (ckexpf(rest))
255 				cleanup(EX_CANTCREAT);
256 			if (redir == '<')
257 				fprintf(fprx, "%c %s\n", X_STDIN, rest);
258 			else
259 				APPCMD(rest);
260 			redir = '\0';
261 			continue;
262 		}
263 
264 		if (strcmp(syspart, local) == SAME) {
265 			/*  generate send file */
266 			if (ckexpf(rest))
267 				cleanup(EX_CANTCREAT);
268 			gename(DATAPRE, local, 'A', dfile);
269 			DEBUG(4, "rest %s\n", rest);
270 			if ((chkpth(User, "", rest) || anyread(rest)) != 0) {
271 				fprintf(stderr, "permission denied %s\n", rest);
272 				cleanup(EX_NOINPUT);
273 			}
274 			link_failed = 0;
275 			if (Linkit) {
276 				if (link(subfile(rest), subfile(dfile)) != 0)
277 					link_failed++;
278 				else
279 					GENSEND(fpc, rest, dfile, User, "", dfile);
280 			}
281 			if (Copy || link_failed) {
282 				if (xcp(rest, dfile) != 0) {
283 					fprintf(stderr, "can't copy %s to %s\n", rest, dfile);
284 					cleanup(EX_NOINPUT);
285 				}
286 				GENSEND(fpc, rest, dfile, User, "", dfile);
287 			}
288 			if (!Copy && !Linkit) {
289 				GENSEND(fpc, rest, dfile, User, "c", "D.0");
290 			}
291 			cflag++;
292 			if (redir == '<') {
293 				fprintf(fprx, "%c %s\n", X_STDIN, dfile);
294 				fprintf(fprx, "%c %s\n", X_RQDFILE, dfile);
295 			} else {
296 				APPCMD(lastpart(rest));
297 				fprintf(fprx, "%c %s %s\n", X_RQDFILE,
298 				 dfile, lastpart(rest));
299 			}
300 			redir = '\0';
301 			continue;
302 		}
303 
304 		if (strcmp(local, xsys) == SAME) {
305 			/*  generate local receive  */
306 			gename(CMDPRE, syspart, 'R', tfile);
307 			strcpy(dfile, tfile);
308 			dfile[0] = DATAPRE;
309 			fp = ufopen(tfile, "w");
310 			ASSERT(fp != NULL, "CAN'T OPEN", tfile, 0);
311 			if (ckexpf(rest))
312 				cleanup(EX_CANTCREAT);
313 			GENRCV(fp, rest, dfile, User);
314 			fclose(fp);
315 			rflag++;
316 			if (rest[0] != '~')
317 				if (ckexpf(rest))
318 					cleanup(EX_CANTCREAT);
319 			if (redir == '<') {
320 				fprintf(fprx, "%c %s\n", X_RQDFILE, dfile);
321 				fprintf(fprx, "%c %s\n", X_STDIN, dfile);
322 			} else {
323 				fprintf(fprx, "%c %s %s\n", X_RQDFILE, dfile,
324 				  lastpart(rest));
325 				APPCMD(lastpart(rest));
326 			}
327 
328 			redir = '\0';
329 			continue;
330 		}
331 
332 		if (strcmp(syspart, xsys) != SAME) {
333 			/* generate remote receives */
334 			gename(DATAPRE, syspart, 'R', dfile);
335 			strcpy(tfile, dfile);
336 			tfile[0] = CMDPRE;
337 			fpd = ufopen(dfile, "w");
338 			ASSERT(fpd != NULL, "CAN'T OPEN", dfile, 0);
339 			gename(DATAPRE, local, 'T', t2file);
340 			GENRCV(fpd, rest, t2file, User);
341 			fclose(fpd);
342 			GENSEND(fpc, dfile, tfile, User, "", dfile);
343 			cflag++;
344 			if (redir == '<') {
345 				fprintf(fprx, "%c %s\n", X_RQDFILE, t2file);
346 				fprintf(fprx, "%c %s\n", X_STDIN, t2file);
347 			} else {
348 				fprintf(fprx, "%c %s %s\n", X_RQDFILE, t2file,
349 				  lastpart(rest));
350 				APPCMD(lastpart(rest));
351 			}
352 			redir = '\0';
353 			continue;
354 		}
355 
356 		/* file on remote system */
357 		if (rest[0] != '~')
358 			if (ckexpf(rest))
359 				cleanup(EX_CANTCREAT);
360 		if (redir == '<')
361 			fprintf(fprx, "%c %s\n", X_STDIN, rest);
362 		else
363 			APPCMD(rest);
364 		redir = '\0';
365 		continue;
366 
367 	}
368 	/*
369 	 * clean up trailing ' ' in command.
370 	 */
371 	if (cmdp > cmd && cmdp[0] == '\0' && cmdp[-1] == ' ')
372 		*--cmdp = '\0';
373 	/* block multi-hop uux, which doesn't work */
374 	for (ap = cmd; *ap && *ap != ' '; ap++)
375 		if (*ap == '!') {
376 			fprintf(stderr, "uux handles only adjacent sites.\n");
377 			fprintf(stderr, "Try uusend for multi-hop delivery.\n");
378 			cleanup(1);
379 		}
380 
381 	fprintf(fprx, "%c %s\n", X_CMD, cmd);
382 	logent(cmd, "XQT QUE'D");
383 	fclose(fprx);
384 
385 	gename(XQTPRE, local, Grade, tfile);
386 	if (strcmp(xsys, local) == SAME) {
387 		/* rti!trt: xmv() works across filesystems, link(II) doesnt */
388 		xmv(rxfile, tfile);
389 		if (startjob)
390 			if (rflag)
391 				xuucico(xsys);
392 			else
393 				xuuxqt();
394 	}
395 	else {
396 		GENSEND(fpc, rxfile, tfile, User, "", rxfile);
397 		cflag++;
398 	}
399 
400 	fclose(fpc);
401 	if (cflag) {
402 		gename(CMDPRE, xsys, Grade, cfile);
403 		/* rti!trt: use xmv() rather than link(II) */
404 		xmv(tcfile, cfile);
405 		if (startjob)
406 			xuucico(xsys);
407 		cleanup(0);
408 	}
409 	else
410 		unlink(subfile(tcfile));
411 	exit(0);
412 }
413 
414 #define FTABSIZE 30
415 char Fname[FTABSIZE][NAMESIZE];
416 int Fnamect = 0;
417 
418 /*
419  *	cleanup and unlink if error
420  *
421  *	return - none - do exit()
422  */
423 
424 cleanup(code)
425 int code;
426 {
427 	int i;
428 
429 	logcls();
430 	rmlock(CNULL);
431 	if (code) {
432 		for (i = 0; i < Fnamect; i++)
433 			unlink(subfile(Fname[i]));
434 		fprintf(stderr, "uux failed. code %d\n", code);
435 	}
436 	DEBUG(1, "exit code %d\n", code);
437 	exit(code);
438 }
439 
440 /*
441  *	open file and record name
442  *
443  *	return file pointer.
444  */
445 
446 FILE *ufopen(file, mode)
447 char *file, *mode;
448 {
449 	if (Fnamect < FTABSIZE)
450 		strcpy(Fname[Fnamect++], file);
451 	else
452 		logent("Fname", "TABLE OVERFLOW");
453 	return fopen(subfile(file), mode);
454 }
455 #ifdef	VMS
456 /*
457  * EUNICE bug:
458  *	quotes are not stripped from DCL.  Do it here.
459  *	Note if we are running under Unix shell we don't
460  *	do the right thing.
461  */
462 arg_fix(argc, argv)
463 char **argv;
464 {
465 	register char *cp, *tp;
466 
467 	for (; argc > 0; --argc, argv++) {
468 		cp = *argv;
469 		if (cp == (char *)0 || *cp++ != '"')
470 			continue;
471 		tp = cp;
472 		while (*tp++) ;
473 		tp -= 2;
474 		if (*tp == '"') {
475 			*tp = '\0';
476 			*argv = cp;
477 		}
478 	}
479 }
480 #endif VMS
481