static char sccsid
[] = "@(#)cntrl.c 5.3 (Berkeley) %G%";
extern int gturnon(), gturnoff();
extern int grdmsg(), grddata();
extern int gwrmsg(), gwrdata();
extern int nturnon(), nturnoff();
extern int nrdmsg(), nrddata();
extern int nwrmsg(), nwrdata();
extern int imsg(), omsg();
'n', nturnon
, nrdmsg
, nwrmsg
, nrddata
, nwrdata
, nturnoff
,
'g', gturnon
, grdmsg
, gwrmsg
, grddata
, gwrdata
, gturnoff
,
int (*Imsg
)() = imsg
, (*Omsg
)() = omsg
; /* avoid SEL compiler limitation */
int (*Rdmsg
)()=imsg
, (*Rddata
)();
int (*Wrmsg
)()=omsg
, (*Wrdata
)();
int (*Turnon
)(), (*Turnoff
)();
#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 */
"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"
#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_FILE1 wrkvec[1]
#define W_FILE2 wrkvec[2]
#define W_OPTNS wrkvec[4]
#define W_DFILE wrkvec[5]
#define W_NUSER wrkvec[7]
#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'};
* To avoid a huge backlog of X. files, start uuxqt every so often.
* To avoid a huge number of uuxqt zombies,
* wait for one occasionally!
static int nXfiles
= 0; /* number of X files since last uuxqt start */
static int nXQTs
= 0; /* number of uuxqts started */
* cntrl - this routine will execute the conversation
* between the two machines after both programs are
char msg
[BUFSIZ
], rqstr
[BUFSIZ
];
char filename
[MAXFULLNAME
], wrktype
, *wrkvec
[20];
extern (*Rdmsg
)(), (*Wrmsg
)();
extern char *index(), *lastpart();
static int pnum
, tmpnum
= 0;
* ima.247, John Levine, IECC, PO Box 349, Cambridge MA 02238; (617) 491-5450
* zap Wfile to prevent reuse of wrong C. file
for (i
= 0; i
< sizeof wrkvec
/ sizeof wrkvec
[0]; i
++)
DEBUG(4, "*** TOP *** - role=%d, ", role
);
if ((narg
= gtwvec(Wfile
, Spool
, wkpre
, wrkvec
)) == 0) {
mailopt
= index(W_OPTNS
, 'm') != NULL
;
ntfyopt
= index(W_OPTNS
, 'n') != NULL
;
for (i
= 1; i
< narg
; i
++) {
sprintf(rqstr
, "X %s", msg
);
logent(rqstr
, "REQUEST");
ASSERT(narg
> 4, "ARG COUNT<5", "", i
);
sprintf(User
, "%.9s", W_USER
);
sprintf(rqstr
, "%s %s %s %s", W_TYPE
, W_FILE1
,
logent(rqstr
, "REQUEST");
if (wrktype
== SNDFILE
) {
strcpy(filename
, W_FILE1
);
DEBUG(4, "expfile type - %d", i
);
if (i
!= 0 && chkpth(User
, "", filename
))
if (index(W_OPTNS
, 'c') == NULL
) {
fp
= fopen(subfile(Dfile
), "r");
(fp
= fopen(subfile(filename
), "r")) == NULL
) {
/* can not read data file */
logent("CAN'T READ DATA", "FAILED");
lnotify(User
, filename
, "can't access");
/* if file exists but is not generally readable... */
if (i
!= 0 && fstat(fileno(fp
), &stbuf
) == 0
&& (stbuf
.st_mode
& ANYREAD
) == 0) {
logent("DENIED", "ACCESS");
lnotify(User
, filename
, "access denied");
if (wrktype
== RCVFILE
) {
strcpy(filename
, W_FILE2
);
if (chkpth(User
, "", filename
)
|| chkperm(filename
, index(W_OPTNS
, 'd'))) {
logent("DENIED", "ACCESS");
lnotify(User
, filename
, "access denied");
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");
DEBUG(4, "wrktype - %c\n ", wrktype
);
/* rti!trt: ultouch is now done in gio.c (yes, kludge)
DEBUG(4, " PROCESS: msg - %s\n", msg
);
DEBUG(4, "%s\n", "RQSTCMPT:");
if (i
<0 || i
>EM_MAX
) i
=0;
/* duke!rti: only note failed requests */
logent(msg
, "REQUESTED");
notify(mailopt
, W_USER
, W_FILE1
, Rmtname
, &msg
[1]);
DEBUG(4, "%s\n", "HUP:");
ASSERT(role
== MASTER
, "WRONG ROLE", "", role
);
if (!iswrk(Wfile
, "chk", Spool
, wkpre
)) {
i
= getargs(msg
, wrkvec
);
strcpy(filename
, W_FILE1
);
if (index(filename
, ';') != NULL
|| index(W_FILE2
, ';') != NULL
if (chkpth("", Rmtname
, filename
)) {
logent("XUUCP DENIED", filename
);
sprintf(rqstr
, "%s %s", filename
, W_FILE2
);
/* MASTER section of SNDFILE */
DEBUG(4, "%s\n", "SNDFILE:");
logent(Em_msg
[i
], "REQUEST");
notify(mailopt
, W_USER
, W_FILE1
, Rmtname
, &msg
[1]);
ASSERT(role
== MASTER
, "WRONG ROLE", "", role
);
ASSERT(role
== MASTER
, "WRONG ROLE", "", role
);
ret
= fstat(fileno(fp
), &stbuf
);
ASSERT(ret
!= -1, "STAT FAILED", filename
, 0);
i
= 1 + (int)(stbuf
.st_size
/ XFRRATE
);
ret
= (*Wrdata
)(fp
, Ofn
);
/* put the unlink *after* the RMESG -- fortune!Dave-Yost */
/* SLAVE section of SNDFILE */
ASSERT(role
== SLAVE
, "WRONG ROLE", "", role
);
/* request to receive file */
i
= getargs(msg
, wrkvec
);
ASSERT(i
> 4, "ARG COUNT<5", "", i
);
sprintf(rqstr
, "%s %s %s %s", W_TYPE
, W_FILE1
,
logent(rqstr
, "REQUESTED");
DEBUG(4, "msg - %s\n", msg
);
strcpy(filename
, W_FILE2
);
/* Run uuxqt occasionally */
if (filename
[0] == XQTPRE
) {
/* I sure hope the wait(II) does not hang.
* One can never tell about UNIX variants.
/* rti!trt: expand filename, i is set to 0 if this is
* is a vanilla spool file, so no stat(II)s are needed */
DEBUG(4, "expfile type - %d\n", i
);
if (chkpth("", Rmtname
, filename
)
|| chkperm(filename
, index(W_OPTNS
, 'd'))) {
WMESG(SNDFILE
, EM_RMTACC
);
logent("DENIED", "PERMISSION");
strcat(filename
, lastpart(W_FILE1
));
sprintf(User
, "%.9s", W_USER
);
DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname
);
sprintf(Dfile
, "%s/TM.%05d.%03d", Spool
, pnum
, tmpnum
++);
if((fp
= fopen(subfile(Dfile
), "w")) == NULL
) {
WMESG(SNDFILE
, EM_NOTMP
);
logent("CAN'T OPEN", "DENIED");
ret
= (*Rddata
)(Ifn
, fp
);
/* ittvax!swatt: (try to) make sure IO successful */
if (ferror(fp
) || fclose(fp
))
/* copy to user directory */
ntfyopt
= index(W_OPTNS
, 'n') != NULL
;
status
= xmv(Dfile
, filename
);
WMESG(RQSTCMPT
, status
? EM_RMTCP
: YES
);
sscanf(W_MODE
, "%o", &filemode
);
chmod(subfile(filename
), filemode
| BASEMODE
);
arrived(ntfyopt
, filename
, W_NUSER
, Rmtname
, User
);
logent("FAILED", "COPY");
status
= putinpub(filename
, Dfile
, W_USER
);
DEBUG(4, "->PUBDIR %d\n", status
);
arrived(ntfyopt
, filename
, W_NUSER
,
/* MASTER section of RCVFILE */
DEBUG(4, "%s\n", "RCVFILE:");
logent(Em_msg
[i
], "REQUEST");
notify(mailopt
, W_USER
, W_FILE1
, Rmtname
, &msg
[1]);
ASSERT(role
== MASTER
, "WRONG ROLE", "", role
);
ASSERT(role
== MASTER
, "WRONG ROLE", "", role
);
ret
= (*Rddata
)(Ifn
, fp
);
/* ittvax!swatt: (try to) make sure IO successful */
if (ferror(fp
) || fclose(fp
))
/* copy to user directory */
strcat(filename
, lastpart(W_FILE1
));
status
= xmv(Dfile
, filename
);
WMESG(RQSTCMPT
, status
? EM_RMTCP
: YES
);
notify(mailopt
, W_USER
, filename
, Rmtname
,
status
? EM_LOCCP
: YES
);
sscanf(&msg
[2], "%o", &filemode
);
chmod(subfile(filename
), filemode
| BASEMODE
);
logent("FAILED", "COPY");
putinpub(filename
, Dfile
, W_USER
);
/* SLAVE section of RCVFILE */
ASSERT(role
== SLAVE
, "WRONG ROLE", "", role
);
/* request to send file */
logent(rqstr
, "REQUESTED");
i
= getargs(msg
, wrkvec
);
ASSERT(i
> 3, "ARG COUNT<4", "", i
);
DEBUG(4, "msg - %s\n", msg
);
DEBUG(4, "W_FILE1 - %s\n", W_FILE1
);
strcpy(filename
, W_FILE1
);
strcat(filename
, lastpart(W_FILE2
));
sprintf(User
, "%.9s", W_USER
);
if (chkpth("", Rmtname
, filename
) || anyread(filename
)) {
WMESG(RCVFILE
, EM_RMTACC
);
logent("DENIED", "PERMISSION");
DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname
);
if ((fp
= fopen(subfile(filename
), "r")) == NULL
) {
WMESG(RCVFILE
, EM_RMTACC
);
logent("CAN'T OPEN", "DENIED");
ret
= fstat(fileno(fp
), &stbuf
);
ASSERT(ret
!= -1, "STAT FAILED", filename
, 0);
i
= 1 + (int)(stbuf
.st_size
/ XFRRATE
);
sprintf(msg
, "%s %o", YES
, stbuf
.st_mode
& 0777);
ret
= (*Wrdata
)(fp
, Ofn
);
* rmesg(c, msg, n) read message 'c'
DEBUG(4, "rmesg - '%c' ", c
);
while ((*Rdmsg
)(msg
, Ifn
) != 0) {
DEBUG(4, "got %s\n", "FAIL");
sprintf(str
, "expected '%c' got FAIL", c
);
if (c
!= '\0' && msg
[0] != c
) {
DEBUG(4, "got %s\n", msg
);
sprintf(str
, "expected '%c' got %.25s", c
, msg
);
DEBUG(4, "got %.25s\n", msg
);
* wmesg(m, s) write a message (type m)
* return codes: 0 - ok | FAIL - ng
DEBUG(4, "wmesg '%c'", m
);
return((*Wrmsg
)(m
, s
, Ofn
));
* notify mail results of command
notify(mailopt
, user
, file
, sys
, msgcode
)
char *user
, *file
, *sys
, *msgcode
;
if (!mailopt
&& *msgcode
== 'Y')
sprintf(str
, "file %s, system %s\n%s\n",
* lnotify(user, file, mesg) - local notify
lnotify(user
, file
, mesg
)
char *user
, *file
, *mesg
;
sprintf(mbuf
, "file %s on %s\n%s\n", file
, Myname
, mesg
);
* startup - this routine will converse with the remote
* machine, agree upon a protocol (if possible) and start the
* SUCCESS - successful protocol selection
* FAIL - can't find common or open failed
extern (*Rdmsg
)(), (*Wrmsg
)();
extern char *blptcl(), fptcl();
char msg
[BUFSIZ
], str
[BUFSIZ
];
if ((str
[0] = fptcl(&msg
[1])) == NULL
) {
DEBUG(4, "protocol %s\n", str
);
WMESG(SLTPTCL
, blptcl(str
));
if (stptcl(&msg
[1]) != 0)
DEBUG(4, "Protocol %s\n", msg
);
* fptcl - this routine will choose a protocol from
* the input string (str) and return the found letter.
* '\0' - no acceptable protocol
* any character - the chosen protocol
register struct Proto
*p
;
if (fstat(Ifn
, &stbuf
) < 0)
for (p
= Ptbl
; p
->P_id
!= '\0'; p
++) {
* Hack to avoid using network protocol if not connected
if ((stbuf
.st_mode
& S_IFMT
) != S_IFSOCK
&& p
->P_id
== 'n')
if (index(str
, p
->P_id
) != NULL
) {
* blptcl - this will build a string of the
* letters of the available protocols and return
* a pointer to string (str)
register struct Proto
*p
;
if (fstat(Ofn
, &stbuf
) < 0)
for (p
= Ptbl
, s
= str
; p
->P_id
!= '\0'; p
++) {
* Hack to avoid using network protocol if not connected
if ((stbuf
.st_mode
& S_IFMT
) != S_IFSOCK
&& p
->P_id
== 'n')
* stptcl - this routine will set up the six routines
* (Rdmsg, Wrmsg, Rddata, Wrdata, Turnon, Turnoff) for the
* FAIL - no find or failed to open
register struct Proto
*p
;
for (p
= Ptbl
; p
->P_id
!= '\0'; p
++) {
/* found protocol - set routines */
DEBUG(4, "Proto started %c\n", *c
);
DEBUG(4, "Proto start-fail %c\n", *c
);
* putinpub put file in public place
* if successful, filename is modified
putinpub(file
, tmp
, user
)
register char *file
, *user
, *tmp
;
char fullname
[MAXFULLNAME
];
sprintf(fullname
, "%s/%s/", PUBDIR
, user
);
if (mkdirs(fullname
) != 0) {
/* can not make directories */
strcat(fullname
, lastpart(file
));
status
= xmv(tmp
, fullname
);
chmod(subfile(fullname
), BASEMODE
);
* unlinkdf(file) - unlink D. file
* arrived - notify receiver of arrived file
arrived(opt
, file
, nuser
, rmtsys
, rmtuser
)
char *file
, *nuser
, *rmtsys
, *rmtuser
;
sprintf(mbuf
, "%s from %s!%s arrived\n", file
, rmtsys
, rmtuser
);