diff options
Diffstat (limited to 'usr.bin/uucp/uusend/uusend.c')
-rw-r--r-- | usr.bin/uucp/uusend/uusend.c | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/usr.bin/uucp/uusend/uusend.c b/usr.bin/uucp/uusend/uusend.c new file mode 100644 index 0000000..207108e --- /dev/null +++ b/usr.bin/uucp/uusend/uusend.c @@ -0,0 +1,403 @@ +/*- + * Copyright (c) 1980, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1980, 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)uusend.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * uusend: primitive operation to allow uucp like copy of binary files + * but handle indirection over systems. + * + * usage: uusend [-r] [-m ooo] localfile sysname1!sysname2!...!destfile + * uusend [-r] [-m ooo] - sysname1!sysname2!...!destfile + * + * Author: Mark Horton, May 1980. + * + * "-r" switch added. Has same effect as "-r" in uux. 11/82 CCW + * + * Error recovery (a la uucp) added & ifdefs for ruusend (as in rmail). + * Checks for illegal access to /usr/lib/uucp. + * February 1983 Christopher Woodbury + * Fixed mode set[ug]id loophole. 4/8/83 CCW + * + * Add '-f' to make uusend syntax more similar to UUCP. "destname" + * can now be a directory. June 1983 CCW + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <pwd.h> + +/* + * define RECOVER to permit requests like 'uusend file sys1!sys2!~uucp' + * (abbreviation for 'uusend file sys1!sys2!~uucp/file'). + * define DEBUG to keep log of uusend uusage. + * define RUUSEND if neighboring sites permit 'ruusend', + * which they certainly should to avoid security holes + */ +#define RECOVER +/*#define DEBUG "/usr/spool/uucp/uusend.log"/**/ + +FILE *in, *out; +FILE *dout; + +extern FILE *popen(); +extern char *index(), *strcpy(), *strcat(), *ctime(); + +#ifdef RUUSEND +int rsend; +#endif RUUSEND +int mode = -1; /* mode to chmod new file to */ +char *nextsys; /* next system in the chain */ +char dnbuf[200]; /* buffer for result of ~user/file */ +char cmdbuf[256]; /* buffer to build uux command in */ +char *rflg = ""; /* default value of rflg ccw -- 1 Nov '82 */ + +struct passwd *user; /* entry in /etc/passwd for ~user */ +struct passwd *getpwnam(); +struct stat stbuf; + +char *excl; /* location of first ! in destname */ +char *sl; /* location of first / in destname */ +char *sourcename; /* argv[1] */ +char *destname; /* argv[2] */ +char *UULIB = "/usr/lib/uucp"; /* UUCP lib directory */ + +#ifdef RECOVER +char *UUPUB = "/usr/spool/uucppublic/"; /* public UUCP directory */ +char *filename; /* file name from end of destname */ +char *getfname(); /* routine to get filename from destname */ +int fflg; +char f[100]; /* name of default output file */ +#else !RECOVER +char *f = ""; /* so we waste a little space */ +#endif !RECOVER + +main(argc, argv) +int argc; +char **argv; +{ + register int c; + long count; + extern char **environ; + +#ifdef DEBUG + long t; + umask(022); + dout = fopen(DEBUG, "a"); + if (dout == NULL) { + printf("Cannot append to %s\n", DEBUG); + exit(1); + } + freopen(DEBUG, "a", stdout); + fprintf(dout, "\nuusend run: "); + for (c=0; c<argc; c++) + fprintf(dout, "%s ", argv[c]); + time(&t); + fprintf(dout, "%s", ctime(&t)); +#endif DEBUG + +#ifdef RUUSEND + if(argv[0][0] == 'r') + rsend++; +#endif RUUSEND + while (argc > 1 && argv[1][0] == '-' && argv[1][1]) { + switch(argv[1][1]) { + case 'm': + sscanf(argv[2], "%o", &mode); + mode &= 0777; /* fix set[ug]id loophole */ + argc--; argv++; + break; + case 'r': /* -r flag for uux */ + rflg = "-r "; + break; +#ifdef RECOVER + case 'f': + fflg++; + strcpy(f, argv[1]); + break; +#endif RECOVER + default: + fprintf(stderr, "Bad flag: %s\n", argv[1]); + break; + } + argc--; argv++; + } + + if (argc != 3) { + fprintf(stderr, "Usage: uusend [-m ooo] [-r] -/file sys!sys!..!rfile\n"); + exit(1); + } + + sourcename = argv[1]; + destname = argv[2]; + + if (sourcename[0] == '-') + in = stdin; + else { +#ifdef RUUSEND + if (rsend) { + fprintf(stderr, "illegal input\n"); + exit(2); + } +#endif RUUSEND + in = fopen(sourcename, "r"); + if (in == NULL) { + perror(argv[1]); + exit(2); + } + if (!fflg || f[2] == '\0') { + strcpy(f, "-f"); + strcat(f, getfname(sourcename)); + fflg++; + } + } + + excl = index(destname, '!'); + if (excl) { + /* + * destname is on a remote system. + */ + nextsys = destname; + *excl++ = 0; + destname = excl; + if (mode < 0) { + fstat(fileno(in), &stbuf); + mode = stbuf.st_mode & 0777; + } +#ifdef RUUSEND + sprintf(cmdbuf,"uux -gn -z %s- \"%s!ruusend %s -m %o - (%s)\"", +#else !RUUSEND + sprintf(cmdbuf, "uux -gn -z %s- \"%s!uusend %s -m %o - (%s)\"", +#endif !RUUSEND + rflg, nextsys, f, mode, destname); +#ifdef DEBUG + fprintf(dout, "remote: nextsys='%s', destname='%s', cmd='%s'\n", nextsys, destname, cmdbuf); +#endif DEBUG + out = popen(cmdbuf, "w"); + } else { + /* + * destname is local. + */ + if (destname[0] == '~') { +#ifdef DEBUG + fprintf(dout, "before ~: '%s'\n", destname); +fflush(dout); +#endif DEBUG + sl = index(destname, '/'); +#ifdef RECOVER + if (sl == NULL && !fflg) { + fprintf(stderr, "Illegal ~user\n"); + exit(3); + } + for (sl = destname; *sl != '\0'; sl++) + ; /* boy, is this a hack! */ +#else !RECOVER + if (sl == NULL) { + fprintf(stderr, "Illegal ~user\n"); + exit(3); + } + *sl++ = 0; +#endif !RECOVER + user = getpwnam(destname+1); + if (user == NULL) { + fprintf(stderr, "No such user as %s\n", + destname); +#ifdef RECOVER + if ((filename =getfname(sl)) == NULL && + !fflg) + exit(4); + strcpy(dnbuf, UUPUB); + if (fflg) + strcat(dnbuf, &f[2]); + else + strcat(dnbuf, filename); + } + else { + strcpy(dnbuf, user->pw_dir); + strcat(dnbuf, "/"); + strcat(dnbuf, sl); + } +#else !RECOVER + exit(4); + } + strcpy(dnbuf, user->pw_dir); + strcat(dnbuf, "/"); + strcat(dnbuf, sl); +#endif !RECOVER + destname = dnbuf; + } +#ifdef RECOVER + else + destname = strcpy(dnbuf, destname); +#endif !RECOVER + if(strncmp(UULIB, destname, strlen(UULIB)) == 0) { + fprintf(stderr, "illegal file: %s", destname); + exit(4); + } +#ifdef RECOVER + if (stat(destname, &stbuf) == 0 && + (stbuf.st_mode & S_IFMT) == S_IFDIR && + fflg) { + strcat(destname, "/"); + strcat(destname, &f[2]); + } +#endif RECOVER + out = fopen(destname, "w"); +#ifdef DEBUG + fprintf(dout, "local, file='%s'\n", destname); +#endif DEBUG + if (out == NULL) { + perror(destname); +#ifdef RECOVER + if (strncmp(destname,UUPUB,strlen(UUPUB)) == 0) + exit(5); /* forget it! */ + filename = getfname(destname); + if (destname == dnbuf) /* cmdbuf is scratch */ + filename = strcpy(cmdbuf, filename); + destname = strcpy(dnbuf, UUPUB); + if (user != NULL) { + strcat(destname, user->pw_name); + if (stat(destname, &stbuf) == -1) { + mkdir(destname, 0777); + } + strcat(destname, "/"); + } + if (fflg) + strcat(destname, &f[2]); + else + strcat(destname, filename); + if ((out = fopen(destname, "w")) == NULL) + exit(5); /* all for naught! */ +#else !RECOVER + exit(5); +#endif !RECOVER + } + if (mode > 0) + chmod(destname, mode); /* don't bother to check it */ + } + + /* + * Now, in any case, copy from in to out. + */ + + count = 0; + while ((c=getc(in)) != EOF) { + putc(c, out); + count++; + } +#ifdef DEBUG + fprintf(dout, "count %ld bytes\n", count); + fclose(dout); +#endif DEBUG + + fclose(in); + fclose(out); /* really should pclose in that case */ + exit(0); +} + +/* + * Return the ptr in sp at which the character c appears; + * NULL if not found. Included so I don't have to fight the + * index/strchr battle. + */ + +#define NULL 0 + +char * +index(sp, c) +register char *sp, c; +{ + do { + if (*sp == c) + return(sp); + } while (*sp++); + return(NULL); +} + +#ifdef RECOVER +char * +getfname(p) +register char *p; +{ + register char *s; + s = p; + while (*p != '\0') + p++; + if (p == s) + return (NULL); + for (;p != s; p--) + if (*p == '/') { + p++; + break; + } + return (p); +} + +#ifndef BSD4_2 +makedir(dirname, mode) +char *dirname; +int mode; +{ + register int pid; + int retcode, status; + switch ((pid = fork())) { + case -1: /* error */ + return (-1); + case 0: /* child */ + umask(0); + execl("/bin/mkdir", "mkdir", dirname, (char *)0); + exit(1); + /* NOTREACHED */ + default: /* parent */ + while ((retcode=wait(&status)) != pid && retcode != -1) + ; + if (retcode == -1) + return -1; + else { + chmod(dirname, mode); + return status; + } + } + /* NOTREACHED */ +} +#endif !BSD4_2 +#endif RECOVER |