static char sccsid
[] = "@(#)cico.c 5.10 (Berkeley) %G%";
#if defined(VMS) && defined(BSDTCP)
int turntime
= 30 * 60; /* 30 minutes expressed in seconds */
extern char MaxGrade
, DefMaxGrade
;
extern char Myfullname
[];
* 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();
char rflags
[MAXFULLNAME
];
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] == '-'){
MaxGrade
= DefMaxGrade
= argv
[1][2];
Role
= atoi(&argv
[1][2]);
strncpy(Rmtname
, &argv
[1][2], MAXBASENAME
);
Rmtname
[MAXBASENAME
] = '\0';
Debug
= atoi(&argv
[1][2]);
logent("ENABLED", "DEBUG");
turntime
= atoi(&argv
[1][2])*60;/* minutes to seconds */
case 'L': /* local calls only */
Hostnumber
= inet_addr(&argv
[1][2]);
printf("unknown flag %s (ignored)\n", argv
[1]);
printf("unknown argument %s (ignored)\n", argv
[1]);
* 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 */
if (access(NOLOGIN
, 0) == 0) {
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", Myfullname
);
signal(SIGALRM
, timeout
);
ret
= ioctl(0, TCSETA
, &Savettyb
);
ret
= ioctl(0, TIOCSETP
, &Savettyb
);
ret
= ioctl(0, TCSETA
, &Savettyb
);
ret
= ioctl(0, TIOCSETP
, &Savettyb
);
strncpy(Rmtname
, q
, MAXBASENAME
);
Rmtname
[MAXBASENAME
] = '\0';
sprintf(wkpre
,"%s/%s", RMTDEBUG
, Rmtname
);
if (link(file
, wkpre
) == 0)
DEBUG(4, "sys-%s\n", Rmtname
);
/* The versys will also do an alias on the incoming name */
/* If we don't know them, we won't talk to them... */
logent(Rmtname
, "UNKNOWN HOST");
omsg('R', "You are unknown to me", Ofn
);
/* 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();
extern char PhoneNumber
[];
from
.sin_addr
.s_addr
= Hostnumber
;
from
.sin_family
= AF_INET
;
if (getpeername(0, &from
, &len
) < 0) {
logent(Rmtname
, "NOT A TCP CONNECTION");
omsg('R', "NOT TCP", Ofn
);
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
* given its network number (remote machine) in our
* We could check the aliases, but that won't work in
* all cases (like if you are running the domain
* server, where you don't get any aliases). The only
* reliable way I can think of that works in ALL cases
* is too look up the site in L.sys and see if the
* sitename matches what we would call him if we
/* PhoneNumber contains the official network name of the host we are checking. (set in versys.c) */
if (sncncmp(PhoneNumber
, hp
->h_name
, SYSNSIZE
) == 0) {
logent(q
,"Found in host Tables");
logent(hp
->h_name
, "FORGED HOSTNAME");
logent(inet_ntoa(from
.sin_addr
), "ORIGINATED AT");
logent(PhoneNumber
, "SHOULD BE");
sprintf(wkpre
, "You're not who you claim to be: %s != %s", hp
->h_name
, PhoneNumber
);
if (mlock(Rmtname
) == FAIL
) {
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));
MaxGrade
= DefMaxGrade
= *++p
;
DEBUG(4, "MaxGrade set to %c\n", MaxGrade
);
if (strncmp(p
, "grade", 5) == 0) {
MaxGrade
= DefMaxGrade
= *p
++;
DEBUG(4, "MaxGrade set to %c\n", MaxGrade
);
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", "FAILED HANDSHAKE");
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.%.*s", CMDPRE
, SYSNSIZE
, Rmtname
);
signal(SIGQUIT
, SIG_IGN
);
/* check for /etc/nologin */
if (access(NOLOGIN
, 0) == 0) {
logent(NOLOGIN
, "UUCICO SHUTDOWN");
logent("DEBUGGING", "continuing anyway");
if (Ifn
!= -1 && Role
== MASTER
) {
write(Ofn
, EOTMSG
, strlen(EOTMSG
));
sprintf(msg
, "call to %s ", Rmtname
);
if (mlock(Rmtname
) != SUCCESS
) {
Ofn
= Ifn
= conn(Rmtname
);
/* avoid excessive 'wrong time' info */
if (Stattype
[-Ofn
] != SS_WRONGTIME
){
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(rflags
, "-x%d", Debug
);
if (MaxGrade
!= '\177') {
sprintf(buf
, " -p%c -vgrade=%c", MaxGrade
, MaxGrade
);
sprintf(msg
, "%s -Q%d %s", Myname
, seq
, rflags
);
DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade
);
DEBUG(4, "msg-%s\n", msg
);
logent("imsg 2", _FAILED
);
logent("BAD SEQ", "FAILED HANDSHAKE");
systat(Rmtname
, SS_BADSEQ
, Stattext
[SS_BADSEQ
]);
if (strcmp(&msg
[1], "OK") != SAME
) {
logent(&msg
[1], "FAILED HANDSHAKE");
systat(Rmtname
, SS_INPROGRESS
,
strcmp(&msg
[1], "CB") == SAME
?
"AWAITING CALLBACK": "FAILED HANDSHAKE");
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
, ret
> 0 ? "CONVERSATION 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
;
(void) ioctl(0, TCSETA
, &Savettyb
);
(void) ioctl(0, TIOCHPCL
, STBNULL
);
(void) ioctl(0, TIOCCDTR
, STBNULL
);
(void) ioctl(0, TIOCSDTR
, STBNULL
);
(void) ioctl(0, TIOCGETP
, &Hupvec
);
(void) ioctl(0, TIOCSETP
, &Hupvec
);
(void) ioctl(0, TIOCSETP
, &Savettyb
);
/* make *sure* exclusive access is off */
(void) ioctl(0, TIOCNXCL
, STBNULL
);
write(Ofn
, EOTMSG
, strlen(EOTMSG
));
/* reenable logins on dialout */
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
&& strncmp(Rmtname
, Myname
, MAXBASENAME
))
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.
if (Debug
&& !StdErrIsTty
) {
sprintf(buf
,"%s/%s", RMTDEBUG
, Rmtname
);
freopen(buf
, "w", stderr
);
* fixmode(tty) fix kill/echo/raw on line
ioctl(tty
, TCGETA
, &ttbuf
);
ttbuf
.c_iflag
= ttbuf
.c_oflag
= ttbuf
.c_lflag
= (ushort
)0;
ttbuf
.c_cflag
&= (CBAUD
);
ttbuf
.c_cflag
|= (CS8
|CREAD
);
ioctl(tty
, TCSETA
, &ttbuf
);
ioctl(tty
, TIOCGETP
, &ttbuf
);
ttbuf
.sg_flags
= (ANYP
| RAW
);
ioctl(tty
, TIOCSETP
, &ttbuf
);
ioctl(tty
, TIOCEXCL
, STBNULL
);
* timeout() catch SIGALRM routine
logent(Rmtname
, "TIMEOUT");
if (*Rmtname
&& strncmp(Rmtname
, Myname
, MAXBASENAME
)) {
systat(Rmtname
, SS_FAIL
, "TIMEOUT");