921 lines
21 KiB
C
921 lines
21 KiB
C
#include "uucp.h"
|
|
#include <sys/stat.h>
|
|
#include <strings.h>
|
|
#include <sys/wait.h>
|
|
#include <errno.h>
|
|
#include "uust.h"
|
|
|
|
extern int turntime;
|
|
int willturn;
|
|
int HaveSentHup = 0;
|
|
|
|
static int nullf(void);
|
|
|
|
struct Proto {
|
|
char P_id;
|
|
int (*P_turnon)(void);
|
|
int (*P_rdmsg)(char *amsg, int fn);
|
|
int (*P_wrmsg)(char type, char *msg, int fn);
|
|
int (*P_rddata)(int fn, FILE *fp);
|
|
int (*P_wrdata)(FILE *fp, int fn);
|
|
int (*P_turnoff)(void);
|
|
};
|
|
|
|
struct Proto Ptbl[] = {
|
|
#ifdef TCPIP
|
|
't', nullf, trdmsg, twrmsg, trddata, twrdata, nullf,
|
|
#endif
|
|
#ifdef PAD
|
|
'f', fturnon, frdmsg, fwrmsg, frddata, fwrdata, fturnoff,
|
|
#endif
|
|
'g', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff,
|
|
'\0'
|
|
};
|
|
|
|
int (*Imsg)(char *amsg, int fn) = imsg;
|
|
int (*Omsg)(char type, char *msg, int fn) = omsg;
|
|
|
|
int (*Rdmsg)(char *amsg, int fn) = imsg;
|
|
int (*Rddata)(int fn, FILE *fp);
|
|
int (*Wrmsg)(char type, char *msg, int fn) = omsg;
|
|
int (*Wrdata)(FILE *fp, int fn);
|
|
int (*Turnon)(void) = nullf;
|
|
int (*Turnoff)(void) = nullf;
|
|
|
|
struct timeval Now, LastTurned, LastCheckedNoLogin;
|
|
|
|
static char *YES = "Y";
|
|
static char *NO = "N";
|
|
|
|
int TransferSucceeded = 1;
|
|
|
|
/* failure messages */
|
|
#define EM_MAX 6
|
|
#define EM_LOCACC "N1" /* local access to file denied */
|
|
#define EM_RMTACC "N2" /* remote access to file/path denied */
|
|
#define EM_BADUUCP "N3" /* a bad uucp command was generated */
|
|
#define EM_NOTMP "N4" /* remote error - can't create temp */
|
|
#define EM_RMTCP "N5" /* can't copy to remote directory - file in public */
|
|
#define EM_LOCCP "N6" /* can't copy on local system */
|
|
|
|
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 on local system - file left in PUBDIR/user/file"
|
|
};
|
|
|
|
#define XUUCP 'X' /* execute uucp (string) */
|
|
#define SLTPTCL 'P' /* select protocol (string) */
|
|
#define USEPTCL 'U' /* use protocol (character) */
|
|
#define RCVFILE 'R' /* receive file (string) */
|
|
#define SNDFILE 'S' /* send file (string) */
|
|
#define RQSTCMPT 'C' /* request complete (string - yes | no) */
|
|
#define HUP 'H' /* ready to hangup (string - yes | no) */
|
|
#define RESET 'X' /* reset line modes */
|
|
|
|
#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 XFRRATE 35000L
|
|
#define RMESG(m, s, n) if (rmesg(m, s, n) != 0) {(*Turnoff)(); return FAIL;} else
|
|
#define RAMESG(s, n) if (rmesg('\0', s, n) != 0) {(*Turnoff)(); return FAIL;} else
|
|
#define WMESG(m, s) if(wmesg(m, s) != 0) {(*Turnoff)(); return FAIL;} else
|
|
|
|
char Wfile[MAXFULLNAME] = {'\0'};
|
|
char Dfile[MAXFULLNAME];
|
|
|
|
/*
|
|
* To avoid a huge backlog of X. files, start uuxqt every so often.
|
|
*/
|
|
static int nXfiles = 0; /* number of X files since last uuxqt start */
|
|
static char send_or_receive;
|
|
struct stat stbuf;
|
|
|
|
static int wmesg(char m, char *s);
|
|
static int rmesg(char c, char *msg, int n);
|
|
static void unlinkdf(char *file);
|
|
static void lnotify(char *user, char *file, char *mesg);
|
|
static void notify(int mailopt, char *user, char *file, char *sys, char *msgcode);
|
|
static void arrived(int opt, char *file, char *nuser, char *rmtsys, char *rmtuser);
|
|
static int putinpub(char *file, char *tmp, char *user);
|
|
static char fptcl(char *str);
|
|
static int stptcl(char *c);
|
|
static char *blptcl(char *str);
|
|
|
|
/*
|
|
* cntrl - this routine will execute the conversation
|
|
* between the two machines after both programs are
|
|
* running.
|
|
*
|
|
* return codes
|
|
* SUCCESS - ok
|
|
* FAIL - failed
|
|
*/
|
|
int cntrl(role, wkpre)
|
|
int role;
|
|
char *wkpre;
|
|
{
|
|
char msg[BUFSIZ], rqstr[BUFSIZ];
|
|
register FILE *fp;
|
|
int filemode;
|
|
char filename[MAXFULLNAME], wrktype, *wrkvec[20];
|
|
int status = 1;
|
|
register int i, narg;
|
|
int mailopt, ntfyopt;
|
|
int ret;
|
|
static int pnum, tmpnum = 0;
|
|
extern int ReverseRole;
|
|
|
|
pnum = getpid();
|
|
Wfile[0] = '\0';
|
|
willturn = turntime > 0;
|
|
remaster:
|
|
gettimeofday(&LastTurned, NULL);
|
|
|
|
send_or_receive = RESET;
|
|
HaveSentHup = 0;
|
|
top:
|
|
for (i = 0; i < sizeof wrkvec / sizeof wrkvec[0]; i++)
|
|
wrkvec[i] = 0;
|
|
DEBUG(4, "*** TOP *** - role=%s\n", role ? "MASTER" : "SLAVE");
|
|
setupline(RESET);
|
|
if (Now.tv_sec > (LastCheckedNoLogin.tv_sec+60)) {
|
|
LastCheckedNoLogin = Now;
|
|
if (access(NOLOGIN, 0) == 0) {
|
|
logent(NOLOGIN, "UUCICO SHUTDOWN");
|
|
if (Debug > 4)
|
|
logent("DEBUGGING", "continuing anyway");
|
|
else {
|
|
WMESG(HUP, YES);
|
|
RMESG(HUP, msg, 1);
|
|
goto process;
|
|
}
|
|
}
|
|
}
|
|
if (role == MASTER) {
|
|
/* get work */
|
|
if (ReverseRole || (narg = gtwvec(Wfile, Spool, wkpre, wrkvec)) == 0) {
|
|
ReverseRole = 0;
|
|
WMESG(HUP, "");
|
|
RMESG(HUP, msg, 1);
|
|
goto process;
|
|
}
|
|
wrktype = W_TYPE[0];
|
|
|
|
msg[0] = '\0';
|
|
for (i = 1; i < narg; i++) {
|
|
strcat(msg, " ");
|
|
strcat(msg, wrkvec[i]);
|
|
}
|
|
|
|
if (wrktype == XUUCP) {
|
|
sprintf(rqstr, "X %s", msg);
|
|
logent(rqstr, "REQUEST");
|
|
goto sendmsg;
|
|
}
|
|
mailopt = index(W_OPTNS, 'm') != NULL;
|
|
ntfyopt = index(W_OPTNS, 'n') != NULL;
|
|
|
|
if (narg < 5) {
|
|
char *bnp;
|
|
bnp = rindex(Wfile, '/');
|
|
sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile);
|
|
xmv(Wfile, rqstr);
|
|
logent(Wfile, "CMD FILE CORRUPTED");
|
|
Wfile[0] = '\0';
|
|
goto top;
|
|
}
|
|
sprintf(User, "%.9s", W_USER);
|
|
sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1,
|
|
W_FILE2, W_USER);
|
|
logent(rqstr, "REQUEST");
|
|
if (wrktype == SNDFILE ) {
|
|
strcpy(filename, W_FILE1);
|
|
i = expfile(filename);
|
|
DEBUG(4, "expfile type - %d, ", i);
|
|
if (i != 0 && chkpth(User, "", filename))
|
|
goto e_access;
|
|
strcpy(Dfile, W_DFILE);
|
|
fp = NULL;
|
|
if (index(W_OPTNS, 'c') == NULL) {
|
|
fp = fopen(subfile(Dfile), "r");
|
|
if (fp != NULL)
|
|
i = 0;
|
|
}
|
|
if (fp == NULL &&
|
|
(fp = fopen(subfile(filename), "r")) == NULL) {
|
|
/* can not read data file */
|
|
logent("CAN'T READ DATA", _FAILED);
|
|
TransferSucceeded = 1; /* else will keep sending */
|
|
USRF(USR_LOCACC);
|
|
unlinkdf(Dfile);
|
|
lnotify(User, filename, "can't access");
|
|
goto top;
|
|
}
|
|
/* if file exists but is not generally readable... */
|
|
if (i != 0 && fstat(fileno(fp), &stbuf) == 0
|
|
&& (stbuf.st_mode & ANYREAD) == 0) {
|
|
e_access:;
|
|
/* access denied */
|
|
fclose(fp);
|
|
fp = NULL;
|
|
TransferSucceeded = 1; /* else will keep sending */
|
|
logent("DENIED", "ACCESS");
|
|
USRF(USR_LOCACC);
|
|
unlinkdf(W_DFILE);
|
|
lnotify(User, filename, "access denied");
|
|
goto top;
|
|
}
|
|
|
|
setupline(SNDFILE);
|
|
}
|
|
|
|
if (wrktype == RCVFILE) {
|
|
strcpy(filename, W_FILE2);
|
|
expfile(filename);
|
|
if (chkpth(User, "", filename)
|
|
|| chkperm(filename, index(W_OPTNS, 'd'))) {
|
|
/* access denied */
|
|
logent("DENIED", "ACCESS");
|
|
TransferSucceeded = 1; /* else will keep trying */
|
|
USRF(USR_LOCACC);
|
|
lnotify(User, filename, "access denied");
|
|
goto top;
|
|
}
|
|
sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++);
|
|
if ((fp = fopen(subfile(Dfile), "w")) == NULL) {
|
|
/* can not create temp */
|
|
logent("CAN'T CREATE TM", _FAILED);
|
|
USRF(USR_LNOTMP);
|
|
unlinkdf(Dfile);
|
|
goto top;
|
|
}
|
|
setupline(RCVFILE);
|
|
}
|
|
sendmsg:
|
|
DEBUG(4, "wrktype - %c\n", wrktype);
|
|
WMESG(wrktype, msg);
|
|
RMESG(wrktype, msg, 1);
|
|
goto process;
|
|
}
|
|
|
|
/* role is slave */
|
|
RAMESG(msg, 1);
|
|
if (willturn < 0)
|
|
willturn = msg[0] == HUP;
|
|
|
|
process:
|
|
DEBUG(4, "PROCESS: msg - %s\n", msg);
|
|
switch (msg[0]) {
|
|
|
|
case RQSTCMPT:
|
|
DEBUG(4, "RQSTCMPT:\n", CNULL);
|
|
if (msg[1] == 'N') {
|
|
i = atoi(&msg[2]);
|
|
if (i<0 || i>EM_MAX)
|
|
i = 0;
|
|
USRF( 1 << i );
|
|
logent(Em_msg[i], "REQUEST FAILED");
|
|
TransferSucceeded = 1; /* He had his chance */
|
|
}
|
|
if (msg[1] == 'Y') {
|
|
USRF(USR_COK);
|
|
TransferSucceeded = 1;
|
|
}
|
|
if (role == MASTER) {
|
|
notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
|
|
}
|
|
if (msg[2] == 'M') {
|
|
extern int Nfiles;
|
|
WMESG(HUP, "");
|
|
RMESG(HUP, msg, 1);
|
|
logent(Rmtname, "TURNAROUND");
|
|
gettimeofday(&LastTurned, NULL);
|
|
Nfiles = 0; /* force rescan of queue for work */
|
|
goto process;
|
|
}
|
|
goto top;
|
|
|
|
case HUP:
|
|
DEBUG(4, "HUP:\n", CNULL);
|
|
HaveSentHup = 1;
|
|
if (msg[1] == 'Y') {
|
|
if (role == MASTER) {
|
|
WMESG(HUP, YES);
|
|
}
|
|
(*Turnoff)();
|
|
Rdmsg = Imsg;
|
|
Wrmsg = Omsg;
|
|
return SUCCESS;
|
|
}
|
|
|
|
if (msg[1] == 'N') {
|
|
ASSERT(role == MASTER, "WRONG ROLE - HUP", CNULL, role);
|
|
role = SLAVE;
|
|
goto remaster;
|
|
}
|
|
|
|
/* get work */
|
|
if (!iswrk(Wfile, "chk", Spool, wkpre)) {
|
|
WMESG(HUP, YES);
|
|
RMESG(HUP, msg, 1);
|
|
goto process;
|
|
}
|
|
|
|
WMESG(HUP, NO);
|
|
role = MASTER;
|
|
goto remaster;
|
|
|
|
case XUUCP:
|
|
if (role == MASTER) {
|
|
goto top;
|
|
}
|
|
|
|
/* slave part */
|
|
i = getargs(msg, wrkvec, 20);
|
|
strcpy(filename, W_FILE1);
|
|
if (index(filename, ';') != NULL || index(W_FILE2, ';') != NULL
|
|
|| i < 3) {
|
|
WMESG(XUUCP, NO);
|
|
goto top;
|
|
}
|
|
expfile(filename);
|
|
if (chkpth("", Rmtname, filename)) {
|
|
WMESG(XUUCP, NO);
|
|
logent("XUUCP DENIED", filename);
|
|
USRF(USR_XUUCP);
|
|
goto top;
|
|
}
|
|
sprintf(rqstr, "%s %s", filename, W_FILE2);
|
|
xuucp(rqstr);
|
|
WMESG(XUUCP, YES);
|
|
goto top;
|
|
|
|
case SNDFILE:
|
|
/* MASTER section of 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 FAILED");
|
|
USRF( 1 << i );
|
|
fclose(fp);
|
|
fp = NULL;
|
|
/* dont send him files he can't save */
|
|
if (strcmp(&msg[1], EM_NOTMP) == 0) {
|
|
WMESG(HUP, "");
|
|
RMESG(HUP, msg, 1);
|
|
goto process;
|
|
}
|
|
notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
|
|
ASSERT(role == MASTER, "WRONG ROLE - SN", CNULL, role);
|
|
if (msg[1] != '4')
|
|
unlinkdf(W_DFILE);
|
|
goto top;
|
|
}
|
|
|
|
if (msg[1] == 'Y') {
|
|
/* send file */
|
|
ASSERT(role == MASTER, "WRONG ROLE - SY", CNULL, role);
|
|
ret = fstat(fileno(fp), &stbuf);
|
|
ASSERT(ret != -1, "STAT FAILED", filename, 0);
|
|
i = 1 + (int)(stbuf.st_size / XFRRATE);
|
|
if (send_or_receive != SNDFILE) {
|
|
send_or_receive = SNDFILE;
|
|
systat(Rmtname, SS_INPROGRESS, "SENDING");
|
|
}
|
|
ret = (*Wrdata)(fp, Ofn);
|
|
fclose(fp);
|
|
fp = NULL;
|
|
if (ret != SUCCESS) {
|
|
(*Turnoff)();
|
|
USRF(USR_CFAIL);
|
|
return FAIL;
|
|
}
|
|
RMESG(RQSTCMPT, msg, i);
|
|
unlinkdf(W_DFILE);
|
|
goto process;
|
|
}
|
|
|
|
/* SLAVE section of SNDFILE */
|
|
ASSERT(role == SLAVE, "WRONG ROLE - SLAVE", CNULL, role);
|
|
|
|
/* request to receive file */
|
|
/* check permissions */
|
|
i = getargs(msg, wrkvec, 20);
|
|
if (i < 5) {
|
|
char *bnp;
|
|
bnp = rindex(Wfile, '/');
|
|
sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile);
|
|
xmv(Wfile, rqstr);
|
|
logent(Wfile, "CMD FILE CORRUPTED");
|
|
Wfile[0] = '\0';
|
|
goto top;
|
|
}
|
|
sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1, W_FILE2, W_USER);
|
|
logent(rqstr, "REQUESTED");
|
|
DEBUG(4, "msg - %s\n", msg);
|
|
strcpy(filename, W_FILE2);
|
|
/* Run uuxqt occasionally */
|
|
if (filename[0] == XQTPRE) {
|
|
if (++nXfiles > 10) {
|
|
nXfiles = 0;
|
|
/*
|
|
* want to create an orphan uuxqt,
|
|
* so a double-fork is needed.
|
|
*/
|
|
if (fork() == 0) {
|
|
xuuxqt();
|
|
_exit(0);
|
|
}
|
|
wait((int *)0);
|
|
}
|
|
}
|
|
/* expand filename, i is set to 0 if this is
|
|
* is a vanilla spool file, so no stat(II)s are needed */
|
|
i = expfile(filename);
|
|
DEBUG(4, "expfile type - %d\n", i);
|
|
if (i != 0) {
|
|
if (chkpth("", Rmtname, filename)
|
|
|| chkperm(filename, index(W_OPTNS, 'd'))) {
|
|
WMESG(SNDFILE, EM_RMTACC);
|
|
logent("DENIED", "PERMISSION");
|
|
goto top;
|
|
}
|
|
if (isdir(filename)) {
|
|
strcat(filename, "/");
|
|
strcat(filename, lastpart(W_FILE1));
|
|
}
|
|
}
|
|
sprintf(User, "%.9s", W_USER);
|
|
|
|
DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
|
|
/* speed things up by OKing file before
|
|
* creating TM file. If the TM file cannot be created,
|
|
* then the conversation bombs, but that seems reasonable,
|
|
* as there are probably serious problems then.
|
|
*/
|
|
WMESG(SNDFILE, YES);
|
|
sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++);
|
|
if((fp = fopen(subfile(Dfile), "w")) == NULL) {
|
|
/* WMESG(SNDFILE, EM_NOTMP);*/
|
|
logent("CAN'T OPEN", "TM FILE");
|
|
unlinkdf(Dfile);
|
|
(*Turnoff)();
|
|
return FAIL;
|
|
}
|
|
|
|
if (send_or_receive != RCVFILE) {
|
|
send_or_receive = RCVFILE;
|
|
systat(Rmtname, SS_INPROGRESS, "RECEIVING");
|
|
}
|
|
ret = (*Rddata)(Ifn, fp);
|
|
fflush(fp);
|
|
if (ferror(fp) || fclose(fp))
|
|
ret = FAIL;
|
|
|
|
if (ret != SUCCESS) {
|
|
(void) unlinkdf(Dfile);
|
|
(*Turnoff)();
|
|
return FAIL;
|
|
}
|
|
/* copy to user directory */
|
|
ntfyopt = index(W_OPTNS, 'n') != NULL;
|
|
status = xmv(Dfile, filename);
|
|
|
|
if (willturn && Now.tv_sec > (LastTurned.tv_sec + turntime)
|
|
&& iswrk(Wfile, "chk", Spool, wkpre)) {
|
|
WMESG(RQSTCMPT, status ? EM_RMTCP : "YM");
|
|
willturn = -1;
|
|
} else
|
|
WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
|
|
if (i == 0)
|
|
; /* vanilla file, nothing to do */
|
|
else if (status == 0) {
|
|
if (W_MODE == 0 || sscanf(W_MODE, "%o", &filemode) != 1)
|
|
filemode = BASEMODE;
|
|
chmod(subfile(filename), (filemode|BASEMODE)&0777);
|
|
arrived(ntfyopt, filename, W_NUSER, Rmtname, User);
|
|
} else {
|
|
logent(_FAILED, "COPY");
|
|
status = putinpub(filename, Dfile, W_USER);
|
|
DEBUG(4, "->PUBDIR %d\n", status);
|
|
if (status == 0)
|
|
arrived(ntfyopt, filename, W_NUSER, Rmtname, User);
|
|
}
|
|
|
|
goto top;
|
|
|
|
case RCVFILE:
|
|
/* MASTER section of 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 FAILED");
|
|
USRF( 1 << i );
|
|
fclose(fp);
|
|
fp = NULL;
|
|
notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]);
|
|
ASSERT(role == MASTER, "WRONG ROLE - RN", CNULL, role);
|
|
unlinkdf(Dfile);
|
|
goto top;
|
|
}
|
|
|
|
if (msg[1] == 'Y') {
|
|
/* receive file */
|
|
ASSERT(role == MASTER, "WRONG ROLE - RY", CNULL, role);
|
|
if (send_or_receive != RCVFILE) {
|
|
send_or_receive = RCVFILE;
|
|
systat(Rmtname, SS_INPROGRESS, "RECEIVING");
|
|
}
|
|
ret = (*Rddata)(Ifn, fp);
|
|
fflush(fp);
|
|
if (ferror(fp) || fclose(fp))
|
|
ret = FAIL;
|
|
if (ret != SUCCESS) {
|
|
unlinkdf(Dfile);
|
|
(*Turnoff)();
|
|
USRF(USR_CFAIL);
|
|
return FAIL;
|
|
}
|
|
/* copy to user directory */
|
|
if (isdir(filename)) {
|
|
strcat(filename, "/");
|
|
strcat(filename, lastpart(W_FILE1));
|
|
}
|
|
status = xmv(Dfile, filename);
|
|
if (willturn && Now.tv_sec > (LastTurned.tv_sec + turntime)
|
|
&& iswrk(Wfile, "chk", Spool, wkpre)) {
|
|
WMESG(RQSTCMPT, status ? EM_RMTCP : "YM");
|
|
willturn = -1;
|
|
} else
|
|
WMESG(RQSTCMPT, status ? EM_RMTCP : YES);
|
|
notify(mailopt, W_USER, filename, Rmtname,
|
|
status ? EM_LOCCP : YES);
|
|
if (status == 0) {
|
|
sscanf(&msg[2], "%o", &filemode);
|
|
if (filemode <= 0)
|
|
filemode = BASEMODE;
|
|
chmod(subfile(filename), (filemode|BASEMODE)&0777);
|
|
USRF(USR_COK);
|
|
} else {
|
|
logent(_FAILED, "COPY");
|
|
putinpub(filename, Dfile, W_USER);
|
|
USRF(USR_LOCCP);
|
|
}
|
|
goto top;
|
|
}
|
|
|
|
/* SLAVE section of RCVFILE */
|
|
ASSERT(role == SLAVE, "WRONG ROLE - SLAVE RCV", CNULL, role);
|
|
|
|
/* request to send file */
|
|
strcpy(rqstr, msg);
|
|
logent(rqstr, "REQUESTED");
|
|
|
|
/* check permissions */
|
|
i = getargs(msg, wrkvec, 20);
|
|
if (i < 4) {
|
|
char *bnp;
|
|
bnp = rindex(Wfile, '/');
|
|
sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile);
|
|
xmv(Wfile, rqstr);
|
|
logent(Wfile, "CMD FILE CORRUPTED");
|
|
Wfile[0] = '\0';
|
|
goto top;
|
|
}
|
|
DEBUG(4, "msg - %s\n", msg);
|
|
DEBUG(4, "W_FILE1 - %s\n", W_FILE1);
|
|
strcpy(filename, W_FILE1);
|
|
expfile(filename);
|
|
if (isdir(filename)) {
|
|
strcat(filename, "/");
|
|
strcat(filename, lastpart(W_FILE2));
|
|
}
|
|
sprintf(User, "%.9s", W_USER);
|
|
if (chkpth("", Rmtname, filename) || anyread(filename)) {
|
|
WMESG(RCVFILE, EM_RMTACC);
|
|
logent("DENIED", "PERMISSION");
|
|
goto top;
|
|
}
|
|
DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
|
|
|
|
if ((fp = fopen(subfile(filename), "r")) == NULL) {
|
|
WMESG(RCVFILE, EM_RMTACC);
|
|
logent("CAN'T OPEN", "DENIED");
|
|
goto top;
|
|
}
|
|
|
|
/* ok to send file */
|
|
ret = fstat(fileno(fp), &stbuf);
|
|
ASSERT(ret != -1, "STAT FAILED", filename, 0);
|
|
i = 1 + (int)(stbuf.st_size / XFRRATE);
|
|
sprintf(msg, "%s %o", YES, (int)stbuf.st_mode & 0777);
|
|
WMESG(RCVFILE, msg);
|
|
if (send_or_receive != SNDFILE) {
|
|
send_or_receive = SNDFILE;
|
|
systat(Rmtname, SS_INPROGRESS, "SENDING");
|
|
}
|
|
ret = (*Wrdata)(fp, Ofn);
|
|
fclose(fp);
|
|
if (ret != SUCCESS) {
|
|
(*Turnoff)();
|
|
return FAIL;
|
|
}
|
|
RMESG(RQSTCMPT, msg, i);
|
|
goto process;
|
|
}
|
|
(*Turnoff)();
|
|
return FAIL;
|
|
}
|
|
|
|
/*
|
|
* read message 'c'. try 'n' times
|
|
*
|
|
* return code: SUCCESS | FAIL
|
|
*/
|
|
int rmesg(char c, char *msg, int n)
|
|
{
|
|
char str[MAXFULLNAME];
|
|
|
|
DEBUG(4, "rmesg - '%c' ", c);
|
|
while ((*Rdmsg)(msg, Ifn) != SUCCESS) {
|
|
if (--n > 0) {
|
|
sprintf(str, "%d", n);
|
|
logent(str, "PATIENCE");
|
|
continue;
|
|
}
|
|
DEBUG(4, "got FAIL\n", CNULL);
|
|
if (c != '\0')
|
|
sprintf(str, "expected '%c' got FAIL (%d)", c, errno);
|
|
else
|
|
sprintf(str, "expected ANY got FAIL (%d)", errno);
|
|
logent(str, "BAD READ");
|
|
return FAIL;
|
|
}
|
|
if (c != '\0' && msg[0] != c) {
|
|
DEBUG(4, "got %s\n", msg);
|
|
sprintf(str, "expected '%c' got %s", c, msg);
|
|
logent(str, "BAD READ");
|
|
return FAIL;
|
|
}
|
|
DEBUG(4, "got %s\n", msg);
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* write a message (type m)
|
|
*
|
|
* return codes: SUCCESS - ok | FAIL - ng
|
|
*/
|
|
int wmesg(char m, char *s)
|
|
{
|
|
DEBUG(4, "wmesg '%c' ", m);
|
|
DEBUG(4, "%s\n", s);
|
|
return (*Wrmsg)(m, s, Ofn);
|
|
}
|
|
|
|
/*
|
|
* mail results of command
|
|
*
|
|
* return codes: none
|
|
*/
|
|
void notify(mailopt, user, file, sys, msgcode)
|
|
char *user, *file, *sys, *msgcode;
|
|
{
|
|
char str[BUFSIZ];
|
|
int i;
|
|
char *msg;
|
|
|
|
if (!mailopt && *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];
|
|
}
|
|
sprintf(str, "file %s!%s -- %s\n",
|
|
sys,file, msg);
|
|
mailst(user, str, CNULL);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* local notify
|
|
*
|
|
* return code - none
|
|
*/
|
|
void lnotify(user, file, mesg)
|
|
char *user, *file, *mesg;
|
|
{
|
|
char mbuf[200];
|
|
sprintf(mbuf, "file %s!%s -- %s\n", Myname, file, mesg);
|
|
mailst(user, mbuf, CNULL);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* converse with the remote machine, agree upon a protocol (if possible)
|
|
* and start the protocol.
|
|
*
|
|
* return codes:
|
|
* SUCCESS - successful protocol selection
|
|
* FAIL - can't find common or open failed
|
|
*/
|
|
int startup(role)
|
|
int role;
|
|
{
|
|
char msg[BUFSIZ], str[MAXFULLNAME];
|
|
|
|
Rdmsg = Imsg;
|
|
Wrmsg = Omsg;
|
|
if (role == MASTER) {
|
|
RMESG(SLTPTCL, msg, 1);
|
|
if ((str[0] = fptcl(&msg[1])) == NULL) {
|
|
/* no protocol match */
|
|
WMESG(USEPTCL, NO);
|
|
return FAIL;
|
|
}
|
|
str[1] = '\0';
|
|
WMESG(USEPTCL, str);
|
|
if (stptcl(str) != 0)
|
|
return FAIL;
|
|
DEBUG(4, "protocol %s\n", str);
|
|
return SUCCESS;
|
|
}
|
|
else {
|
|
WMESG(SLTPTCL, blptcl(str));
|
|
RMESG(USEPTCL, msg, 1);
|
|
if (msg[1] == 'N') {
|
|
return FAIL;
|
|
}
|
|
|
|
if (stptcl(&msg[1]) != 0)
|
|
return FAIL;
|
|
DEBUG(4, "Protocol %s\n", msg);
|
|
return SUCCESS;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* choose a protocol from the input string (str) and return the it
|
|
*
|
|
* return codes:
|
|
* '\0' - no acceptable protocol
|
|
* any character - the chosen protocol
|
|
*/
|
|
char
|
|
fptcl(str)
|
|
register char *str;
|
|
{
|
|
register struct Proto *p;
|
|
extern char LineType[];
|
|
|
|
for (p = Ptbl; p->P_id != '\0'; p++) {
|
|
#ifdef TCPIP
|
|
/* Only use 't' on TCP/IP */
|
|
if (p->P_id == 't' && strcmp("TCP", LineType))
|
|
continue;
|
|
#endif
|
|
#ifdef PAD
|
|
/* only use 'f' protocol on PAD */
|
|
if (p->P_id == 'f' && strcmp("PAD", LineType))
|
|
continue;
|
|
#endif
|
|
if (index(str, p->P_id) != NULL) {
|
|
return p->P_id;
|
|
}
|
|
}
|
|
|
|
return '\0';
|
|
}
|
|
|
|
/*
|
|
* build a string of the letters of the available protocols
|
|
*/
|
|
char *
|
|
blptcl(str)
|
|
register char *str;
|
|
{
|
|
register struct Proto *p;
|
|
register char *s;
|
|
|
|
for (p = Ptbl, s = str; (*s++ = p->P_id) != '\0'; p++)
|
|
;
|
|
*s = '\0';
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* this routine will set up the six routines
|
|
* (Rdmsg, Wrmsg, Rddata, Wrdata, Turnon, Turnoff) for the
|
|
* desired protocol.
|
|
*
|
|
* return codes:
|
|
* SUCCESS - ok
|
|
* FAIL - no find or failed to open
|
|
*
|
|
*/
|
|
int stptcl(c)
|
|
register char *c;
|
|
{
|
|
register struct Proto *p;
|
|
|
|
for (p = Ptbl; p->P_id != '\0'; p++) {
|
|
if (*c == p->P_id) {
|
|
/* found protocol - set routines */
|
|
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)() != SUCCESS)
|
|
return FAIL;
|
|
DEBUG(4, "Proto started %c\n", *c);
|
|
return SUCCESS;
|
|
}
|
|
}
|
|
DEBUG(4, "Proto start-fail %c\n", *c);
|
|
return FAIL;
|
|
}
|
|
|
|
/*
|
|
* put file in public place. if successful, filename is modified
|
|
*
|
|
* return code SUCCESS | FAIL
|
|
*/
|
|
int putinpub(file, tmp, user)
|
|
register char *file, *tmp, *user;
|
|
{
|
|
char fullname[MAXFULLNAME];
|
|
int status;
|
|
|
|
sprintf(fullname, "%s/%s/", PUBDIR, user);
|
|
if (mkdirs(fullname) != 0) {
|
|
/* can not make directories */
|
|
DEBUG(1, "Cannot mkdirs(%s)\n", fullname);
|
|
return FAIL;
|
|
}
|
|
strcat(fullname, lastpart(file));
|
|
status = xmv(tmp, fullname);
|
|
if (status == 0) {
|
|
strcpy(file, fullname);
|
|
chmod(subfile(fullname), BASEMODE);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* unlink D. file
|
|
*
|
|
* return code - none
|
|
*/
|
|
void unlinkdf(file)
|
|
register char *file;
|
|
{
|
|
if (strlen(file) > 6)
|
|
unlink(subfile(file));
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* notify receiver of arrived file
|
|
*
|
|
* return code - none
|
|
*/
|
|
void arrived(opt, file, nuser, rmtsys, rmtuser)
|
|
char *file, *nuser, *rmtsys, *rmtuser;
|
|
{
|
|
char mbuf[200];
|
|
|
|
if (!opt)
|
|
return;
|
|
sprintf(mbuf, "%s from %s!%s arrived\n", file, rmtsys, rmtuser);
|
|
mailst(nuser, mbuf, CNULL);
|
|
return;
|
|
}
|
|
|
|
static int nullf()
|
|
{
|
|
return SUCCESS;
|
|
}
|