FreeCalypso > hg > freecalypso-sw
changeset 335:40b8557b9d04
rvinterf suite: libasync factored out of fc-tmsh
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Tue, 22 Apr 2014 06:51:09 +0000 |
parents | 73a2b359b3cd |
children | 922efdd65dce |
files | rvinterf/Makefile rvinterf/libasync/Makefile rvinterf/libasync/README rvinterf/libasync/init.c rvinterf/libasync/interf.c rvinterf/libasync/launchrvif.c rvinterf/libasync/rvtrace.c rvinterf/libasync/ttymagic.c rvinterf/tmsh/Makefile rvinterf/tmsh/init.c rvinterf/tmsh/interf.c rvinterf/tmsh/launchrvif.c rvinterf/tmsh/pktsort.c rvinterf/tmsh/ttymagic.c |
diffstat | 14 files changed, 424 insertions(+), 379 deletions(-) [+] |
line wrap: on
line diff
--- a/rvinterf/Makefile Tue Apr 22 05:52:38 2014 +0000 +++ b/rvinterf/Makefile Tue Apr 22 06:51:09 2014 +0000 @@ -1,10 +1,11 @@ PROGDIR=etmsync lowlevel misc tmsh -LIBDIR= libg23 +LIBDIR= libasync libg23 SUBDIR= ${PROGDIR} ${LIBDIR} all: ${SUBDIR} lowlevel: libg23 +tmsh: libasync ${SUBDIR}: FRC cd $@; ${MAKE} ${MFLAGS}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/libasync/Makefile Tue Apr 22 06:51:09 2014 +0000 @@ -0,0 +1,13 @@ +CC= gcc +CFLAGS= -O2 -I../include +OBJS= init.o interf.o launchrvif.o rvtrace.o ttymagic.o +LIB= libasync.a + +all: ${LIB} + +${LIB}: ${OBJS} + ar rcu $@ ${OBJS} + ranlib $@ + +clean: + rm -f *.[oa] errs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/libasync/README Tue Apr 22 06:51:09 2014 +0000 @@ -0,0 +1,3 @@ +This host side library contains common modules for tools like fc-tmsh and +g23sh which operate asynchronously. This code has been factored out of +fc-tmsh.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/libasync/init.c Tue Apr 22 06:51:09 2014 +0000 @@ -0,0 +1,66 @@ +/* + * This module contains the common initialization code for fc-tmsh and g23sh. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <unistd.h> +#include "pktmux.h" +#include "localsock.h" + +extern char *socket_pathname; +extern int sock; + +connect_local_socket() +{ + /* local socket binding voodoo copied from osmocon */ + struct sockaddr_un local; + unsigned int namelen; + int rc; + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + perror("socket(AF_UNIX, SOCK_STREAM, 0)"); + exit(1); + } + + local.sun_family = AF_UNIX; + strncpy(local.sun_path, socket_pathname, sizeof(local.sun_path)); + local.sun_path[sizeof(local.sun_path) - 1] = '\0'; + + /* we use the same magic that X11 uses in Xtranssock.c for + * calculating the proper length of the sockaddr */ +#if defined(BSD44SOCKETS) || defined(__UNIXWARE__) + local.sun_len = strlen(local.sun_path); +#endif +#if defined(BSD44SOCKETS) || defined(SUN_LEN) + namelen = SUN_LEN(&local); +#else + namelen = strlen(local.sun_path) + + offsetof(struct sockaddr_un, sun_path) + 1; +#endif + + rc = connect(sock, (struct sockaddr *) &local, namelen); + if (rc != 0) { + perror(socket_pathname); + exit(1); + } + + return(0); +} + +send_init_command(cmdpkt, cmdlen) + u_char *cmdpkt; +{ + u_char lenbuf[2]; + + lenbuf[0] = 0; + lenbuf[1] = cmdlen; + write(sock, lenbuf, 2); + write(sock, cmdpkt, cmdlen); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/libasync/interf.c Tue Apr 22 06:51:09 2014 +0000 @@ -0,0 +1,106 @@ +/* + * This module implements the link to rvinterf. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include "localsock.h" + +extern int sock; + +u_char rvi_msg[LOCALSOCK_MAX_MSG]; +int rvi_msg_len; + +static int rx_state, rx_left; +static u_char *rx_ptr; + +void +localsock_prep_for_length_rx() +{ + rx_state = 0; + rx_ptr = rvi_msg; + rx_left = 2; +} + +static void +prep_for_message_rx() +{ + rx_state = 1; + rx_ptr = rvi_msg; + rx_left = rvi_msg_len; +} + +void +process_msg_from_rvinterf() +{ + switch (rvi_msg[0]) { + case RVI2CLI_PKT_FROM_TARGET: + process_pkt_from_target(); + return; + case RVI2CLI_LOCAL_CMD_RESP: + if (rvi_msg_len < 2) + goto bad; + if (rvi_msg[1] == '+') + return; + tty_cleanup(); + fprintf(stderr, "Error from rvinterf: %.*s\n", rvi_msg_len - 1, + rvi_msg + 1); + exit(1); + default: + bad: + tty_cleanup(); + fprintf(stderr, + "Error: unexpected message type %02X from rvinterf\n", + rvi_msg[0]); + exit(1); + } +} + +void +handle_rvinterf_input() +{ + int cc; + + cc = read(sock, rx_ptr, rx_left); + if (cc <= 0) { + tty_cleanup(); + perror("read from rvinterf socket"); + exit(1); + } + rx_ptr += cc; + rx_left -= cc; + if (rx_left) + return; + /* got the thing, process it */ + if (rx_state) { + process_msg_from_rvinterf(); + localsock_prep_for_length_rx(); + } else { + rvi_msg_len = rvi_msg[0] << 8 | rvi_msg[1]; + if (rvi_msg_len < 1 || rvi_msg_len > LOCALSOCK_MAX_MSG) { + tty_cleanup(); + fprintf(stderr, + "Invalid length from rvinterf: %02X%02X\n", + rvi_msg[0], rvi_msg[1]); + exit(1); + } + prep_for_message_rx(); + } +} + +void +send_pkt_to_target(pkt, pktlen) + u_char *pkt; +{ + u_char hdrbuf[3]; + int len1; + + len1 = pktlen + 1; + hdrbuf[0] = len1 >> 8; + hdrbuf[1] = len1 & 0xFF; + hdrbuf[2] = CLI2RVI_PKT_TO_TARGET; + write(sock, hdrbuf, 3); + write(sock, pkt, pktlen); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/libasync/launchrvif.c Tue Apr 22 06:51:09 2014 +0000 @@ -0,0 +1,63 @@ +/* + * This module implements the optional "behind the scenes" invokation + * of rvinterf from fc-tmsh. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static char rvinterf_pathname[] = "/usr/local/bin/rvinterf"; + +extern int sock; + +char *rvinterf_Bopt, *rvinterf_lopt, *rvinterf_wopt; + +launch_rvinterf(ttyport) + char *ttyport; +{ + int sp[2], rc; + char *rvif_argv[11], Sarg[16], **ap; + + rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sp); + if (rc < 0) { + perror("socketpair"); + exit(1); + } + sock = sp[0]; + sprintf(Sarg, "-S%d", sp[1]); + ap = rvif_argv; + *ap++ = "rvinterf"; + *ap++ = Sarg; + *ap++ = "-n"; + if (rvinterf_Bopt) { + *ap++ = "-B"; + *ap++ = rvinterf_Bopt; + } + if (rvinterf_lopt) { + *ap++ = "-l"; + *ap++ = rvinterf_lopt; + } + if (rvinterf_wopt) { + *ap++ = "-w"; + *ap++ = rvinterf_wopt; + } + *ap++ = ttyport; + *ap = 0; + rc = vfork(); + if (rc < 0) { + perror("vfork for launching rvinterf"); + exit(1); + } + if (!rc) { + /* we are in the child - do the exec */ + close(sp[0]); + execv(rvinterf_pathname, rvif_argv); + perror(rvinterf_pathname); + _exit(1); + } + close(sp[1]); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/libasync/rvtrace.c Tue Apr 22 06:51:09 2014 +0000 @@ -0,0 +1,54 @@ +/* + * Here we detect and handle "Lost Message" packets. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include "pktmux.h" +#include "limits.h" +#include "localsock.h" + +extern u_char rvi_msg[]; +extern int rvi_msg_len; + +void +safe_print_trace(src, srclen, dest) + u_char *src; + char *dest; +{ + int i, c; + char *dp; + + dp = dest; + for (i = 0; i < srclen; i++) { + c = src[i]; + if (c & 0x80) { + *dp++ = 'M'; + *dp++ = '-'; + c &= 0x7F; + } + if (c < 0x20) { + *dp++ = '^'; + *dp++ = c + '@'; + } else if (c == 0x7F) { + *dp++ = '^'; + *dp++ = '?'; + } else + *dp++ = c; + } + *dp = '\0'; +} + +void +handle_useid_0() +{ + char buf[MAX_PKT_FROM_TARGET*4]; + + if (strncmp(rvi_msg + 7, "RVT: Lost Message", 17)) + return; + safe_print_trace(rvi_msg + 7, rvi_msg_len - 7, buf); + async_msg_output(buf); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/libasync/ttymagic.c Tue Apr 22 06:51:09 2014 +0000 @@ -0,0 +1,112 @@ +/* + * This module contains the tty "magic" code for fc-tmsh. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <unistd.h> +#include <termios.h> + +extern int ttyhacks; + +struct termios orig_termios, our_termios; + +#define MAX_USER_CMD 78 +char usercmd[MAX_USER_CMD+1]; +int usercmd_len; + +void +tty_init() +{ + if (!ttyhacks) + return; + tcgetattr(0, &orig_termios); + bcopy(&orig_termios, &our_termios, sizeof(struct termios)); + our_termios.c_oflag &= ~(OCRNL | ONOCR | ONLRET); + our_termios.c_lflag &= ~(ICANON | ECHO); + our_termios.c_cc[VMIN] = 1; + our_termios.c_cc[VTIME] = 0; + tcsetattr(0, TCSAFLUSH, &our_termios); + putchar('>'); + fflush(stdout); +} + +void +tty_cleanup() +{ + if (!ttyhacks) + return; + tcsetattr(0, TCSAFLUSH, &orig_termios); +} + +void +handle_tty_input() +{ + char buf[256]; + int i, c, cc; + + cc = read(0, buf, sizeof buf); + if (cc <= 0) { + tty_cleanup(); + exit(0); + } + for (i = 0; i < cc; i++) { + c = buf[i]; + if (c >= ' ' && c <= '~') { + if (usercmd_len >= MAX_USER_CMD) + continue; + usercmd[usercmd_len++] = c; + if (ttyhacks) + putchar(c); /* echo */ + continue; + } + switch (c) { + case '\b': + case 0x7F: + if (!usercmd_len) + continue; + usercmd_len--; + if (ttyhacks) { + putchar('\b'); + putchar(' '); + putchar('\b'); + } + continue; + case '\n': + case '\r': + usercmd[usercmd_len] = '\0'; + if (ttyhacks) + putchar('\n'); /* echo */ + dispatch_user_cmd(); + usercmd_len = 0; + if (ttyhacks) + putchar('>'); /* new prompt */ + } + } +} + +void +async_msg_output(msg) + char *msg; +{ + int msglen, i; + + msglen = strlen(msg); + if (ttyhacks) + putchar('\r'); + fputs(msg, stdout); + if (ttyhacks) + for (i = msglen; i < usercmd_len + 1; i++) + putchar(' '); + putchar('\n'); + if (!ttyhacks) + return; + /* reprint the input line */ + putchar('>'); + if (!usercmd_len) + return; + fwrite(usercmd, 1, usercmd_len, stdout); +}
--- a/rvinterf/tmsh/Makefile Tue Apr 22 05:52:38 2014 +0000 +++ b/rvinterf/tmsh/Makefile Tue Apr 22 06:51:09 2014 +0000 @@ -2,15 +2,15 @@ CFLAGS= -O2 -I../include PROGS= fc-tmsh INSTBIN=/usr/local/bin +LIBS= ../libasync/libasync.a -TMSH_OBJS= abb.o etmbasic.o ffs2.o ffs2resp.o ffs2wr.o init.o interf.o \ - launchrvif.o main.o misc.o pktsort.o tmcore.o ttymagic.o \ - usercmd.o +TMSH_OBJS= abb.o etmbasic.o ffs2.o ffs2resp.o ffs2wr.o init.o main.o \ + misc.o pktsort.o tmcore.o usercmd.o all: ${PROGS} -fc-tmsh: ${TMSH_OBJS} - ${CC} ${CFLAGS} -o $@ ${TMSH_OBJS} +fc-tmsh: ${TMSH_OBJS} ${LIBS} + ${CC} ${CFLAGS} -o $@ ${TMSH_OBJS} ${LIBS} install: ${PROGS} mkdir -p ${INSTBIN}
--- a/rvinterf/tmsh/init.c Tue Apr 22 05:52:38 2014 +0000 +++ b/rvinterf/tmsh/init.c Tue Apr 22 06:51:09 2014 +0000 @@ -3,68 +3,15 @@ */ #include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> #include <stdio.h> #include <string.h> #include <strings.h> #include <stdlib.h> -#include <unistd.h> #include "pktmux.h" #include "localsock.h" -extern char *socket_pathname; extern int sock; -connect_local_socket() -{ - /* local socket binding voodoo copied from osmocon */ - struct sockaddr_un local; - unsigned int namelen; - int rc; - - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { - perror("socket(AF_UNIX, SOCK_STREAM, 0)"); - exit(1); - } - - local.sun_family = AF_UNIX; - strncpy(local.sun_path, socket_pathname, sizeof(local.sun_path)); - local.sun_path[sizeof(local.sun_path) - 1] = '\0'; - - /* we use the same magic that X11 uses in Xtranssock.c for - * calculating the proper length of the sockaddr */ -#if defined(BSD44SOCKETS) || defined(__UNIXWARE__) - local.sun_len = strlen(local.sun_path); -#endif -#if defined(BSD44SOCKETS) || defined(SUN_LEN) - namelen = SUN_LEN(&local); -#else - namelen = strlen(local.sun_path) + - offsetof(struct sockaddr_un, sun_path) + 1; -#endif - - rc = connect(sock, (struct sockaddr *) &local, namelen); - if (rc != 0) { - perror(socket_pathname); - exit(1); - } - - return(0); -} - -send_init_command(cmdpkt, cmdlen) - u_char *cmdpkt; -{ - u_char lenbuf[2]; - - lenbuf[0] = 0; - lenbuf[1] = cmdlen; - write(sock, lenbuf, 2); - write(sock, cmdpkt, cmdlen); -} - init() { static u_char want_rvt_lost[9] = {CLI2RVI_WANT_RVTRACE,
--- a/rvinterf/tmsh/interf.c Tue Apr 22 05:52:38 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/* - * This module implements the link to rvinterf. - */ - -#include <sys/types.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include "localsock.h" - -extern int sock; - -u_char rvi_msg[LOCALSOCK_MAX_MSG]; -int rvi_msg_len; - -static int rx_state, rx_left; -static u_char *rx_ptr; - -void -localsock_prep_for_length_rx() -{ - rx_state = 0; - rx_ptr = rvi_msg; - rx_left = 2; -} - -static void -prep_for_message_rx() -{ - rx_state = 1; - rx_ptr = rvi_msg; - rx_left = rvi_msg_len; -} - -void -process_msg_from_rvinterf() -{ - switch (rvi_msg[0]) { - case RVI2CLI_PKT_FROM_TARGET: - process_pkt_from_target(); - return; - case RVI2CLI_LOCAL_CMD_RESP: - if (rvi_msg_len < 2) - goto bad; - if (rvi_msg[1] == '+') - return; - tty_cleanup(); - fprintf(stderr, "Error from rvinterf: %.*s\n", rvi_msg_len - 1, - rvi_msg + 1); - exit(1); - default: - bad: - tty_cleanup(); - fprintf(stderr, - "Error: unexpected message type %02X from rvinterf\n", - rvi_msg[0]); - exit(1); - } -} - -void -handle_rvinterf_input() -{ - int cc; - - cc = read(sock, rx_ptr, rx_left); - if (cc <= 0) { - tty_cleanup(); - perror("read from rvinterf socket"); - exit(1); - } - rx_ptr += cc; - rx_left -= cc; - if (rx_left) - return; - /* got the thing, process it */ - if (rx_state) { - process_msg_from_rvinterf(); - localsock_prep_for_length_rx(); - } else { - rvi_msg_len = rvi_msg[0] << 8 | rvi_msg[1]; - if (rvi_msg_len < 1 || rvi_msg_len > LOCALSOCK_MAX_MSG) { - tty_cleanup(); - fprintf(stderr, - "Invalid length from rvinterf: %02X%02X\n", - rvi_msg[0], rvi_msg[1]); - exit(1); - } - prep_for_message_rx(); - } -} - -void -send_pkt_to_target(pkt, pktlen) - u_char *pkt; -{ - u_char hdrbuf[3]; - int len1; - - len1 = pktlen + 1; - hdrbuf[0] = len1 >> 8; - hdrbuf[1] = len1 & 0xFF; - hdrbuf[2] = CLI2RVI_PKT_TO_TARGET; - write(sock, hdrbuf, 3); - write(sock, pkt, pktlen); -}
--- a/rvinterf/tmsh/launchrvif.c Tue Apr 22 05:52:38 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * This module implements the optional "behind the scenes" invokation - * of rvinterf from fc-tmsh. - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -static char rvinterf_pathname[] = "/usr/local/bin/rvinterf"; - -extern int sock; - -char *rvinterf_Bopt, *rvinterf_lopt, *rvinterf_wopt; - -launch_rvinterf(ttyport) - char *ttyport; -{ - int sp[2], rc; - char *rvif_argv[11], Sarg[16], **ap; - - rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sp); - if (rc < 0) { - perror("socketpair"); - exit(1); - } - sock = sp[0]; - sprintf(Sarg, "-S%d", sp[1]); - ap = rvif_argv; - *ap++ = "rvinterf"; - *ap++ = Sarg; - *ap++ = "-n"; - if (rvinterf_Bopt) { - *ap++ = "-B"; - *ap++ = rvinterf_Bopt; - } - if (rvinterf_lopt) { - *ap++ = "-l"; - *ap++ = rvinterf_lopt; - } - if (rvinterf_wopt) { - *ap++ = "-w"; - *ap++ = rvinterf_wopt; - } - *ap++ = ttyport; - *ap = 0; - rc = vfork(); - if (rc < 0) { - perror("vfork for launching rvinterf"); - exit(1); - } - if (!rc) { - /* we are in the child - do the exec */ - close(sp[0]); - execv(rvinterf_pathname, rvif_argv); - perror(rvinterf_pathname); - _exit(1); - } - close(sp[1]); - return 0; -}
--- a/rvinterf/tmsh/pktsort.c Tue Apr 22 05:52:38 2014 +0000 +++ b/rvinterf/tmsh/pktsort.c Tue Apr 22 06:51:09 2014 +0000 @@ -16,45 +16,6 @@ extern u_char rvi_msg[]; extern int rvi_msg_len; -void -safe_print_trace(src, srclen, dest) - u_char *src; - char *dest; -{ - int i, c; - char *dp; - - dp = dest; - for (i = 0; i < srclen; i++) { - c = src[i]; - if (c & 0x80) { - *dp++ = 'M'; - *dp++ = '-'; - c &= 0x7F; - } - if (c < 0x20) { - *dp++ = '^'; - *dp++ = c + '@'; - } else if (c == 0x7F) { - *dp++ = '^'; - *dp++ = '?'; - } else - *dp++ = c; - } - *dp = '\0'; -} - -static void -handle_useid_0() -{ - char buf[MAX_PKT_FROM_TARGET*4]; - - if (strncmp(rvi_msg + 7, "RVT: Lost Message", 17)) - return; - safe_print_trace(rvi_msg + 7, rvi_msg_len - 7, buf); - async_msg_output(buf); -} - static void print_etm_trace() {
--- a/rvinterf/tmsh/ttymagic.c Tue Apr 22 05:52:38 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -/* - * This module contains the tty "magic" code for fc-tmsh. - */ - -#include <sys/types.h> -#include <stdio.h> -#include <string.h> -#include <strings.h> -#include <stdlib.h> -#include <unistd.h> -#include <termios.h> - -extern int ttyhacks; - -struct termios orig_termios, our_termios; - -#define MAX_USER_CMD 78 -char usercmd[MAX_USER_CMD+1]; -int usercmd_len; - -void -tty_init() -{ - if (!ttyhacks) - return; - tcgetattr(0, &orig_termios); - bcopy(&orig_termios, &our_termios, sizeof(struct termios)); - our_termios.c_oflag &= ~(OCRNL | ONOCR | ONLRET); - our_termios.c_lflag &= ~(ICANON | ECHO); - our_termios.c_cc[VMIN] = 1; - our_termios.c_cc[VTIME] = 0; - tcsetattr(0, TCSAFLUSH, &our_termios); - putchar('>'); - fflush(stdout); -} - -void -tty_cleanup() -{ - if (!ttyhacks) - return; - tcsetattr(0, TCSAFLUSH, &orig_termios); -} - -void -handle_tty_input() -{ - char buf[256]; - int i, c, cc; - - cc = read(0, buf, sizeof buf); - if (cc <= 0) { - tty_cleanup(); - exit(0); - } - for (i = 0; i < cc; i++) { - c = buf[i]; - if (c >= ' ' && c <= '~') { - if (usercmd_len >= MAX_USER_CMD) - continue; - usercmd[usercmd_len++] = c; - if (ttyhacks) - putchar(c); /* echo */ - continue; - } - switch (c) { - case '\b': - case 0x7F: - if (!usercmd_len) - continue; - usercmd_len--; - if (ttyhacks) { - putchar('\b'); - putchar(' '); - putchar('\b'); - } - continue; - case '\n': - case '\r': - usercmd[usercmd_len] = '\0'; - if (ttyhacks) - putchar('\n'); /* echo */ - dispatch_user_cmd(); - usercmd_len = 0; - if (ttyhacks) - putchar('>'); /* new prompt */ - } - } -} - -void -async_msg_output(msg) - char *msg; -{ - int msglen, i; - - msglen = strlen(msg); - if (ttyhacks) - putchar('\r'); - fputs(msg, stdout); - if (ttyhacks) - for (i = msglen; i < usercmd_len + 1; i++) - putchar(' '); - putchar('\n'); - if (!ttyhacks) - return; - /* reprint the input line */ - putchar('>'); - if (!usercmd_len) - return; - fwrite(usercmd, 1, usercmd_len, stdout); -}