#include "uucp.h"
#include "log.h"
void notify(), lnotify(), unlinkdf(), arrived();
static void stmesg();
static int nospace();
struct Proto {
char P_id;
int (*P_turnon)();
int (*P_rdmsg)();
int (*P_wrmsg)();
int (*P_rddata)();
int (*P_wrdata)();
int (*P_turnoff)();
};
extern char _Protocol[];
extern char *findProto();
extern char uuxqtarg[];
extern int gturnon(), gturnoff();
extern int grdmsg(), grddata();
extern int gwrmsg(), gwrdata();
extern int wmesg(), rmesg(), expfile(), putinpub(), stptcl();
extern void setline(), TMname(), cleanup(), pfEndfile(), statlog(), mailst();
#ifdef D_PROTOCOL
extern int dturnon(), dturnoff();
extern int drdmsg(), drddata();
extern int dwrmsg(), dwrdata();
#endif
#ifdef X_PROTOCOL
extern int xturnon(), xturnoff();
extern int xrdmsg(), xrddata();
extern int xwrmsg(), xwrdata();
#endif
#ifdef E_PROTOCOL
extern int eturnon(), eturnoff();
extern int erdmsg(), erddata();
extern int ewrmsg(), ewrdata();
extern int trdmsg(), twrmsg();
extern int trddata(), twrdata();
#endif
#ifdef F_PROTOCOL
extern int fturnon(), fturnoff();
extern int frdmsg(), frddata();
extern int fwrmsg(), fwrdata();
#endif
extern int imsg();
extern int omsg();
extern int turnoff();
extern long strtol();
struct Proto Ptbl[]={
{'g', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff},
{'G', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff},
#ifdef E_PROTOCOL
{'e', eturnon, erdmsg, ewrmsg, erddata, ewrdata, eturnoff},
{'t', eturnon, trdmsg, twrmsg, trddata, twrdata, eturnoff},
#endif
#ifdef D_PROTOCOL
{'d', dturnon, drdmsg, dwrmsg, drddata, dwrdata, dturnoff},
#endif
#ifdef X_PROTOCOL
{'x', xturnon, xrdmsg, xwrmsg, xrddata, xwrdata, xturnoff},
#endif
#ifdef F_PROTOCOL
{'f', fturnon, frdmsg, fwrmsg, frddata, fwrdata, fturnoff},
#endif
'\0'
};
#define VALIDSIZE sizeof(Ptbl)/sizeof(struct Proto)
int (*Rdmsg)()=imsg, (*Rddata)();
int (*Wrmsg)()=omsg, (*Wrdata)();
int (*Turnon)(), (*Turnoff)()=turnoff;
#define YES "Y"
#define NO "N"
#define TBUFSIZE 128
#define FLENRADIX (16)
#define EM_MAX 10
#define EM_LOCACC "N1"
#define EM_RMTACC "N2"
#define EM_BADUUCP "N3"
#define EM_NOTMP "N4"
#define EM_RMTCP "N5"
#define EM_LOCCP "N6"
#define EM_SEEK "N7"
#define EM_ULIMIT "N10"
char *Em_msg[] = {
"COPY FAILED (reason not given by remote)",
"local access to file denied",
"remote access to path/file denied",
"system error - bad uucp command generated",
"remote system can't create temp file",
"can't copy to file/directory - file left in PUBDIR/user/file",
"can't copy to file/directory - file left in PUBDIR/user/file",
"can't seek to checkpoint",
"COPY FAILED (reason not given by remote)",
"COPY FAILED (reason not given by remote)",
"file exceeds ulimit of receiving system",
"forwarding error"
};
#define XUUCP 'X'
#define SLTPTCL 'P'
#define USEPTCL 'U'
#define RCVFILE 'R'
#define SNDFILE 'S'
#define RQSTCMPT 'C'
#define HUP 'H'
#define RESET 'X'
#define W_MAX 10
#define W_MIN 7
#define W_TYPE wrkvec[0]
#define W_FILE1 wrkvec[1]
#define W_FILE2 wrkvec[2]
#define W_USER wrkvec[3]
#define W_OPTNS wrkvec[4]
#define W_DFILE wrkvec[5]
#define W_MODE wrkvec[6]
#define W_NUSER wrkvec[7]
#define W_SFILE wrkvec[8]
#define W_RDFILE wrkvec[8]
#define W_POINT wrkvec[9]
#define W_FSIZE wrkvec[9]
#define W_RFILE wrkvec[5]
#define W_XFILE wrkvec[5]
char *mf;
#define RMESG(m, s) if (rmesg(m, s) != 0) {(*Turnoff)(); return(FAIL);}
#define RAMESG(s) if (rmesg('\0', s) != 0) {(*Turnoff)(); return(FAIL);}
#define WMESG(m, s) if(wmesg(m, s) != 0) {(*Turnoff)(); return(FAIL);}
char Wfile[MAXFULLNAME] = {'\0'};
char Dfile[MAXFULLNAME];
char *wrkvec[W_MAX+1];
int statfopt;
static void
Pname(fileid, dfile, direct)
char *fileid;
char *dfile;
int direct;
{
char *p;
if (direct) {
if (p = strrchr(dfile, '/')) {
p++;
strcpy(p, fileid);
*p++ = '.';
*p = 'P';
DEBUG(7, "Point file (direct) =%s\n", dfile);
return;
}
}
strcpy(dfile, RemSpool);
strcat(dfile, "/");
p = dfile + strlen(Dfile);
strcat(dfile, fileid);
*p = 'P';
DEBUG(7, "Point file=%s\n", dfile);
return;
}
int
cntrl()
{
FILE * fp;
struct stat stbuf;
char * p;
long startp;
long actualsize;
long im;
long lfilemode;
mode_t filemode;
int status;
int i, narg;
int mailopt, ntfyopt;
int ret;
char tbuf[TBUFSIZE];
char rqstr[BUFSIZ];
char msg[BUFSIZ];
char filename[MAXFULLNAME], wrktype;
char fsize[NAMESIZE];
char localname[MAXFULLNAME];
char Recspool[MAXFULLNAME];
static pid_t pnum;
extern int uuxqtflag;
pnum = getpid();
Wfile[0] = '\0';
(void) sprintf(Recspool, "%s/%s", SPOOL, Rmtname);
top:
(void) strcpy(User, Uucp);
statfopt = 0;
*Jobid = '\0';
DEBUG(4, "*** TOP *** - Role=%d, ", Role);
setline(RESET);
if (Role == MASTER) {
pfFindFile();
if ((narg = gtwvec(Wfile, wrkvec, W_MAX)) == 0) {
acEnd(COMPLETE);
WMESG(HUP, "");
RMESG(HUP, msg);
goto process;
}
DEBUG(7, "Wfile - %s,", Wfile);
strncpy(Jobid, BASENAME(Wfile, '/')+2, NAMESIZE);
Jobid[NAMESIZE-1] = '\0';
DEBUG(7, "Jobid = %s\n", Jobid);
wrktype = W_TYPE[0];
pfFound(Jobid, W_OPTNS, Nstat.t_qtime);
mailopt = strchr(W_OPTNS, 'm') != NULL;
statfopt = strchr(W_OPTNS, 'o') != NULL;
ntfyopt = strchr(W_OPTNS, 'n') != NULL;
uucpname(localname);
acDojob(Jobid, localname, W_USER);
scRequser(W_USER);
(void) sprintf(User, "%s", W_USER);
if (wrktype == SNDFILE ) {
(void) sprintf(rqstr, "%s!%s --> %s!%s (%s)", Myname,
W_FILE1, Rmtname, W_FILE2, User);
scDest(Rmtname,NOTAVAIL,W_FILE2);
scSrc(Myname,scOwn(W_FILE1),W_FILE1,scMtime(W_FILE1)
,scSize(W_FILE1));
logent(rqstr, "REQUEST");
CDEBUG(1, "Request: %s\n", rqstr);
mf = W_SFILE;
(void) strcpy(filename, W_FILE1);
expfile(filename);
(void) strcpy(Dfile, W_DFILE);
if ( (fp = fopen(Dfile, "r")) == NULL) {
if ( (fp = fopen(filename, "r")) == NULL) {
unlinkdf(Dfile);
lnotify(User, rqstr, "can't access");
(void) sprintf(msg, "CAN'T READ %s %d",
filename, errno);
logent(msg, "FAILED");
CDEBUG(1, "Failed: Can't Read %s\n", filename);
scWrite();
goto top;
} else {
if ( !F_READANY(fileno(fp)) ) {
logent("DENIED", "ACCESS");
unlinkdf(W_DFILE);
lnotify(User, rqstr, "access denied");
CDEBUG(1, "Failed: Access Denied\n%s", "");
scWrite();
goto top;
}
}
}
if (Restart && !(fstat(fileno(fp), &stbuf))) {
(void) sprintf(fsize, "0x%lx", stbuf.st_size);
W_FSIZE = fsize;
}
if (SizeCheck) {
if (((stbuf.st_size-1)/512 + 1) > RemUlimit) {
unlinkdf(Dfile);
lnotify(User, rqstr, "remote ulimit exceeded");
logent("DENIED", "REMOTE ULIMIT EXCEEDED");
CDEBUG(1, "Denied: remote ulimit exceeded %s\n", filename);
scWrite();
(void) fclose(fp);
goto top;
}
}
}
if (wrktype == RCVFILE) {
(void) sprintf(rqstr, "%s!%s --> %s!%s (%s)", Rmtname,
W_FILE1, Myname, W_FILE2, User);
scDest(Myname,NOTAVAIL,W_FILE2);
scSrc(Rmtname,NOTAVAIL,W_FILE1,NOTAVAIL,NOTAVAIL);
logent(rqstr, "REQUEST");
CDEBUG(1, "Request: %s\n", rqstr);
mf = W_RFILE;
(void) strcpy(filename, W_FILE2);
(void) strcpy(Wrkdir, Recspool);
expfile(filename);
(void) strcpy(Wrkdir, RemSpool);
if (chkperm(W_FILE1, filename, strchr(W_OPTNS, 'd'))) {
logent("DENIED", "ACCESS");
lnotify(User, rqstr, "access denied");
CDEBUG(1, "Failed: Access Denied--File: %s\n",
filename);
scWrite();
goto top;
}
if (Restart && (strlen(W_RDFILE) > (size_t) 6)) {
if (noSpool()) {
strcpy(Dfile, filename);
Pname(W_RDFILE, Dfile, TRUE);
}
else
Pname(W_RDFILE, Dfile, FALSE);
}
else {
TMname(Dfile, pnum);
unlink(Dfile);
}
if (Restart && noSpool()) {
if ((! stat(Dfile, &stbuf)) &&
((stbuf.st_mode != (DFILEMODE|S_IFREG)) ||
((stbuf.st_gid != UUCPGID) ||
(stbuf.st_uid != UUCPUID)))) {
lnotify(User, rqstr,
"bad spool file ownership/permissions");
logent("BAD DESTFILE OWNER/PERMS", "FAIL");
CDEBUG(1, "Failed: bad dest file owner/perms 0%o; fail\n", stbuf.st_mode);
goto top;
}
}
if ( ((fp = fopen(Dfile, "a+")) == NULL)
|| nospace(Dfile)) {
if (noSpool())
logent("CAN'T CREATE/OPEN DEST FILE", "FAILED");
else
logent("CAN'T CREATE TM FILE", "FAILED");
CDEBUG(1, "Failed: No Space!\n%s", "");
unlinkdf(Dfile);
assert(Ct_CREATE, Dfile, nospace(Dfile),
__FILE__, __LINE__);
cleanup(FAIL);
}
if (Restart) {
if (fstat (fileno(fp), &stbuf)) {
logent("CAN'T STAT DFILE", "START FROM BEGINNING");
stbuf.st_size = 0L;
}
DEBUG(7, "Dfile length 0x%lx\n", stbuf.st_size);
startp = stbuf.st_size - (stbuf.st_size % BUFSIZ);
if((stbuf.st_size >= 0) && (startp < 0))
startp = 0;
if(startp)
{
if(startp < 0)
sprintf(tbuf,"start=0x%lx", startp);
else
sprintf(tbuf,"start=%ld", startp);
logent(tbuf, "RESTART");
}
sprintf(fsize, "0x%lx", startp);
W_POINT = fsize;
if (lseek(fileno(fp), startp, 0) == -1) {
WMESG(SNDFILE, EM_SEEK);
logent("CAN'T SEEK", "DENIED");
CDEBUG(1, "Failed, Can't seek in Dfile\n%s", "");
unlinkdf(Dfile);
goto top;
}
fp->_cnt = 0;
fp->_ptr = fp->_base;
}
Seqn++;
chmod(Dfile, DFILEMODE);
chown(Dfile, UUCPUID, UUCPGID);
}
DEBUG(4, "wrktype - %c\n ", wrktype);
msg[0] = '\0';
for (i = 1; i < narg; i++) {
(void) strcat(msg, " ");
(void) strcat(msg, wrkvec[i]);
}
WMESG(wrktype, msg);
RMESG(wrktype, msg);
goto process;
}
RAMESG(msg);
process:
DEBUG(4, " PROCESS: msg - %s\n", msg);
switch (msg[0]) {
case RQSTCMPT:
DEBUG(4, "%s\n", "RQSTCMPT:");
if (msg[1] == 'N') {
i = atoi(&msg[2]);
if (i < 0 || i > EM_MAX)
i = 0;
logent(Em_msg[i], "REQUESTED");
}
if (Role == MASTER) {
notify(mailopt, W_USER, rqstr, Rmtname, &msg[1]);
}
pfEndfile("");
goto top;
case HUP:
DEBUG(4, "%s\n", "HUP:");
if (msg[1] == 'Y') {
WMESG(HUP, YES);
(*Turnoff)();
Rdmsg = imsg;
Wrmsg = omsg;
Turnoff = turnoff;
return(0);
}
if (msg[1] == 'N') {
ASSERT(Role == MASTER, Wr_ROLE, "", Role);
Role = SLAVE;
scReqsys(Rmtname);
chremdir(Rmtname);
goto top;
}
if ( (switchRole() == FALSE) || !iswrk(Wfile) ) {
DEBUG(5, "SLAVE-switchRole (%s)\n",
switchRole() ? "TRUE" : "FALSE");
WMESG(HUP, YES);
RMESG(HUP, msg);
goto process;
}
if (uuxqtflag) {
xuuxqt(uuxqtarg);
uuxqtflag = 0;
}
WMESG(HUP, NO);
Role = MASTER;
uucpname(localname);
scReqsys(localname);
acInit("xfer");
goto top;
case XUUCP:
WMESG(XUUCP, NO);
goto top;
case SNDFILE:
DEBUG(4, "%s\n", "SNDFILE:");
if (msg[1] == 'N')
{
i = atoi(&msg[2]);
if (i < 0 || i > EM_MAX)
i = 0;
logent(Em_msg[i], "REQUEST");
notify(mailopt, W_USER, rqstr, Rmtname, &msg[1]);
ASSERT(Role == MASTER, Wr_ROLE, "", Role);
(void) fclose(fp);
ASSERT(i != 4, Em_msg[4], Rmtname, i);
unlinkdf(W_DFILE);
scWrite();
Seqn++;
goto top;
}
if (msg[1] == 'Y') {
ASSERT(Role == MASTER, Wr_ROLE, "", Role);
if (fstat(fileno(fp), &stbuf))
stbuf.st_size = 0;
if (Restart) {
if((startp = strtol(&msg[2], (char **) 0, FLENRADIX))) {
CDEBUG(1, "Restart point=0x%lx\n", startp);
if(startp < 0)
sprintf(tbuf,"start=0x%lx", startp);
else
sprintf(tbuf,"start=%ld", startp);
p = tbuf + strlen(tbuf);
if (stbuf.st_size < 0)
sprintf(p,", length=0x%lx", stbuf.st_size);
else
sprintf(p,", length=%ld", stbuf.st_size);
logent(tbuf, "RESTART");
errno = 0;
if (lseek(fileno(fp), startp, 0) == -1) {
logent(strerror(errno), "FSEEK ERROR");
(void) fclose(fp);
(*Turnoff)();
Seqn++;
return(FAIL);
}
fp->_cnt = 0;
fp->_ptr = fp->_base;
}
}
(void) millitick();
pfStrtXfer(MCHAR, SNDFILE);
scStime();
ret = (*Wrdata)(fp, Ofn);
statlog( "->", getfilesize(), millitick(),
(ret) ? "PARTIAL FILE" : "" );
acInc();
pfEndXfer();
scEtime();
Seqn++;
(void) fclose(fp);
if (ret != 0) {
pfEndfile("PARTIAL FILE");
acEnd(PARTIAL);
(*Turnoff)();
return(FAIL);
}
for (im = stbuf.st_size >> 10; im >= 0; --im) {
if ((ret = rmesg(RQSTCMPT, msg)) == 0)
break;
}
if (ret != 0) {
(*Turnoff)();
return(FAIL);
}
unlinkdf(W_DFILE);
goto process;
}
ASSERT(Role == SLAVE, Wr_ROLE, "", Role);
i = getargs(msg, wrkvec, W_MAX);
scRequser(W_USER);
scDest(Myname,NOTAVAIL,W_FILE2);
scSrc(Rmtname,NOTAVAIL,W_FILE1,NOTAVAIL,NOTAVAIL);
if (i < W_MIN) {
WMESG(SNDFILE, EM_BADUUCP);
logent("DENIED", "TOO FEW ARGS IN SLAVE SNDFILE");
goto top;
}
if (Restart) {
if (W_FSIZE && (*W_FSIZE != '\0')) {
actualsize = strtol(W_FSIZE, (char **) 0, FLENRADIX);
CDEBUG(7, "Actual File Length %ld\n", actualsize);
} else {
actualsize = -1;
CDEBUG(7, "Actual File Length Not Provided\n%s", "");
}
}
mf = W_SFILE;
(void) sprintf(rqstr, "%s!%s --> %s!%s (%s)", Rmtname,
W_FILE1, Myname, W_FILE2, W_USER);
logent(rqstr, "REMOTE REQUESTED");
DEBUG(4, "msg - %s\n", msg);
CDEBUG(1, "Remote Requested: %s\n", rqstr);
(void) strcpy(filename, W_FILE2);
expfile(filename);
DEBUG(4, "SLAVE - filename: %s\n", filename);
if (chkpth(filename, CK_WRITE)
|| chkperm(W_FILE1, filename, strchr(W_OPTNS, 'd'))) {
WMESG(SNDFILE, EM_RMTACC);
logent("DENIED", "PERMISSION");
CDEBUG(1, "Failed: Access Denied\n%s", "");
scWrite();
goto top;
}
(void) sprintf(User, "%s", W_USER);
DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
if (Restart && (strlen(W_DFILE) > (size_t) 6)) {
if (noSpool()) {
strcpy(Dfile, filename);
Pname(W_DFILE, Dfile, TRUE);
if (! Restart)
unlink(Dfile);
}
else
Pname(W_DFILE, Dfile, FALSE);
}
else {
TMname(Dfile, pnum);
unlink(Dfile);
}
if (Restart && noSpool()) {
if ((! stat(Dfile, &stbuf)) &&
((stbuf.st_mode != (DFILEMODE|S_IFREG)) ||
((stbuf.st_gid != UUCPGID) ||
(stbuf.st_uid != UUCPUID)))) {
WMESG(SNDFILE, EM_NOTMP);
logent("BAD DESTFILE OWNER/PERMS", "FAILED");
CDEBUG(1, "Failed: bad dest file owner/perms 0%o\n", stbuf.st_mode);
goto top;
}
}
if ( ((fp = fopen(Dfile, "a+")) == NULL) || nospace(Dfile) ) {
WMESG(SNDFILE, EM_NOTMP);
logent("CAN'T OPEN", "DENIED");
CDEBUG(1, "Failed: Can't Create Temp File\n%s", "");
unlinkdf(Dfile);
goto top;
}
chmod(Dfile, DFILEMODE);
chown(Dfile, UUCPUID, UUCPGID);
if (Restart && (strlen(W_DFILE) > (size_t) 6)) {
if(fstat(fileno(fp), &stbuf)) {
WMESG(SNDFILE, EM_NOTMP);
logent("CAN'T STAT", "DENIED");
CDEBUG(1, "Failed: Can't Stat Temp File\n%s", "");
unlinkdf(Dfile);
Seqn++;
goto top;
}
DEBUG(7, "Dfile length 0x%lx\n", stbuf.st_size);
startp = stbuf.st_size - (stbuf.st_size % BUFSIZ);
if((stbuf.st_size >= 0) && (startp < 0))
startp = 0;
if(startp)
{
if(startp < 0)
sprintf(tbuf,"start=0x%lx", startp);
else
sprintf(tbuf,"start=%ld", startp);
logent(tbuf, "RESTART");
}
sprintf(tbuf, "%s 0x%lx", YES, startp);
if (lseek(fileno(fp), startp, 0) == -1) {
WMESG(SNDFILE, EM_SEEK);
logent("CAN'T SEEK", "DENIED");
CDEBUG(1, "Failed, Can't seek in Dfile\n%s", "");
unlinkdf(Dfile);
Seqn++;
goto top;
}
fp->_cnt = 0;
fp->_ptr = fp->_base;
CDEBUG(1," restart msg %s\n", tbuf);
WMESG(SNDFILE, tbuf);
}
else
WMESG(SNDFILE, YES);
(void) millitick();
pfStrtXfer(SCHAR, RCVFILE);
scStime();
setline(RCVFILE);
ret = (*Rddata)(Ifn, fp);
setline(SNDFILE);
statlog( "<-", getfilesize(), millitick(),
(ret) ? "PARTIAL FILE" : "" );
pfEndXfer();
scEtime();
Seqn++;
if (ret != 0) {
pfEndfile("PARTIAL FILE");
(void) fclose(fp);
if ( ret == EFBIG ) {
WMESG(RQSTCMPT, EM_ULIMIT);
logent("FILE EXCEEDS ULIMIT","FAILED");
CDEBUG(1, "Failed: file size exceeds ulimit%s\n", "");
goto top;
}
(*Turnoff)();
logent("INPUT FAILURE", "IN SEND/SLAVE MODE");
return(FAIL);
}
if (Restart && (actualsize != -1)) {
if (fstat(fileno(fp), &stbuf)) {
(void) fclose(fp);
unlinkdf(Dfile);
(*Turnoff)();
logent("CAN'T STAT PFILE", "FAILED");
return(FAIL);
}
if (stbuf.st_size != actualsize) {
(void) fclose(fp);
unlinkdf(Dfile);
(*Turnoff)();
logent("RECEIVED SIZE NOT EQUAL TO ACTUAL SIZE", "FAILED");
CDEBUG(1, "Failed: receive size %ld ", stbuf.st_size);
CDEBUG(1, "not equal to actual size %ld\n", actualsize);
return(FAIL);
}
}
(void) fclose(fp);
ntfyopt = strchr(W_OPTNS, 'n') != NULL;
ret = 0;
if (p = strrchr(Dfile, '/'))
{
*p = '\0';
ret = PREFIX(Dfile, filename);
*p = '/';
}
if (noSpool() && ret)
{
if(strcmp (filename, Dfile)) {
unlink(filename);
if(link(Dfile, filename))
{
logent("FAILED", "MOVE");
scWrite();
putinpub(filename, Dfile, BASENAME(W_USER,'!'));
}
else
DEBUG(7, "linked Point file to %s\n", filename);
unlink(Dfile);
}
else
DEBUG(7, "Point file and %s the same\n", filename);
status = 0;
}
else
status = xmv(Dfile, filename);
scSize(Dfile);
WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
if (status == 0) {
sscanf(W_MODE, "%lo", &lfilemode);
if (lfilemode <= 0)
filemode = PUB_FILEMODE;
else
filemode = (mode_t)lfilemode;
if (PREFIX(RemSpool, filename))
chmod(filename, DFILEMODE);
else
chmod(filename, (filemode & LEGALMODE) | PUB_FILEMODE);
arrived(ntfyopt, filename, W_NUSER, Rmtname, User);
} else {
logent("FAILED", "COPY");
scWrite();
status = putinpub(filename, Dfile,
BASENAME(W_USER, '!'));
DEBUG(4, "->PUBDIR %d\n", status);
if (status == 0)
arrived(ntfyopt, filename, W_NUSER,
Rmtname, User);
}
pfEndfile("");
if ( W_FILE2[1] == '.' &&
(W_FILE2[0] == XQTPRE || W_FILE2[0] == DATAPRE) )
uuxqtflag = 1;
goto top;
case RCVFILE:
DEBUG(4, "%s\n", "RCVFILE:");
if (msg[1] == 'N') {
i = atoi(&msg[2]);
if (i < 0 || i > EM_MAX)
i = 0;
logent(Em_msg[i], "REQUEST");
notify(mailopt, W_USER, rqstr, Rmtname, &msg[1]);
ASSERT(Role == MASTER, Wr_ROLE, "", Role);
(void) fclose(fp);
unlinkdf(Dfile);
scWrite();
goto top;
}
if (msg[1] == 'Y') {
if (Restart) {
*fsize = '\0';
sscanf(&msg[2], "%*o %s", fsize);
if (*fsize != '\0') {
actualsize = strtol(fsize, (char **) 0, FLENRADIX);
CDEBUG(7, "Actual File Length %ld\n", actualsize);
} else {
actualsize = -1;
CDEBUG(7, "Actual File Length Not Provided\n%s", "");
}
}
ASSERT(Role == MASTER, Wr_ROLE, "", Role);
(void) millitick();
pfStrtXfer(MCHAR, SNDFILE);
scStime();
ret = (*Rddata)(Ifn, fp);
statlog( "<-", getfilesize(), millitick(),
(ret) ? "PARTIAL FILE" : "" );
pfEndXfer();
scEtime();
if (ret != 0) {
pfEndfile("PARTIAL FILE");
(void) fclose(fp);
if ( ret == EFBIG ) {
WMESG(RQSTCMPT, EM_ULIMIT);
logent("FILE EXCEEDS ULIMIT","FAILED");
CDEBUG(1, "Failed: file size exceeds ulimit%s\n", "");
goto top;
}
(*Turnoff)();
logent("INPUT FAILURE", "IN RECEIVE/MASTER MODE");
return(FAIL);
}
if (Restart && (actualsize != -1)) {
if (fstat(fileno(fp), &stbuf)) {
(void) fclose(fp);
unlinkdf(Dfile);
(*Turnoff)();
logent("CAN'T STAT PFILE", "FAILED");
return(FAIL);
}
if (stbuf.st_size != actualsize) {
(void) fclose(fp);
unlinkdf(Dfile);
(*Turnoff)();
logent("RECEIVED SIZE NOT EQUAL TO ACTUAL SIZE", "FAILED");
CDEBUG(1, "Failed: receive size %ld ", stbuf.st_size);
CDEBUG(1, "not equal to actual size %ld\n", actualsize);
return(FAIL);
}
}
(void) fclose(fp);
ret = 0;
if (p = strrchr(Dfile, '/'))
{
*p = '\0';
ret = PREFIX(Dfile, filename);
*p = '/';
}
if (noSpool() && ret)
{
if(strcmp (filename, Dfile)) {
unlink(filename);
if(link(Dfile, filename))
{
logent("FAILED", "MOVE");
scWrite();
putinpub(filename, Dfile, W_USER);
}
else
DEBUG(7, "linked Point file to %s\n", filename);
unlink(Dfile);
}
else
DEBUG(7, "Point file and %s the same\n", filename);
status = 0;
}
else
status = xmv(Dfile, filename);
WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
notify(mailopt, W_USER, rqstr, Rmtname,
status ? EM_LOCCP : YES);
if (status == 0) {
sscanf(&msg[2], "%lo", &lfilemode);
if (lfilemode <= 0)
filemode = PUB_FILEMODE;
else
filemode = (mode_t)lfilemode;
if (PREFIX(RemSpool, filename))
chmod(filename, DFILEMODE);
else
chmod(filename, (filemode & LEGALMODE) | PUB_FILEMODE);
} else {
logent("FAILED", "COPY");
scWrite();
putinpub(filename, Dfile, W_USER);
}
pfEndfile("");
if ( W_FILE2[1] == '.' &&
(W_FILE2[0] == XQTPRE || W_FILE2[0] == DATAPRE) )
uuxqtflag = 1;
goto top;
}
ASSERT(Role == SLAVE, Wr_ROLE, "", Role);
i = getargs(msg, wrkvec, W_MAX);
scRequser(W_USER);
scDest(Rmtname,NOTAVAIL,W_FILE2);
scSrc(Myname,scOwn(W_FILE1),W_FILE1,scMtime(W_FILE1),scSize(W_FILE1));
if (i < 5) {
WMESG(RCVFILE, EM_BADUUCP);
logent("DENIED", "TOO FEW ARGS IN SLAVE RCVFILE");
goto top;
}
(void) sprintf(rqstr, "%s!%s --> %s!%s (%s)", Myname,
W_FILE1, Rmtname, W_FILE2, W_USER);
logent(rqstr, "REMOTE REQUESTED");
CDEBUG(1, "Remote Requested: %s\n", rqstr);
mf = W_RFILE;
DEBUG(4, "msg - %s\n", msg);
DEBUG(4, "W_FILE1 - %s\n", W_FILE1);
(void) strcpy(filename, W_FILE1);
expfile(filename);
if (DIRECTORY(filename)) {
(void) strcat(filename, "/");
(void) strcat(filename, BASENAME(W_FILE2, '/'));
}
(void) sprintf(User, "%s", W_USER);
if (requestOK() == FALSE) {
WMESG(RCVFILE, EM_RMTACC);
logent("DENIED", "REQUESTING");
CDEBUG(1, "Failed: Access Denied\n%s", "");
scWrite();
goto top;
}
DEBUG(4, "requestOK for Loginuser - %s\n", Loginuser);
if ((fp = fopen(filename, "r")) == NULL) {
WMESG(RCVFILE, EM_RMTACC);
logent("CAN'T OPEN", "DENIED");
CDEBUG(1, "Failed: Can't Open %s\n", filename);
scWrite();
goto top;
}
if (chkpth(filename, CK_READ) || !F_READANY(fileno(fp))) {
WMESG(RCVFILE, EM_RMTACC);
logent("DENIED", "PERMISSION");
CDEBUG(1, "Failed: Access Denied\n%s", "");
scWrite();
fclose(fp);
goto top;
}
DEBUG(4, "chkpth ok Loginuser - %s\n", Loginuser);
ASSERT(fstat(fileno(fp), &stbuf) == 0, Ct_STAT,
filename, errno);
if (SizeCheck) {
if (((stbuf.st_size-1)/512 + 1) > RemUlimit) {
WMESG(RCVFILE, EM_ULIMIT);
logent("DENIED", "REMOTE ULIMIT EXCEEDED");
CDEBUG(1, "Denied: remote ulimit exceeded %s\n", filename);
scWrite();
(void) fclose(fp);
goto top;
}
}
if (Restart && i >= 10) {
if (startp = strtol(W_POINT, (char **) 0, FLENRADIX)) {
CDEBUG(1,"Restart point=0x%lx\n", startp);
errno = 0;
if (lseek(fileno(fp), startp, 0) == -1) {
WMESG(RCVFILE, EM_SEEK);
logent(strerror(errno), "FSEEK ERROR");
(void) fclose(fp);
goto top;
}
fp->_cnt = 0;
fp->_ptr = fp->_base;
if(startp < 0)
sprintf(tbuf,"start=0x%lx", startp);
else
sprintf(tbuf,"start=%ld", startp);
p = tbuf + strlen(tbuf);
if (stbuf.st_size < 0)
sprintf(p,", length=0x%lx", stbuf.st_size);
else
sprintf(p,", length=%ld", stbuf.st_size);
logent(tbuf, "RESTART");
}
}
if (Restart)
(void) sprintf(msg, "%s %lo 0x%lx", YES,
(long) (stbuf.st_mode & LEGALMODE),
(long) stbuf.st_size);
else
(void) sprintf(msg, "%s %lo", YES,
(long) (stbuf.st_mode & LEGALMODE));
WMESG(RCVFILE, msg);
Seqn++;
(void) millitick();
scStime();
pfStrtXfer(SCHAR, SNDFILE);
ret = (*Wrdata)(fp, Ofn);
statlog( "->", getfilesize(), millitick(),
(ret) ? "PARTIAL FILE" : "" );
pfEndXfer();
scEtime();
(void) fclose(fp);
if (ret != 0) {
pfEndfile("PARTIAL FILE");
(*Turnoff)();
return(FAIL);
}
for (im = stbuf.st_size >> 10; im >= 0; --im) {
if ((ret = rmesg(RQSTCMPT, msg)) == 0)
break;
}
if (ret != 0) {
(*Turnoff)();
return(FAIL);
}
goto process;
}
(*Turnoff)();
return(FAIL);
}
int
rmesg(c, msg)
char *msg, c;
{
char str[50];
DEBUG(4, "rmesg - '%c' ", c);
if ((*Rdmsg)(msg, Ifn) != 0) {
DEBUG(4, "got %s\n", "FAIL");
(void) sprintf(str, "expected '%c' got FAIL", c);
logent(str, "BAD READ");
return(FAIL);
}
if (c != '\0' && msg[0] != c) {
DEBUG(4, "got %s\n", msg);
(void) sprintf(str, "expected '%c' got %s", c, msg);
logent(str, "BAD READ");
return(FAIL);
}
DEBUG(4, "got %s\n", msg);
return(0);
}
int
wmesg(m, s)
char *s, m;
{
CDEBUG(4, "wmesg '%c'", m);
CDEBUG(4, "%s\n", s);
return((*Wrmsg)(m, s, Ofn));
}
void
notify(int mailopt, char *user, char *msgin, char *sys, char *msgcode)
{
int i;
char str[BUFSIZ];
char *msg;
DEBUG(4,"mailopt %d, ", mailopt);
DEBUG(4,"statfopt %d\n", statfopt);
if (statfopt == 0 && mailopt == 0 && *msgcode == 'Y')
return;
if (*msgcode == 'Y')
msg = "copy succeeded";
else {
i = atoi(msgcode + 1);
if (i < 1 || i > EM_MAX)
i = 0;
msg = Em_msg[i];
}
if(statfopt){
stmesg(msgin, msg);
return;
}
(void) sprintf(str, "REQUEST: %s\n(SYSTEM: %s) %s\n",
msgin, sys, msg);
mailst(user, msg, str, "", "");
return;
}
void
lnotify(user, msgin, mesg)
char *user, *msgin, *mesg;
{
char mbuf[BUFSIZ];
if(statfopt){
stmesg(msgin, mesg);
return;
}
(void) sprintf(mbuf, "REQUEST: %s\n(SYSTEM: %s) %s\n",
msgin, Myname, mesg);
mailst(user, mesg, mbuf, "", "");
return;
}
static void
stmesg(f, m)
char *f, *m;
{
#ifdef notdef
FILE *Cf;
time_t clock;
long td, th, tm, ts;
#endif
char msg[BUFSIZ];
DEBUG(4,"STMES %s\n",mf);
sprintf(msg, "STMESG - %s", mf);
logent("DENIED", msg);
#ifdef notdef
if((Cf = fopen(mf, "a+")) == NULL){
chmod(mf, PUB_FILEMODE);
return;
}
(void) time(&clock);
(void) fprintf(Cf, "uucp job: %s (%s) ", Jobid, timeStamp());
td = clock - Nstat.t_qtime;
ts = td%60;
td /= 60;
tm = td%60;
td /= 60;
th = td;
(void) fprintf(Cf, "(%ld:%ld:%ld)\n%s\n%s\n\n", th, tm, ts, f, m);
(void) fclose(Cf);
chmod(mf, PUB_FILEMODE);
#endif
}
int
startup(void)
{
extern void blptcl();
extern int fptcl();
char msg[BUFSIZ], str[BUFSIZ];
Rdmsg = imsg;
Wrmsg = omsg;
Turnoff = turnoff;
blptcl(str);
if (Role == MASTER) {
RMESG(SLTPTCL, msg);
if ( fptcl(&msg[1], str) == FAIL) {
WMESG(USEPTCL, NO);
return(FAIL);
} else {
WMESG(USEPTCL, &msg[1]);
return(stptcl(&msg[1]));
}
} else {
WMESG(SLTPTCL, str);
RMESG(USEPTCL, msg);
if ( fptcl(&msg[1], str) == FAIL ) {
return(FAIL);
} else {
return(stptcl(&msg[1]));
}
}
}
int
fptcl(str, valid)
char *str, *valid;
{
char *l;
DEBUG(9, "Slave protocol list(%s)\n", str);
DEBUG(9, "Master protocol list(%s)\n", valid);
for (l = valid; *l != '\0'; l++) {
if ( strchr(str, *l) != NULL) {
*str = *l;
*(str+1) = '\0';
strcpy(_Protocol, findProto(_Protocol, *str));
return(SUCCESS);
}
}
return(FAIL);
}
void
blptcl(str)
char *str;
{
struct Proto *p;
char *validPtr;
for (validPtr = str, p = Ptbl; (*validPtr = p->P_id) != NULLCHAR;
validPtr++, p++);
(void) protoString(str);
return;
}
int
stptcl(c)
char *c;
{
struct Proto *p;
for (p = Ptbl; p->P_id != '\0'; p++) {
if (*c == p->P_id) {
Rdmsg = p->P_rdmsg;
Wrmsg = p->P_wrmsg;
Rddata = p->P_rddata;
Wrdata = p->P_wrdata;
Turnon = p->P_turnon;
Turnoff = p->P_turnoff;
if ((*Turnon)() != 0)
break;
CDEBUG(4, "Proto started %c\n", *c);
pfPtcl(c);
return(SUCCESS);
}
}
CDEBUG(4, "Proto start-fail %c\n", *c);
return(FAIL);
}
void
unlinkdf(file)
char *file;
{
if (strlen(file) > (size_t) 6)
(void) unlink(file);
return;
}
void
arrived(int opt, char *file, char *nuser, char *rmtsys, char *rmtuser)
{
char mbuf[200];
if (!opt)
return;
(void) sprintf(mbuf, "%s from %s!%s arrived\n", file, rmtsys, rmtuser);
mailst(nuser, mbuf, mbuf, "", "");
return;
}
#define FREESPACE 50
#define FREENODES 5
static int
nospace(name)
char *name;
#ifdef NOUSTAT
{return(FALSE);}
#else
{
struct stat statb;
#ifdef STATFS
struct statfs statfsb;
#else
struct ustat ustatb;
#endif
if( stat(name, &statb) < 0 )
return(TRUE);
#ifdef RT
if( (statb.st_mode|S_IFMT) == S_IFREG ||
(statb.st_mode|S_IFMT) == S_IFEXT ||
(statb.st_mode&S_IFMT) == S_IF1EXT )
#else
if( (statb.st_mode&S_IFMT) == S_IFREG )
#endif
{
#ifdef STATFS
if( statfs(name, &statfsb)<0 )
#else
if( ustat(statb.st_dev, &ustatb)<0 )
#endif
return(TRUE);
#ifdef STATFS
if( ((statfsb.f_bavail*statfsb.f_bsize)/512) < FREESPACE )
#else
if( ustatb.f_tfree < FREESPACE )
#endif
{
logent("FREESPACE IS LOW","REMOTE TRANSFER DENIED - ");
return(TRUE);
}
#ifdef STATFS
if( statfsb.f_ffree > 0
&& statfsb.f_ffree < FREENODES )
#else
if( ustatb.f_tinode < FREENODES )
#endif
{
logent("TOO FEW INODES","REMOTE TRANSFER DENIED - ");
return(TRUE);
}
}
return(FALSE);
}
#endif
#ifdef V7USTAT
int
ustat(dev, ustat)
int dev;
struct ustat *ustat;
{
FILE *dfp, *popen();
char *fval, buf[BUFSIZ];
sprintf(buf, "%s %d %d 2>&1", V7USTAT, major(dev), minor(dev));
if ((dfp = popen(buf, "r")) == NULL)
return(-1);
fval = fgets(buf, sizeof(buf), dfp);
if (pclose(dfp) != 0
|| fval == NULL
|| sscanf(buf, "%d %d", &ustat->f_tfree, &ustat->f_tinode) != 2)
return(-1);
return(0);
}
#endif