static char *sccsid
= "@(#)cu.c 4.7 (Berkeley) 82/10/21";
* defs that come from uucp.h
#define SLCKTIME 5400 /* system/device timeout (LCK.. files) in seconds */
#define ASSERT(e, f, v) if (!(e)) {\
fprintf(stderr, "AERROR - (%s) ", "e");\
* cu telno [-t] [-s speed] [-l line] [-a acu] [-p]
* -t is for dial-out to terminal.
* speeds are: 110, 134, 150, 300, 1200, 2400. 300 is default.
* -p says strip parity of characters transmitted. (to compensate
* Escape with `~' at beginning of line.
* Ordinary diversions are ~<, ~> and ~>>.
* Silent output diversions are ~>: and ~>>:.
* Terminate output diversion with ~> alone.
* Quit is ~. and ~! gives local command or shell.
* Also ~$ for canned procedure pumping remote.
* ~%put from [to] and ~%take from [to] invoke builtins
#define wrc(ds) write(ds,&c,1)
char *devcul
= "/dev/cul0";
char *devcua
= "/dev/cua0";
int ln
; /* fd for comm line */
char tkill
, terase
; /* current input kill & erase */
int efk
; /* process of id of listener */
"usage: cu telno [-t] [-s speed] [-l line] [-a acu]",
int pflag
; /* strip parity on chars sent to remote */
int nullbrk
; /* turn breaks (nulls) into dels */
int pipes
[2] = { -1, -1 };
* main: get connection, set speed for line.
* spawn child to invoke rd to read from line, output to fd 1
* main line invokes wr to read tty, write to line
signal(SIGQUIT
, cleanup
);
for (; ac
> 1; av
++,ac
--) {
lspeed
= av
[2]; ++av
; --ac
;
devcul
= av
[2]; ++av
; --ac
;
devcua
= av
[2]; ++av
; --ac
;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
devcua
[strlen(devcua
)-1] = av
[1][1];
devcul
[strlen(devcul
)-1] = av
[1][1];
prf("Bad flag %s", av
[1]);
if (!exists(devcua
) || !exists(devcul
))
ln
= conn(devcul
, devcua
, telno
);
prf("Connect failed: %s",connmsg
[-ln
]);
stbuf
.sg_flags
= EVENP
|ODDP
;
ioctl(ln
, TIOCSETP
, &stbuf
);
ioctl(ln
, TIOCEXCL
, (struct sgttyb
*)NULL
);
ioctl(ln
, TIOCHPCL
, (struct sgttyb
*)NULL
);
nhup
= (int)signal(SIGINT
, SIG_IGN
);
if (fk
!= -1) kill(fk
, SIGKILL
);
ioctl(ln
, TIOCSETP
, &stbuf
);
* conn: establish dial-out connection.
* Example: fd = conn("/dev/ttyh","/dev/dn1","4500");
* Returns descriptor open to tty for reading and writing.
* Negative values (-1...-7) denote errors in connmsg.
* Uses alarm and fork/wait; requires sig14 handler.
* Be sure to disconnect tty when done, via HUPCL or stty 0.
atail
= rindex(acu
, '/')+1;
if (mlock(atail
) == FAIL
) {
ltail
= rindex(dev
, '/')+1;
if (mlock(ltail
) == FAIL
) {
if ((dn
=open(acu
,1))<0) {
if ((fk
=fork()) == (-1)) {
* copy phone #, assure EON
/*if (*(p-1)!='-') *p++='-';*/
xalarm(40); /* was 5; sometimes missed carrier */
ioctl(dh
, TIOCGETP
, &stbuf
);
ioctl(dh
, TIOCSETP
, &stbuf
);
ioctl(dh
, TIOCHPCL
, (struct sgttyb
*)NULL
);
while ((t
=wait((int *)NULL
))!=(-1) && t
!=fk
);
* wr: write to remote: 0 -> line.
* ~! local login-style shell
* ~!cmd execute cmd locally
* ~$proc execute proc locally, send output to line
* ~%cmd execute builtin cmd (put and take)
* ~^Z suspend cu process.
if (p
== b
) lcl
=(c
== '~');
if (p
== b
+1 && b
[0] == '~') lcl
=(c
!='~');
if (nullbrk
&& c
== 0) oc
=c
=0177; /* fake break kludge */
prf("line gone"); return;
if (c
== '\r' || c
== '\n') goto A
;
if (c
== tkill
|| c
== 0177 || c
== '\4' || c
== '\r' || c
== '\n') p
=b
;
char *shell
= getenv("SHELL");
if (shell
== 0) shell
= "/bin/sh";
if (!nhup
) signal(SIGINT
, SIG_DFL
);
if (b
[2] == 0) execl(shell
,shell
,0);
/* if (b[2] == 0) execl(shell,"-",0); */
else execl(shell
,"sh","-c",b
+2,0);
prf("Can't execute shell");
if (b
[1] == '!') echo("!");
if ((ds
=open(b
+2,0))<0) {
prf("Can't divert %s",b
+1);
if (!nhup
) signal(SIGINT
, sig2
);
while (!intr
&& rdc(ds
) == 1) {
prf("Can't tell other demon to divert");
write(pipes
[1],q
,strlen(q
)+1);
if(dbflag
) prf("msg to be delivered:"),prf(q
);
if (efk
!= -1) kill(efk
,SIGEMT
);
prf("Use `~~' to start line with `~'");
for (narg
= 0; narg
< 10;) {
while(*line
== ' ' || *line
== '\t')
while(*line
!= '\0' && *line
!= ' ' && *line
!= '\t')
if (equal(args
[0], "take")) {
prf("usage: ~%%take from [to]");
write(pipes
[1], ">:/dev/null",sizeof(">:/dev/null"));
if(dbflag
) prf("sending take message");
if (efk
!= -1) kill(efk
,SIGEMT
);
wrln("'; tee /dev/null <");
} else if (equal(args
[0], "put")) {
prf("usage: ~%%put from [to]");
if ((f
= open(args
[1], 0)) < 0) {
prf("cannot open: %s", args
[1]);
wrln("stty -echo;cat >");
while(!intr
&& rdc(f
) == 1) {
if (c
== tkill
|| c
== terase
)
prf("stopped after %d bytes", rcount
);
prf("~%%%s unknown\n", args
[0]);
/* chwrsig: Catch orders from wr process
static char dobuff
[128], morejunk
[256];
prf("About to read from pipe");
n
= read(pipes
[0],morejunk
,256);
prf("diversion mesg recieved is");
if (*msg
!='>' || (ds
=open(cp
,1))<0) ds
=creat(cp
,0644);
if(ds
< 0) prf("Creat failed:"), prf(cp
);
if (ds
<0) prf("Can't divert %s",cp
+1);
* rd: read from remote: line -> 1
* catch: diversion caught by interrupt routine
char rb
[600], lb
[600], *rlim
, *llim
, c
;
int cnt
, state
= 0, mustecho
, oldslnt
;
while((cnt
= read(ln
,rb
,600)) > 0) {
if(!slnt
) write(1,rb
,cnt
);
for( q
=rb
, rlim
= rb
+ cnt
- 1; q
<= rlim
; ) {
if(c
=='\r') state
= SAWCR
;
state
= (c
=='~' ? SAWTL
:
(c
=='\r' ? SAWCR
: ORDIN
));
state
= (c
=='>' ? DIVER
:
(c
=='\r' ? SAWCR
: ORDIN
));
write(ln
,CRLF
,sizeof(CRLF
));
c
= '\n'; /*force flush to file*/
struct {char lobyte
; char hibyte
;};
ioctl(0, TIOCGETP
, &stbuf
);
stbuf
.sg_flags
|= ECHO
|CRMOD
;
stbuf
.sg_flags
&= ~(ECHO
|CRMOD
);
stbuf
.sg_flags
&= ~(ECHO
|CRMOD
);
ioctl(0, TIOCSETP
, &stbuf
);
write(0,CRLF
, sizeof(CRLF
));
if (access(devname
, 0)==0)
prf("%s does not exist", devname
);
* This code is taken directly from uucp and follows the same
* conventions. This is important since uucp and cu should
* respect each others locks.
/* ulockf 3.2 10/26/79 11:40:29 */
* ulockf - this routine will create a lock file (file).
* If one already exists, the create time is checked for
* older than the age time (atime).
* If it is older, an attempt will be made to unlink it
static char tempfile
[NAMESIZE
];
sprintf(tempfile
, "/usr/spool/uucp/LTMP.%d", pid
);
if (onelock(pid
, tempfile
, file
) == -1) {
/* get status to check age of the lock file */
ret
= stat(file
, &stbuf
);
if ((ptime
- stbuf
.st_ctime
) < atime
) {
/* file not old enough to delete */
ret
= onelock(pid
, tempfile
, file
);
#define MAXLOCKS 10 /* maximum number of lock files */
char *Lockfile
[MAXLOCKS
];
* stlock(name) put name in list of lock files
for (i
= 0; i
< Nlocks
; i
++) {
ASSERT(i
< MAXLOCKS
, "TOO MANY LOCKS %d", i
);
p
= calloc(strlen(name
) + 1, sizeof (char));
ASSERT(p
!= NULL
, "CAN NOT ALLOCATE FOR %s", name
);
* rmlock(name) remove all lock files in list
for (i
= 0; i
< Nlocks
; i
++) {
|| strcmp(name
, Lockfile
[i
]) == SAME
) {
/* this stuff from pjw */
/* /usr/pjw/bin/recover - check pids to remove unnecessary locks */
/* isalock(name) returns 0 if the name is a lock */
/* unlock(name) unlocks name if it is a lock*/
/* onelock(pid,tempfile,name) makes lock a name
on behalf of pid. Tempfile must be in the same
/* lock(pid,tempfile,names) either locks all the
isalock(name
) char *name
;
if(stat(name
,&xstat
)<0) return(0);
if(xstat
.st_size
!=sizeof(int)) return(0);
if(isalock(name
)) return(unlink(name
));
onelock(pid
,tempfile
,name
) char *tempfile
,*name
;
write(fd
,(char *) &pid
,sizeof(int));
if(link(tempfile
,name
)<0)
lock(pid
,tempfile
,names
) char *tempfile
,**names
;
{ if(onelock(pid
,tempfile
,names
[i
])==0) continue;
for(j
=0;j
<i
;j
++) unlink(names
[j
]);
#define LOCKPRE "/usr/spool/uucp/LCK."
* delock(s) remove a lock file
sprintf(ln
, "%s.%s", LOCKPRE
, s
);
* mlock(sys) create system lock
sprintf(lname
, "%s.%s", LOCKPRE
, sys
);
return(ulockf(lname
, (time_t) SLCKTIME
) < 0 ? FAIL
: 0);
* ultouch() update access and modify times for lock files
ut
.actime
= time(&ut
.modtime
);
for (i
= 0; i
< Nlocks
; i
++) {