static char sccsid
[] = "@(#)tip.c 4.17 (Berkeley) %G%";
* tip - UNIX link to other systems
* tip [-v] [-speed] system-name
* cu phone-number [-s speed] [-l line] [-a acu]
* Baud rate mapping table
0, 50, 75, 110, 134, 150, 200, 300, 600,
1200, 1800, 2400, 4800, 9600, 19200, -1
int disc
= OTTYDISC
; /* tip normally runs this way */
if (equal(sname(argv
[0]), "cu")) {
fprintf(stderr
, "usage: tip [-v] [-speed] [system-name]\n");
fprintf(stderr
, "tip: must be interactive\n");
for (; argc
> 1; argv
++, argc
--) {
else switch (argv
[1][1]) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
fprintf(stderr
, "tip: %s, unknown option\n", argv
[1]);
for (p
= system
; *p
; p
++)
PN
= system
; /* system name is really a phone number */
system
= sprintf(sbuf
, "tip%d", BR
);
signal(SIGQUIT
, cleanup
);
signal(SIGTERM
, cleanup
);
if ((i
= hunt(system
)) == 0) {
printf("all ports busy\n");
* Now that we have the logfile and the ACU open
* return to the real uid and gid. These things will
* be closed on exit. Note that we can't run as root,
* because locking mechanism on the tty and the accounting
* Kludge, their's no easy way to get the initialization
* in the right order, so force it here
if ((PH
= getenv("PHONES")) == NOSTR
)
vinit(); /* init variables */
setparity("even"); /* set the parity table */
if ((i
= speed(number(value(BAUDRATE
)))) == NULL
) {
printf("tip: bad baud rate %d\n", number(value(BAUDRATE
)));
* Hardwired connections require the
* line speed set before they make any transmissions
* (this is particularly true of things like a DF03-AC)
printf("\07%s\n[EOT]\n", p
);
* 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
.sg_flags
= ANYP
| CBREAK
;
tchars
.t_intrc
= tchars
.t_quitc
= -1;
ltchars
.t_suspc
= ltchars
.t_dsuspc
= ltchars
.t_flushc
pipe(fildes
); pipe(repdes
);
signal(SIGALRM
, timeout
);
* Everything's set up now:
* connection established (hardwired or diaulup)
* line conditioned (baud rate, mode, etc.)
* internal data structures (variables)
* so, fork one process for local side and one for remote.
printf(cumode
? "Connected\r\n" : "\07connected\r\n");
ioctl(0, TIOCSETD
, (char *)&odisc
);
* put the controlling keyboard into raw mode
ioctl(0, TIOCSETP
, &arg
);
ioctl(0, TIOCSETC
, &tchars
);
ioctl(0, TIOCSLTC
, <chars
);
ioctl(0, TIOCSETD
, (char *)&disc
);
* return keyboard to normal mode
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.
int (*oint
)(), (*oquit
)();
oint
= signal(SIGINT
, intprompt
);
oint
= signal(SIGQUIT
, SIG_IGN
);
if (setjmp(promptbuf
) == 0)
while ((*p
= getchar()) != EOF
&& *p
!= '\n')
return (stoprompt
|| p
== b
);
* Interrupt service routine during prompting
* 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
))) {
if ((gch
== character(value(ESCAPE
))) && bol
) {
} else if (!cumode
&& gch
== character(value(RAISECHAR
))) {
boolean(value(RAISE
)) = !boolean(value(RAISE
));
} else if (gch
== '\r') {
if (boolean(value(HALFDUPLEX
)))
} else if (!cumode
&& gch
== character(value(FORCE
)))
bol
= any(gch
, value(EOL
));
if (boolean(value(RAISE
)) && islower(gch
))
if (boolean(value(HALFDUPLEX
)))
* called on recognition of ``escapec'' at the beginning of a line
char c
= character(value(ESCAPE
));
extern esctable_t etable
[];
for (p
= etable
; p
->e_char
; p
++)
if ((p
->e_flags
&PRIV
) && getuid())
/* ESCAPE ESCAPE forces ESCAPE */
for (p
= bauds
; *p
!= -1; p
++)
register char *p
= buf
, c
, *q
;
for (q
= "\nn\rr\tt\ff\033E\bb"; *q
; q
++)
*p
++ = '^'; *p
++ = c
+ 'A'-1;
if (c
< 040 || c
== 0177) {
s
[1] = c
== 0177 ? '?' : c
+'A'-1;
extern esctable_t etable
[];
for (p
= etable
; p
->e_char
; p
++) {
if ((p
->e_flags
&PRIV
) && getuid())
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
arg
.sg_ispeed
= arg
.sg_ospeed
= speed
;
if (boolean(value(TAND
)))
ioctl(FD
, TIOCSETP
, (char *)&arg
);
ioctl(FD
, TIOCLBIS
, (char *)&bits
);
* Return "simple" name from a file name,
* strip leading directories.
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.
for (i
= 0; i
< n
; i
++) {
*bp
= partab
[(*bp
) & 0177];
if (write(fd
, buf
, n
) < 0) {
/* this is questionable */
* Build a parity table with appropriate high-order bit.
extern char evenpartab
[];
if (value(PARITY
) == NOSTR
)
value(PARITY
) = defparity
;
for (i
= 0; i
< 0200; i
++)
partab
[i
] = evenpartab
[i
];
if (equal(parity
, "even"))
if (equal(parity
, "odd")) {
for (i
= 0; i
< 0200; i
++)
partab
[i
] ^= 0200; /* reverse bit 7 */
if (equal(parity
, "none") || equal(parity
, "zero")) {
for (i
= 0; i
< 0200; i
++)
partab
[i
] &= ~0200; /* turn off bit 7 */
if (equal(parity
, "one")) {
for (i
= 0; i
< 0200; i
++)
partab
[i
] |= 0200; /* turn on bit 7 */
fprintf(stderr
, "%s: unknown parity value\n", PA
);