2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * Copyright (c) 1983 Regents of the University of California.
8 * All rights reserved. The Berkeley software License Agreement
9 * specifies the terms and conditions for redistribution.
12 #pragma ident "%Z%%M% %I% %E% SMI"
25 * miscellaneous commands
28 int quant
[] = { 60, 60, 24 };
31 char *sep
[] = { "second", "minute", "hour" };
32 static char *argv
[10]; /* argument vector for take and put */
34 sigjmp_buf intbuf
; /* for interrupts and timeouts */
36 void timeout(void); /* timeout function called on alarm */
37 void intcopy(void); /* interrupt routine for file transfers */
38 void transfer(char *, int, char *);
39 void transmit(FILE *, char *, char *);
42 void prtime(char *, time_t);
43 void hardwareflow(char *);
45 int args(char *, char *[], size_t);
46 int anyof(char *, char *);
49 * FTP - remote ==> local
50 * get a file from the remote host
59 * get the UNIX receiving file's name
61 if (prompt("Local file name? ", copyname
, sizeof (copyname
)))
63 cp
= expand(copyname
);
66 if ((sfd
= creat(cp
, 0666)) < 0) {
67 (void) printf("\r\n%s: cannot creat\r\n", copyname
);
74 if (prompt("List command for remote system? ", buf
, sizeof (buf
))) {
75 (void) unlink(copyname
);
78 transfer(buf
, sfd
, value(EOFREAD
));
82 * Cu-like take command
89 char line
[BUFSIZ
], *cp
;
91 if (prompt("[take] ", copyname
, sizeof (copyname
)))
93 argc
= args(copyname
, argv
, sizeof (argv
)/sizeof (char *));
94 if (argc
< 1 || argc
> 2) {
95 (void) printf("usage: <take> from [to]\r\n");
100 cp
= expand(argv
[1]);
103 if ((fd
= creat(cp
, 0666)) < 0) {
104 (void) printf("\r\n%s: cannot create\r\n", argv
[1]);
107 (void) snprintf(line
, sizeof (line
), "cat %s; echo \01", argv
[0]);
108 transfer(line
, fd
, "\01");
112 * Bulk transfer routine --
113 * used by getfl(), cu_take(), and pipefile()
116 transfer(char *buf
, int fd
, char *eofchars
)
119 char c
, buffer
[BUFSIZ
];
120 char *p
= buffer
; /* can't be register because of longjmp */
125 parwrite(FD
, (unsigned char *)buf
, strlen(buf
));
126 (void) kill(pid
, SIGIOT
);
127 /* Wait until read process stops */
128 (void) read(repdes
[0], (char *)&ccc
, 1);
133 parwrite(FD
, (unsigned char *)"\r", 1);
135 (void) read(FD
, &c
, 1);
136 while ((c
&0177) != '\n')
139 if (sigsetjmp(intbuf
, 1))
141 f
= signal(SIGINT
, (sig_handler_t
)intcopy
);
148 eof
= read(FD
, &c
, 1) <= 0;
153 if (eof
|| (bol
&& any(c
, eofchars
)))
156 continue; /* ignore nulls */
163 if (boolean(value(VERBOSE
)))
164 (void) printf("\r%d", ++ct
);
167 if ((cnt
= (p
-buffer
)) == number(value(FRAMESIZE
))) {
168 if (write(fd
, buffer
, cnt
) != cnt
) {
169 (void) printf("\r\nwrite error\r\n");
176 if ((cnt
= (p
-buffer
)) != 0)
177 if (write(fd
, buffer
, cnt
) != cnt
)
178 (void) printf("\r\nwrite error\r\n");
180 if (boolean(value(VERBOSE
)))
181 prtime(" lines transferred in ", time(0)-start
);
183 (void) write(fildes
[1], (char *)&ccc
, 1);
184 (void) signal(SIGINT
, f
);
189 * FTP - remote ==> local process
190 * send remote input to local process via pipe
200 if (prompt("Local command? ", buf
, sizeof (buf
)))
204 (void) printf("can't establish pipe\r\n");
208 if ((cpid
= fork()) < 0) {
209 (void) printf("can't fork!\r\n");
212 if (prompt("List command for remote system? ", buf
,
214 (void) close(pdes
[0]), (void) close(pdes
[1]);
215 (void) kill(cpid
, SIGKILL
);
217 (void) close(pdes
[0]);
218 (void) signal(SIGPIPE
, (sig_handler_t
)intcopy
);
219 transfer(buf
, pdes
[1], value(EOFREAD
));
220 (void) signal(SIGPIPE
, SIG_DFL
);
221 while ((p
= wait(&status
)) > 0 && p
!= cpid
)
228 (void) dup2(pdes
[0], 0);
229 (void) close(pdes
[0]);
230 for (f
= 3; f
< 20; f
++)
233 (void) printf("can't execl!\r\n");
239 * FTP - local ==> remote
240 * send local file to remote host
241 * terminate transmission with pseudo EOF sequence
253 if (prompt("Local file name? ", fname
, sizeof (fname
)))
259 fnamex
= expand(fname
);
262 if ((fd
= fopen(fnamex
, "r")) == NULL
) {
263 (void) printf("%s: cannot open\r\n", fname
);
266 transmit(fd
, value(EOFWRITE
), NULL
);
267 if (!boolean(value(ECHOCHECK
))) {
270 (void) ioctl(FD
, TCGETS
, (char *)&buf
); /* this does a */
271 (void) ioctl(FD
, TCSETSF
, (char *)&buf
); /* wflushtty */
276 * Bulk transfer routine to remote host --
277 * used by tip_sendfile() and cu_put()
280 transmit(FILE *fd
, char *eofchars
, char *command
)
284 int c
, ccount
, lcount
;
285 time_t start_t
, stop_t
;
287 (void) kill(pid
, SIGIOT
); /* put TIPOUT into a wait state */
289 if (sigsetjmp(intbuf
, 1)) {
291 (void) printf("\r\ntimed out at eol\r\n");
295 ointr
= signal(SIGINT
, (sig_handler_t
)intcopy
);
297 (void) read(repdes
[0], (char *)&ccc
, 1);
298 if (command
!= NULL
) {
299 for (pc
= command
; *pc
; pc
++)
301 if (boolean(value(ECHOCHECK
)))
302 (void) read(FD
, (char *)&c
, 1); /* trailing \n */
305 /* wait for remote stty to take effect */
308 (void) ioctl(FD
, TCGETS
, (char *)&buf
);
310 (void) ioctl(FD
, TCSETSF
, (char *)&buf
);
316 if (boolean(value(RAWFTP
))) {
317 while ((c
= getc(fd
)) != EOF
) {
320 if (boolean(value(VERBOSE
)) && lcount
%100 == 0)
321 (void) printf("\r%d", lcount
);
323 if (boolean(value(VERBOSE
)))
324 (void) printf("\r%d", lcount
);
339 } else if (c
== '\t') {
340 if (boolean(value(TABEXPAND
))) {
342 while ((++ccount
% 8) != 0)
351 if (boolean(value(VERBOSE
)))
352 (void) printf("\r%d", ++lcount
);
353 if (boolean(value(ECHOCHECK
))) {
354 (void) alarm(number(value(ETIMEOUT
)));
355 do { /* wait for prompt */
356 (void) read(FD
, &rc
, 1);
357 } while ((rc
&0177) != character(value(PROMPT
)));
362 if (lastc
!= '\n' && !boolean(value(RAWFTP
)))
365 for (pc
= eofchars
; *pc
; pc
++)
369 if (boolean(value(VERBOSE
)))
370 if (boolean(value(RAWFTP
)))
371 prtime(" chars transferred in ", stop_t
-start_t
);
373 prtime(" lines transferred in ", stop_t
-start_t
);
374 (void) write(fildes
[1], (char *)&ccc
, 1);
376 (void) signal(SIGINT
, ointr
);
380 * Cu-like put command
391 if (prompt("[put] ", copyname
, sizeof (copyname
)))
393 argc
= args(copyname
, argv
, sizeof (argv
)/sizeof (char *));
394 if (argc
< 1 || argc
> 2) {
395 (void) printf("usage: <put> from [to]\r\n");
400 copynamex
= expand(argv
[0]);
401 if (copynamex
== NOSTR
)
403 if ((fd
= fopen(copynamex
, "r")) == NULL
) {
404 (void) printf("%s: cannot open\r\n", copynamex
);
407 if (boolean(value(ECHOCHECK
)))
408 (void) snprintf(line
, sizeof (line
), "cat>%s\r", argv
[1]);
410 (void) snprintf(line
, sizeof (line
),
411 "stty -echo; cat>%s; stty echo\r", argv
[1]);
412 transmit(fd
, "\04", line
);
416 * FTP - send single character
417 * wait for echo & handle timeout
426 parwrite(FD
, (unsigned char *)&cc
, 1);
428 if (number(value(CDELAY
)) > 0 && c
!= '\r')
429 nap(number(value(CDELAY
)));
431 if (!boolean(value(ECHOCHECK
))) {
433 if (number(value(LDELAY
)) > 0 && c
== '\r')
434 nap(number(value(LDELAY
)));
440 if (sigsetjmp(intbuf
, 1) && timedout
) {
441 (void) printf("\r\ntimeout error (%s)\r\n", ctrl(c
));
444 parwrite(FD
, (unsigned char *)&null
, 1); /* poke it */
447 (void) alarm(number(value(ETIMEOUT
)));
448 (void) read(FD
, &cc
, 1);
455 (void) signal(SIGALRM
, (sig_handler_t
)timeout
);
457 siglongjmp(intbuf
, 1);
461 * Stolen from consh() -- puts a remote file on the output of a local command.
462 * Identical to consh() except for where stdout goes.
472 if (prompt("Local command? ", buf
, sizeof (buf
)))
474 (void) kill(pid
, SIGIOT
); /* put TIPOUT into a wait state */
475 (void) signal(SIGINT
, SIG_IGN
);
476 (void) signal(SIGQUIT
, SIG_IGN
);
478 (void) read(repdes
[0], (char *)&ccc
, 1);
480 * Set up file descriptors in the child and
483 if ((cpid
= fork()) < 0)
484 (void) printf("can't fork!\r\n");
487 while ((p
= wait(&status
)) > 0 && p
!= cpid
)
494 for (i
= 3; i
< 20; i
++)
496 (void) signal(SIGINT
, SIG_DFL
);
497 (void) signal(SIGQUIT
, SIG_DFL
);
499 (void) printf("can't find `%s'\r\n", buf
);
502 if (boolean(value(VERBOSE
)))
503 prtime("away for ", time(0)-start
);
504 (void) write(fildes
[1], (char *)&ccc
, 1);
506 (void) signal(SIGINT
, SIG_DFL
);
507 (void) signal(SIGQUIT
, SIG_DFL
);
511 * Fork a program with:
512 * 0 <-> remote tty in
513 * 1 <-> remote tty out
514 * 2 <-> local tty stderr out
521 sig_handler_t ointr
, oquit
;
525 if (prompt("Local command? ", buf
, sizeof (buf
)))
527 (void) kill(pid
, SIGIOT
); /* put TIPOUT into a wait state */
528 (void) read(repdes
[0], (char *)&ccc
, 1);
529 ointr
= signal(SIGINT
, SIG_IGN
);
530 oquit
= signal(SIGQUIT
, SIG_IGN
);
533 * Set up file descriptors in the child and
536 if ((cpid
= fork()) < 0)
537 (void) printf("can't fork!\r\n");
540 while ((p
= wait(&status
)) > 0 && p
!= cpid
)
543 (void) signal(SIGINT
, ointr
);
544 (void) signal(SIGQUIT
, oquit
);
551 for (i
= 3; i
< 20; i
++)
553 (void) signal(SIGINT
, SIG_DFL
);
554 (void) signal(SIGQUIT
, SIG_DFL
);
556 (void) printf("can't find `%s'\r\n", buf
);
559 if (boolean(value(VERBOSE
)))
560 prtime("\r\naway for ", time(0)-start
);
561 (void) write(fildes
[1], (char *)&ccc
, 1);
565 * Escape to local shell
572 sig_handler_t ointr
, oquit
;
575 (void) printf("[sh]\r\n");
576 ointr
= signal(SIGINT
, SIG_IGN
);
577 oquit
= signal(SIGQUIT
, SIG_IGN
);
579 if (shpid
= fork()) {
580 while (shpid
!= wait(&status
))
583 (void) printf("\r\n!\r\n");
584 (void) signal(SIGINT
, ointr
);
585 (void) signal(SIGQUIT
, oquit
);
588 (void) signal(SIGQUIT
, SIG_DFL
);
589 (void) signal(SIGINT
, SIG_DFL
);
590 if ((cp
= strrchr(value(SHELL
), '/')) == NULL
)
594 (void) execl(value(SHELL
), cp
, 0);
595 (void) printf("\r\ncan't execl!\r\n");
601 * TIPIN portion of scripting
602 * initiate the conversation with TIPOUT
609 if (strlen(value(RECORD
)) >= PATH_MAX
-1) {
610 (void) fprintf(stderr
, "tip: record file name too long\r\n");
614 * enable TIPOUT side for dialogue
616 (void) kill(pid
, SIGEMT
);
617 if (boolean(value(SCRIPT
)))
618 (void) write(fildes
[1], value(RECORD
), strlen(value(RECORD
)));
619 (void) write(fildes
[1], "\n", 1);
621 * wait for TIPOUT to finish
623 (void) read(repdes
[0], &c
, 1);
625 (void) fprintf(stderr
, "tip: can't create record file %s\r\n",
630 * Change current working directory of
631 * local portion of tip
640 if (prompt("[cd] ", dirname
, sizeof (dirname
))) {
646 (void) printf("%s: bad directory\r\n", cp
);
647 (void) printf("!\r\n");
653 /* don't want to hear about our child */
654 (void) signal(SIGCHLD
, SIG_DFL
);
655 (void) kill(pid
, SIGTERM
);
659 (void) printf("\r\n%s", msg
);
660 (void) printf("\r\n[EOT]\r\n");
672 if ((dismsg
= value(DISCONNECT
)) != NOSTR
) {
673 (void) write(FD
, dismsg
, strlen(dismsg
));
683 (void) signal(SIGINT
, SIG_IGN
);
684 siglongjmp(intbuf
, 1);
692 if ((cp
= strrchr(value(SHELL
), '/')) == NULL
)
696 (void) execl(value(SHELL
), cp
, "-c", s
, 0);
700 args(char *buf
, char *a
[], size_t na
)
702 char *p
= buf
, *start
;
707 while (*p
&& (*p
== ' ' || *p
== '\t'))
712 while (*p
&& (*p
!= ' ' && *p
!= '\t'))
718 } while (*p
&& n
< na
);
724 prtime(char *s
, time_t a
)
729 for (i
= 0; i
< 3; i
++) {
730 nums
[i
] = (int)(a
% quant
[i
]);
733 (void) printf("%s", s
);
735 if (nums
[i
] || i
== 0 && nums
[1] == 0 && nums
[2] == 0)
736 (void) printf("%d %s%c ", nums
[i
], sep
[i
],
737 nums
[i
] == 1 ? '\0' : 's');
738 (void) printf("\r\n!\r\n");
747 if (prompt("[set] ", buf
, sizeof (buf
)))
750 if (vtable
[BEAUTIFY
].v_access
&CHANGED
) {
751 vtable
[BEAUTIFY
].v_access
&= ~CHANGED
;
752 (void) kill(pid
, SIGSYS
);
754 if (vtable
[SCRIPT
].v_access
&CHANGED
) {
755 vtable
[SCRIPT
].v_access
&= ~CHANGED
;
758 * So that "set record=blah script" doesn't
759 * cause two transactions to occur.
761 if (vtable
[RECORD
].v_access
&CHANGED
)
762 vtable
[RECORD
].v_access
&= ~CHANGED
;
764 if (vtable
[RECORD
].v_access
&CHANGED
) {
765 vtable
[RECORD
].v_access
&= ~CHANGED
;
766 if (boolean(value(SCRIPT
)))
769 if (vtable
[TAND
].v_access
&CHANGED
) {
770 vtable
[TAND
].v_access
&= ~CHANGED
;
771 if (boolean(value(TAND
)))
776 if (vtable
[LECHO
].v_access
&CHANGED
) {
777 vtable
[LECHO
].v_access
&= ~CHANGED
;
778 boolean(value(HALFDUPLEX
)) = boolean(value(LECHO
));
780 if (vtable
[PARITY
].v_access
&CHANGED
) {
781 vtable
[PARITY
].v_access
&= ~CHANGED
;
784 if (vtable
[BAUDRATE
].v_access
&CHANGED
) {
785 vtable
[BAUDRATE
].v_access
&= ~CHANGED
;
786 ttysetup(speed(number(value(BAUDRATE
))));
788 if (vtable
[HARDWAREFLOW
].v_access
& CHANGED
) {
789 vtable
[HARDWAREFLOW
].v_access
&= ~CHANGED
;
790 if (boolean(value(HARDWAREFLOW
)))
798 * Turn tandem mode on or off for remote tty.
803 struct termios rmtty
;
805 (void) ioctl(FD
, TCGETS
, (char *)&rmtty
);
806 if (equal(option
, "on")) {
807 rmtty
.c_iflag
|= IXOFF
|IXON
;
808 arg
.c_iflag
|= IXOFF
|IXON
;
809 rmtty
.c_cc
[VSTART
] = defarg
.c_cc
[VSTART
];
810 rmtty
.c_cc
[VSTOP
] = defarg
.c_cc
[VSTOP
];
812 rmtty
.c_iflag
&= ~(IXOFF
|IXON
);
813 arg
.c_iflag
&= ~(IXOFF
|IXON
);
815 (void) ioctl(FD
, TCSETSF
, (char *)&rmtty
);
816 (void) ioctl(0, TCSETSF
, (char *)&arg
);
820 * Turn hardwareflow mode on or off for remote tty.
823 hardwareflow(char *option
)
825 struct termios rmtty
;
827 (void) ioctl(FD
, TCGETS
, (char *)&rmtty
);
828 if (equal(option
, "on")) {
829 rmtty
.c_cflag
|= (CRTSCTS
|CRTSXOFF
);
831 rmtty
.c_cflag
&= ~(CRTSCTS
|CRTSXOFF
);
833 (void) ioctl(FD
, TCSETSF
, (char *)&rmtty
);
837 * Turn interrupts from local tty on or off.
843 if (equal(option
, "on"))
846 arg
.c_lflag
&= ~ISIG
;
847 (void) ioctl(0, TCSETSF
, (char *)&arg
);
858 (void) ioctl(FD
, TCSBRK
, 0);
869 (void) kill(c
== _CTRL('y') ? getpid() : 0, SIGTSTP
);
874 * expand a file name if it includes shell meta characters
880 static char xname
[BUFSIZ
];
886 if (!anyof(name
, "~{[*?$`'\"\\"))
888 if (pipe(pivec
) < 0) {
892 (void) snprintf(cmdbuf
, sizeof (cmdbuf
), "echo %s", name
);
893 if ((pid
= vfork()) == 0) {
895 Shell
= value(SHELL
);
898 (void) close(pivec
[0]);
900 (void) dup(pivec
[1]);
901 (void) close(pivec
[1]);
903 (void) execl(Shell
, Shell
, "-c", cmdbuf
, 0);
908 (void) close(pivec
[0]);
909 (void) close(pivec
[1]);
912 (void) close(pivec
[1]);
913 l
= read(pivec
[0], xname
, BUFSIZ
);
914 (void) close(pivec
[0]);
915 while (wait(&s
) != pid
)
918 if (s
!= 0 && s
!= SIGPIPE
) {
919 (void) fprintf(stderr
, "\"Echo\" failed\n");
927 (void) fprintf(stderr
, "\"%s\": No match\n", name
);
931 (void) fprintf(stderr
, "Buffer overflow expanding \"%s\"\n",
936 for (cp
= &xname
[l
-1]; *cp
== '\n' && cp
> xname
; cp
--)
943 * Are any of the characters in the two strings the same?
947 anyof(char *s1
, char *s2
)
951 while ((c
= *s1
++) != 0)