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