added -m message option
[unix-history] / usr / src / usr.bin / tip / cmds.c
CommitLineData
22daf918
BJ
1/* cmds.c 4.1 81/05/09 */
2#include "tip.h"
3/*
4 * tip
5 *
6 * miscellaneous commands
7 */
8
9int quant[] = { 60, 60, 24 };
10
11char null = '\0';
12char *sep[] = { "second", "minute", "hour" };
13static char *argv[10]; /* argument vector for take and put */
14
15int timeout(); /* timeout function called on alarm */
16int stopsnd(); /* SIGINT handler during file transfers */
17int intprompt(); /* used in handling SIG_INT during prompt */
18int intcopy(); /* interrupt routine for file transfers */
19
20/*
21 * FTP - remote ==> local
22 * get a file from the remote host
23 */
24getfl(c)
25 char c;
26{
27 char buf[256];
28
29 putchar(c);
30 /*
31 * get the UNIX receiving file's name
32 */
33 if (prompt("Local file name? ", copyname))
34 return;
35 if ((sfd = creat(copyname, 0666)) < 0) {
36 printf("\r\n%s: cannot creat\r\n", copyname);
37 return;
38 }
39
40 /*
41 * collect parameters
42 */
43 if (prompt("List command for remote system? ", buf)) {
44 unlink(copyname);
45 return;
46 }
47 transfer(buf, sfd, value(EOFREAD));
48}
49
50/*
51 * Cu-like take command
52 */
53cu_take(cc)
54 char cc;
55{
56 int fd, argc;
57 char line[BUFSIZ];
58
59 if (prompt("[take] ", copyname))
60 return;
61 if ((argc = args(copyname, argv)) < 1 || argc > 2) {
62 printf("usage: <take> from [to]\r\n");
63 return;
64 }
65 if (argc == 1)
66 argv[1] = argv[0];
67 if ((fd = creat(argv[1], 0666)) < 0) {
68 printf("\r\n%s: cannot create\r\n", argv[1]);
69 return;
70 }
71 sprintf(line, "cat '%s';echo \01", argv[0]);
72 transfer(line, fd, "\01");
73}
74
75/*
76 * Bulk transfer routine --
77 * used by getfl(), cu_take(), and pipefile()
78 */
79transfer(buf, fd, eofchars)
80 char *buf, *eofchars;
81{
82 register int ct;
83 char c, buffer[BUFSIZ];
84 register char *p = buffer;
85 register int cnt, eof;
86 time_t start;
87
88 write(FD, buf, size(buf));
89 quit = 0;
90 signal(SIGINT, intcopy);
91 kill(pid, SIGIOT);
92 read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */
93
94 /*
95 * finish command
96 */
97 write(FD, "\r", 1);
98 do
99 read(FD, &c, 1);
100 while ((c&0177) != '\n');
101 ioctl(0, TIOCSETC, &defchars);
102
103 start = time(0);
104 for (ct = 0; !quit;) {
105 eof = read(FD, &c, 1) <= 0;
106 c &= 0177;
107 if (quit)
108 continue;
109 if (eof || any(c, eofchars))
110 break;
111 if (c == 0)
112 continue; /* ignore nulls */
113 if (c == '\r')
114 continue;
115 *p++ = c;
116
117 if (c == '\n' && boolean(value(VERBOSE)))
118 printf("\r%d", ++ct);
119 if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) {
120 if (write(fd, buffer, cnt) != cnt) {
121 printf("\r\nwrite error\r\n");
122 quit = 1;
123 }
124 p = buffer;
125 }
126 }
127 if (cnt = (p-buffer))
128 if (write(fd, buffer, cnt) != cnt)
129 printf("\r\nwrite error\r\n");
130
131 if (boolean(value(VERBOSE)))
132 prtime(" lines transferred in ", time(0)-start);
133 ioctl(0, TIOCSETC, &tchars);
134 write(fildes[1], (char *)&ccc, 1);
135 signal(SIGINT, SIG_DFL);
136 close(fd);
137}
138
139/*
140 * FTP - remote ==> local process
141 * send remote input to local process via pipe
142 */
143pipefile()
144{
145 int cpid, pdes[2];
146 char buf[256];
147 int status, p;
148 extern int errno;
149
150 if (prompt("Local command? ", buf))
151 return;
152
153 if (pipe(pdes)) {
154 printf("can't establish pipe\r\n");
155 return;
156 }
157
158 if ((cpid = fork()) < 0) {
159 printf("can't fork!\r\n");
160 return;
161 } else if (cpid) {
162 if (prompt("List command for remote system? ", buf)) {
163 close(pdes[0]), close(pdes[1]);
164 kill (cpid, SIGKILL);
165 } else {
166 close(pdes[0]);
167 signal(SIGPIPE, intcopy);
168 transfer(buf, pdes[1], value(EOFREAD));
169 signal(SIGPIPE, SIG_DFL);
170 while ((p = wait(&status)) > 0 && p != cpid)
171 ;
172 }
173 } else {
174 register int f;
175
176 dup2(pdes[0], 0);
177 close(pdes[0]);
178 for (f = 3; f < 20; f++)
179 close(f);
180 execute(buf);
181 printf("can't execl!\r\n");
182 exit(0);
183 }
184}
185
186/*
187 * Interrupt service routine for FTP
188 */
189stopsnd()
190{
191 stop = 1;
192 signal(SIGINT, SIG_IGN);
193}
194
195/*
196 * FTP - local ==> remote
197 * send local file to remote host
198 * terminate transmission with pseudo EOF sequence
199 */
200sendfile(cc)
201 char cc;
202{
203 FILE *fd;
204
205 putchar(cc);
206 /*
207 * get file name
208 */
209 if (prompt("Local file name? ", fname))
210 return;
211
212 /*
213 * look up file
214 */
215 if ((fd = fopen(fname, "r")) == NULL) {
216 printf("%s: cannot open\r\n", fname);
217 return;
218 }
219 transmit(fd, value(EOFWRITE), NULL);
220}
221
222/*
223 * Bulk transfer routine to remote host --
224 * used by sendfile() and cu_put()
225 */
226transmit(fd, eofchars, command)
227 FILE *fd;
228 char *eofchars, *command;
229{
230 char *pc, lastc;
231 int c, ccount, lcount;
232 time_t start_t, stop_t;
233
234 kill(pid, SIGIOT); /* put TIPOUT into a wait state */
235 signal(SIGINT, stopsnd);
236 stop = 0;
237 ioctl(0, TIOCSETC, &defchars);
238 read(repdes[0], (char *)&ccc, 1);
239 if (command != NULL) {
240 for (pc = command; *pc; pc++)
241 send(*pc);
242 read(FD, (char *)&c, 1); /* trailing \n */
243 }
244 lcount = 0;
245 lastc = '\0';
246 start_t = time(0);
247 while(1) {
248 ccount = 0;
249 do {
250 c = getc(fd);
251 if (stop)
252 goto out;
253 if (c == EOF)
254 goto out;
255 if (c == 0177)
256 continue;
257 lastc = c;
258 if (c < 040) {
259 if (c == '\n')
260 c = '\r';
261 else if (c == '\t') {
262 if (boolean(value(TABEXPAND))) {
263 send(' ');
264 while((++ccount % 8) != 0)
265 send(' ');
266 continue;
267 }
268 } else
269 continue;
270 }
271 send(c);
272 } while (c != '\r');
273 if (boolean(value(VERBOSE)))
274 printf("\r%d", ++lcount);
275 alarm(10);
276 timedout = 0;
277 do { /* wait for prompt */
278 read(FD, (char *)&c, 1);
279 if (timedout || stop) {
280 if (timedout)
281 printf("\r\ntimed out at eol\r\n");
282 alarm(0);
283 goto out;
284 }
285 } while ((c&0177) != character(value(PROMPT)));
286 alarm(0);
287 }
288out:
289 if (lastc != '\n')
290 send('\r');
291 for (pc = eofchars; *pc; pc++)
292 send(*pc);
293 stop_t = time(0);
294 fclose(fd);
295 signal(SIGINT, SIG_DFL);
296 if (boolean(value(VERBOSE)))
297 prtime(" lines transferred in ", stop_t-start_t);
298 write(fildes[1], (char *)&ccc, 1);
299 ioctl(0, TIOCSETC, &tchars);
300}
301
302/*
303 * Cu-like put command
304 */
305cu_put(cc)
306 char cc;
307{
308 FILE *fd;
309 char line[BUFSIZ];
310 int argc;
311
312 if (prompt("[put] ", copyname))
313 return;
314 if ((argc = args(copyname, argv)) < 1 || argc > 2) {
315 printf("usage: <put> from [to]\r\n");
316 return;
317 }
318 if (argc == 1)
319 argv[1] = argv[0];
320 if ((fd = fopen(argv[0], "r")) == NULL) {
321 printf("%s: cannot open\r\n", argv[0]);
322 return;
323 }
324 sprintf(line, "cat>'%s'\r", argv[1]);
325 transmit(fd, "\04", line);
326}
327
328/*
329 * FTP - send single character
330 * wait for echo & handle timeout
331 */
332send(c)
333 char c;
334{
335 int cc;
336 int retry = 0;
337
338 cc = c;
339 write(FD, (char *)&cc, 1);
340tryagain:
341 timedout = 0;
342 alarm(10);
343 read(FD, (char *)&cc, 1);
344 alarm(0);
345 if (timedout) {
346 printf("\r\ntimeout error (%s)\r\n", ctrl(c));
347 if (retry++ > 3)
348 return;
349 write(FD, &null, 1); /* poke it */
350 goto tryagain;
351 }
352}
353
354timeout()
355{
356 signal(SIGALRM, timeout);
357 timedout = 1;
358}
359
360#ifdef CONNECT
361/*
362 * Fork a program with:
363 * 0 <-> local tty in
364 * 1 <-> local tty out
365 * 2 <-> local tty out
366 * 3 <-> remote tty in
367 * 4 <-> remote tty out
368 */
369consh(c)
370{
371 char buf[256];
372 int cpid, status, p;
373 time_t start;
374
375 putchar(c);
376 if (prompt("Local command? ", buf))
377 return;
378 kill(pid, SIGIOT); /* put TIPOUT into a wait state */
379 signal(SIGINT, SIG_IGN);
380 signal(SIGQUIT, SIG_IGN);
381 ioctl(0, TIOCSETC, &defchars);
382 read(repdes[0], (char *)&ccc, 1);
383 /*
384 * Set up file descriptors in the child and
385 * let it go...
386 */
387 if ((cpid = fork()) < 0)
388 printf("can't fork!\r\n");
389 else if (cpid) {
390 start = time(0);
391 while ((p = wait(&status)) > 0 && p != cpid)
392 ;
393 } else {
394 register int i;
395
396 dup2(FD, 3);
397 dup2(3, 4);
398 for (i = 5; i < 20; i++)
399 close(i);
400 signal(SIGINT, SIG_DFL);
401 signal(SIGQUIT, SIG_DFL);
402 execute(buf);
403 printf("can't find `%s'\r\n", buf);
404 exit(0);
405 }
406 if (boolean(value(VERBOSE)))
407 prtime("away for ", time(0)-start);
408 write(fildes[1], (char *)&ccc, 1);
409 ioctl(0, TIOCSETC, &tchars);
410 signal(SIGINT, SIG_DFL);
411 signal(SIGQUIT, SIG_DFL);
412}
413#endif
414
415/*
416 * Escape to local shell
417 */
418shell()
419{
420 int shpid, status;
421 extern char **environ;
422 char *cp;
423
424 printf("[sh]\r\n");
425 signal(SIGINT, SIG_IGN);
426 signal(SIGQUIT, SIG_IGN);
427 unraw();
428 if (shpid = fork()) {
429 while (shpid != wait(&status));
430 raw();
431 printf("\r\n!\r\n");
432 signal(SIGINT, SIG_DFL);
433 signal(SIGQUIT, SIG_DFL);
434 return;
435 } else {
436 signal(SIGQUIT, SIG_DFL);
437 signal(SIGINT, SIG_DFL);
438 if ((cp = rindex(value(SHELL), '/')) == NULL)
439 cp = value(SHELL);
440 else
441 cp++;
442 execl(value(SHELL), cp, 0);
443 printf("\r\ncan't execl!\r\n");
444 exit(1);
445 }
446}
447
448/*
449 * TIPIN portion of scripting
450 * initiate the conversation with TIPOUT
451 */
452setscript()
453{
454 char c;
455 /*
456 * enable TIPOUT side for dialogue
457 */
458 kill(pid, SIGEMT);
459 if (boolean(value(SCRIPT)))
460 write(fildes[1], value(RECORD), size(value(RECORD)));
461 write(fildes[1], "\n", 1);
462 /*
463 * wait for TIPOUT to finish
464 */
465 read(repdes[0], &c, 1);
466 if (c == 'n')
467 printf("can't create %s\r\n", value(RECORD));
468}
469
470/*
471 * Change current working directory of
472 * local portion of tip
473 */
474chdirectory()
475{
476 char dirname[80];
477 register char *cp = dirname;
478
479 if (prompt("[cd] ", dirname))
480 if (stoprompt)
481 return;
482 else
483 cp = value(HOME);
484 if (chdir(cp) < 0)
485 printf("%s: bad directory\r\n", cp);
486 printf("!\r\n");
487}
488
489finish()
490{
491 kill(pid, SIGTERM);
492 disconnect();
493 printf("\r\n[EOT]\r\n");
494 delock(uucplock);
495#ifdef VMUNIX
496 ioctl(0, TIOCSETD, (char *)&odisc);
497#endif
498 unraw();
499 exit(0);
500}
501
502intcopy()
503{
504 raw();
505 quit = 1;
506}
507
508execute(s)
509 char *s;
510{
511 register char *cp;
512
513 if ((cp = rindex(value(SHELL), '/')) == NULL)
514 cp = value(SHELL);
515 else
516 cp++;
517 execl(value(SHELL), cp, "-c", s, 0);
518}
519
520args(buf, a)
521 char *buf, *a[];
522{
523 register char *p = buf, *start;
524 register char **parg = a;
525 register int n = 0;
526
527 do {
528 while (*p && (*p == ' ' || *p == '\t'))
529 p++;
530 start = p;
531 if (*p)
532 *parg = p;
533 while (*p && (*p != ' ' && *p != '\t'))
534 p++;
535 if (p != start)
536 parg++, n++;
537 if (*p)
538 *p++ = '\0';
539 } while (*p);
540
541 return(n);
542}
543
544prtime(s, a)
545 char *s;
546 time_t a;
547{
548 register i;
549 int nums[3];
550
551 for (i = 0; i < 3; i++) {
552 nums[i] = (int)(a % quant[i]);
553 a /= quant[i];
554 }
555 printf("%s", s);
556 while (--i >= 0)
557 if (nums[i])
558 printf("%d %s%c ", nums[i], sep[i],
559 nums[i] == 1 ? '\0' : 's');
560 printf("\r\n!\r\n");
561}
562
563variable()
564{
565 char buf[256];
566
567 if (prompt("[set] ", buf))
568 return;
569 vlex(buf);
570 if (vtable[BEAUTIFY].v_access&CHANGED) {
571 vtable[BEAUTIFY].v_access &= ~CHANGED;
572 signal(pid, SIGSYS);
573 }
574 if (vtable[SCRIPT].v_access&CHANGED) {
575 vtable[SCRIPT].v_access &= ~CHANGED;
576 setscript();
577 }
578 if (vtable[RECORD].v_access&CHANGED) {
579 vtable[RECORD].v_access &= ~CHANGED;
580 if (boolean(value(SCRIPT)))
581 setscript();
582 }
583}