temporary kluge fix for setting script in .tiprc file
[unix-history] / usr / src / usr.bin / tip / tip.c
CommitLineData
388a70dc 1/* tip.c 4.3 81/05/18 */
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
46 */
47
48#include "tip.h"
49
50/*
51 * Baud rate mapping table
52 */
53int bauds[] = {
54 0, 50, 75, 110, 134, 150, 200, 300, 600,
55 1200, 1800, 2400, 4800, 9600, 19200, -1
56};
57
58int intprompt();
59int timeout();
60static int cleanup();
61
62main(argc, argv)
63char *argv[];
64{
65 char *system = NOSTR;
66 register int i;
67#ifdef VMUNIX
68 int disc;
69#endif
70 char *p;
71
72 if (argc > 4) {
73 fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
74 exit(1);
75 }
76 if (!isatty(0)) {
77 fprintf(stderr, "tip: must be interactive\n");
78 exit(1);
79 }
80 if (argc > 1 && argv[argc-1][0] != '-')
81 system = argv[argc-1]; /* always last item */
82 signal(SIGINT, cleanup);
83 signal(SIGQUIT, cleanup);
84 signal(SIGHUP, cleanup);
85 signal(SIGTERM, cleanup);
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");
92 exit(3);
93 }
eaa86232 94 setbuf(stdout, NULL);
5f50159a
BJ
95 loginit();
96 /*
97 * Now that we have the logfile and the ACU open
98 * return to the real uid and gid. These things will
99 * be closed on exit. Note that we can't run as root,
100 * because locking mechanism on the tty and the accounting
101 * will be bypassed.
102 */
103 setuid(getuid());
104 setgid(getgid());
105 for (i = 1; i < argc-1; i++)
106 if (equal(argv[i], "-v"))
107 vflag++;
108 /*
109 * Kludge, their's no easy way to get the initialization
110 * in the right order, so force it here
111 */
112 if ((PH = getenv("PHONES")) == NOSTR)
113 PH = "/etc/phones";
114 vinit(); /* init variables */
115 for (i = 1; i < argc-1; i++)
116 if (argv[i][0] == '-' && argv[i][1] != 'v') {
117 if (isnum(argv[i][1]))
118 number(value(BAUDRATE)) = atoi(&argv[i][1]);
119 else
120 printf("%s: unknown option\n", argv[i]);
121 }
122 if ((arg.sg_ispeed = speed(number(value(BAUDRATE)))) == NULL) {
123 printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
124 delock(uucplock);
125 exit(3);
126 }
127 arg.sg_ospeed = arg.sg_ispeed;
128 /*
129 * NOTE that remote side runs in TANDEM mode,
130 * if the host doesn't honor X-ON/X-OFF with default
131 * start/stop chars, the remote description must be
132 * extended and tchars will have to be set up here.
133 * If the host doesn't honor TANDEM mode, then watch
134 * out, as you'll get garbage.
135 */
136 arg.sg_flags = RAW | TANDEM;
137 ioctl(FD, TIOCSETP, &arg);
138
139 ioctl(0, TIOCGETP, &defarg); /* store initial status */
140 ioctl(0, TIOCGETC, &defchars);
141 arg = defarg;
142 arg.sg_flags = ANYP | CBREAK;
143 tchars = defchars;
144 tchars.t_intrc = tchars.t_quitc = -1;
145
146 if (p = connect()) {
147 printf("\07%s\n[EOT]\n", p);
148 delock(uucplock);
149 exit(1);
150 }
151 write(1, "\07connected\n", 11);
152 raw();
153#ifdef VMUNIX
154 ioctl(0, TIOCGETD, (char *)&odisc);
155 disc = OTTYDISC;
156 ioctl(0, TIOCSETD, (char *)&disc);
157#endif
158 pipe(fildes); pipe(repdes);
159 signal(SIGALRM, timeout);
160 if (pid = fork())
161 tipin();
162 else
163 tipout();
164 /*NOTREACHED*/
165}
166
167static
168cleanup()
169{
170 delock(uucplock);
171 exit(0);
172}
173
174/*
175 * put the controlling keyboard into raw mode
176 */
177raw()
178{
179 ioctl(0, TIOCSETP, &arg);
180 ioctl(0, TIOCSETC, &tchars);
181}
182
183
184/*
185 * return keyboard to normal mode
186 */
187unraw()
188{
189 ioctl(0, TIOCSETP, &defarg);
190 ioctl(0, TIOCSETC, &defchars);
191}
192
193/*
194 * Print string ``s'', then read a string
195 * in from the terminal. Handles signals & allows use of
196 * normal erase and kill characters.
197 */
198prompt(s, p)
199 char *s;
200 register char *p;
201{
202 register char *b = p;
203
204 stoprompt = 0;
205 signal(SIGINT, intprompt);
206 signal(SIGQUIT, SIG_IGN);
207 unraw();
208 printf("%s", s);
209 while ((*p = getchar()) != EOF && *p != '\n') {
210 if (stoprompt)
211 goto pbreak;
212 p++;
213 }
214 *p = '\0';
215pbreak:
216 raw();
217 signal(SIGINT, SIG_DFL);
218 signal(SIGQUIT,SIG_DFL);
219 return(stoprompt || p == b);
220}
221
222/*
223 * Interrupt service routine during prompting
224 */
225intprompt()
226{
227 signal(SIGINT, SIG_IGN);
228 stoprompt = 1;
229 printf("\r\n");
230}
231
232/*
233 * ****TIPIN TIPIN****
234 */
235tipin()
236{
237 char gch, bol = 1;
238
388a70dc
SL
239 /*
240 * Kinda klugey here...
241 * check for scripting being turned on from the .tiprc file,
242 * but be careful about just using setscript(), as we may
243 * send a SIGEMT before tipout has a chance to set up catching
244 * it; so wait a second, then setscript()
245 */
246 if (boolean(value(SCRIPT))) {
247 sleep(1);
248 setscript();
249 }
250
5f50159a
BJ
251 while (1) {
252 gch = getchar()&0177;
253 if ((gch == character(value(ESCAPE))) && bol) {
254 if (!(gch = escape()))
255 continue;
256 } else if (gch == character(value(RAISECHAR))) {
257 boolean(value(RAISE)) = !boolean(value(RAISE));
258 printf("%s", ctrl(character(value(RAISECHAR))));
259 continue;
260 } else if (gch == '\r') {
261 bol = 1;
262 write(FD, &gch, 1);
263 continue;
264 } else if (gch == character(value(FORCE))) {
265 printf("%s", ctrl(character(value(FORCE))));
266 gch = getchar()&0177;
267 }
268 bol = any(gch, value(EOL));
269 if (boolean(value(RAISE)) && islower(gch))
270 toupper(gch);
271 write(FD, &gch, 1);
272 }
273}
274
275/*
276 * Escape handler --
277 * called on recognition of ``escapec'' at the beginning of a line
278 */
279escape()
280{
281 register char gch;
282 register esctable_t *p;
283 char c = character(value(ESCAPE));
284 extern esctable_t etable[];
285
286 gch = (getchar()&0177);
287 for (p = etable; p->e_char; p++)
288 if (p->e_char == gch) {
289 if ((p->e_flags&PRIV) && getuid())
290 continue;
291 printf("%s", ctrl(c));
292 (*p->e_func)(gch);
293 return(0);
294 }
295
296 write(FD, &c, 1);
297 return(gch);
298}
299
300speed(n)
301{
302 register int *p;
303
304 for (p = bauds; *p != -1; p++)
305 if (*p == n)
306 return(p-bauds);
307 return(NULL);
308}
309
310any(c, p)
311 register char c, *p;
312{
313 while (*p)
314 if (*p++ == c)
315 return(1);
316 return(0);
317}
318
319size(s)
320 register char *s;
321{
322 register int i = 0;
323
324 while (*s++) i++;
325 return(i);
326}
327
328char *
329interp(s)
330 register char *s;
331{
332 static char buf[256];
333 register char *p = buf, c, *q;
334
335 while (c = *s++) {
336 for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
337 if (*q++ == c) {
338 *p++ = '\\'; *p++ = *q;
339 goto next;
340 }
341 if (c < 040) {
342 *p++ = '^'; *p++ = c + 'A'-1;
343 } else if (c == 0177) {
344 *p++ = '^'; *p++ = '?';
345 } else
346 *p++ = c;
347 next:
348 ;
349 }
350 *p = '\0';
351 return(buf);
352}
353
354char *
355ctrl(c)
356 char c;
357{
358 static char s[3];
359
360 if (c < 040 || c == 0177) {
361 s[0] = '^';
362 s[1] = c == 0177 ? '?' : c+'A'-1;
363 s[2] = '\0';
364 } else {
365 s[0] = c;
366 s[1] = '\0';
367 }
368 return(s);
369}
370
371/*
372 * Help command
373 */
374help(c)
375 char c;
376{
377 register esctable_t *p;
378 extern esctable_t etable[];
379
380 printf("%c\r\n", c);
381 for (p = etable; p->e_char; p++) {
382 if ((p->e_flags&PRIV) && getuid())
383 continue;
384 printf("%2s", ctrl(character(value(ESCAPE))));
385 printf("%-2s %c %s\r\n", ctrl(p->e_char),
386 p->e_flags&EXP ? '*': ' ', p->e_help);
387 }
388}