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