date and time created 83/02/24 12:55:54 by mckusick
[unix-history] / usr / src / usr.bin / tip / tip.c
CommitLineData
d080fb0b 1/* tip.c 4.12 82/07/29 */
3f48242d 2
5f50159a 3/*
3f48242d 4 * tip - UNIX link to other systems
5f50159a 5 * tip [-v] [-speed] system-name
3f48242d
SL
6 * or
7 * cu phone-number [-s speed] [-l line] [-a acu]
5f50159a 8 */
5f50159a
BJ
9#include "tip.h"
10
11/*
12 * Baud rate mapping table
13 */
14int bauds[] = {
15 0, 50, 75, 110, 134, 150, 200, 300, 600,
16 1200, 1800, 2400, 4800, 9600, 19200, -1
17};
18
4b675d70
SL
19#ifdef VMUNIX
20int disc = OTTYDISC; /* tip normally runs this way */
21#endif
22
5f50159a
BJ
23int intprompt();
24int timeout();
3f48242d 25int cleanup();
c731dacc
BS
26char *sname();
27extern char *sprintf();
5f50159a
BJ
28
29main(argc, argv)
d8feebc2 30 char *argv[];
5f50159a
BJ
31{
32 char *system = NOSTR;
33 register int i;
c731dacc
BS
34 register char *p;
35 char sbuf[12];
5f50159a 36
c731dacc 37 if (equal(sname(argv[0]), "cu")) {
3f48242d
SL
38 cumain(argc, argv);
39 cumode = 1;
40 goto cucommon;
41 }
42
5f50159a
BJ
43 if (argc > 4) {
44 fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
45 exit(1);
46 }
47 if (!isatty(0)) {
48 fprintf(stderr, "tip: must be interactive\n");
49 exit(1);
50 }
c731dacc
BS
51
52 for (; argc > 1; argv++, argc--) {
53 if (argv[1][0] != '-')
54 system = argv[1];
55 else switch (argv[1][1]) {
56
57 case 'v':
58 vflag++;
59 break;
60
61 case '0': case '1': case '2': case '3': case '4':
62 case '5': case '6': case '7': case '8': case '9':
63 BR = atoi(&argv[1][1]);
64 break;
65
66 default:
67 fprintf(stderr, "tip: %s, unknown option\n", argv[1]);
68 break;
69 }
70 }
71
d080fb0b
BS
72 if (system == NOSTR)
73 goto notnumber;
c731dacc
BS
74 for (p = system; *p; p++)
75 if (isalpha(*p))
76 goto notnumber;
77 PN = system; /* system name is really a phone number */
78 system = sprintf(sbuf, "tip%d", BR);
79
80notnumber:
5f50159a
BJ
81 signal(SIGINT, cleanup);
82 signal(SIGQUIT, cleanup);
83 signal(SIGHUP, cleanup);
84 signal(SIGTERM, cleanup);
f0211bf2 85
5f50159a
BJ
86 if ((i = hunt(system)) == 0) {
87 printf("all ports busy\n");
88 exit(3);
89 }
90 if (i == -1) {
91 printf("link down\n");
1603e05e 92 delock(uucplock);
5f50159a
BJ
93 exit(3);
94 }
eaa86232 95 setbuf(stdout, NULL);
5f50159a
BJ
96 loginit();
97 /*
98 * Now that we have the logfile and the ACU open
99 * return to the real uid and gid. These things will
100 * be closed on exit. Note that we can't run as root,
101 * because locking mechanism on the tty and the accounting
102 * will be bypassed.
103 */
104 setuid(getuid());
105 setgid(getgid());
c731dacc 106
5f50159a
BJ
107 /*
108 * Kludge, their's no easy way to get the initialization
109 * in the right order, so force it here
110 */
111 if ((PH = getenv("PHONES")) == NOSTR)
112 PH = "/etc/phones";
113 vinit(); /* init variables */
4b675d70 114 if ((i = speed(number(value(BAUDRATE)))) == NULL) {
5f50159a
BJ
115 printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
116 delock(uucplock);
117 exit(3);
118 }
f0211bf2 119
4b675d70
SL
120 /*
121 * Hardwired connections require the
122 * line speed set before they make any transmissions
123 * (this is particularly true of things like a DF03-AC)
124 */
125 if (HW)
126 ttysetup(i);
f0211bf2
SL
127 if (p = connect()) {
128 printf("\07%s\n[EOT]\n", p);
129 delock(uucplock);
130 exit(1);
131 }
4b675d70
SL
132 if (!HW)
133 ttysetup(i);
3f48242d 134cucommon:
5f50159a 135 /*
3f48242d
SL
136 * From here down the code is shared with
137 * the "cu" version of tip.
5f50159a 138 */
4b675d70
SL
139 ioctl(0, TIOCGETP, (char *)&defarg);
140 ioctl(0, TIOCGETC, (char *)&defchars);
5d1f1475 141#ifdef VMUNIX
4b675d70 142 ioctl(0, TIOCGETD, (char *)&odisc);
5d1f1475 143#endif
5f50159a
BJ
144 arg = defarg;
145 arg.sg_flags = ANYP | CBREAK;
146 tchars = defchars;
147 tchars.t_intrc = tchars.t_quitc = -1;
5f50159a 148 raw();
4b675d70 149
5f50159a
BJ
150 pipe(fildes); pipe(repdes);
151 signal(SIGALRM, timeout);
f0211bf2
SL
152
153 /*
154 * Everything's set up now:
155 * connection established (hardwired or diaulup)
156 * line conditioned (baud rate, mode, etc.)
157 * internal data structures (variables)
158 * so, fork one process for local side and one for remote.
159 */
3f48242d 160 printf(cumode ? "Connected\r\n" : "\07connected\r\n");
5f50159a
BJ
161 if (pid = fork())
162 tipin();
163 else
164 tipout();
165 /*NOTREACHED*/
166}
167
5f50159a
BJ
168cleanup()
169{
170 delock(uucplock);
f0211bf2
SL
171#ifdef VMUNIX
172 if (odisc)
173 ioctl(0, TIOCSETD, (char *)&odisc);
174#endif
5f50159a
BJ
175 exit(0);
176}
177
178/*
179 * put the controlling keyboard into raw mode
180 */
181raw()
182{
183 ioctl(0, TIOCSETP, &arg);
184 ioctl(0, TIOCSETC, &tchars);
4b675d70
SL
185#ifdef VMUNIX
186 ioctl(0, TIOCSETD, (char *)&disc);
187#endif
5f50159a
BJ
188}
189
190
191/*
192 * return keyboard to normal mode
193 */
194unraw()
195{
4b675d70
SL
196#ifdef VMUNIX
197 ioctl(0, TIOCSETD, (char *)&odisc);
198#endif
199 ioctl(0, TIOCSETP, (char *)&defarg);
200 ioctl(0, TIOCSETC, (char *)&defchars);
5f50159a
BJ
201}
202
203/*
204 * Print string ``s'', then read a string
205 * in from the terminal. Handles signals & allows use of
206 * normal erase and kill characters.
207 */
208prompt(s, p)
209 char *s;
210 register char *p;
211{
212 register char *b = p;
213
214 stoprompt = 0;
215 signal(SIGINT, intprompt);
216 signal(SIGQUIT, SIG_IGN);
217 unraw();
218 printf("%s", s);
219 while ((*p = getchar()) != EOF && *p != '\n') {
220 if (stoprompt)
221 goto pbreak;
222 p++;
223 }
224 *p = '\0';
225pbreak:
226 raw();
227 signal(SIGINT, SIG_DFL);
228 signal(SIGQUIT,SIG_DFL);
229 return(stoprompt || p == b);
230}
231
232/*
233 * Interrupt service routine during prompting
234 */
235intprompt()
236{
237 signal(SIGINT, SIG_IGN);
238 stoprompt = 1;
239 printf("\r\n");
240}
241
242/*
243 * ****TIPIN TIPIN****
244 */
245tipin()
246{
247 char gch, bol = 1;
248
388a70dc
SL
249 /*
250 * Kinda klugey here...
251 * check for scripting being turned on from the .tiprc file,
252 * but be careful about just using setscript(), as we may
253 * send a SIGEMT before tipout has a chance to set up catching
254 * it; so wait a second, then setscript()
255 */
256 if (boolean(value(SCRIPT))) {
257 sleep(1);
258 setscript();
259 }
260
5f50159a
BJ
261 while (1) {
262 gch = getchar()&0177;
263 if ((gch == character(value(ESCAPE))) && bol) {
264 if (!(gch = escape()))
265 continue;
3f48242d 266 } else if (!cumode && gch == character(value(RAISECHAR))) {
5f50159a 267 boolean(value(RAISE)) = !boolean(value(RAISE));
5f50159a
BJ
268 continue;
269 } else if (gch == '\r') {
270 bol = 1;
271 write(FD, &gch, 1);
272 continue;
3f48242d 273 } else if (!cumode && gch == character(value(FORCE)))
5f50159a 274 gch = getchar()&0177;
5f50159a
BJ
275 bol = any(gch, value(EOL));
276 if (boolean(value(RAISE)) && islower(gch))
277 toupper(gch);
278 write(FD, &gch, 1);
279 }
280}
281
282/*
283 * Escape handler --
284 * called on recognition of ``escapec'' at the beginning of a line
285 */
286escape()
287{
288 register char gch;
289 register esctable_t *p;
290 char c = character(value(ESCAPE));
291 extern esctable_t etable[];
292
293 gch = (getchar()&0177);
294 for (p = etable; p->e_char; p++)
295 if (p->e_char == gch) {
296 if ((p->e_flags&PRIV) && getuid())
297 continue;
298 printf("%s", ctrl(c));
299 (*p->e_func)(gch);
300 return(0);
301 }
62f62be8
SL
302 /* ESCAPE ESCAPE forces ESCAPE */
303 if (c != gch)
304 write(FD, &c, 1);
5f50159a
BJ
305 return(gch);
306}
307
308speed(n)
309{
310 register int *p;
311
312 for (p = bauds; *p != -1; p++)
313 if (*p == n)
314 return(p-bauds);
315 return(NULL);
316}
317
318any(c, p)
319 register char c, *p;
320{
d080fb0b 321 if (p)
5f50159a
BJ
322 while (*p)
323 if (*p++ == c)
324 return(1);
325 return(0);
326}
327
328size(s)
329 register char *s;
330{
331 register int i = 0;
332
333 while (*s++) i++;
334 return(i);
335}
336
337char *
338interp(s)
339 register char *s;
340{
341 static char buf[256];
342 register char *p = buf, c, *q;
343
344 while (c = *s++) {
345 for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
346 if (*q++ == c) {
347 *p++ = '\\'; *p++ = *q;
348 goto next;
349 }
350 if (c < 040) {
351 *p++ = '^'; *p++ = c + 'A'-1;
352 } else if (c == 0177) {
353 *p++ = '^'; *p++ = '?';
354 } else
355 *p++ = c;
356 next:
357 ;
358 }
359 *p = '\0';
360 return(buf);
361}
362
363char *
364ctrl(c)
365 char c;
366{
367 static char s[3];
368
369 if (c < 040 || c == 0177) {
370 s[0] = '^';
371 s[1] = c == 0177 ? '?' : c+'A'-1;
372 s[2] = '\0';
373 } else {
374 s[0] = c;
375 s[1] = '\0';
376 }
377 return(s);
378}
379
380/*
381 * Help command
382 */
383help(c)
384 char c;
385{
386 register esctable_t *p;
387 extern esctable_t etable[];
388
389 printf("%c\r\n", c);
390 for (p = etable; p->e_char; p++) {
391 if ((p->e_flags&PRIV) && getuid())
392 continue;
393 printf("%2s", ctrl(character(value(ESCAPE))));
394 printf("%-2s %c %s\r\n", ctrl(p->e_char),
395 p->e_flags&EXP ? '*': ' ', p->e_help);
396 }
397}
4b675d70
SL
398
399/*
400 * Set up the "remote" tty's state
401 */
4b675d70
SL
402ttysetup(speed)
403{
404#ifdef VMUNIX
405 unsigned bits = LDECCTQ;
406#endif
407
408 arg.sg_ispeed = arg.sg_ospeed = speed;
409 arg.sg_flags = TANDEM|RAW;
410 ioctl(FD, TIOCSETP, (char *)&arg);
411#ifdef VMUNIX
412 ioctl(FD, TIOCLBIS, (char *)&bits);
413#endif
414}
c731dacc
BS
415
416/*
417 * Return "simple" name from a file name,
418 * strip leading directories.
419 */
420char *
421sname(s)
422 register char *s;
423{
424 register char *p = s;
425
426 while (*s)
427 if (*s++ == '/')
428 p = s;
429 return (p);
430}