static char sccsid
[] = "@(#)cico.c 5.5 (Berkeley) %G%";
* cico - this program is used to place a call to a
* remote machine, login, and copy files between the two machines.
char wkpre
[NAMESIZE
], file
[NAMESIZE
];
char msg
[MAXFULLNAME
], *q
, **alias
;
extern onintr(), timeout(), setdebug();
#if defined(VMS) && defined(BSDTCP)
strcpy(Progname
, "uucico");
signal(SIGPIPE
, onintr
); /* 4.1a tcp-ip stupidity */
signal(SIGFPE
, setdebug
);
ret
= guinfo(getuid(), User
, msg
);
ASSERT(ret
== 0, "BAD UID", CNULL
, ret
);
while(argc
>1 && argv
[1][0] == '-'){
Role
= atoi(&argv
[1][2]);
sprintf(Rmtname
, "%.7s", &argv
[1][2]);
Debug
= atoi(&argv
[1][2]);
logent("ENABLED", "DEBUG");
case 'L': /* local calls only */
#if defined(VMS) && defined(BSDTCP)
Hostnumber
= inet_addr(&argv
[1][2]);
printf("unknown flag %s (ignored)\n", argv
[1]);
printf("unknown argument %s (ignored)\n", argv
[1]);
/* Try to run as uucp -- rti!trt */
* detach uucico from controlling terminal
* to defend against rlogind sending us a SIGKILL (!!!)
if (Role
== MASTER
&& (ret
= open("/dev/tty", 2)) >= 0) {
ioctl(ret
, TIOCNOTTY
, STBNULL
);
if (getpgrp(0) == 0) { /*We have no controlling terminal */
ASSERT(ret
>= 0, "CHDIR FAILED", Spool
, ret
);
/* check for /etc/nologin */
ultouch(); /* sets nologinflag as a side effect */
logent(NOLOGIN
, "UUCICO SHUTDOWN");
logent("DEBUGGING", "continuing anyway");
* Determine if we are on TCPIP
DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL
);
ret
= ioctl(0, TCGETA
, &Savettyb
);
Savettyb
.c_cflag
= (Savettyb
.c_cflag
& ~CS8
) | CS7
;
Savettyb
.c_oflag
|= OPOST
;
Savettyb
.c_lflag
|= (ISIG
|ICANON
|ECHO
);
ret
= ioctl(0, TIOCGETP
, &Savettyb
);
Savettyb
.sg_flags
|= ECHO
;
Savettyb
.sg_flags
&= ~RAW
;
sprintf(file
,"%s/%d", RMTDEBUG
, getpid());
/* hold the version number down */
freopen(file
, "w", stderr
);
sprintf(msg
, "here=%s", Myname
);
signal(SIGALRM
, timeout
);
ret
= ioctl(0, TCSETA
, &Savettyb
);
ret
= ioctl(0, TIOCSETP
, &Savettyb
);
ret
= ioctl(0, TCSETA
, &Savettyb
);
ret
= ioctl(0, TIOCSETP
, &Savettyb
);
sprintf(Rmtname
, "%.7s", q
);
sprintf(wkpre
,"%s/%s", RMTDEBUG
, Rmtname
);
if (link(file
, wkpre
) == 0)
DEBUG(4, "sys-%s\n", Rmtname
);
/* we must make sure they are really who they say they
* are. We compare the hostnumber with the number in the hosts
* table for the site they claim to be.
char *cpnt
, *inet_ntoa();
if (getpeername(0, &from
, &fromlen
) < 0) {
logent(Rmtname
, "NOT A TCP CONNECTION");
omsg('R', "NOT TCP", Ofn
);
from
.sin_addr
.s_addr
= Hostnumber
;
from
.sin_family
= AF_INET
;
hp
= gethostbyaddr(&from
.sin_addr
,
sizeof (struct in_addr
), from
.sin_family
);
/* security break or just old host table? */
logent(Rmtname
, "UNKNOWN IP-HOST Name =");
cpnt
= inet_ntoa(from
.sin_addr
),
logent(cpnt
, "UNKNOWN IP-HOST Number =");
sprintf(wkpre
, "%s/%s isn't in my host table",
logent(Rmtname
,"Request from IP-Host name =");
/* The following is to determine if the name given us by
* the Remote uucico matches any of the names(aliases)
* given its network number (remote machine) in our
if (strncmp(q
, hp
->h_name
, 7) == 0) {
logent(q
,"Found in host Tables");
} else { /* Scan The host aliases */
for(alias
=hp
->h_aliases
; *alias
!=0 &&
strncmp(q
, *alias
, 7) != 0; ++alias
)
if (strncmp(q
, *alias
, 7) != 0) {
logent(q
, "FORGED HOSTNAME");
logent(inet_ntoa(from
.sin_addr
), "ORIGINATED AT");
omsg('R',"You're not who you claim to be");
logent(q
,"Found in host Tables");
/* If we don't know them, we won't talk to them... */
logent(Rmtname
, "UNKNOWN HOST");
omsg('R', "You are unknown to me", Ofn
);
else if (callback(Loginuser
)) {
logent("CALLBACK", "REQUIRED");
/* set up for call back */
systat(Rmtname
, SS_CALLBACK
, "CALLING BACK");
gename(CMDPRE
, Rmtname
, 'C', file
);
close(creat(subfile(file
), 0666));
if (callok(Rmtname
) == SS_BADSEQ
) {
logent("BADSEQ", "PREVIOUS");
omsg('R', "BADSEQ", Ofn
);
if ((ret
= gnxseq(Rmtname
)) == seq
) {
systat(Rmtname
, Stattype
[7], Stattext
[7]);
logent("BAD SEQ", "HANDSHAKE FAIL");
omsg('R', "BADSEQ", Ofn
);
} else { /* Role == MASTER */
if (isatty(fileno(stderr
)) || (fstat(fileno(stderr
),&stbuf
) == 0
&& stbuf
.st_mode
&S_IFREG
) )
if(setjmp(Pipebuf
)) { /* come here on SIGPIPE */
sprintf(file
, "%s/%s", RMTDEBUG
, Rmtname
);
if (stat(file
, &sbuf
) == 0 && sbuf
.st_size
== 0)
ret
= gnsys(Rmtname
, Spool
, CMDPRE
);
} else if (Role
== MASTER
&& callok(Rmtname
) != 0) {
logent("SYSTEM STATUS", "CAN NOT CALL");
sprintf(wkpre
, "%c.%.7s", CMDPRE
, Rmtname
);
signal(SIGQUIT
, SIG_IGN
);
/* check for /etc/nologin */
ultouch(); /* sets nologinflag as a side effect */
logent(NOLOGIN
, "UUCICO SHUTDOWN");
logent("DEBUGGING", "continuing anyway");
if (!iswrk(file
, "chk", Spool
, wkpre
) && !onesys
) {
logent(Rmtname
, "NO WORK");
if (Ifn
!= -1 && Role
== MASTER
) {
write(Ofn
, EOTMSG
, strlen(EOTMSG
));
sprintf(msg
, "call to %s ", Rmtname
);
if (mlock(Rmtname
) != 0) {
Ofn
= Ifn
= conn(Rmtname
);
/* avoid excessive 'wrong time' info */
if (Stattype
[-Ofn
] != SS_WRONGTIME
|| argv
[0][0] != 'U'){
systat(Rmtname
, Stattype
[-Ofn
], Stattext
[-Ofn
]);
logent(msg
, "SUCCEEDED");
* Determine if we are on TCPIP
DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL
);
signal(SIGALRM
, timeout
);
logent("imsg 1", _FAILED
);
sprintf(msg
, "%.7s -Q%d %s", Myname
, seq
, rflags
);
DEBUG(4, "msg-%s\n", msg
);
logent("imsg 2", _FAILED
);
logent("BAD SEQ", "HANDSHAKE FAIL");
systat(Rmtname
, SS_BADSEQ
, Stattext
[SS_BADSEQ
]);
if (strcmp(&msg
[1], "OK") != SAME
) {
logent(&msg
[1], "HANDSHAKE FAIL");
systat(Rmtname
, SS_INPROGRESS
,
strcmp(&msg
[1], "CB") == SAME
?
"AWAITING CALLBACK": "HANDSHAKE FAIL");
DEBUG(1, "Rmtname %s, ", Rmtname
);
DEBUG(1, "Role %s, ", Role
? "MASTER" : "SLAVE");
DEBUG(1, "Ifn - %d, ", Ifn
);
DEBUG(1, "Loginuser - %s\n", Loginuser
);
logent("startup", _FAILED
);
systat(Rmtname
, SS_FAIL
, "STARTUP FAILED");
systat(Rmtname
, SS_INPROGRESS
, "TALKING");
ret
= cntrl(Role
, wkpre
);
DEBUG(1, "cntrl - %d\n", ret
);
signal(SIGALRM
, timeout
);
logent("conversation complete", "OK");
logent("conversation complete", _FAILED
);
systat(Rmtname
, SS_FAIL
, "CONVERSATION FAILED");
DEBUG(4, "send OO %d,", ret
);
* cleanup(code) cleanup and exit with "code" status
Savettyb
.c_cflag
|= HUPCL
;
ret
= ioctl(0, TCSETA
, &Savettyb
);
ret
= ioctl(0, TIOCHPCL
, STBNULL
);
ret
= ioctl(0, TIOCGETP
, &Hupvec
);
ret
= ioctl(0, TIOCSETP
, &Hupvec
);
ret
= ioctl(0, TIOCSETP
, &Savettyb
);
/* make *sure* exclusive access is off */
ret
= ioctl(0, TIOCNXCL
, STBNULL
);
DEBUG(4, "ret ioctl - %d\n", ret
);
write(Ofn
, EOTMSG
, strlen(EOTMSG
));
DEBUG(1, "exit code %d\n", code
);
sprintf(bfr
, "%s/%s", RMTDEBUG
, Rmtname
);
if (stat(bfr
, &sbuf
) == 0 && sbuf
.st_size
== 0)
sprintf(bfr
, "%s/%d", RMTDEBUG
, getpid());
* onintr(inter) interrupt - remove locks and exit
sprintf(str
, "SIGNAL %d", inter
);
if (*Rmtname
&& strcmp(Rmtname
, Myname
))
systat(Rmtname
, SS_FAIL
, str
);
if (inter
== SIGPIPE
&& !onesys
)
* (SIGFPE, ugh), and toggle debugging between 0 and 30.
* Handy for looking in on long running uucicos.
sprintf(buf
,"%s/%s", RMTDEBUG
, Rmtname
);
freopen(buf
, "w", stderr
);
* fixmode(tty) fix kill/echo/raw on line
ret
= ioctl(tty
, TCGETA
, &ttbuf
);
ttbuf
.c_iflag
= ttbuf
.c_oflag
= ttbuf
.c_lflag
= (ushort
)0;
ttbuf
.c_cflag
&= (CBAUD
);
ttbuf
.c_cflag
|= (CS8
|CREAD
);
ret
= ioctl(tty
, TCSETA
, &ttbuf
);
ioctl(tty
, TIOCGETP
, &ttbuf
);
ttbuf
.sg_flags
= (ANYP
| RAW
);
ret
= ioctl(tty
, TIOCSETP
, &ttbuf
);
/* ASSERT(ret >= 0, "STTY FAILED", CNULL, ret); */
ret
= ioctl(tty
, TIOCEXCL
, STBNULL
);
* timeout() catch SIGALRM routine
logent(Rmtname
, "TIMEOUT");
if (*Rmtname
&& strcmp(Rmtname
, Myname
)) {
systat(Rmtname
, SS_FAIL
, "TIMEOUT");