|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)uusend.c 5.2 (Berkeley) 1/22/85";
3: #endif
4:
5: /*
6: * uusend: primitive operation to allow uucp like copy of binary files
7: * but handle indirection over systems.
8: *
9: * usage: uusend [-r] [-m ooo] localfile sysname1!sysname2!...!destfile
10: * uusend [-r] [-m ooo] - sysname1!sysname2!...!destfile
11: *
12: * Author: Mark Horton, May 1980.
13: *
14: * "-r" switch added. Has same effect as "-r" in uux. 11/82 CCW
15: *
16: * Error recovery (a la uucp) added & ifdefs for ruusend (as in rmail).
17: * Checks for illegal access to /usr/lib/uucp.
18: * February 1983 Christopher Woodbury
19: * Fixed mode set[ug]id loophole. 4/8/83 CCW
20: *
21: * Add '-f' to make uusend syntax more similar to UUCP. "destname"
22: * can now be a directory. June 1983 CCW
23: */
24:
25: #include <stdio.h>
26: #include <pwd.h>
27: #include <sys/types.h>
28: #include <sys/stat.h>
29:
30: /*
31: * define RECOVER to permit requests like 'uusend file sys1!sys2!~uucp'
32: * (abbreviation for 'uusend file sys1!sys2!~uucp/file').
33: * define DEBUG to keep log of uusend uusage.
34: * define RUUSEND if neighboring sites permit 'ruusend',
35: * which they certainly should to avoid security holes
36: */
37: #define RECOVER
38: /*#define DEBUG "/usr/spool/uucp/uusend.log"/**/
39:
40: FILE *in, *out;
41: FILE *dout;
42:
43: extern FILE *popen();
44: extern char *index(), *strcpy(), *strcat(), *ctime();
45:
46: #ifdef RUUSEND
47: int rsend;
48: #endif RUUSEND
49: int mode = -1; /* mode to chmod new file to */
50: char *nextsys; /* next system in the chain */
51: char dnbuf[200]; /* buffer for result of ~user/file */
52: char cmdbuf[256]; /* buffer to build uux command in */
53: char *rflg = ""; /* default value of rflg ccw -- 1 Nov '82 */
54:
55: struct passwd *user; /* entry in /etc/passwd for ~user */
56: struct passwd *getpwnam();
57: struct stat stbuf;
58:
59: char *excl; /* location of first ! in destname */
60: char *sl; /* location of first / in destname */
61: char *sourcename; /* argv[1] */
62: char *destname; /* argv[2] */
63: char *UULIB = "/usr/lib/uucp"; /* UUCP lib directory */
64:
65: #ifdef RECOVER
66: char *UUPUB = "/usr/spool/uucppublic/"; /* public UUCP directory */
67: char *filename; /* file name from end of destname */
68: char *getfname(); /* routine to get filename from destname */
69: int fflg;
70: char f[100]; /* name of default output file */
71: #else !RECOVER
72: char *f = ""; /* so we waste a little space */
73: #endif !RECOVER
74:
75: main(argc, argv)
76: int argc;
77: char **argv;
78: {
79: register int c;
80: long count;
81: extern char **environ;
82:
83: #ifdef DEBUG
84: long t;
85: umask(022);
86: dout = fopen(DEBUG, "a");
87: if (dout == NULL) {
88: printf("Cannot append to %s\n", DEBUG);
89: exit(1);
90: }
91: freopen(DEBUG, "a", stdout);
92: fprintf(dout, "\nuusend run: ");
93: for (c=0; c<argc; c++)
94: fprintf(dout, "%s ", argv[c]);
95: time(&t);
96: fprintf(dout, "%s", ctime(&t));
97: #endif DEBUG
98:
99: #ifdef RUUSEND
100: if(argv[0][0] == 'r')
101: rsend++;
102: #endif RUUSEND
103: while (argc > 1 && argv[1][0] == '-' && argv[1][1]) {
104: switch(argv[1][1]) {
105: case 'm':
106: sscanf(argv[2], "%o", &mode);
107: mode &= 0777; /* fix set[ug]id loophole */
108: argc--; argv++;
109: break;
110: case 'r': /* -r flag for uux */
111: rflg = "-r ";
112: break;
113: #ifdef RECOVER
114: case 'f':
115: fflg++;
116: strcpy(f, argv[1]);
117: break;
118: #endif RECOVER
119: default:
120: fprintf(stderr, "Bad flag: %s\n", argv[1]);
121: break;
122: }
123: argc--; argv++;
124: }
125:
126: if (argc != 3) {
127: fprintf(stderr, "Usage: uusend [-m ooo] [-r] -/file sys!sys!..!rfile\n");
128: exit(1);
129: }
130:
131: sourcename = argv[1];
132: destname = argv[2];
133:
134: if (sourcename[0] == '-')
135: in = stdin;
136: else {
137: #ifdef RUUSEND
138: if (rsend) {
139: fprintf(stderr, "illegal input\n");
140: exit(2);
141: }
142: #endif RUUSEND
143: in = fopen(sourcename, "r");
144: if (in == NULL) {
145: perror(argv[1]);
146: exit(2);
147: }
148: if (!fflg || f[2] == '\0') {
149: strcpy(f, "-f");
150: strcat(f, getfname(sourcename));
151: fflg++;
152: }
153: }
154:
155: excl = index(destname, '!');
156: if (excl) {
157: /*
158: * destname is on a remote system.
159: */
160: nextsys = destname;
161: *excl++ = 0;
162: destname = excl;
163: if (mode < 0) {
164: fstat(fileno(in), &stbuf);
165: mode = stbuf.st_mode & 0777;
166: }
167: #ifdef RUUSEND
168: sprintf(cmdbuf,"uux -gn -z %s- \"%s!ruusend %s -m %o - (%s)\"",
169: #else !RUUSEND
170: sprintf(cmdbuf, "uux -gn -z %s- \"%s!uusend %s -m %o - (%s)\"",
171: #endif !RUUSEND
172: rflg, nextsys, f, mode, destname);
173: #ifdef DEBUG
174: fprintf(dout, "remote: nextsys='%s', destname='%s', cmd='%s'\n", nextsys, destname, cmdbuf);
175: #endif DEBUG
176: out = popen(cmdbuf, "w");
177: } else {
178: /*
179: * destname is local.
180: */
181: if (destname[0] == '~') {
182: #ifdef DEBUG
183: fprintf(dout, "before ~: '%s'\n", destname);
184: fflush(dout);
185: #endif DEBUG
186: sl = index(destname, '/');
187: #ifdef RECOVER
188: if (sl == NULL && !fflg) {
189: fprintf(stderr, "Illegal ~user\n");
190: exit(3);
191: }
192: for (sl = destname; *sl != '\0'; sl++)
193: ; /* boy, is this a hack! */
194: #else !RECOVER
195: if (sl == NULL) {
196: fprintf(stderr, "Illegal ~user\n");
197: exit(3);
198: }
199: *sl++ = 0;
200: #endif !RECOVER
201: user = getpwnam(destname+1);
202: if (user == NULL) {
203: fprintf(stderr, "No such user as %s\n",
204: destname);
205: #ifdef RECOVER
206: if ((filename =getfname(sl)) == NULL &&
207: !fflg)
208: exit(4);
209: strcpy(dnbuf, UUPUB);
210: if (fflg)
211: strcat(dnbuf, &f[2]);
212: else
213: strcat(dnbuf, filename);
214: }
215: else {
216: strcpy(dnbuf, user->pw_dir);
217: strcat(dnbuf, "/");
218: strcat(dnbuf, sl);
219: }
220: #else !RECOVER
221: exit(4);
222: }
223: strcpy(dnbuf, user->pw_dir);
224: strcat(dnbuf, "/");
225: strcat(dnbuf, sl);
226: #endif !RECOVER
227: destname = dnbuf;
228: }
229: #ifdef RECOVER
230: else
231: destname = strcpy(dnbuf, destname);
232: #endif !RECOVER
233: if(strncmp(UULIB, destname, strlen(UULIB)) == 0) {
234: fprintf(stderr, "illegal file: %s", destname);
235: exit(4);
236: }
237: #ifdef RECOVER
238: if (stat(destname, &stbuf) == 0 &&
239: (stbuf.st_mode & S_IFMT) == S_IFDIR &&
240: fflg) {
241: strcat(destname, "/");
242: strcat(destname, &f[2]);
243: }
244: #endif RECOVER
245: out = fopen(destname, "w");
246: #ifdef DEBUG
247: fprintf(dout, "local, file='%s'\n", destname);
248: #endif DEBUG
249: if (out == NULL) {
250: perror(destname);
251: #ifdef RECOVER
252: if (strncmp(destname,UUPUB,strlen(UUPUB)) == 0)
253: exit(5); /* forget it! */
254: filename = getfname(destname);
255: if (destname == dnbuf) /* cmdbuf is scratch */
256: filename = strcpy(cmdbuf, filename);
257: destname = strcpy(dnbuf, UUPUB);
258: if (user != NULL) {
259: strcat(destname, user->pw_name);
260: if (stat(destname, &stbuf) == -1) {
261: mkdir(destname, 0777);
262: }
263: strcat(destname, "/");
264: }
265: if (fflg)
266: strcat(destname, &f[2]);
267: else
268: strcat(destname, filename);
269: if ((out = fopen(destname, "w")) == NULL)
270: exit(5); /* all for naught! */
271: #else !RECOVER
272: exit(5);
273: #endif !RECOVER
274: }
275: if (mode > 0)
276: chmod(destname, mode); /* don't bother to check it */
277: }
278:
279: /*
280: * Now, in any case, copy from in to out.
281: */
282:
283: count = 0;
284: while ((c=getc(in)) != EOF) {
285: putc(c, out);
286: count++;
287: }
288: #ifdef DEBUG
289: fprintf(dout, "count %ld bytes\n", count);
290: fclose(dout);
291: #endif DEBUG
292:
293: fclose(in);
294: fclose(out); /* really should pclose in that case */
295: exit(0);
296: }
297:
298: /*
299: * Return the ptr in sp at which the character c appears;
300: * NULL if not found. Included so I don't have to fight the
301: * index/strchr battle.
302: */
303:
304: #define NULL 0
305:
306: char *
307: index(sp, c)
308: register char *sp, c;
309: {
310: do {
311: if (*sp == c)
312: return(sp);
313: } while (*sp++);
314: return(NULL);
315: }
316:
317: #ifdef RECOVER
318: char *
319: getfname(p)
320: register char *p;
321: {
322: register char *s;
323: s = p;
324: while (*p != '\0')
325: p++;
326: if (p == s)
327: return (NULL);
328: for (;p != s; p--)
329: if (*p == '/') {
330: p++;
331: break;
332: }
333: return (p);
334: }
335:
336: #ifndef BSD4_2
337: makedir(dirname, mode)
338: char *dirname;
339: int mode;
340: {
341: register int pid;
342: int retcode, status;
343: switch ((pid = fork())) {
344: case -1: /* error */
345: return (-1);
346: case 0: /* child */
347: umask(0);
348: execl("/bin/mkdir", "mkdir", dirname, (char *)0);
349: exit(1);
350: /* NOTREACHED */
351: default: /* parent */
352: while ((retcode=wait(&status)) != pid && retcode != -1)
353: ;
354: if (retcode == -1)
355: return -1;
356: else {
357: chmod(dirname, mode);
358: return status;
359: }
360: }
361: /* NOTREACHED */
362: }
363: #endif !BSD4_2
364: #endif RECOVER
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.