ctdb: Remove an unnecessary cast
[vlendec/samba-autobuild/.git] / lib / texpect / texpect.c
index 2ce33a286cc48d47e977f731abdd4cd334a8e609..1a6ebf486ae687223a4a873b05668136089b8004 100644 (file)
@@ -34,6 +34,7 @@
 #include "replace.h"
 #include "system/filesys.h"
 #include "system/wait.h"
+#include "lib/util/sys_rw.h"
 
 #ifdef HAVE_PTY_H
 #include <pty.h>
@@ -41,7 +42,9 @@
 #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;
@@ -143,24 +180,6 @@ static char *iscmd(const char *buf, const char *s)
        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;
@@ -202,23 +221,6 @@ static void parse_configuration(const char *fn)
        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;
-}
-
-
 /*
  *
  */
@@ -347,8 +349,20 @@ static int eval_parent(pid_t pid)
  */
 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
 };
 
@@ -356,10 +370,11 @@ int main(int argc, const char **argv)
 {
        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,
@@ -369,15 +384,27 @@ int main(int argc, const char **argv)
 
        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) {
@@ -385,7 +412,7 @@ int main(int argc, const char **argv)
 
                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");
@@ -399,6 +426,9 @@ int main(int argc, const char **argv)
        switch (pid) {
                case -1:
                        err(1, "Failed to fork");
+
+                       /* Never reached */
+                       goto out;
                case 0:
 
                        if(setsid()<0)
@@ -408,11 +438,14 @@ int main(int argc, const char **argv)
                        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);
                        {
@@ -425,6 +458,13 @@ int main(int argc, const char **argv)
                                sigaction(SIGALRM, &sa, NULL);
                        }
 
+                       poptFreeContext(pc);
                        return eval_parent(pid);
        }
+
+       /* Never reached */
+
+out:
+       poptFreeContext(pc);
+       return 1;
 }