summaryrefslogtreecommitdiffstats
path: root/usr.bin/uucp/uusend/uusend.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/uucp/uusend/uusend.c')
-rw-r--r--usr.bin/uucp/uusend/uusend.c403
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
OpenPOWER on IntegriCloud