static char sccsid
[] = "@(#)uusend.c 5.3 (Berkeley) %G%";
* 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
* 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 DEBUG "/usr/spool/uucp/uusend.log"/**/
extern char *index(), *strcpy(), *strcat(), *ctime();
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();
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 */
char *UUPUB
= "/usr/spool/uucppublic/"; /* public UUCP directory */
char *filename
; /* file name from end of destname */
char *getfname(); /* routine to get filename from destname */
char f
[100]; /* name of default output file */
char *f
= ""; /* so we waste a little space */
dout
= fopen(DEBUG
, "a");
printf("Cannot append to %s\n", DEBUG
);
freopen(DEBUG
, "a", stdout
);
fprintf(dout
, "\nuusend run: ");
fprintf(dout
, "%s ", argv
[c
]);
fprintf(dout
, "%s", ctime(&t
));
while (argc
> 1 && argv
[1][0] == '-' && argv
[1][1]) {
sscanf(argv
[2], "%o", &mode
);
mode
&= 0777; /* fix set[ug]id loophole */
case 'r': /* -r flag for uux */
fprintf(stderr
, "Bad flag: %s\n", argv
[1]);
fprintf(stderr
, "Usage: uusend [-m ooo] [-r] -/file sys!sys!..!rfile\n");
if (sourcename
[0] == '-')
fprintf(stderr
, "illegal input\n");
in
= fopen(sourcename
, "r");
if (!fflg
|| f
[2] == '\0') {
strcat(f
, getfname(sourcename
));
excl
= index(destname
, '!');
* destname is on a remote system.
fstat(fileno(in
), &stbuf
);
mode
= stbuf
.st_mode
& 0777;
sprintf(cmdbuf
,"uux -gn -z %s- \"%s!ruusend %s -m %o - (%s)\"",
sprintf(cmdbuf
, "uux -gn -z %s- \"%s!uusend %s -m %o - (%s)\"",
rflg
, nextsys
, f
, mode
, destname
);
fprintf(dout
, "remote: nextsys='%s', destname='%s', cmd='%s'\n", nextsys
, destname
, cmdbuf
);
out
= popen(cmdbuf
, "w");
if (destname
[0] == '~') {
fprintf(dout
, "before ~: '%s'\n", destname
);
sl
= index(destname
, '/');
if (sl
== NULL
&& !fflg
) {
fprintf(stderr
, "Illegal ~user\n");
for (sl
= destname
; *sl
!= '\0'; sl
++)
; /* boy, is this a hack! */
fprintf(stderr
, "Illegal ~user\n");
user
= getpwnam(destname
+1);
fprintf(stderr
, "No such user as %s\n",
if ((filename
=getfname(sl
)) == NULL
&&
strcpy(dnbuf
, user
->pw_dir
);
strcpy(dnbuf
, user
->pw_dir
);
destname
= strcpy(dnbuf
, destname
);
if(strncmp(UULIB
, destname
, strlen(UULIB
)) == 0) {
fprintf(stderr
, "illegal file: %s", destname
);
if (stat(destname
, &stbuf
) == 0 &&
(stbuf
.st_mode
& S_IFMT
) == S_IFDIR
&&
out
= fopen(destname
, "w");
fprintf(dout
, "local, file='%s'\n", destname
);
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
);
strcat(destname
, user
->pw_name
);
if (stat(destname
, &stbuf
) == -1) {
strcat(destname
, filename
);
if ((out
= fopen(destname
, "w")) == NULL
)
exit(5); /* all for naught! */
chmod(destname
, mode
); /* don't bother to check it */
* Now, in any case, copy from in to out.
while ((c
=getc(in
)) != EOF
) {
fprintf(dout
, "count %ld bytes\n", count
);
fclose(out
); /* really should pclose in that case */
* Return the ptr in sp at which the character c appears;
* NULL if not found. Included so I don't have to fight the
switch ((pid
= fork())) {
execl("/bin/mkdir", "mkdir", dirname
, (char *)0);
while ((retcode
=wait(&status
)) != pid
&& retcode
!= -1)