This is tip.c in view mode; [Download] [Up]
char *tipx_rev = "x1.21";
#define PATCHLEVEL 1
/*
* Copyright (c) 1983 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* Modifications by Warren Tucker <wht%n4hgf.uucp@emory.mathcs.emory.edu>
* for eight-bit transparent pass through and file transfer protocols
* are unencumbered in any way. They are yours, ours, everybody's, nobody's.
*/
/*+:EDITS:*/
/*:05-08-1990-15:05-wht@n4hgf-rawthru */
/*:05-08-1990-15:00-wht@n4hgf-move tip.c original to tip-orig.c */
#ifndef lint
char copyright[] =
"@(#) Copyright(c) 1983 The Regents of the University of California.\n\
All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)tip.c 5.8 (Berkeley) 9/2/88 (mod by wht@n4hgf)";
#endif /* not lint */
/*
* tip - UNIX link to other systems
* tip [-psv] [-speed] system-name [data]
* or
* cu phone-number [-s speed] [-l line] [-a acu]
*/
#include "tip.h"
/*
* Baud rate mapping table
*/
int bauds[] =
{
0,50,75,110,134,150,200,300,600,
1200,1800,2400,4800,9600,19200,38400,-1
};
#ifdef TIPX
int rawthru = 0;
char *rawthru_msg = "\r\n--> raw tip: 3 ~ rapidly for ~ equivalent\r\n";
char *no_rawthru_msg = "\r\n--> normal tip: 1 ~ == ~\r\n";
extern char opened_tty[];
#endif
int page;
int disc = OTTYDISC; /* tip normally runs this way */
sigfunc_t intprompt();
sigfunc_t timeout();
sigfunc_t cleanup();
char *login();
char *sname();
char PNbuf[256]; /* This limits the size of a number */
struct sgttyb ttyarg;
#ifdef TIPX
typedef struct b_to_br
{
char *baud_rate;
int B_code;
} B_TO_BR;
B_TO_BR speeds[] = /* ordered to put less common rates later in table */
{ /* and the vagaries of baud rates above 9600 "handled" */
"2400", B2400,
"1200", B1200,
"9600", B9600,
#if defined(B19200)
"19200",B19200,
#endif
#if defined(B38400)
"38400",B38400,
#endif
"4800", B4800,
"300", B300,
"110", B110,
"600", B600,
"75", B75,
"50", B50,
"HUP", B0,
"EXTA", EXTA,
"EXTB", EXTB,
(char *)0,0
};
#endif /* TIPX */
/*+-------------------------------------------------------------------------
B_to_baud_rate(code) - convert CBAUD B_ code to baud rate string
--------------------------------------------------------------------------*/
#ifdef TIPX
char *
B_to_baud_rate(code)
int code;
{
register int n;
for(n=0; speeds[n].baud_rate; n++)
if(speeds[n].B_code == code)
return(speeds[n].baud_rate);
return("-----");
} /* end of B_to_baud_rate */
#endif /* TIPX */
main(argc,argv)
char *argv[];
{
int uuid;
char *system = NOSTR;
char *data = NOSTR;
register int i;
register char *p;
char sbuf[12];
uid = getuid();
gid = getgid();
euid = geteuid(); /* should be root */
egid = getegid();
uuid = getuucpuid();
if(equal(sname(argv[0]),"cu"))
{
setreuid(uid,uuid);
cumode = 1;
cumain(argc,argv);
goto cucommon;
}
if(argc < 2)
{
/**
fprintf(stderr,"usage: tip [-psv] [-speed] [system-name] [data]\n");
**/
fprintf(stderr,"usage: tip [-v] [-speed] [system-name] [data]\n");
exit(1);
}
for(; argc > 1; argv++,argc--)
{
if(argv[1][0] != '-')
{
if(system)
data = argv[1];
else
system = argv[1];
}
else switch(argv[1][1])
{
/***
case 'p':
page++;
break;
case 's':
slip++;
break;
***/
case 'v':
vflag++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
BR = atoi(&argv[1][1]);
break;
default:
fprintf(stderr,"tip: %s, unknown option\n",argv[1]);
break;
}
}
/**
if(!isatty(0) && !slip && !page)
{
fprintf(stderr,"tip: warning: input is not a tty\n");
}
if(slip)
{
setreuid(euid,uuid);
uid = 0;
}
else
{
setreuid(uid,uuid);
}
euid = uuid;
**/
if(system == NOSTR)
goto notnumber;
if(isalpha(*system))
goto notnumber;
/*
* System name is really a phone number...
* Copy the number then stomp on the original (in case the number
* is private, we don't want 'ps' or 'w' to find it).
*/
if(strlen(system) > sizeof PNbuf - 1)
{
fprintf(stderr,"tip: phone number too long (max = %d bytes)\n",
sizeof PNbuf - 1);
exit(1);
}
strncpy( PNbuf,system,sizeof PNbuf - 1 );
for(p = system; *p; p++)
*p = '\0';
PN = PNbuf;
(void)sprintf(sbuf,"tip%d",BR);
system = sbuf;
notnumber:
signal(SIGINT,cleanup);
signal(SIGQUIT,cleanup);
signal(SIGHUP,cleanup);
signal(SIGTERM,cleanup);
signal(SIGPIPE,cleanup);
if((i = hunt(system)) == 0)
{
printf("all ports busy\n");
exit(3);
}
if(i == -1)
{
printf("link down\n");
(void)uu_unlock(uucplock);
exit(3);
}
setbuf(stdout,NULL);
loginit();
/*
* Kludge, their's no easy way to get the initialization
* in the right order, so force it here
*/
if((PH = getenv("PHONES")) == NOSTR)
PH = "/etc/phones";
vinit(); /* init variables */
setparity("none"); /* set the parity table */
if((i = speed(number(value(BAUDRATE)))) == 0)
{
printf("tip: bad baud rate %d\n",number(value(BAUDRATE)));
(void)uu_unlock(uucplock);
exit(3);
}
/***
if(slip)
{
if(SA == NOSTR)
{
printf("tip: local addr not set\n");
uu_unlock(uucplock);
exit(3);
}
if(DA == NOSTR)
{
printf("tip: destination addr not set\n");
uu_unlock(uucplock);
exit(3);
}
if(SM == NOSTR)
{
printf("tip: slip netmask not set\n");
uu_unlock(uucplock);
exit(3);
}
}
***/
/*
* Now that we have the logfile and the ACU open
* return to the real uid and gid. These things will
* be closed on exit. Swap real and effective uid's
* so we can get the original permissions back
* for removing the uucp lock.
*/
user_uid(); /* in the case of slip, we are now priviliged */
/*
* Hardwired connections require the
* line speed set before they make any transmissions
* (this is particularly true of things like a DF03-AC)
*/
if(HW)
ttysetup(i);
if(p = lconnect())
{
printf("\07%s\n[EOT]\n",p);
daemon_uid();
(void)uu_unlock(uucplock);
exit(1);
}
if(!HW)
ttysetup(i);
/****
if(LS != NOSTR)
{
fprintf(stderr,"\07[Logging in...]\r\n");
if(p = login())
{
printf("\07%s\n[EOT]\n",p);
daemon_uid();
(void)uu_unlock(uucplock);
exit(1);
}
}
if(page)
{
i = sendpage(data);
daemon_uid();
(void)uu_unlock(uucplock);
exit(i);
}
if(slip)
{
i = runslip();
daemon_uid();
(void)uu_unlock(uucplock);
exit(i);
}
***/
cucommon:
/*
* From here down the code is shared with
* the "cu" version of tip.
*/
ioctl(0,TIOCGETP,(char *)&defarg);
ioctl(0,TIOCGETC,(char *)&defchars);
ioctl(0,TIOCGLTC,(char *)&deflchars);
ioctl(0,TIOCGETD,(char *)&odisc);
arg = defarg;
#ifdef TIPX
arg.sg_flags = CBREAK;
#else
arg.sg_flags = ANYP | CBREAK;
#endif
tchars = defchars;
tchars.t_intrc = tchars.t_quitc = -1;
ltchars = deflchars;
ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc
= ltchars.t_lnextc = -1;
raw();
pipe(fildes);
pipe(repdes);
signal(SIGALRM,timeout);
/*
* Everything's set up now:
* connection established (hardwired or dialup)
* line conditioned (baud rate, mode, etc.)
* internal data structures (variables)
* so, fork one process for local side and one for remote.
*/
#ifdef TIPX
printf("tipx (tip 4.3 mod by wht@n4hgf %s.%02d) connected to %s\r\n",
tipx_rev,PATCHLEVEL,opened_tty);
fputs("Copyright (c) 1983 The Regents of the University of California.\r\n",
stdout);
printf("line speed = %s, tandem = %s\r\n",
B_to_baud_rate(ttyarg.sg_ospeed),
(ttyarg.sg_flags & TANDEM) ? "yes" : "no");
#else
printf(cumode ? "Connected\r\n" : "\07connected\r\n");
#endif
if(pid = fork())
tipin();
else
tipout();
/*NOTREACHED*/
}
sigfunc_t
cleanup()
{
daemon_uid();
(void)uu_unlock(uucplock);
if(pid)
{
(void) kill(pid,SIGTERM);
unraw();
}
else if(odisc)
ioctl(0,TIOCSETD,(char *)&odisc);
exit(0);
}
/*
* Muck with user ID's. We are setuid to the owner of the lock
* directory when we start. user_uid() reverses real and effective
* ID's after startup, to run with the user's permissions.
* daemon_uid() switches back to the privileged uid for unlocking.
* Finally, to avoid running a shell with the wrong real uid,
* shell_uid() sets real and effective uid's to the user's real ID.
*/
static int uidswapped;
user_uid()
{
if(uidswapped == 0)
{
setregid(egid,gid);
setreuid(euid,uid);
uidswapped = 1;
}
}
daemon_uid()
{
if(uidswapped)
{
setreuid(uid,euid);
setregid(gid,egid);
uidswapped = 0;
}
}
shell_uid()
{
setreuid(uid,uid);
setregid(gid,gid);
}
/*
* put the controlling keyboard into raw mode
*/
raw()
{
ioctl(0,TIOCSETP,&arg);
ioctl(0,TIOCSETC,&tchars);
ioctl(0,TIOCSLTC,<chars);
ioctl(0,TIOCSETD,(char *)&disc);
}
/*
* return keyboard to normal mode
*/
unraw()
{
ioctl(0,TIOCSETD,(char *)&odisc);
ioctl(0,TIOCSETP,(char *)&defarg);
ioctl(0,TIOCSETC,(char *)&defchars);
ioctl(0,TIOCSLTC,(char *)&deflchars);
}
static jmp_buf promptbuf;
/*
* Print string ``s'', then read a string
* in from the terminal. Handles signals & allows use of
* normal erase and kill characters.
*/
prompt(s,p)
char *s;
register char *p;
{
register char *b = p;
sigfunc_t(*oint)(),(*oquit)();
stoprompt = 0;
oint = signal(SIGINT,intprompt);
oquit = signal(SIGQUIT,SIG_IGN);
unraw();
printf("%s",s);
if(setjmp(promptbuf) == 0)
while((*p = getchar()) != EOF && *p != '\n')
p++;
*p = '\0';
raw();
signal(SIGINT,oint);
signal(SIGQUIT,oint);
return(stoprompt || p == b);
}
/*
* Interrupt service routine during prompting
*/
sigfunc_t
intprompt()
{
signal(SIGINT,SIG_IGN);
stoprompt = 1;
printf("\r\n");
longjmp(promptbuf,1);
}
/*
* ****TIPIN TIPIN****
*/
tipin()
{
char gch,bol = 1;
/*
* Kinda klugey here...
* check for scripting being turned on from the .tiprc file,
* but be careful about just using setscript(), as we may
* send a SIGEMT before tipout has a chance to set up catching
* it; so wait a second, then setscript()
*/
if(boolean(value(SCRIPT)))
{
sleep(1);
setscript();
}
#ifdef TIPX
if(!rawthru)
goto NORMAL_TIP2;
RAWTHRU_TIP:
printf(rawthru_msg);
while(1)
{
long count;
char chbuf[4];
read(0,&gch,1);
if((gch == character(value(ESCAPE))))
{
sleep(1);
ioctl(0,FIONREAD,&count);
if(count == 2)
{ /* might have raw mode escape */
read(0,chbuf,2);
if((chbuf[0] == character(value(ESCAPE))) &&
(chbuf[1] == character(value(ESCAPE))))
{
printf("rawthru%s",ctrl(chbuf[0]));
if(!(gch = escape()))
{
if(!rawthru)
{
bol = 1;
goto NORMAL_TIP;
}
continue;
}
}
else
{
gch = character(value(ESCAPE));
write(FD,&gch,1);
write(FD,chbuf,2);
continue;
}
}
}
write(FD,&gch,1);
}
NORMAL_TIP:
printf(no_rawthru_msg);
NORMAL_TIP2:
#endif /* TIPX */
while(1)
{
gch = getchar()&0177;
if((gch == character(value(ESCAPE))) && bol)
{
if(!(gch = escape()))
#ifdef TIPX
{
if(rawthru)
goto RAWTHRU_TIP;
continue;
}
#else /* TIPX */
continue;
#endif /* TIPX */
}
else if(!cumode && gch == character(value(RAISECHAR)))
{
boolean(value(RAISE)) = !boolean(value(RAISE));
continue;
}
else if(gch == '\r')
{
bol = 1;
pwrite(FD,&gch,1);
if(boolean(value(HALFDUPLEX)))
printf("\r\n");
continue;
}
else if(!cumode && gch == character(value(FORCE)))
gch = getchar()&0177;
bol = any(gch,value(EOL));
if(boolean(value(RAISE)) && islower(gch))
gch = toupper(gch);
pwrite(FD,&gch,1);
if(boolean(value(HALFDUPLEX)))
printf("%c",gch);
}
}
/*
* Escape handler --
* called on recognition of ``escapec'' at the beginning of a line
*/
escape()
{
register char gch;
register esctable_t *p;
char c = character(value(ESCAPE));
extern esctable_t etable[];
gch = (getchar()&0177);
for(p = etable; p->e_char; p++)
if(p->e_char == gch)
{
if((p->e_flags&PRIV) && uid)
continue;
#ifdef TIPX
if(!rawthru)
#endif
printf("%s",ctrl(c));
(*p->e_func)(gch);
return(0);
}
/* ESCAPE ESCAPE forces ESCAPE */
if(c != gch)
pwrite(FD,&c,1);
return(gch);
}
speed(n)
int n;
{
register int *p;
for(p = bauds; *p != -1; p++)
if(*p == n)
return(p - bauds);
return(0);
}
any(c,p)
register char c,*p;
{
while(p && *p)
if(*p++ == c)
return(1);
return(0);
}
size(s)
register char *s;
{
register int i = 0;
while(s && *s++)
i++;
return(i);
}
char *
interp(s)
register char *s;
{
static char buf[256];
register char *p = buf,c,*q;
while(c = *s++)
{
for(q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
if(*q++ == c)
{
*p++ = '\\';
*p++ = *q;
goto next;
}
if(c < 040)
{
*p++ = '^';
*p++ = c + 'A'-1;
}
else if(c == 0177)
{
*p++ = '^';
*p++ = '?';
}
else
*p++ = c;
next:
;
}
*p = '\0';
return(buf);
}
char *
ctrl(c)
char c;
{
static char s[3];
if(c < 040 || c == 0177)
{
s[0] = '^';
s[1] = c == 0177 ? '?' : c+'A'-1;
s[2] = '\0';
}
else
{
s[0] = c;
s[1] = '\0';
}
return(s);
}
/*
* Help command
*/
help(c)
char c;
{
register esctable_t *p;
extern esctable_t etable[];
printf("%c\r\n",c);
for(p = etable; p->e_char; p++)
{
if((p->e_flags&PRIV) && uid)
continue;
printf("%2s",ctrl(character(value(ESCAPE))));
printf("%-2s %c %s\r\n",ctrl(p->e_char),
p->e_flags&EXP ? '*': ' ',p->e_help);
}
}
/*
* Set up the "remote" tty's state
*/
ttysetup(speed)
int speed;
{
unsigned bits = LDECCTQ;
ttyarg.sg_ispeed = ttyarg.sg_ospeed = speed;
ttyarg.sg_flags = RAW;
if(boolean(value(TAND)))
ttyarg.sg_flags |= TANDEM;
/***
if(boolean(value(DTRHUP)))
{
ioctl(FD,TIOCSDTR,0);
ioctl(FD,TIOCHPCL,0);
}
***/
ioctl(FD,TIOCSETP,(char *)&ttyarg);
ioctl(FD,TIOCLBIS,(char *)&bits);
}
/*
* Return "simple" name from a file name,
* strip leading directories.
*/
char *
sname(s)
register char *s;
{
register char *p = s;
while(*s)
if(*s++ == '/')
p = s;
return(p);
}
static char partab[0200];
/*
* Do a write to the remote machine with the correct parity.
* We are doing 8 bit wide output, so we just generate a character
* with the right parity and output it.
*/
pwrite(fd,buf,n)
int fd;
char *buf;
register int n;
{
register int i;
register char *bp;
extern int errno;
extern void tip_abort();
#ifdef TIPX
extern int rawthru;
if(rawthru)
{
write(fd,buf,n);
return;
}
#endif /* TIPX */
bp = buf;
for(i = 0; i < n; i++)
{
*bp = partab[(*bp) & 0177];
bp++;
}
if(write(fd,buf,n) < 0)
{
if(errno == EIO)
tip_abort("Lost carrier.");
/* this is questionable */
perror("write");
}
}
/*
* Build a parity table with appropriate high-order bit.
*/
setparity(defparity)
char *defparity;
{
register int i;
char *parity;
extern char evenpartab[];
if(value(PARITY) == NOSTR)
value(PARITY) = defparity;
parity = value(PARITY);
for(i = 0; i < 0200; i++)
partab[i] = evenpartab[i];
if(equal(parity,"even"))
return;
if(equal(parity,"odd"))
{
for(i = 0; i < 0200; i++)
partab[i] ^= 0200; /* reverse bit 7 */
return;
}
if(equal(parity,"none") || equal(parity,"zero"))
{
for(i = 0; i < 0200; i++)
partab[i] &= ~0200; /* turn off bit 7 */
return;
}
if(equal(parity,"one"))
{
for(i = 0; i < 0200; i++)
partab[i] |= 0200; /* turn on bit 7 */
return;
}
fprintf(stderr,"%s: unknown parity value\n",PA);
fflush(stderr);
}
/* The uid could be determined by stat()-ing ACULOG */
getuucpuid()
{
struct passwd *pw;
if((pw = getpwnam("uucp")) == NULL)
{
fprintf(stderr,"tip: unable to get uucp uid\n");
exit(1);
}
return(pw->pw_uid);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.