+/*
+ * 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.
+ */
+
+#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 4.15 (Berkeley) %G%";
-#endif
+static char sccsid[] = "@(#)tip.c 5.12 (Berkeley) %G%";
+#endif /* not lint */
/*
* tip - UNIX link to other systems
* cu phone-number [-s speed] [-l line] [-a acu]
*/
#include "tip.h"
+#include "pathnames.h"
/*
* Baud rate mapping table
};
int disc = OTTYDISC; /* tip normally runs this way */
-int intprompt();
-int timeout();
-int cleanup();
+void intprompt();
+void timeout();
+void cleanup();
char *sname();
-extern char *sprintf();
+char PNbuf[256]; /* This limits the size of a number */
main(argc, argv)
char *argv[];
register char *p;
char sbuf[12];
+ gid = getgid();
+ egid = getegid();
+ uid = getuid();
+ euid = geteuid();
if (equal(sname(argv[0]), "cu")) {
- cumain(argc, argv);
cumode = 1;
+ cumain(argc, argv);
goto cucommon;
}
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++)
- if (isalpha(*p))
- goto notnumber;
- PN = system; /* system name is really a phone number */
- system = sprintf(sbuf, "tip%d", BR);
+ *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);
+ (void)signal(SIGINT, cleanup);
+ (void)signal(SIGQUIT, cleanup);
+ (void)signal(SIGHUP, cleanup);
+ (void)signal(SIGTERM, cleanup);
if ((i = hunt(system)) == 0) {
printf("all ports busy\n");
}
if (i == -1) {
printf("link down\n");
- delock(uucplock);
+ (void)uu_unlock(uucplock);
exit(3);
}
setbuf(stdout, NULL);
loginit();
- /*
- * 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
- * will be bypassed.
- */
- setgid(getgid());
- setuid(getuid());
/*
* 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";
+ PH = _PATH_PHONES;
vinit(); /* init variables */
- setparity(); /* set the parity table */
+ setparity("even"); /* set the parity table */
if ((i = speed(number(value(BAUDRATE)))) == NULL) {
printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
- delock(uucplock);
+ (void)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();
+
/*
* Hardwired connections require the
* line speed set before they make any transmissions
ttysetup(i);
if (p = connect()) {
printf("\07%s\n[EOT]\n", p);
- delock(uucplock);
+ daemon_uid();
+ (void)uu_unlock(uucplock);
exit(1);
}
if (!HW)
* 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);
raw();
pipe(fildes); pipe(repdes);
- signal(SIGALRM, timeout);
+ (void)signal(SIGALRM, timeout);
/*
* Everything's set up now:
- * connection established (hardwired or diaulup)
+ * 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.
/*NOTREACHED*/
}
+void
cleanup()
{
- delock(uucplock);
+ daemon_uid();
+ (void)uu_unlock(uucplock);
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
*/
register char *p;
{
register char *b = p;
- int (*oint)(), (*oquit)();
+ sig_t oint, oquit;
stoprompt = 0;
oint = signal(SIGINT, intprompt);
- oint = signal(SIGQUIT, SIG_IGN);
+ oquit = signal(SIGQUIT, SIG_IGN);
unraw();
printf("%s", s);
if (setjmp(promptbuf) == 0)
*p = '\0';
raw();
- signal(SIGINT, oint);
- signal(SIGQUIT, oint);
+ (void)signal(SIGINT, oint);
+ (void)signal(SIGQUIT, oquit);
return (stoprompt || p == b);
}
/*
* Interrupt service routine during prompting
*/
+void
intprompt()
{
- signal(SIGINT, SIG_IGN);
+ (void)signal(SIGINT, SIG_IGN);
stoprompt = 1;
printf("\r\n");
longjmp(promptbuf, 1);
gch = (getchar()&0177);
for (p = etable; p->e_char; p++)
if (p->e_char == gch) {
- if ((p->e_flags&PRIV) && getuid())
+ if ((p->e_flags&PRIV) && uid)
continue;
printf("%s", ctrl(c));
(*p->e_func)(gch);
printf("%c\r\n", c);
for (p = etable; p->e_char; p++) {
- if ((p->e_flags&PRIV) && getuid())
+ if ((p->e_flags&PRIV) && uid)
continue;
printf("%2s", ctrl(character(value(ESCAPE))));
printf("%-2s %c %s\r\n", ctrl(p->e_char),
}
static char partab[0200];
+static int bits8;
/*
* Do a write to the remote machine with the correct parity.
{
register int i;
register char *bp;
+ extern int errno;
bp = buf;
- for (i = 0; i < n; i++) {
- *bp = partab[(*bp) & 0177];
- bp++;
+ if (bits8 == 0)
+ for (i = 0; i < n; i++) {
+ *bp = partab[(*bp) & 0177];
+ bp++;
+ }
+ if (write(fd, buf, n) < 0) {
+ if (errno == EIO)
+ abort("Lost carrier.");
+ /* this is questionable */
+ perror("write");
}
- write(fd, buf, n);
}
/*
* Build a parity table with appropriate high-order bit.
*/
-setparity()
+setparity(defparity)
+ char *defparity;
{
register int i;
char *parity;
extern char evenpartab[];
if (value(PARITY) == NOSTR)
- value(PARITY) = "even";
+ value(PARITY) = defparity;
parity = value(PARITY);
+ if (equal(parity, "none")) {
+ bits8 = 1;
+ return;
+ } else
+ bits8 = 0;
for (i = 0; i < 0200; i++)
partab[i] = evenpartab[i];
if (equal(parity, "even"))
partab[i] ^= 0200; /* reverse bit 7 */
return;
}
- if (equal(parity, "none") || equal(parity, "zero")) {
+ if (equal(parity, "zero")) {
for (i = 0; i < 0200; i++)
partab[i] &= ~0200; /* turn off bit 7 */
return;