Research V7 development
[unix-history] / usr / src / cmd / uucp / cico.c
#include "uucp.h"
#include "uucpdefs.h"
#include <signal.h>
#include <sgtty.h>
#include <setjmp.h>
jmp_buf Sjbuf;
/* call fail text */
char *Stattext[] = {
"",
"BAD SYSTEM",
"WRONG TIME",
"SYSTEM LOCKED",
"NO DEVICE",
"DIAL FAILED",
"LOGIN FAILED",
"BAD SEQUENCE"
};
int Role = 0;
/* call fail codes */
int Stattype[] = {0, 0, 0, 0,
SS_NODEVICE, SS_FAIL, SS_FAIL, SS_BADSEQ
};
int Errorrate = 0;
struct sgttyb Savettyb;
/*******
* cico - this program is used to place a call to a
* remote machine, login, and copy files between the two machines.
*/
main(argc, argv)
char *argv[];
{
int ret, seq;
int onesys = 0;
char wkpre[NAMESIZE], file[NAMESIZE];
char msg[BUFSIZ], *p, *q;
extern onintr(), timeout();
extern intrINT();
extern intrHUP();
extern intrQUIT();
extern intrTERM();
extern intrEXIT();
extern char *pskip();
char rflags[30];
char *ttyn;
char *ttyname();
signal(SIGILL, intrEXIT);
signal(SIGTRAP, intrEXIT);
signal(SIGIOT, intrEXIT);
signal(SIGEMT, intrEXIT);
signal(SIGFPE, intrEXIT);
signal(SIGBUS, intrEXIT);
signal(SIGSEGV, intrEXIT);
signal(SIGSYS, intrEXIT);
signal(SIGINT, intrINT);
signal(SIGHUP, intrHUP);
signal(SIGQUIT, intrQUIT);
signal(SIGTERM, intrTERM);
ret = guinfo(getuid(), User, msg);
strcpy(Loginuser, User);
ASSERT(ret == 0, "BAD UID ret %d", ret);
rflags[0] = '\0';
strcpy(Rmtname, MYNAME);
Ifn = Ofn = -1;
while(argc>1 && argv[1][0] == '-'){
switch(argv[1][1]){
case 'd':
Spool = &argv[1][2];
break;
/*
* case 'E':
* Errorrate = atoi(&argv[1][2]);
* if (Errorrate <= 0)
* Errorrate = 100;
* break;
* case 'g':
* Pkdrvon = 1;
* break;
* case 'G':
* Pkdrvon = 1;
* strcat(rflags, " -g ");
* break;
*/
case 'r':
Role = atoi(&argv[1][2]);
break;
case 's':
sprintf(Rmtname, "%.7s", &argv[1][2]);
if (Rmtname[0] != '\0')
onesys = 1;
break;
case 'x':
Debug = atoi(&argv[1][2]);
if (Debug <= 0)
Debug = 1;
strcat(rflags, argv[1]);
break;
default:
printf("unknown flag %s\n", argv[1]);
break;
}
--argc; argv++;
}
chdir(Spool);
strcpy(Wrkdir, Spool);
if (Role == SLAVE) {
/* initial handshake */
onesys = 1;
ret = ioctl(0, TIOCGETP, &Savettyb);
Savettyb.sg_flags |= ECHO;
Savettyb.sg_flags &= ~RAW;
Ifn = 0;
Ofn = 1;
fixmode(Ifn);
fclose(stderr);
fopen(RMTDEBUG, "w");
chmod(RMTDEBUG, 0666);
omsg('S', "here", Ofn);
signal(SIGALRM, timeout);
alarm(MAXMSGTIME);
if (setjmp(Sjbuf)) {
/* timed out */
ret = ioctl(0, TIOCSETP, &Savettyb);
exit(0);
}
for (;;) {
ret = imsg(msg, Ifn);
if (ret != 0) {
alarm(0);
ret = ioctl(0, TIOCSETP, &Savettyb);
exit(0);
}
if (msg[0] == 'S')
break;
}
alarm(0);
DEBUG(4, "msg-%s,", msg);
q = &msg[1];
p = pskip(q);
sprintf(Rmtname, "%.7s", q);
DEBUG(4, "sys-%s\n", Rmtname);
if (mlock(Rmtname)) {
omsg('R', "LCK", Ofn);
cleanup(0);
}
else if (callback(Loginuser)) {
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
omsg('R', "CB", Ofn);
DEBUG(4, "CALLBACK Role %d\n", Role);
logent("CALLBACK", "REQUIRED");
/* set up for call back */
systat(Rmtname, SS_CALLBACK, "CALL BACK");
gename(CMDPRE, Rmtname, 'C', file);
close(creat(file, 0666));
chmod(file, 0666);
xuucico(Rmtname);
cleanup(0);
}
seq = 0;
while (*p == '-') {
q = pskip(p);
switch(*(++p)) {
case 'g':
Pkdrvon = 1;
break;
case 'x':
Debug = atoi(++p);
if (Debug <= 0)
Debug = 1;
break;
case 'Q':
seq = atoi(++p);
break;
default:
break;
}
p = q;
}
if (callok(Rmtname) == SS_BADSEQ) {
logent("BADSEQ", "PREVIOUS");
omsg('R', "BADSEQ", Ofn);
cleanup(0);
}
if ((ret = gnxseq(Rmtname)) == seq) {
omsg('R', "OK", Ofn);
cmtseq();
}
else {
systat(Rmtname, Stattype[7], Stattext[7]);
logent("BAD SEQ", "HANDSHAKE FAILED");
ulkseq();
omsg('R', "BADSEQ", Ofn);
cleanup(0);
}
}
loop:
if (!onesys) {
ret = gnsys(Rmtname, Spool, CMDPRE);
if (ret == FAIL)
cleanup(100);
if (ret == 0)
cleanup(0);
}
else if (Role == MASTER && callok(Rmtname) != 0) {
logent("SYSTEM STATUS", "CAN NOT CALL");
cleanup(0);
}
sprintf(wkpre, "%c.%.7s", CMDPRE, Rmtname);
if (Role == MASTER) {
/* master part */
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
if (!iswrk(file, "chk", Spool, wkpre) && !onesys) {
logent(Rmtname, "NO WORK");
cleanup(0);
}
if (Ifn != -1 && Role == MASTER) {
write(Ofn, EOTMSG, strlen(EOTMSG));
close(Ofn);
close(Ifn);
Ifn = Ofn = -1;
rmlock(NULL);
clsacu();
sleep(3);
}
sprintf(msg, "call to %s ", Rmtname);
if (mlock(Rmtname) != 0) {
logent(msg, "LOCKED");
goto next;
}
Ofn = Ifn = conn(Rmtname);
if (Ofn < 0) {
logent(msg, "FAILED");
systat(Rmtname, Stattype[-Ofn],
Stattext[-Ofn]);
goto next;
}
else {
logent(msg, "SUCCEEDED");
}
if (setjmp(Sjbuf))
goto next;
signal(SIGALRM, timeout);
alarm(2 * MAXMSGTIME);
for (;;) {
ret = imsg(msg, Ifn);
if (ret != 0) {
alarm(0);
goto next;
}
if (msg[0] == 'S')
break;
}
alarm(MAXMSGTIME);
seq = gnxseq(Rmtname);
sprintf(msg, "%.7s -Q%d %s", Myname, seq, rflags);
omsg('S', msg, Ofn);
for (;;) {
ret = imsg(msg, Ifn);
DEBUG(4, "msg-%s\n", msg);
if (ret != 0) {
alarm(0);
ulkseq();
goto next;
}
if (msg[0] == 'R')
break;
}
alarm(0);
if (msg[1] == 'B') {
/* bad sequence */
logent("BAD SEQ", "HANDSHAKE FAILED");
systat(Rmtname, Stattype[7], Stattext[7]);
ulkseq();
goto next;
}
if (strcmp(&msg[1], "OK") != SAME) {
logent(&msg[1], "HANDSHAKE FAILED");
ulkseq();
goto next;
}
cmtseq();
}
ttyn = ttyname(Ifn);
if (ttyn != NULL)
chmod(ttyn, 0600);
DEBUG(1, " Rmtname %s, ", Rmtname);
DEBUG(1, "my Role %s, ", Role ? "MASTER" : "SLAVE");
DEBUG(1, "Spool - %s\n", Spool);
DEBUG(1, "Ifn - %d, ", Ifn);
DEBUG(1, "Ofn - %d, ", Ofn);
DEBUG(1, "Loginuser - %s\n", Loginuser);
ret = startup(Role);
if (ret != SUCCESS) {
logent("startup", "FAILED");
systat(Rmtname, SS_FAIL, "STARTUP");
goto next;
}
else {
systat(Rmtname, SS_INPROGRESS, "TALKING");
ret = cntrl(Role, wkpre);
DEBUG(1, "ret from cntrl - %d\n", ret);
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGALRM, timeout);
if (ret == 0)
rmstat(Rmtname);
else
systat(Rmtname, SS_FAIL, "CONVERSATION");
alarm(MAXMSGTIME);
omsg('O', "OOOOO", Ofn);
DEBUG(4, "send OO %d,", ret);
if (!setjmp(Sjbuf)) {
for (;;) {
omsg('O', "OOOOO", Ofn);
ret = imsg(msg, Ifn);
if (ret != 0)
break;
if (msg[0] == 'O')
break;
}
}
alarm(0);
}
next:
if (!onesys) {
goto loop;
}
cleanup(0);
}
int Hupvec[] = {0, 0, 1};
/***
* cleanup(code) cleanup and exit with "code" status
* int code;
*/
cleanup(code)
int code;
{
int ret;
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
rmlock(NULL);
clsacu();
logcls();
if (Role == SLAVE) {
ret = ioctl(0, TIOCSETP, &Savettyb);
DEBUG(4, "\nIfn - %d, ", Ifn);
DEBUG(4, "ret ioctl - %d\n", ret);
DEBUG(4, "tty.flags %o,", Savettyb.sg_flags);
DEBUG(4, "tty.ispeed %d, ", Savettyb.sg_ispeed);
DEBUG(4, "tty.ospeed %d, ", Savettyb.sg_ospeed);
ret = ioctl(0, TIOCSETP, Hupvec);
DEBUG(4, "ret ioctl - %d\n", ret);
}
if (Ofn != -1) {
if (Role == MASTER)
write(Ofn, EOTMSG, strlen(EOTMSG));
close(Ifn);
close(Ofn);
}
DEBUG(1, "exit code %d\n", code);
if (code == 0)
xuuxqt();
exit(code);
}
/***
* onintr(inter) interrupt - remove locks and exit
*/
onintr(inter)
int inter;
{
char str[30];
signal(inter, SIG_IGN);
sprintf(str, "SIGNAL %d", inter);
logent(str, "CAUGHT");
cleanup(inter);
}
intrINT() { onintr(SIGINT);}
intrHUP() { onintr(SIGHUP);}
intrQUIT() { onintr(SIGQUIT);}
intrTERM() { onintr(SIGTERM);}
intrEXIT() {_exit(77);}
/***
* fixmode(tty) fix kill/echo/raw on line
*
* return codes: none
*/
fixmode(tty)
int tty;
{
struct sgttyb ttbuf;
int ret;
ioctl(tty, TIOCGETP, &ttbuf);
ttbuf.sg_flags |= (ANYP | RAW);
ttbuf.sg_flags &= ~(ECHO | ALLDELAY);
ret = ioctl(tty, TIOCSETP, &ttbuf);
ASSERT(ret >= 0, "RETURN FROM STTY %d", ret);
ioctl(tty, TIOCEXCL, 0);
return;
}
/***
* timeout() catch SIGALRM routine
*/
timeout()
{
longjmp(Sjbuf, 1);
}
static char *
pskip(p)
register char *p;
{
while( *p && *p != ' ' )
++p;
if( *p ) *p++ = 0;
return(p);
}