#include "uucp.h"
int Copy = 0;
static int _Transfer = 0;
char Nuser[32];
char *Ropt = " ";
char Optns[10];
char Uopts[BUFSIZ];
char Xopts[BUFSIZ];
char Sgrade[NAMESIZE];
int Mail = 0;
int Notify = 0;
void cleanup(), ruux(), usage();
int eaccess(), guinfo(), vergrd(), gwd(), ckexpf(), uidstat(), uidxcp(),
copy(), gtcfile();
void commitall(), wfabort(), mailst(), gename(), svcfile();
char Sfile[MAXFULLNAME];
int
main(argc, argv, envp)
int argc;
char *argv[];
char **envp;
{
char *jid();
int ret;
int errors = 0;
char *fopt, *sys2p;
char sys1[MAXFULLNAME], sys2[MAXFULLNAME];
char fwd1[MAXFULLNAME], fwd2[MAXFULLNAME];
char file1[MAXFULLNAME], file2[MAXFULLNAME];
short jflag = 0;
extern int split();
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
Uid = getuid();
Euid = geteuid();
if (Uid == 0)
(void) setuid(UUCPUID);
(void) strcpy(Logfile, LOGUUCP);
Env = envp;
fopt = NULL;
(void) strcpy(Progname, "uucp");
Pchar = 'U';
*Uopts = NULLCHAR;
*Xopts = NULLCHAR;
*Sgrade = NULLCHAR;
if (eaccess(GRADES, 0) != -1) {
Grade = 'A';
Sgrades = TRUE;
sprintf(Sgrade, "%s", "default");
}
uucpname(Myname);
Optns[0] = '-';
Optns[1] = 'd';
Optns[2] = 'c';
Optns[3] = Nuser[0] = Sfile[0] = NULLCHAR;
(void) guinfo(Uid, User);
commandlog(argc,argv);
while ((ret = getopt(argc, argv, "Ccdfg:jmn:rs:x:")) != EOF) {
switch (ret) {
case 'C':
Copy = 1;
Optns[2] = 'C';
break;
case 'c':
break;
case 'd':
break;
case 'f':
Optns[1] = 'f';
break;
case 'g':
snprintf(Xopts, sizeof (Xopts), "-g%s", optarg);
if (!Sgrades) {
if (strlen(optarg) < (size_t)2 && isalnum(*optarg))
Grade = *optarg;
else {
(void) fprintf(stderr, gettext("No"
" administrator defined service"
" grades available on this"
" machine.\n"));
(void) fprintf(stderr, gettext("UUCP"
" service grades range from"
" [A-Z][a-z] only.\n"));
cleanup(-1);
}
}
else {
(void) strncpy(Sgrade, optarg, NAMESIZE-1);
Sgrade[NAMESIZE-1] = NULLCHAR;
if (vergrd(Sgrade) != SUCCESS)
cleanup(FAIL);
}
break;
case 'j':
jflag = 1;
break;
case 'm':
Mail = 1;
(void) strcat(Optns, "m");
break;
case 'n':
if (!Notify) {
(void) strlcat(Optns, "n", sizeof (Optns));
Notify = 1;
}
(void) sprintf(Nuser, "%.8s", optarg);
(void) snprintf(Uopts, sizeof (Uopts), "-n%s ", Nuser);
break;
case 'r':
Ropt = "-r";
break;
case 's':
fopt = optarg;
(void) strcat(Optns, "mo");
break;
case 'x':
Debug = atoi(optarg);
if (Debug <= 0)
Debug = 1;
#ifdef SMALL
fprintf(stderr, gettext("WARNING: uucp built with SMALL"
" flag defined -- no debug info available\n"));
#endif
break;
default:
usage();
break;
}
}
DEBUG(4, "\n\n** %s **\n", "START");
gwd(Wrkdir);
if (fopt) {
if (*fopt != '/')
(void) snprintf(Sfile, MAXFULLNAME, "%s/%s",
Wrkdir, fopt);
else
(void) snprintf(Sfile, MAXFULLNAME, "%s", fopt);
}
else
if (strlcpy(Sfile, "dummy", sizeof (Sfile)) >= sizeof (Sfile))
return (2);
ret = chdir(WORKSPACE);
if (ret != 0) {
(void) fprintf(stderr, gettext("No work directory - %s -"
" get help\n"), WORKSPACE);
cleanup(-12);
}
if (Nuser[0] == NULLCHAR)
(void) strcpy(Nuser, User);
(void) strcpy(Loginuser, User);
DEBUG(4, "UID %ld, ", (long) Uid);
DEBUG(4, "User %s\n", User);
if (argc - optind < 2) {
usage();
}
(void) split(argv[argc - 1], sys2, fwd2, file2);
if (*sys2 != NULLCHAR) {
(void) strncpy(Rmtname, sys2, MAXBASENAME);
Rmtname[MAXBASENAME] = NULLCHAR;
(void) mchFind(Rmtname);
myName(Myname);
if (versys(sys2) != 0) {
(void) fprintf(stderr,
gettext("bad system: %s\n"), sys2);
cleanup(-EX_NOHOST);
}
}
DEBUG(9, "sys2: %s, ", sys2);
DEBUG(9, "fwd2: %s, ", fwd2);
DEBUG(9, "file2: %s\n", file2);
if (argc - optind > 2)
(void) strcat(file2, "/");
for ( ; optind < argc - 1; optind++) {
(void) split(argv[optind], sys1, fwd1, file1);
if (*sys1 != NULLCHAR) {
if (versys(sys1) != 0) {
(void) fprintf(stderr,
gettext("bad system: %s\n"), sys1);
cleanup(-EX_NOHOST);
}
}
if (*fwd1 != NULLCHAR) {
(void) fprintf(stderr,
gettext("illegal syntax %s\n"), argv[optind]);
exit(2);
}
if (*sys1 != NULLCHAR)
if ((strchr(file1, '*') != NULL
|| strchr(file1, '?') != NULL
|| strchr(file1, '[') != NULL)) {
if (ckexpf(file1) == FAIL)
exit(6);
(void) strncpy(Rmtname, sys1, MAXBASENAME);
Rmtname[MAXBASENAME] = NULLCHAR;
(void) mchFind(Rmtname);
myName(Myname);
if (*sys2 == NULLCHAR)
sys2p = Myname;
ruux(sys1, sys1, file1, sys2p, fwd2, file2);
continue;
}
if (*fwd2 != NULLCHAR) {
ruux(sys2, sys1, file1, "", fwd2, file2);
continue;
}
if (*sys1 != NULLCHAR )
if ( (!EQUALS(Myname, sys1))
&& *sys2 != NULLCHAR
&& (!EQUALS(sys2, Myname)) ) {
ruux(sys2, sys1, file1, "", fwd2, file2);
continue;
}
sys2p = sys2;
if (*sys1 == NULLCHAR) {
if (*sys2 == NULLCHAR)
sys2p = Myname;
(void) strcpy(sys1, Myname);
} else {
(void) strncpy(Rmtname, sys1, MAXBASENAME);
Rmtname[MAXBASENAME] = NULLCHAR;
(void) mchFind(Rmtname);
myName(Myname);
if (*sys2 == NULLCHAR)
sys2p = Myname;
}
DEBUG(4, "sys1 - %s, ", sys1);
DEBUG(4, "file1 - %s, ", file1);
DEBUG(4, "Rmtname - %s\n", Rmtname);
if (copy(sys1, file1, sys2p, file2))
errors++;
}
commitall();
while (wait(NULL) != -1)
;
if (*Ropt != '-') {
#ifndef V7
long limit;
char msg[100];
limit = ulimit(1, (long) 0);
if (limit < MINULIMIT) {
(void) sprintf(msg,
"ULIMIT (%ld) < MINULIMIT (%ld)", limit, MINULIMIT);
logent(msg, "Low-ULIMIT");
}
else
#endif
xuucico(Rmtname);
}
if (jflag) {
(void) strncpy(Jobid, jid(), NAMESIZE);
printf("%s\n", Jobid);
}
cleanup(errors);
return (0);
}
void
cleanup(code)
int code;
{
static int first = 1;
if (first) {
first = 0;
rmlock(CNULL);
if (code != 0)
wfabort();
}
if (code < 0) {
(void) fprintf(stderr,
gettext("uucp failed completely (%d)\n"), (-code));
exit(-code);
}
else if (code > 0) {
(void) fprintf(stderr, gettext(
"uucp failed partially: %d file(s) sent; %d error(s)\n"),
_Transfer, code);
exit(code);
}
exit(code);
}
static FILE *syscfile();
int
copy(s1, f1, s2, f2)
char *s1, *f1, *s2, *f2;
{
FILE *cfp;
struct stat stbuf, stbuf1;
int type, statret;
char dfile[NAMESIZE];
char cfile[NAMESIZE];
char command[10+(2*MAXFULLNAME)];
char file1[MAXFULLNAME], file2[MAXFULLNAME];
char msg[BUFSIZ];
type = 0;
(void) strcpy(file1, f1);
(void) strcpy(file2, f2);
if (!EQUALS(s1, Myname))
type = 1;
if (!EQUALS(s2, Myname))
type = 2;
DEBUG(4, "copy: file1=<%s> ", file1);
DEBUG(4, "file2=<%s>\n", file2);
switch (type) {
case 0:
DEBUG(4, "all work here %d\n", type);
if (ckexpf(file1))
return(-6);
if (ckexpf(file2))
return(-7);
setuid(Uid);
if (chkperm(file1, file2, strchr(Optns, 'd')) &&
(access(file2, W_OK) == -1)) {
(void) fprintf(stderr, gettext("permission denied\n"));
cleanup(1);
}
DEBUG(2, "local copy: %s -> ", file1);
DEBUG(2, "%s\n", file2);
sprintf(command, "cp %s %s", file1, file2);
if ((cfp = popen(command, "r")) == NULL) {
perror("popen");
DEBUG(5, "popen failed - errno %d\n", errno);
setuid(Euid);
return (FAIL);
}
if (pclose(cfp) != 0) {
DEBUG(5, "Copy failed - errno %d\n", errno);
return (FAIL);
}
setuid(Euid);
if ( Mail ) {
sprintf(msg,
"REQUEST: %s!%s --> %s!%s (%s)\n(SYSTEM %s) copy succeeded\n",
s1, file1, s2, file2, User, s2 );
mailst(User, "copy succeeded", msg, "", "");
}
if ( Notify ) {
sprintf(msg, "%s from %s!%s arrived\n",
file2, s1, User );
mailst(Nuser, msg, msg, "", "");
}
return(0);
case 1:
DEBUG(4, "receive file - %d\n", type);
if (file1[0] != '~')
if (ckexpf(file1))
return(6);
if (ckexpf(file2))
return(7);
gename(DATAPRE, s2, Grade, dfile);
cfp = syscfile(cfile, s1);
(void) fprintf(cfp,
"R %s %s %s %s %s %o %s %s\n", file1, file2,
User, Optns,
*Sfile ? Sfile : "dummy",
0777, Nuser, dfile);
(void) fclose(cfp);
(void) sprintf(msg, "%s!%s --> %s!%s", Rmtname, file1,
Myname, file2);
logent(msg, "QUEUED");
break;
case 2:
if (ckexpf(file1))
return(6);
DEBUG(4, "Workdir = <%s>\n", Wrkdir);
if (file2[0] != '~' && !EQUALS(Wrkdir, XQTDIR))
if (ckexpf(file2))
return(7);
DEBUG(4, "send file - %d\n", type);
if (uidstat(file1, &stbuf) != 0) {
(void) fprintf(stderr,
gettext("can't get status for file %s\n"), file1);
return(8);
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
(void) fprintf(stderr,
gettext("directory name illegal - %s\n"), file1);
return(9);
}
if (access(file1, R_OK) != 0) {
(void) fprintf(stderr,
gettext("uucp can't read (%s) mode (%o)\n"),
file1, stbuf.st_mode&0777);
return(3);
}
gename(DATAPRE, s2, Grade, dfile);
if (Copy || !READANY(file1) ) {
if (uidxcp(file1, dfile))
return(5);
(void) chmod(dfile, DFILEMODE);
}
cfp = syscfile(cfile, s2);
(void) fprintf(cfp, "S %s %s %s %s %s %lo %s %s\n",
file1, file2, User, Optns, dfile,
(long) stbuf.st_mode & LEGALMODE, Nuser, Sfile);
(void) fclose(cfp);
(void) sprintf(msg, "%s!%s --> %s!%s", Myname, file1,
Rmtname, file2);
logent(msg, "QUEUED");
break;
}
_Transfer++;
return(0);
}
static FILE *
syscfile(file, sys)
char *file, *sys;
{
FILE *cfp;
if (gtcfile(file, sys) == FAIL) {
gename(CMDPRE, sys, Grade, file);
ASSERT(access(file, 0) != 0, Fl_EXISTS, file, errno);
cfp = fdopen(creat(file, CFILEMODE), "w");
svcfile(file, sys, Sgrade);
} else
cfp = fopen(file, "a");
ASSERT(cfp != NULL, Ct_OPEN, file, errno);
return(cfp);
}
void
ruux(rmt, sys1, file1, sys2, fwd2, file2)
char *rmt, *sys1, *file1, *sys2, *fwd2, *file2;
{
char cmd[BUFSIZ];
char xcmd[BUFSIZ];
char * xarg[6];
int narg = 0;
int i;
(void) mchFind(rmt);
myName(Myname);
xarg[narg++] = UUX;
xarg[narg++] = "-C";
if (*Xopts != NULLCHAR)
xarg[narg++] = Xopts;
if (*Ropt != ' ')
xarg[narg++] = Ropt;
(void) sprintf(cmd, "%s!uucp -C", rmt);
if (*Uopts != NULLCHAR)
(void) sprintf(cmd+strlen(cmd), " (%s) ", Uopts);
if (*sys1 == NULLCHAR || EQUALS(sys1, Myname)) {
if (ckexpf(file1))
exit(6);
(void) sprintf(cmd+strlen(cmd), " %s!%s ", sys1, file1);
}
else
if (!EQUALS(rmt, sys1))
(void) sprintf(cmd+strlen(cmd), " (%s!%s) ", sys1, file1);
else
(void) sprintf(cmd+strlen(cmd), " (%s) ", file1);
if (*fwd2 != NULLCHAR) {
if (*sys2 != NULLCHAR)
(void) sprintf(cmd+strlen(cmd),
" (%s!%s!%s) ", sys2, fwd2, file2);
else
(void) sprintf(cmd+strlen(cmd), " (%s!%s) ", fwd2, file2);
}
else {
if (*sys2 == NULLCHAR || EQUALS(sys2, Myname))
if (ckexpf(file2))
exit(7);
(void) sprintf(cmd+strlen(cmd), " (%s!%s) ", sys2, file2);
}
xarg[narg++] = cmd;
xarg[narg] = (char *) 0;
xcmd[0] = NULLCHAR;
for (i=0; i < narg; i++) {
strcat(xcmd, xarg[i]);
strcat(xcmd, " ");
}
DEBUG(2, "cmd: %s\n", xcmd);
logent(xcmd, "QUEUED");
if (fork() == 0) {
ASSERT(setuid(getuid()) == 0, "setuid", "failed", 99);
execv(UUX, xarg);
exit(0);
}
return;
}
void
usage()
{
(void) fprintf(stderr, gettext(
"Usage: %s [-c|-C] [-d|-f] [-g GRADE] [-jm] [-n USER]\\\n"
"[-r] [-s FILE] [-x DEBUG_LEVEL] source-files destination-file\n"),
Progname);
cleanup(-2);
}