#include "replace.h"
#include "system/filesys.h"
#include "system/wait.h"
+#include "lib/util/sys_rw.h"
#ifdef HAVE_PTY_H
#include <pty.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
-#ifdef HAVE_LIBUTIL_H
+#ifdef HAVE_BSD_LIBUTIL_H
+#include <bsd/libutil.h>
+#elif defined HAVE_LIBUTIL_H
#include <libutil.h>
#endif
#endif /* STREAMPTY */
#include <popt.h>
+
+#ifdef HAVE_ERR_H
#include <err.h>
+#else
+const char progname[] = "unknown program";
+
+static void err(int eval, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 0);
+static void errx(int eval, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 0);
+
+static void err(int eval, const char *fmt, ...)
+{
+ int err_errno = errno;
+ va_list ap;
+
+ fprintf(stderr, "%s: ", progname);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, ": %s\n", strerror(err_errno));
+ exit(eval);
+}
+
+static void errx(int eval, const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s: ", progname);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+ exit(eval);
+}
+
+#endif
struct command {
enum { CMD_EXPECT = 0, CMD_SEND, CMD_PASSWORD } type;
return strdup(buf + len);
}
-/*******************************************************************
-A write wrapper that will deal with EINTR.
-********************************************************************/
-
-static ssize_t sys_write(int fd, const void *buf, size_t count)
-{
- ssize_t ret;
-
- do {
- ret = write(fd, buf, count);
-#if defined(EWOULDBLOCK)
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-#else
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
-#endif
- return ret;
-}
-
static void parse_configuration(const char *fn)
{
struct command *c;
fclose(cmd);
}
-/* A wrapper to close als file descriptors above the given fd */
-static int sys_closefrom(int fd)
-{
- int num = getdtablesize();
-
- if (num < 0) {
- num = 1024;
- }
-
- for (; fd <= num; fd++) {
- close(fd);
- }
-
- return 0;
-}
-
-
/*
*
*/
*/
struct poptOption long_options[] = {
POPT_AUTOHELP
- {"timeout", 't', POPT_ARG_INT, &opt_timeout, 't'},
- {"verbose", 'v', POPT_ARG_NONE, &opt_verbose, 'v'},
+ {
+ .longName = "timeout",
+ .shortName = 't',
+ .argInfo = POPT_ARG_INT,
+ .arg = &opt_timeout,
+ .val = 't',
+ },
+ {
+ .longName = "verbose",
+ .shortName = 'v',
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_verbose,
+ .val = 'v',
+ },
POPT_TABLEEND
};
{
int optidx = 0;
pid_t pid;
- poptContext pc;
+ poptContext pc = NULL;
const char *instruction_file;
+ const char **args;
const char *program;
- char* const *program_args;
+ char * const *program_args;
pc = poptGetContext("texpect",
argc,
if (argc == 1) {
poptPrintHelp(pc, stderr, 0);
- return 1;
+ goto out;
}
while ((optidx = poptGetNextOpt(pc)) != -1) {
- ;;
+ switch (optidx) {
+ case POPT_ERROR_BADOPT:
+ fprintf(stderr, "\nInvalid option %s: %s\n\n",
+ poptBadOption(pc, 0), poptStrerror(optidx));
+ poptPrintUsage(pc, stderr, 0);
+ exit(1);
+ }
}
instruction_file = poptGetArg(pc);
- program_args = poptGetArgs(pc);
+ args = poptGetArgs(pc);
+ if (args == NULL) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ program_args = (char * const *)discard_const_p(char *, args);
program = program_args[0];
if (opt_verbose) {
printf("Using instruction_file: %s\n", instruction_file);
printf("Executing '%s' ", program);
- for (i = 0; program_args && program_args[i] != NULL; i++) {
+ for (i = 0; program_args[i] != NULL; i++) {
printf("'%s' ", program_args[i]);
}
printf("\n");
switch (pid) {
case -1:
err(1, "Failed to fork");
+
+ /* Never reached */
+ goto out;
case 0:
if(setsid()<0)
dup2(slave, STDOUT_FILENO);
dup2(slave, STDERR_FILENO);
- sys_closefrom(STDERR_FILENO + 1);
+ closefrom(STDERR_FILENO + 1);
/* texpect <expect_instructions> <progname> [<args>] */
execvp(program, program_args);
err(1, "Failed to exec: %s", program);
+
+ /* Never reached */
+ goto out;
default:
close(slave);
{
sigaction(SIGALRM, &sa, NULL);
}
+ poptFreeContext(pc);
return eval_parent(pid);
}
+
+ /* Never reached */
+
+out:
+ poptFreeContext(pc);
+ return 1;
}