view loadtools/tpinterf.c @ 619:f82551c77e58

libserial-newlnx: ASYNC_LOW_LATENCY patch reverted Reports from Das Signal indicate that loadtools performance on Debian is about the same as on Slackware, and that including or omitting the ASYNC_LOW_LATENCY patch from Serg makes no difference. Because the patch in question does not appear to be necessary, it is being reverted until and unless someone other than Serg reports an actual real-world system on which loadtools operation times are slowed compared to the Mother's Slackware reference and on which Slackware-like performance can be restored by setting the ASYNC_LOW_LATENCY flag.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 27 Feb 2020 01:09:48 +0000
parents e7502631a0f9
children 8d7dcfd9df53
line wrap: on
line source

/*
 * 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;
		}
	}
}