FreeCalypso > hg > freecalypso-tools
diff loadtools/tpinterf.c @ 0:e7502631a0f9
initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 11 Jun 2016 00:13:35 +0000 |
parents | |
children | 8d7dcfd9df53 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadtools/tpinterf.c Sat Jun 11 00:13:35 2016 +0000 @@ -0,0 +1,178 @@ +/* + * Target program interface - this module provides some primitives + * for communicating programmatically with loadagent and possibly + * other target-utils. This module will be linked by both + * fc-loadtool and fc-chainload. + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/errno.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> + +extern int errno; + +extern int target_fd; + +/* definition matches ../target-utils/libcommon/cmdentry.c */ +#define MAXCMD 527 + +/* + * static buffer between tpinterf_make_cmd and tpinterf_send_cmd + * + * We store the command with an ending \r\n so we can use it for + * matching the received echo as well, hence the sizing of the + * buffer. + */ +static char cmdbuf[MAXCMD+2]; +static int cmdlen; + +static int +arg_chars_valid(arg) + char *arg; +{ + char *cp; + + for (cp = arg; *cp; cp++) + if (*cp < ' ' || *cp > '~') + return(0); + return(1); +} + +/* + * This function takes a command for the target in argv form and + * converts it to a space-separated continuous string which can be + * passed as tty "keyboard" input to the target, enforcing length + * and character validity limits in the process. The output is + * stored in an internal static buffer for subsequent + * tpinterf_send_cmd(). + * + * Return value: 0 if everything OK, or -1 if some constraint is + * violated. + */ +tpinterf_make_cmd(argv) + char **argv; +{ + int arglen; + char **ap, *dp; + + dp = cmdbuf; + cmdlen = 0; + for (ap = argv; *ap; ap++) { + arglen = strlen(*ap); + if (ap != argv) + arglen++; /* separating space */ + if (arglen > MAXCMD - cmdlen) + return(-1); + if (!arg_chars_valid(*ap)) + return(-1); + if (ap != argv) + *dp++ = ' '; + strcpy(dp, *ap); + dp += strlen(*ap); + cmdlen += arglen; + } + *dp++ = '\r'; + *dp = '\n'; + return(0); +} + +/* + * This function sends the previously-constructed command to the target, + * and collects the expected echo. + * + * Return value: 0 if successful, -1 on errors (timeout or wrong response) + */ +tpinterf_send_cmd() +{ + char echobuf[MAXCMD+2]; + fd_set fds; + struct timeval tv; + int rcvd, cc; + + write(target_fd, cmdbuf, cmdlen + 1); + for (rcvd = 0; rcvd < cmdlen + 2; ) { + FD_ZERO(&fds); + FD_SET(target_fd, &fds); + tv.tv_sec = 1; + tv.tv_usec = 0; + cc = select(target_fd+1, &fds, NULL, NULL, &tv); + if (cc < 0) { + if (errno == EINTR) + continue; + perror("select"); + return(-1); + } + if (cc < 1) { + fprintf(stderr, + "error: timeout waiting for command echo\n"); + return(-1); + } + cc = read(target_fd, echobuf + rcvd, cmdlen + 2 - rcvd); + if (cc <= 0) { + perror("read after successful select"); + return(-1); + } + rcvd += cc; + } + if (bcmp(echobuf, cmdbuf, cmdlen + 2)) { + fprintf(stderr, "error: command echo mismatch\n"); + return(-1); + } else + return(0); +} + +/* + * This functions reads the serial output from the target until a + * '=' prompt is received. All intermediate output is passed to + * stdout. + * + * Return value: 0 if '=' prompt received immediately, + * positive if some scribble came before the prompt, -1 on errors + * (timeout, read errors, etc). + */ +tpinterf_pass_output(timeout) +{ + char buf[512], *cp; + fd_set fds; + struct timeval tv; + int cc, newline = 1, totout = 0; + + for (;;) { + FD_ZERO(&fds); + FD_SET(target_fd, &fds); + tv.tv_sec = timeout; + tv.tv_usec = 0; + cc = select(target_fd+1, &fds, NULL, NULL, &tv); + if (cc < 0) { + if (errno == EINTR) + continue; + perror("select"); + return(-1); + } + if (cc < 1) { + fprintf(stderr, + "error: timeout waiting for \'=\' prompt from target\n"); + return(-1); + } + cc = read(target_fd, buf, sizeof buf); + if (cc <= 0) { + perror("read after successful select"); + return(-1); + } + for (cp = buf; cc; cp++) { + cc--; + if (*cp == '=' && newline && !cc) + return(totout); + putchar(*cp); + totout++; + if (*cp == '\n') + newline = 1; + else + newline = 0; + } + } +}