1be09fc23SSascha Wildner /*
2be09fc23SSascha Wildner * Copyright (c) 1983, 1993
3be09fc23SSascha Wildner * The Regents of the University of California. All rights reserved.
4be09fc23SSascha Wildner *
5be09fc23SSascha Wildner * Redistribution and use in source and binary forms, with or without
6be09fc23SSascha Wildner * modification, are permitted provided that the following conditions
7be09fc23SSascha Wildner * are met:
8be09fc23SSascha Wildner * 1. Redistributions of source code must retain the above copyright
9be09fc23SSascha Wildner * notice, this list of conditions and the following disclaimer.
10be09fc23SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
11be09fc23SSascha Wildner * notice, this list of conditions and the following disclaimer in the
12be09fc23SSascha Wildner * documentation and/or other materials provided with the distribution.
13*0720b42fSzrj * 3. Neither the name of the University nor the names of its contributors
14be09fc23SSascha Wildner * may be used to endorse or promote products derived from this software
15be09fc23SSascha Wildner * without specific prior written permission.
16be09fc23SSascha Wildner *
17be09fc23SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18be09fc23SSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19be09fc23SSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20be09fc23SSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21be09fc23SSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22be09fc23SSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23be09fc23SSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24be09fc23SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25be09fc23SSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26be09fc23SSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27be09fc23SSascha Wildner * SUCH DAMAGE.
28be09fc23SSascha Wildner *
29be09fc23SSascha Wildner * @(#)cmds.c 8.1 (Berkeley) 6/6/93
30be09fc23SSascha Wildner * $FreeBSD: src/usr.bin/tip/tip/cmds.c,v 1.11.2.2 2000/07/01 12:24:23 ps Exp $
31be09fc23SSascha Wildner */
32be09fc23SSascha Wildner
33be09fc23SSascha Wildner #include "tip.h"
34be09fc23SSascha Wildner #include "pathnames.h"
35be09fc23SSascha Wildner
36be09fc23SSascha Wildner #include <sys/types.h>
37be09fc23SSascha Wildner #include <sys/wait.h>
38be09fc23SSascha Wildner #include <err.h>
39be09fc23SSascha Wildner #include <libutil.h>
40be09fc23SSascha Wildner #include <stdio.h>
41be09fc23SSascha Wildner #include <unistd.h>
42be09fc23SSascha Wildner
43be09fc23SSascha Wildner /*
44be09fc23SSascha Wildner * tip
45be09fc23SSascha Wildner *
46be09fc23SSascha Wildner * miscellaneous commands
47be09fc23SSascha Wildner */
48be09fc23SSascha Wildner
49be09fc23SSascha Wildner int quant[] = { 60, 60, 24 };
50be09fc23SSascha Wildner
51be09fc23SSascha Wildner char null = '\0';
52be09fc23SSascha Wildner char *sep[] = { "second", "minute", "hour" };
53be09fc23SSascha Wildner static char *argv[10]; /* argument vector for take and put */
54be09fc23SSascha Wildner
55be09fc23SSascha Wildner static void stopsnd(int); /* SIGINT handler during file transfers */
56be09fc23SSascha Wildner static void intcopy(int); /* interrupt routine for file transfers */
57be09fc23SSascha Wildner
58be09fc23SSascha Wildner static int anyof(char *, char *);
59be09fc23SSascha Wildner static void tandem(char *);
60be09fc23SSascha Wildner static void prtime(char *, time_t);
61be09fc23SSascha Wildner static int args(char *, char **, int);
62be09fc23SSascha Wildner static void execute(char *);
63be09fc23SSascha Wildner static void send(char);
64be09fc23SSascha Wildner static void transmit(FILE *, char *, char *);
65be09fc23SSascha Wildner static void transfer(char *, int, char *);
66be09fc23SSascha Wildner static void xfer(char *, int, char *);
67be09fc23SSascha Wildner
68be09fc23SSascha Wildner static void
usedefchars(void)69be09fc23SSascha Wildner usedefchars(void)
70be09fc23SSascha Wildner {
71be09fc23SSascha Wildner int cnt;
72be09fc23SSascha Wildner struct termios ttermios;
73be09fc23SSascha Wildner ttermios = ctermios;
74be09fc23SSascha Wildner for (cnt = 0; cnt < NCCS; cnt++)
75be09fc23SSascha Wildner ttermios.c_cc [cnt] = otermios.c_cc [cnt];
76be09fc23SSascha Wildner tcsetattr (0, TCSANOW, &ttermios);
77be09fc23SSascha Wildner }
78be09fc23SSascha Wildner
79be09fc23SSascha Wildner static void
usetchars(void)80be09fc23SSascha Wildner usetchars(void)
81be09fc23SSascha Wildner {
82be09fc23SSascha Wildner tcsetattr (0, TCSANOW, &ctermios);
83be09fc23SSascha Wildner }
84be09fc23SSascha Wildner
85be09fc23SSascha Wildner static void
flush_remote(void)86be09fc23SSascha Wildner flush_remote(void)
87be09fc23SSascha Wildner {
88be09fc23SSascha Wildner int cmd = 0;
89be09fc23SSascha Wildner ioctl (FD, TIOCFLUSH, &cmd);
90be09fc23SSascha Wildner }
91be09fc23SSascha Wildner
92be09fc23SSascha Wildner /*
93be09fc23SSascha Wildner * FTP - remote ==> local
94be09fc23SSascha Wildner * get a file from the remote host
95be09fc23SSascha Wildner */
96be09fc23SSascha Wildner void
getfl(int c)97be09fc23SSascha Wildner getfl(int c)
98be09fc23SSascha Wildner {
99be09fc23SSascha Wildner char buf[256], *cp;
100be09fc23SSascha Wildner
101be09fc23SSascha Wildner putchar(c);
102be09fc23SSascha Wildner /*
103be09fc23SSascha Wildner * get the UNIX receiving file's name
104be09fc23SSascha Wildner */
105be09fc23SSascha Wildner if (prompt("Local file name? ", copyname, sizeof(copyname)))
106be09fc23SSascha Wildner return;
107be09fc23SSascha Wildner cp = expand(copyname);
108be09fc23SSascha Wildner if ((sfd = creat(cp, 0666)) < 0) {
109be09fc23SSascha Wildner printf("\r\n%s: cannot creat\r\n", copyname);
110be09fc23SSascha Wildner return;
111be09fc23SSascha Wildner }
112be09fc23SSascha Wildner
113be09fc23SSascha Wildner /*
114be09fc23SSascha Wildner * collect parameters
115be09fc23SSascha Wildner */
116be09fc23SSascha Wildner if (prompt("List command for remote system? ", buf, sizeof(buf))) {
117be09fc23SSascha Wildner unlink(copyname);
118be09fc23SSascha Wildner return;
119be09fc23SSascha Wildner }
120be09fc23SSascha Wildner transfer(buf, sfd, value(EOFREAD));
121be09fc23SSascha Wildner }
122be09fc23SSascha Wildner
123be09fc23SSascha Wildner /*
124be09fc23SSascha Wildner * Cu-like take command
125be09fc23SSascha Wildner */
126be09fc23SSascha Wildner void
cu_take(int c)127be09fc23SSascha Wildner cu_take(int c)
128be09fc23SSascha Wildner {
129be09fc23SSascha Wildner int fd, argc;
130be09fc23SSascha Wildner char line[BUFSIZ], *cp;
131be09fc23SSascha Wildner
132be09fc23SSascha Wildner if (prompt("[take] ", copyname, sizeof(copyname)))
133be09fc23SSascha Wildner return;
134be09fc23SSascha Wildner if ((argc = args(copyname, argv, sizeof(argv)/sizeof(argv[0]))) < 1 || argc > 2) {
135be09fc23SSascha Wildner printf("usage: <take> from [to]\r\n");
136be09fc23SSascha Wildner return;
137be09fc23SSascha Wildner }
138be09fc23SSascha Wildner if (argc == 1)
139be09fc23SSascha Wildner argv[1] = argv[0];
140be09fc23SSascha Wildner cp = expand(argv[1]);
141be09fc23SSascha Wildner if ((fd = creat(cp, 0666)) < 0) {
142be09fc23SSascha Wildner printf("\r\n%s: cannot create\r\n", argv[1]);
143be09fc23SSascha Wildner return;
144be09fc23SSascha Wildner }
145be09fc23SSascha Wildner (void)snprintf(line, sizeof(line), "cat %s ; echo \"\" ; echo ___tip_end_of_file_marker___", argv[0]);
146be09fc23SSascha Wildner xfer(line, fd, "\n___tip_end_of_file_marker___\n");
147be09fc23SSascha Wildner }
148be09fc23SSascha Wildner
149be09fc23SSascha Wildner static jmp_buf intbuf;
150be09fc23SSascha Wildner
151be09fc23SSascha Wildner static void
xfer(char * buf,int fd,char * eofchars)152be09fc23SSascha Wildner xfer(char *buf, int fd, char *eofchars)
153be09fc23SSascha Wildner {
154be09fc23SSascha Wildner int ct;
155be09fc23SSascha Wildner char c, *match;
156be09fc23SSascha Wildner int cnt, eof, v;
157be09fc23SSascha Wildner time_t start;
158be09fc23SSascha Wildner sig_t f;
159be09fc23SSascha Wildner char r;
160be09fc23SSascha Wildner FILE *ff;
161be09fc23SSascha Wildner
162be09fc23SSascha Wildner v = boolean(value(VERBOSE));
163be09fc23SSascha Wildner
164be09fc23SSascha Wildner if ((ff = fdopen (fd, "w")) == NULL) {
165be09fc23SSascha Wildner warn("file open");
166be09fc23SSascha Wildner return;
167be09fc23SSascha Wildner }
168be09fc23SSascha Wildner if ((cnt = number(value(FRAMESIZE))) != BUFSIZ)
169be09fc23SSascha Wildner if (setvbuf(ff, NULL, _IOFBF, cnt) != 0) {
170be09fc23SSascha Wildner warn("file allocation");
171be09fc23SSascha Wildner (void)fclose(ff);
172be09fc23SSascha Wildner return;
173be09fc23SSascha Wildner }
174be09fc23SSascha Wildner
175be09fc23SSascha Wildner xpwrite(FD, buf, size(buf));
176be09fc23SSascha Wildner quit = 0;
177be09fc23SSascha Wildner kill(pid, SIGIOT);
178be09fc23SSascha Wildner read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */
179be09fc23SSascha Wildner
180be09fc23SSascha Wildner /*
181be09fc23SSascha Wildner * finish command
182be09fc23SSascha Wildner */
183be09fc23SSascha Wildner r = '\r';
184be09fc23SSascha Wildner xpwrite(FD, &r, 1);
185be09fc23SSascha Wildner do
186be09fc23SSascha Wildner read(FD, &c, 1);
187be09fc23SSascha Wildner while ((c&0177) != '\n');
188be09fc23SSascha Wildner
189be09fc23SSascha Wildner usedefchars ();
190be09fc23SSascha Wildner
191be09fc23SSascha Wildner (void) setjmp(intbuf);
192be09fc23SSascha Wildner f = signal(SIGINT, intcopy);
193be09fc23SSascha Wildner start = time(0);
194be09fc23SSascha Wildner match = eofchars;
195be09fc23SSascha Wildner for (ct = 0; !quit;) {
196be09fc23SSascha Wildner eof = read(FD, &c, 1) <= 0;
197be09fc23SSascha Wildner c &= 0177;
198be09fc23SSascha Wildner if (quit)
199be09fc23SSascha Wildner continue;
200be09fc23SSascha Wildner if (eof)
201be09fc23SSascha Wildner break;
202be09fc23SSascha Wildner if (c == 0)
203be09fc23SSascha Wildner continue; /* ignore nulls */
204be09fc23SSascha Wildner if (c == '\r')
205be09fc23SSascha Wildner continue;
206be09fc23SSascha Wildner if (c != *match && match > eofchars) {
207be09fc23SSascha Wildner char *p = eofchars;
208be09fc23SSascha Wildner while (p < match) {
209be09fc23SSascha Wildner if (*p == '\n'&& v)
210be09fc23SSascha Wildner (void)printf("\r%d", ++ct);
211be09fc23SSascha Wildner fputc(*p++, ff);
212be09fc23SSascha Wildner }
213be09fc23SSascha Wildner match = eofchars;
214be09fc23SSascha Wildner }
215be09fc23SSascha Wildner if (c == *match) {
216be09fc23SSascha Wildner if (*++match == '\0')
217be09fc23SSascha Wildner break;
218be09fc23SSascha Wildner } else {
219be09fc23SSascha Wildner if (c == '\n' && v)
220be09fc23SSascha Wildner (void)printf("\r%d", ++ct);
221be09fc23SSascha Wildner fputc(c, ff);
222be09fc23SSascha Wildner }
223be09fc23SSascha Wildner }
224be09fc23SSascha Wildner if (v)
225be09fc23SSascha Wildner prtime(" lines transferred in ", time(0)-start);
226be09fc23SSascha Wildner usetchars ();
227be09fc23SSascha Wildner write(fildes[1], (char *)&ccc, 1);
228be09fc23SSascha Wildner signal(SIGINT, f);
229be09fc23SSascha Wildner (void)fclose(ff);
230be09fc23SSascha Wildner }
231be09fc23SSascha Wildner
232be09fc23SSascha Wildner /*
233be09fc23SSascha Wildner * Bulk transfer routine --
234be09fc23SSascha Wildner * used by getfl(), cu_take(), and pipefile()
235be09fc23SSascha Wildner */
236be09fc23SSascha Wildner static void
transfer(char * buf,int fd,char * eofchars)237be09fc23SSascha Wildner transfer(char *buf, int fd, char *eofchars)
238be09fc23SSascha Wildner {
239be09fc23SSascha Wildner int ct;
240be09fc23SSascha Wildner char c;
241be09fc23SSascha Wildner int cnt, eof, v;
242be09fc23SSascha Wildner time_t start;
243be09fc23SSascha Wildner sig_t f;
244be09fc23SSascha Wildner char r;
245be09fc23SSascha Wildner FILE *ff;
246be09fc23SSascha Wildner
247be09fc23SSascha Wildner v = boolean(value(VERBOSE));
248be09fc23SSascha Wildner
249be09fc23SSascha Wildner if ((ff = fdopen (fd, "w")) == NULL) {
250be09fc23SSascha Wildner warn("file open");
251be09fc23SSascha Wildner return;
252be09fc23SSascha Wildner }
253be09fc23SSascha Wildner if ((cnt = number(value(FRAMESIZE))) != BUFSIZ)
254be09fc23SSascha Wildner if (setvbuf(ff, NULL, _IOFBF, cnt) != 0) {
255be09fc23SSascha Wildner warn("file allocation");
256be09fc23SSascha Wildner (void)fclose(ff);
257be09fc23SSascha Wildner return;
258be09fc23SSascha Wildner }
259be09fc23SSascha Wildner
260be09fc23SSascha Wildner xpwrite(FD, buf, size(buf));
261be09fc23SSascha Wildner quit = 0;
262be09fc23SSascha Wildner kill(pid, SIGIOT);
263be09fc23SSascha Wildner read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */
264be09fc23SSascha Wildner
265be09fc23SSascha Wildner /*
266be09fc23SSascha Wildner * finish command
267be09fc23SSascha Wildner */
268be09fc23SSascha Wildner r = '\r';
269be09fc23SSascha Wildner xpwrite(FD, &r, 1);
270be09fc23SSascha Wildner do
271be09fc23SSascha Wildner read(FD, &c, 1);
272be09fc23SSascha Wildner while ((c&0177) != '\n');
273be09fc23SSascha Wildner usedefchars ();
274be09fc23SSascha Wildner (void) setjmp(intbuf);
275be09fc23SSascha Wildner f = signal(SIGINT, intcopy);
276be09fc23SSascha Wildner start = time(0);
277be09fc23SSascha Wildner for (ct = 0; !quit;) {
278be09fc23SSascha Wildner eof = read(FD, &c, 1) <= 0;
279be09fc23SSascha Wildner c &= 0177;
280be09fc23SSascha Wildner if (quit)
281be09fc23SSascha Wildner continue;
282be09fc23SSascha Wildner if (eof || any(c, eofchars))
283be09fc23SSascha Wildner break;
284be09fc23SSascha Wildner if (c == 0)
285be09fc23SSascha Wildner continue; /* ignore nulls */
286be09fc23SSascha Wildner if (c == '\r')
287be09fc23SSascha Wildner continue;
288be09fc23SSascha Wildner if (c == '\n' && v)
289be09fc23SSascha Wildner printf("\r%d", ++ct);
290be09fc23SSascha Wildner fputc(c, ff);
291be09fc23SSascha Wildner }
292be09fc23SSascha Wildner if (v)
293be09fc23SSascha Wildner prtime(" lines transferred in ", time(0)-start);
294be09fc23SSascha Wildner usetchars ();
295be09fc23SSascha Wildner write(fildes[1], (char *)&ccc, 1);
296be09fc23SSascha Wildner signal(SIGINT, f);
297be09fc23SSascha Wildner (void)fclose(ff);
298be09fc23SSascha Wildner }
299be09fc23SSascha Wildner
300be09fc23SSascha Wildner /*
301be09fc23SSascha Wildner * FTP - remote ==> local process
302be09fc23SSascha Wildner * send remote input to local process via pipe
303be09fc23SSascha Wildner */
304be09fc23SSascha Wildner void
pipefile(int c)305be09fc23SSascha Wildner pipefile(int c)
306be09fc23SSascha Wildner {
307be09fc23SSascha Wildner int cpid, pdes[2];
308be09fc23SSascha Wildner char buf[256];
309be09fc23SSascha Wildner int status, p;
310be09fc23SSascha Wildner
311be09fc23SSascha Wildner if (prompt("Local command? ", buf, sizeof(buf)))
312be09fc23SSascha Wildner return;
313be09fc23SSascha Wildner
314be09fc23SSascha Wildner if (pipe(pdes)) {
315be09fc23SSascha Wildner printf("can't establish pipe\r\n");
316be09fc23SSascha Wildner return;
317be09fc23SSascha Wildner }
318be09fc23SSascha Wildner
319be09fc23SSascha Wildner if ((cpid = fork()) < 0) {
320be09fc23SSascha Wildner printf("can't fork!\r\n");
321be09fc23SSascha Wildner return;
322be09fc23SSascha Wildner } else if (cpid) {
323be09fc23SSascha Wildner if (prompt("List command for remote system? ", buf, sizeof(buf))) {
324be09fc23SSascha Wildner close(pdes[0]), close(pdes[1]);
325be09fc23SSascha Wildner kill (cpid, SIGKILL);
326be09fc23SSascha Wildner } else {
327be09fc23SSascha Wildner close(pdes[0]);
328be09fc23SSascha Wildner signal(SIGPIPE, intcopy);
329be09fc23SSascha Wildner transfer(buf, pdes[1], value(EOFREAD));
330be09fc23SSascha Wildner signal(SIGPIPE, SIG_DFL);
331be09fc23SSascha Wildner while ((p = wait(&status)) > 0 && p != cpid)
332be09fc23SSascha Wildner ;
333be09fc23SSascha Wildner }
334be09fc23SSascha Wildner } else {
335be09fc23SSascha Wildner int f;
336be09fc23SSascha Wildner
337be09fc23SSascha Wildner dup2(pdes[0], 0);
338be09fc23SSascha Wildner close(pdes[0]);
339be09fc23SSascha Wildner for (f = 3; f < 20; f++)
340be09fc23SSascha Wildner close(f);
341be09fc23SSascha Wildner execute(buf);
342be09fc23SSascha Wildner printf("can't execl!\r\n");
343be09fc23SSascha Wildner exit(0);
344be09fc23SSascha Wildner }
345be09fc23SSascha Wildner }
346be09fc23SSascha Wildner
347be09fc23SSascha Wildner /*
348be09fc23SSascha Wildner * Interrupt service routine for FTP
349be09fc23SSascha Wildner */
350be09fc23SSascha Wildner void
stopsnd(int __dummy)351be09fc23SSascha Wildner stopsnd(int __dummy)
352be09fc23SSascha Wildner {
353be09fc23SSascha Wildner
354be09fc23SSascha Wildner stop = 1;
355be09fc23SSascha Wildner signal(SIGINT, SIG_IGN);
356be09fc23SSascha Wildner }
357be09fc23SSascha Wildner
358be09fc23SSascha Wildner /*
359be09fc23SSascha Wildner * FTP - local ==> remote
360be09fc23SSascha Wildner * send local file to remote host
361be09fc23SSascha Wildner * terminate transmission with pseudo EOF sequence
362be09fc23SSascha Wildner */
363be09fc23SSascha Wildner void
sendfile(int c)364be09fc23SSascha Wildner sendfile(int c)
365be09fc23SSascha Wildner {
366be09fc23SSascha Wildner FILE *fd;
367be09fc23SSascha Wildner char *fnamex;
368be09fc23SSascha Wildner
369be09fc23SSascha Wildner putchar(c);
370be09fc23SSascha Wildner /*
371be09fc23SSascha Wildner * get file name
372be09fc23SSascha Wildner */
373be09fc23SSascha Wildner if (prompt("Local file name? ", fname, sizeof(fname)))
374be09fc23SSascha Wildner return;
375be09fc23SSascha Wildner
376be09fc23SSascha Wildner /*
377be09fc23SSascha Wildner * look up file
378be09fc23SSascha Wildner */
379be09fc23SSascha Wildner fnamex = expand(fname);
380be09fc23SSascha Wildner if ((fd = fopen(fnamex, "r")) == NULL) {
381be09fc23SSascha Wildner printf("%s: cannot open\r\n", fname);
382be09fc23SSascha Wildner return;
383be09fc23SSascha Wildner }
384be09fc23SSascha Wildner transmit(fd, value(EOFWRITE), NULL);
385be09fc23SSascha Wildner if (!boolean(value(ECHOCHECK))) {
386be09fc23SSascha Wildner flush_remote ();
387be09fc23SSascha Wildner }
388be09fc23SSascha Wildner }
389be09fc23SSascha Wildner
390be09fc23SSascha Wildner /*
391be09fc23SSascha Wildner * Bulk transfer routine to remote host --
392be09fc23SSascha Wildner * used by sendfile() and cu_put()
393be09fc23SSascha Wildner */
394be09fc23SSascha Wildner static void
transmit(FILE * fd,char * eofchars,char * command)395be09fc23SSascha Wildner transmit(FILE *fd, char *eofchars, char *command)
396be09fc23SSascha Wildner {
397be09fc23SSascha Wildner char *pc, lastc;
398be09fc23SSascha Wildner int c, ccount, lcount;
399be09fc23SSascha Wildner time_t start_t, stop_t;
400be09fc23SSascha Wildner sig_t f;
401be09fc23SSascha Wildner
402be09fc23SSascha Wildner kill(pid, SIGIOT); /* put TIPOUT into a wait state */
403be09fc23SSascha Wildner stop = 0;
404be09fc23SSascha Wildner f = signal(SIGINT, stopsnd);
405be09fc23SSascha Wildner usedefchars ();
406be09fc23SSascha Wildner read(repdes[0], (char *)&ccc, 1);
407be09fc23SSascha Wildner if (command != NULL) {
408be09fc23SSascha Wildner for (pc = command; *pc; pc++)
409be09fc23SSascha Wildner send(*pc);
410be09fc23SSascha Wildner if (boolean(value(ECHOCHECK)))
411be09fc23SSascha Wildner read(FD, (char *)&c, 1); /* trailing \n */
412be09fc23SSascha Wildner else {
413be09fc23SSascha Wildner flush_remote ();
414be09fc23SSascha Wildner sleep(5); /* wait for remote stty to take effect */
415be09fc23SSascha Wildner }
416be09fc23SSascha Wildner }
417be09fc23SSascha Wildner lcount = 0;
418be09fc23SSascha Wildner lastc = '\0';
419be09fc23SSascha Wildner start_t = time(0);
420be09fc23SSascha Wildner while (1) {
421be09fc23SSascha Wildner ccount = 0;
422be09fc23SSascha Wildner do {
423be09fc23SSascha Wildner c = getc(fd);
424be09fc23SSascha Wildner if (stop)
425be09fc23SSascha Wildner goto out;
426be09fc23SSascha Wildner if (c == EOF)
427be09fc23SSascha Wildner goto out;
428be09fc23SSascha Wildner if (c == 0177 && !boolean(value(RAWFTP)))
429be09fc23SSascha Wildner continue;
430be09fc23SSascha Wildner lastc = c;
431be09fc23SSascha Wildner if (c < 040) {
432be09fc23SSascha Wildner if (c == '\n') {
433be09fc23SSascha Wildner if (!boolean(value(RAWFTP)))
434be09fc23SSascha Wildner c = '\r';
435be09fc23SSascha Wildner }
436be09fc23SSascha Wildner else if (c == '\t') {
437be09fc23SSascha Wildner if (!boolean(value(RAWFTP))) {
438be09fc23SSascha Wildner if (boolean(value(TABEXPAND))) {
439be09fc23SSascha Wildner send(' ');
440be09fc23SSascha Wildner while ((++ccount % 8) != 0)
441be09fc23SSascha Wildner send(' ');
442be09fc23SSascha Wildner continue;
443be09fc23SSascha Wildner }
444be09fc23SSascha Wildner }
445be09fc23SSascha Wildner } else
446be09fc23SSascha Wildner if (!boolean(value(RAWFTP)))
447be09fc23SSascha Wildner continue;
448be09fc23SSascha Wildner }
449be09fc23SSascha Wildner send(c);
450be09fc23SSascha Wildner } while (c != '\r' && !boolean(value(RAWFTP)));
451be09fc23SSascha Wildner if (boolean(value(VERBOSE)))
452be09fc23SSascha Wildner printf("\r%d", ++lcount);
453be09fc23SSascha Wildner if (boolean(value(ECHOCHECK))) {
454be09fc23SSascha Wildner timedout = 0;
455be09fc23SSascha Wildner alarm(number(value(ETIMEOUT)));
456be09fc23SSascha Wildner do { /* wait for prompt */
457be09fc23SSascha Wildner read(FD, (char *)&c, 1);
458be09fc23SSascha Wildner if (timedout || stop) {
459be09fc23SSascha Wildner if (timedout)
460be09fc23SSascha Wildner printf("\r\ntimed out at eol\r\n");
461be09fc23SSascha Wildner alarm(0);
462be09fc23SSascha Wildner goto out;
463be09fc23SSascha Wildner }
464be09fc23SSascha Wildner } while ((c&0177) != character(value(PROMPT)));
465be09fc23SSascha Wildner alarm(0);
466be09fc23SSascha Wildner }
467be09fc23SSascha Wildner }
468be09fc23SSascha Wildner out:
469be09fc23SSascha Wildner if (lastc != '\n' && !boolean(value(RAWFTP)))
470be09fc23SSascha Wildner send('\r');
471be09fc23SSascha Wildner for (pc = eofchars; pc && *pc; pc++)
472be09fc23SSascha Wildner send(*pc);
473be09fc23SSascha Wildner stop_t = time(0);
474be09fc23SSascha Wildner fclose(fd);
475be09fc23SSascha Wildner signal(SIGINT, f);
476be09fc23SSascha Wildner if (boolean(value(VERBOSE))) {
477be09fc23SSascha Wildner if (boolean(value(RAWFTP)))
478be09fc23SSascha Wildner prtime(" chars transferred in ", stop_t-start_t);
479be09fc23SSascha Wildner else
480be09fc23SSascha Wildner prtime(" lines transferred in ", stop_t-start_t);
481be09fc23SSascha Wildner }
482be09fc23SSascha Wildner write(fildes[1], (char *)&ccc, 1);
483be09fc23SSascha Wildner usetchars ();
484be09fc23SSascha Wildner }
485be09fc23SSascha Wildner
486be09fc23SSascha Wildner /*
487be09fc23SSascha Wildner * Cu-like put command
488be09fc23SSascha Wildner */
489be09fc23SSascha Wildner void
cu_put(int c)490be09fc23SSascha Wildner cu_put(int c)
491be09fc23SSascha Wildner {
492be09fc23SSascha Wildner FILE *fd;
493be09fc23SSascha Wildner char line[BUFSIZ];
494be09fc23SSascha Wildner int argc;
495be09fc23SSascha Wildner char *copynamex;
496be09fc23SSascha Wildner
497be09fc23SSascha Wildner if (prompt("[put] ", copyname, sizeof(copyname)))
498be09fc23SSascha Wildner return;
499be09fc23SSascha Wildner if ((argc = args(copyname, argv, sizeof(argv)/sizeof(argv[0]))) < 1 || argc > 2) {
500be09fc23SSascha Wildner printf("usage: <put> from [to]\r\n");
501be09fc23SSascha Wildner return;
502be09fc23SSascha Wildner }
503be09fc23SSascha Wildner if (argc == 1)
504be09fc23SSascha Wildner argv[1] = argv[0];
505be09fc23SSascha Wildner copynamex = expand(argv[0]);
506be09fc23SSascha Wildner if ((fd = fopen(copynamex, "r")) == NULL) {
507be09fc23SSascha Wildner printf("%s: cannot open\r\n", copynamex);
508be09fc23SSascha Wildner return;
509be09fc23SSascha Wildner }
510be09fc23SSascha Wildner if (boolean(value(ECHOCHECK)))
511be09fc23SSascha Wildner snprintf(line, sizeof(line), "cat>%s\r", argv[1]);
512be09fc23SSascha Wildner else
513be09fc23SSascha Wildner snprintf(line, sizeof(line), "stty -echo;cat>%s;stty echo\r", argv[1]);
514be09fc23SSascha Wildner transmit(fd, "\04", line);
515be09fc23SSascha Wildner }
516be09fc23SSascha Wildner
517be09fc23SSascha Wildner
518be09fc23SSascha Wildner static int
nap(int msec)519be09fc23SSascha Wildner nap(int msec)
520be09fc23SSascha Wildner {
521be09fc23SSascha Wildner if (usleep(msec*1000) != 0) {
522be09fc23SSascha Wildner fprintf ( stderr, "warning: ldelay or cdelay interrupted, "
523be09fc23SSascha Wildner "delay time cut short: %s\n",
524be09fc23SSascha Wildner strerror(errno) );
525be09fc23SSascha Wildner }
526be09fc23SSascha Wildner
527be09fc23SSascha Wildner return 0;
528be09fc23SSascha Wildner }
529be09fc23SSascha Wildner
530be09fc23SSascha Wildner
531be09fc23SSascha Wildner /*
532be09fc23SSascha Wildner * FTP - send single character
533be09fc23SSascha Wildner * wait for echo & handle timeout
534be09fc23SSascha Wildner */
535be09fc23SSascha Wildner static void
send(char c)536be09fc23SSascha Wildner send(char c)
537be09fc23SSascha Wildner {
538be09fc23SSascha Wildner char cc;
539be09fc23SSascha Wildner int retry = 0;
540be09fc23SSascha Wildner
541be09fc23SSascha Wildner cc = c;
542be09fc23SSascha Wildner xpwrite(FD, &cc, 1);
543be09fc23SSascha Wildner if (number(value(CDELAY)) > 0 && c != '\r')
544be09fc23SSascha Wildner nap(number(value(CDELAY)));
545be09fc23SSascha Wildner if (!boolean(value(ECHOCHECK))) {
546be09fc23SSascha Wildner if (number(value(LDELAY)) > 0 && c == '\r')
547be09fc23SSascha Wildner nap(number(value(LDELAY)));
548be09fc23SSascha Wildner return;
549be09fc23SSascha Wildner }
550be09fc23SSascha Wildner tryagain:
551be09fc23SSascha Wildner timedout = 0;
552be09fc23SSascha Wildner alarm(number(value(ETIMEOUT)));
553be09fc23SSascha Wildner read(FD, &cc, 1);
554be09fc23SSascha Wildner alarm(0);
555be09fc23SSascha Wildner if (timedout) {
556be09fc23SSascha Wildner printf("\r\ntimeout error (%s)\r\n", ctrl(c));
557be09fc23SSascha Wildner if (retry++ > 3)
558be09fc23SSascha Wildner return;
559be09fc23SSascha Wildner xpwrite(FD, &null, 1); /* poke it */
560be09fc23SSascha Wildner goto tryagain;
561be09fc23SSascha Wildner }
562be09fc23SSascha Wildner }
563be09fc23SSascha Wildner
564be09fc23SSascha Wildner void
timeoutfunc(int __dummy)565be09fc23SSascha Wildner timeoutfunc(int __dummy)
566be09fc23SSascha Wildner {
567be09fc23SSascha Wildner signal(SIGALRM, timeoutfunc);
568be09fc23SSascha Wildner timedout = 1;
569be09fc23SSascha Wildner }
570be09fc23SSascha Wildner
571be09fc23SSascha Wildner /*
572be09fc23SSascha Wildner * Stolen from consh() -- puts a remote file on the output of a local command.
573be09fc23SSascha Wildner * Identical to consh() except for where stdout goes.
574be09fc23SSascha Wildner */
575be09fc23SSascha Wildner void
pipeout(int c)576be09fc23SSascha Wildner pipeout(int c)
577be09fc23SSascha Wildner {
578be09fc23SSascha Wildner char buf[256];
579be09fc23SSascha Wildner int cpid, status, p;
580be09fc23SSascha Wildner time_t start;
581be09fc23SSascha Wildner
582be09fc23SSascha Wildner putchar(c);
583be09fc23SSascha Wildner if (prompt("Local command? ", buf, sizeof(buf)))
584be09fc23SSascha Wildner return;
585be09fc23SSascha Wildner kill(pid, SIGIOT); /* put TIPOUT into a wait state */
586be09fc23SSascha Wildner signal(SIGINT, SIG_IGN);
587be09fc23SSascha Wildner signal(SIGQUIT, SIG_IGN);
588be09fc23SSascha Wildner usedefchars ();
589be09fc23SSascha Wildner read(repdes[0], (char *)&ccc, 1);
590be09fc23SSascha Wildner /*
591be09fc23SSascha Wildner * Set up file descriptors in the child and
592be09fc23SSascha Wildner * let it go...
593be09fc23SSascha Wildner */
594be09fc23SSascha Wildner if ((cpid = fork()) < 0)
595be09fc23SSascha Wildner printf("can't fork!\r\n");
596be09fc23SSascha Wildner else if (cpid) {
597be09fc23SSascha Wildner start = time(0);
598be09fc23SSascha Wildner while ((p = wait(&status)) > 0 && p != cpid)
599be09fc23SSascha Wildner ;
600be09fc23SSascha Wildner } else {
601be09fc23SSascha Wildner int i;
602be09fc23SSascha Wildner
603be09fc23SSascha Wildner dup2(FD, 1);
604be09fc23SSascha Wildner for (i = 3; i < 20; i++)
605be09fc23SSascha Wildner close(i);
606be09fc23SSascha Wildner signal(SIGINT, SIG_DFL);
607be09fc23SSascha Wildner signal(SIGQUIT, SIG_DFL);
608be09fc23SSascha Wildner execute(buf);
609be09fc23SSascha Wildner printf("can't find `%s'\r\n", buf);
610be09fc23SSascha Wildner exit(0);
611be09fc23SSascha Wildner }
612be09fc23SSascha Wildner if (boolean(value(VERBOSE)))
613be09fc23SSascha Wildner prtime("away for ", time(0)-start);
614be09fc23SSascha Wildner write(fildes[1], (char *)&ccc, 1);
615be09fc23SSascha Wildner usetchars ();
616be09fc23SSascha Wildner signal(SIGINT, SIG_DFL);
617be09fc23SSascha Wildner signal(SIGQUIT, SIG_DFL);
618be09fc23SSascha Wildner }
619be09fc23SSascha Wildner
620be09fc23SSascha Wildner int
tiplink(char * cmd,unsigned int flags)621be09fc23SSascha Wildner tiplink (char *cmd, unsigned int flags)
622be09fc23SSascha Wildner {
623be09fc23SSascha Wildner int cpid, status, p;
624be09fc23SSascha Wildner time_t start;
625be09fc23SSascha Wildner
626be09fc23SSascha Wildner if (flags & TL_SIGNAL_TIPOUT) {
627be09fc23SSascha Wildner kill(pid, SIGIOT); /* put TIPOUT into a wait state */
628be09fc23SSascha Wildner signal(SIGINT, SIG_IGN);
629be09fc23SSascha Wildner signal(SIGQUIT, SIG_IGN);
630be09fc23SSascha Wildner usedefchars ();
631be09fc23SSascha Wildner read(repdes[0], (char *)&ccc, 1);
632be09fc23SSascha Wildner }
633be09fc23SSascha Wildner
634be09fc23SSascha Wildner /*
635be09fc23SSascha Wildner * Set up file descriptors in the child and
636be09fc23SSascha Wildner * let it go...
637be09fc23SSascha Wildner */
638be09fc23SSascha Wildner if ((cpid = fork()) < 0)
639be09fc23SSascha Wildner printf("can't fork!\r\n");
640be09fc23SSascha Wildner else if (cpid) {
641be09fc23SSascha Wildner start = time(0);
642be09fc23SSascha Wildner while ((p = wait(&status)) > 0 && p != cpid)
643be09fc23SSascha Wildner ;
644be09fc23SSascha Wildner } else {
645be09fc23SSascha Wildner int fd;
646be09fc23SSascha Wildner
647be09fc23SSascha Wildner dup2(FD, 0);
648be09fc23SSascha Wildner dup2(3, 1);
649be09fc23SSascha Wildner for (fd = 3; fd < 20; fd++)
650be09fc23SSascha Wildner close (fd);
651be09fc23SSascha Wildner signal(SIGINT, SIG_DFL);
652be09fc23SSascha Wildner signal(SIGQUIT, SIG_DFL);
653be09fc23SSascha Wildner execute (cmd);
654be09fc23SSascha Wildner printf("can't find `%s'\r\n", cmd);
655be09fc23SSascha Wildner exit(0);
656be09fc23SSascha Wildner }
657be09fc23SSascha Wildner
658be09fc23SSascha Wildner if (flags & TL_VERBOSE && boolean(value(VERBOSE)))
659be09fc23SSascha Wildner prtime("away for ", time(0)-start);
660be09fc23SSascha Wildner
661be09fc23SSascha Wildner if (flags & TL_SIGNAL_TIPOUT) {
662be09fc23SSascha Wildner write(fildes[1], (char *)&ccc, 1);
663be09fc23SSascha Wildner usetchars ();
664be09fc23SSascha Wildner signal(SIGINT, SIG_DFL);
665be09fc23SSascha Wildner signal(SIGQUIT, SIG_DFL);
666be09fc23SSascha Wildner }
667be09fc23SSascha Wildner
668be09fc23SSascha Wildner return 0;
669be09fc23SSascha Wildner }
670be09fc23SSascha Wildner
671be09fc23SSascha Wildner /*
672be09fc23SSascha Wildner * Fork a program with:
673be09fc23SSascha Wildner * 0 <-> remote tty in
674be09fc23SSascha Wildner * 1 <-> remote tty out
675be09fc23SSascha Wildner * 2 <-> local tty out
676be09fc23SSascha Wildner */
677be09fc23SSascha Wildner void
consh(int c)678be09fc23SSascha Wildner consh(int c)
679be09fc23SSascha Wildner {
680be09fc23SSascha Wildner char buf[256];
681be09fc23SSascha Wildner putchar(c);
682be09fc23SSascha Wildner if (prompt("Local command? ", buf, sizeof(buf)))
683be09fc23SSascha Wildner return;
684be09fc23SSascha Wildner tiplink (buf, TL_SIGNAL_TIPOUT | TL_VERBOSE);
685be09fc23SSascha Wildner }
686be09fc23SSascha Wildner
687be09fc23SSascha Wildner /*
688be09fc23SSascha Wildner * Escape to local shell
689be09fc23SSascha Wildner */
690be09fc23SSascha Wildner void
shell(int c)691be09fc23SSascha Wildner shell(int c)
692be09fc23SSascha Wildner {
693be09fc23SSascha Wildner int shpid, status;
694be09fc23SSascha Wildner char *cp;
695be09fc23SSascha Wildner
696be09fc23SSascha Wildner printf("[sh]\r\n");
697be09fc23SSascha Wildner signal(SIGINT, SIG_IGN);
698be09fc23SSascha Wildner signal(SIGQUIT, SIG_IGN);
699be09fc23SSascha Wildner unraw();
700be09fc23SSascha Wildner if ((shpid = fork())) {
701be09fc23SSascha Wildner while (shpid != wait(&status));
702be09fc23SSascha Wildner raw();
703be09fc23SSascha Wildner printf("\r\n!\r\n");
704be09fc23SSascha Wildner signal(SIGINT, SIG_DFL);
705be09fc23SSascha Wildner signal(SIGQUIT, SIG_DFL);
706be09fc23SSascha Wildner return;
707be09fc23SSascha Wildner } else {
708be09fc23SSascha Wildner signal(SIGQUIT, SIG_DFL);
709be09fc23SSascha Wildner signal(SIGINT, SIG_DFL);
710be09fc23SSascha Wildner if ((cp = rindex(value(SHELL), '/')) == NULL)
711be09fc23SSascha Wildner cp = value(SHELL);
712be09fc23SSascha Wildner else
713be09fc23SSascha Wildner cp++;
714be09fc23SSascha Wildner shell_uid();
715be09fc23SSascha Wildner execl(value(SHELL), cp, NULL);
716be09fc23SSascha Wildner printf("\r\ncan't execl!\r\n");
717be09fc23SSascha Wildner exit(1);
718be09fc23SSascha Wildner }
719be09fc23SSascha Wildner }
720be09fc23SSascha Wildner
721be09fc23SSascha Wildner /*
722be09fc23SSascha Wildner * TIPIN portion of scripting
723be09fc23SSascha Wildner * initiate the conversation with TIPOUT
724be09fc23SSascha Wildner */
725be09fc23SSascha Wildner void
setscript(void)726be09fc23SSascha Wildner setscript(void)
727be09fc23SSascha Wildner {
728be09fc23SSascha Wildner char c;
729be09fc23SSascha Wildner /*
730be09fc23SSascha Wildner * enable TIPOUT side for dialogue
731be09fc23SSascha Wildner */
732be09fc23SSascha Wildner kill(pid, SIGEMT);
733be09fc23SSascha Wildner if (boolean(value(SCRIPT)))
734be09fc23SSascha Wildner write(fildes[1], value(RECORD), size(value(RECORD)));
735be09fc23SSascha Wildner write(fildes[1], "\n", 1);
736be09fc23SSascha Wildner /*
737be09fc23SSascha Wildner * wait for TIPOUT to finish
738be09fc23SSascha Wildner */
739be09fc23SSascha Wildner read(repdes[0], &c, 1);
740be09fc23SSascha Wildner if (c == 'n')
741be09fc23SSascha Wildner printf("can't create %s\r\n", value(RECORD));
742be09fc23SSascha Wildner }
743be09fc23SSascha Wildner
744be09fc23SSascha Wildner /*
745be09fc23SSascha Wildner * Change current working directory of
746be09fc23SSascha Wildner * local portion of tip
747be09fc23SSascha Wildner */
748be09fc23SSascha Wildner void
chdirectory(int c)749be09fc23SSascha Wildner chdirectory(int c)
750be09fc23SSascha Wildner {
751be09fc23SSascha Wildner char dirname[PATH_MAX];
752be09fc23SSascha Wildner char *cp = dirname;
753be09fc23SSascha Wildner
754be09fc23SSascha Wildner if (prompt("[cd] ", dirname, sizeof(dirname))) {
755be09fc23SSascha Wildner if (stoprompt)
756be09fc23SSascha Wildner return;
757be09fc23SSascha Wildner cp = value(HOME);
758be09fc23SSascha Wildner }
759be09fc23SSascha Wildner if (chdir(cp) < 0)
760be09fc23SSascha Wildner printf("%s: bad directory\r\n", cp);
761be09fc23SSascha Wildner printf("!\r\n");
762be09fc23SSascha Wildner }
763be09fc23SSascha Wildner
764be09fc23SSascha Wildner void
tipabort(char * msg)765be09fc23SSascha Wildner tipabort(char *msg)
766be09fc23SSascha Wildner {
767be09fc23SSascha Wildner
768be09fc23SSascha Wildner kill(pid, SIGTERM);
769be09fc23SSascha Wildner disconnect(msg);
770be09fc23SSascha Wildner if (msg != NULL)
771be09fc23SSascha Wildner printf("\r\n%s", msg);
772be09fc23SSascha Wildner printf("\r\n[EOT]\r\n");
773be09fc23SSascha Wildner daemon_uid();
774be09fc23SSascha Wildner (void)uu_unlock(uucplock);
775be09fc23SSascha Wildner unraw();
776be09fc23SSascha Wildner exit(0);
777be09fc23SSascha Wildner }
778be09fc23SSascha Wildner
779be09fc23SSascha Wildner void
finish(int c)780be09fc23SSascha Wildner finish(int c)
781be09fc23SSascha Wildner {
782be09fc23SSascha Wildner char *abortmsg = NULL, *dismsg;
783be09fc23SSascha Wildner
784be09fc23SSascha Wildner if (LO != NULL && tiplink (LO, TL_SIGNAL_TIPOUT) != 0) {
785be09fc23SSascha Wildner abortmsg = "logout failed";
786be09fc23SSascha Wildner }
787be09fc23SSascha Wildner
788be09fc23SSascha Wildner if ((dismsg = value(DISCONNECT)) != NULL) {
789be09fc23SSascha Wildner write(FD, dismsg, strlen(dismsg));
790be09fc23SSascha Wildner sleep (2);
791be09fc23SSascha Wildner }
792be09fc23SSascha Wildner tipabort(abortmsg);
793be09fc23SSascha Wildner }
794be09fc23SSascha Wildner
795be09fc23SSascha Wildner void
intcopy(int signo)796be09fc23SSascha Wildner intcopy(int signo)
797be09fc23SSascha Wildner {
798be09fc23SSascha Wildner raw();
799be09fc23SSascha Wildner quit = 1;
800be09fc23SSascha Wildner longjmp(intbuf, 1);
801be09fc23SSascha Wildner }
802be09fc23SSascha Wildner
803be09fc23SSascha Wildner static void
execute(char * s)804be09fc23SSascha Wildner execute(char *s)
805be09fc23SSascha Wildner {
806be09fc23SSascha Wildner char *cp;
807be09fc23SSascha Wildner
808be09fc23SSascha Wildner if ((cp = rindex(value(SHELL), '/')) == NULL)
809be09fc23SSascha Wildner cp = value(SHELL);
810be09fc23SSascha Wildner else
811be09fc23SSascha Wildner cp++;
812be09fc23SSascha Wildner shell_uid();
813be09fc23SSascha Wildner execl(value(SHELL), cp, "-c", s, NULL);
814be09fc23SSascha Wildner }
815be09fc23SSascha Wildner
816be09fc23SSascha Wildner static int
args(char * buf,char ** a,int num)817be09fc23SSascha Wildner args(char *buf, char **a, int num)
818be09fc23SSascha Wildner {
819be09fc23SSascha Wildner char *p = buf, *start;
820be09fc23SSascha Wildner char **parg = a;
821be09fc23SSascha Wildner int n = 0;
822be09fc23SSascha Wildner
823be09fc23SSascha Wildner while (*p && n < num) {
824be09fc23SSascha Wildner while (*p && (*p == ' ' || *p == '\t'))
825be09fc23SSascha Wildner p++;
826be09fc23SSascha Wildner start = p;
827be09fc23SSascha Wildner if (*p)
828be09fc23SSascha Wildner *parg = p;
829be09fc23SSascha Wildner while (*p && (*p != ' ' && *p != '\t'))
830be09fc23SSascha Wildner p++;
831be09fc23SSascha Wildner if (p != start)
832be09fc23SSascha Wildner parg++, n++;
833be09fc23SSascha Wildner if (*p)
834be09fc23SSascha Wildner *p++ = '\0';
835be09fc23SSascha Wildner }
836be09fc23SSascha Wildner return(n);
837be09fc23SSascha Wildner }
838be09fc23SSascha Wildner
839be09fc23SSascha Wildner static void
prtime(char * s,time_t a)840be09fc23SSascha Wildner prtime(char *s, time_t a)
841be09fc23SSascha Wildner {
842be09fc23SSascha Wildner int i;
843be09fc23SSascha Wildner int nums[3];
844be09fc23SSascha Wildner
845be09fc23SSascha Wildner for (i = 0; i < 3; i++) {
846be09fc23SSascha Wildner nums[i] = (int)(a % quant[i]);
847be09fc23SSascha Wildner a /= quant[i];
848be09fc23SSascha Wildner }
849be09fc23SSascha Wildner printf("%s", s);
850be09fc23SSascha Wildner while (--i >= 0)
851be09fc23SSascha Wildner if (nums[i] || (i == 0 && nums[1] == 0 && nums[2] == 0))
852be09fc23SSascha Wildner printf("%d %s%c ", nums[i], sep[i],
853be09fc23SSascha Wildner nums[i] == 1 ? '\0' : 's');
854be09fc23SSascha Wildner printf("\r\n!\r\n");
855be09fc23SSascha Wildner }
856be09fc23SSascha Wildner
857be09fc23SSascha Wildner void
variable(int c)858be09fc23SSascha Wildner variable(int c)
859be09fc23SSascha Wildner {
860be09fc23SSascha Wildner char buf[256];
861be09fc23SSascha Wildner
862be09fc23SSascha Wildner if (prompt("[set] ", buf, sizeof(buf)))
863be09fc23SSascha Wildner return;
864be09fc23SSascha Wildner vlex(buf);
865be09fc23SSascha Wildner if (vtable[BEAUTIFY].v_access&CHANGED) {
866be09fc23SSascha Wildner vtable[BEAUTIFY].v_access &= ~CHANGED;
867be09fc23SSascha Wildner kill(pid, SIGSYS);
868be09fc23SSascha Wildner }
869be09fc23SSascha Wildner if (vtable[SCRIPT].v_access&CHANGED) {
870be09fc23SSascha Wildner vtable[SCRIPT].v_access &= ~CHANGED;
871be09fc23SSascha Wildner setscript();
872be09fc23SSascha Wildner /*
873be09fc23SSascha Wildner * So that "set record=blah script" doesn't
874be09fc23SSascha Wildner * cause two transactions to occur.
875be09fc23SSascha Wildner */
876be09fc23SSascha Wildner if (vtable[RECORD].v_access&CHANGED)
877be09fc23SSascha Wildner vtable[RECORD].v_access &= ~CHANGED;
878be09fc23SSascha Wildner }
879be09fc23SSascha Wildner if (vtable[RECORD].v_access&CHANGED) {
880be09fc23SSascha Wildner vtable[RECORD].v_access &= ~CHANGED;
881be09fc23SSascha Wildner if (boolean(value(SCRIPT)))
882be09fc23SSascha Wildner setscript();
883be09fc23SSascha Wildner }
884be09fc23SSascha Wildner if (vtable[TAND].v_access&CHANGED) {
885be09fc23SSascha Wildner vtable[TAND].v_access &= ~CHANGED;
886be09fc23SSascha Wildner if (boolean(value(TAND)))
887be09fc23SSascha Wildner tandem("on");
888be09fc23SSascha Wildner else
889be09fc23SSascha Wildner tandem("off");
890be09fc23SSascha Wildner }
891be09fc23SSascha Wildner if (vtable[LECHO].v_access&CHANGED) {
892be09fc23SSascha Wildner vtable[LECHO].v_access &= ~CHANGED;
893be09fc23SSascha Wildner HD = boolean(value(LECHO));
894be09fc23SSascha Wildner }
895be09fc23SSascha Wildner if (vtable[PARITY].v_access&CHANGED) {
896be09fc23SSascha Wildner vtable[PARITY].v_access &= ~CHANGED;
897be09fc23SSascha Wildner setparity(value(PARITY));
898be09fc23SSascha Wildner }
899be09fc23SSascha Wildner }
900be09fc23SSascha Wildner
901be09fc23SSascha Wildner /*
902be09fc23SSascha Wildner * Turn tandem mode on or off for remote tty.
903be09fc23SSascha Wildner */
904be09fc23SSascha Wildner static void
tandem(char * option)905be09fc23SSascha Wildner tandem(char *option)
906be09fc23SSascha Wildner {
907be09fc23SSascha Wildner struct termios ttermios;
908be09fc23SSascha Wildner tcgetattr (FD, &ttermios);
909be09fc23SSascha Wildner if (strcmp(option,"on") == 0) {
910be09fc23SSascha Wildner ttermios.c_iflag |= IXOFF;
911be09fc23SSascha Wildner ctermios.c_iflag |= IXOFF;
912be09fc23SSascha Wildner }
913be09fc23SSascha Wildner else {
914be09fc23SSascha Wildner ttermios.c_iflag &= ~IXOFF;
915be09fc23SSascha Wildner ctermios.c_iflag &= ~IXOFF;
916be09fc23SSascha Wildner }
917be09fc23SSascha Wildner tcsetattr (FD, TCSANOW, &ttermios);
918be09fc23SSascha Wildner tcsetattr (0, TCSANOW, &ctermios);
919be09fc23SSascha Wildner }
920be09fc23SSascha Wildner
921be09fc23SSascha Wildner /*
922be09fc23SSascha Wildner * Send a break.
923be09fc23SSascha Wildner */
924be09fc23SSascha Wildner void
genbrk(int c)925be09fc23SSascha Wildner genbrk(int c)
926be09fc23SSascha Wildner {
927be09fc23SSascha Wildner
928be09fc23SSascha Wildner ioctl(FD, TIOCSBRK, NULL);
929be09fc23SSascha Wildner sleep(1);
930be09fc23SSascha Wildner ioctl(FD, TIOCCBRK, NULL);
931be09fc23SSascha Wildner }
932be09fc23SSascha Wildner
933be09fc23SSascha Wildner /*
934be09fc23SSascha Wildner * Suspend tip
935be09fc23SSascha Wildner */
936be09fc23SSascha Wildner void
suspend(int c)937be09fc23SSascha Wildner suspend(int c)
938be09fc23SSascha Wildner {
939be09fc23SSascha Wildner
940be09fc23SSascha Wildner unraw();
941be09fc23SSascha Wildner kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
942be09fc23SSascha Wildner raw();
943be09fc23SSascha Wildner }
944be09fc23SSascha Wildner
945be09fc23SSascha Wildner /*
946be09fc23SSascha Wildner * expand a file name if it includes shell meta characters
947be09fc23SSascha Wildner */
948be09fc23SSascha Wildner
949be09fc23SSascha Wildner char *
expand(char * name)950be09fc23SSascha Wildner expand(char *name)
951be09fc23SSascha Wildner {
952be09fc23SSascha Wildner static char xname[BUFSIZ];
953be09fc23SSascha Wildner char cmdbuf[BUFSIZ];
954be09fc23SSascha Wildner int pid, l;
955be09fc23SSascha Wildner char *cp, *Shell;
956be09fc23SSascha Wildner int s, pivec[2] /*, (*sigint)()*/;
957be09fc23SSascha Wildner
958be09fc23SSascha Wildner if (!anyof(name, "~{[*?$`'\"\\"))
959be09fc23SSascha Wildner return(name);
960be09fc23SSascha Wildner /* sigint = signal(SIGINT, SIG_IGN); */
961be09fc23SSascha Wildner if (pipe(pivec) < 0) {
962be09fc23SSascha Wildner warn("pipe");
963be09fc23SSascha Wildner /* signal(SIGINT, sigint) */
964be09fc23SSascha Wildner return(name);
965be09fc23SSascha Wildner }
966be09fc23SSascha Wildner snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name);
967be09fc23SSascha Wildner if ((pid = vfork()) == 0) {
968be09fc23SSascha Wildner Shell = value(SHELL);
969be09fc23SSascha Wildner if (Shell == NULL)
970be09fc23SSascha Wildner Shell = _PATH_BSHELL;
971be09fc23SSascha Wildner close(pivec[0]);
972be09fc23SSascha Wildner close(1);
973be09fc23SSascha Wildner dup(pivec[1]);
974be09fc23SSascha Wildner close(pivec[1]);
975be09fc23SSascha Wildner close(2);
976be09fc23SSascha Wildner shell_uid();
977be09fc23SSascha Wildner execl(Shell, Shell, "-c", cmdbuf, NULL);
978be09fc23SSascha Wildner _exit(1);
979be09fc23SSascha Wildner }
980be09fc23SSascha Wildner if (pid == -1) {
981be09fc23SSascha Wildner warn("fork");
982be09fc23SSascha Wildner close(pivec[0]);
983be09fc23SSascha Wildner close(pivec[1]);
984be09fc23SSascha Wildner return(NULL);
985be09fc23SSascha Wildner }
986be09fc23SSascha Wildner close(pivec[1]);
987be09fc23SSascha Wildner l = read(pivec[0], xname, BUFSIZ);
988be09fc23SSascha Wildner close(pivec[0]);
989be09fc23SSascha Wildner while (wait(&s) != pid)
990be09fc23SSascha Wildner ;
991be09fc23SSascha Wildner s &= 0377;
992be09fc23SSascha Wildner if (s != 0 && s != SIGPIPE) {
993be09fc23SSascha Wildner fprintf(stderr, "\"Echo\" failed\n");
994be09fc23SSascha Wildner return(NULL);
995be09fc23SSascha Wildner }
996be09fc23SSascha Wildner if (l < 0) {
997be09fc23SSascha Wildner warn("read");
998be09fc23SSascha Wildner return(NULL);
999be09fc23SSascha Wildner }
1000be09fc23SSascha Wildner if (l == 0) {
1001be09fc23SSascha Wildner fprintf(stderr, "\"%s\": No match\n", name);
1002be09fc23SSascha Wildner return(NULL);
1003be09fc23SSascha Wildner }
1004be09fc23SSascha Wildner if (l == BUFSIZ) {
1005be09fc23SSascha Wildner fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
1006be09fc23SSascha Wildner return(NULL);
1007be09fc23SSascha Wildner }
1008be09fc23SSascha Wildner xname[l] = 0;
1009be09fc23SSascha Wildner for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
1010be09fc23SSascha Wildner ;
1011be09fc23SSascha Wildner *++cp = '\0';
1012be09fc23SSascha Wildner return(xname);
1013be09fc23SSascha Wildner }
1014be09fc23SSascha Wildner
1015be09fc23SSascha Wildner /*
1016be09fc23SSascha Wildner * Are any of the characters in the two strings the same?
1017be09fc23SSascha Wildner */
1018be09fc23SSascha Wildner
1019be09fc23SSascha Wildner static int
anyof(char * s1,char * s2)1020be09fc23SSascha Wildner anyof(char *s1, char *s2)
1021be09fc23SSascha Wildner {
1022be09fc23SSascha Wildner int c;
1023be09fc23SSascha Wildner
1024be09fc23SSascha Wildner while ((c = *s1++))
1025be09fc23SSascha Wildner if (any(c, s2))
1026be09fc23SSascha Wildner return(1);
1027be09fc23SSascha Wildner return(0);
1028be09fc23SSascha Wildner }
1029