Include `%'-escape substitution.
[sw-tools] / src / sw_build.c
index 3e8476a..4933363 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: sw_build.c,v 1.1 1999/06/02 16:53:34 mdw Exp $
+ * $Id: sw_build.c,v 1.3 1999/09/10 15:27:33 mdw Exp $
  *
  * Management of build processes
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: sw_build.c,v $
- * Revision 1.1  1999/06/02 16:53:34  mdw
- * Initial revision
+ * Revision 1.3  1999/09/10 15:27:33  mdw
+ * Include `%'-escape substitution.
+ *
+ * Revision 1.2  1999/07/16 12:50:24  mdw
+ * Improve exit status display.  New interface from `doto' project.
+ *
+ * Revision 1.1.1.1  1999/06/02 16:53:34  mdw
+ * Initial import.
  *
  */
 
@@ -53,6 +59,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/wait.h>
+#include <sys/utsname.h>
 
 #ifndef DECL_ENVIRON
   extern char **environ;
@@ -224,13 +231,92 @@ int sw_run(int argc, char *argv[])
 
     {
       archcons *aa;
+      dstr d = DSTR_INIT;
+      char **av;
+      struct utsname u;
+
+      /* --- Fill in the hostname --- */
+
+      if (uname(&u))
+       strcpy(u.nodename, "<unknown>");
+
+      /* --- If necessary, set up the output @argv@ array --- */
+
+      if (opt_flags & optFlag_percent)
+       av = xmalloc(argc * sizeof(char *));
+      else
+       av = argv + 1;
+
+      /* --- Run through the target build hosts --- */
 
       FD_ZERO(&fdin);
       for (aa = a; aa; aa = aa->cdr) {
        archent *e = aa->car;
        sw_remote *r = e->r;
+
+       /* --- If necessary, translate `%'-escapes --- */
+
+       if (opt_flags & optFlag_percent) {
+         char **pp, **qq;
+
+         for (pp = argv + 1, qq = av; *pp; pp++, qq++) {
+           if (strchr(*pp, '%') == 0)
+             *qq = *pp;
+           else {
+             char *p;
+             char *q = *pp;
+             for (p = *pp; *p; p++) {
+               if (*p == '%') {
+                 DPUTM(&d, q, p - q);
+                 p++;
+                 switch (*p) {
+                   case 0:
+                     DPUTC(&d, '%');
+                     goto done_arg;
+                   case '%':
+                     DPUTC(&d, '%');
+                     break;
+                   case 'a':
+                     dstr_puts(&d, e->arch);
+                     break;
+                   case 'h':
+                     dstr_puts(&d, e->flags & archFlag_home ?
+                                     u.nodename : e->host);
+                     break;
+                   case 'P':
+                     dstr_puts(&d, PREFIX);
+                     break;
+                   case 'p':
+                     dstr_puts(&d, sw.package);
+                     break;
+                   case 'v':
+                     dstr_puts(&d, sw.version);
+                     break;
+                   case 'u':
+                     dstr_puts(&d, sw.maintainer);
+                     break;
+                   default:
+                     DPUTC(&d, '%');
+                     DPUTC(&d, *p);
+                     break;
+                 }
+                 q = p + 1;
+               }
+             }
+             DPUTM(&d, q, p - q);
+           done_arg:
+             DPUTZ(&d);
+             *qq = xstrdup(d.buf);
+             DRESET(&d);
+           }
+         }
+         *qq++ = 0;
+       }
+
+       /* --- Start a new process off --- */
+
        if (swrsh(r, e->flags & archFlag_home ? 0 : e->host,
-                 "build", argv + 1)) {
+                 "build", av)) {
          dstr d = DSTR_INIT;
          dstr_putf(&d, "%s: couldn't start build for architecture `%s': %s",
                    QUIS, e->arch, strerror(errno));
@@ -245,7 +331,21 @@ int sw_run(int argc, char *argv[])
          active++;
          FD_SET(fd, &fdin);
        }
+
+       /* --- Free up the argument array --- */
+
+       if (opt_flags & optFlag_percent) {
+         char **pp, **qq;
+
+         for (pp = argv + 1, qq = av; *pp; pp++, qq++) {
+           if (*pp != *qq)
+             free(*qq);
+         }
+       }
       }
+
+      if (opt_flags & optFlag_percent)
+       free(av);
     }
 
     /* --- Watch the builds until they do something interesting --- */
@@ -288,31 +388,29 @@ int sw_run(int argc, char *argv[])
            int ok = 1;
            if (r->sz != 1) {
              r->buf[r->sz] = 0;
-             dstr_putf(&d, "\nTerminated by signal: %s.\n", r->buf);
+             dstr_putf(&d, "failed (%s)", r->buf);
              ok = 0;
              rc = 1;
            } else if (r->buf[0]) {
-             dstr_putf(&d, "\nExited with status %u.\n",
-                       (unsigned char)r->buf[0]);
+             dstr_putf(&d, "failed (status %u)", (unsigned char)r->buf[0]);
              ok = 0;
              rc = 1;
-           } else if (opt_flags & optFlag_install)
-             e->flags |= archFlag_built;
-           if (d.len)
-             p->output(e, d.buf, d.len);
-           dstr_destroy(&d);
+           } else {
+             dstr_puts(&d, "finished");
+             if (opt_flags & optFlag_install)
+               e->flags |= archFlag_built;
+           }
            if (p->close)
-             p->close(e, ok);
+             p->close(e, ok, d.buf);
+           dstr_destroy(&d);
            FD_CLR(r->fdin, &fdin);
            close(r->fdin);
            active--;
          } break;
 
          case PKTYPE_EOF: {
-           const static char msg[] = "\nUnexpected exit.\n";
-           p->output(e, msg, sizeof(msg) - 1);
            if (p->close)
-             p->close(e, 0);
+             p->close(e, 0, "unexpected exit");
            rc = 1;
            FD_CLR(r->fdin, &fdin);
            close(r->fdin);
@@ -339,7 +437,7 @@ int sw_run(int argc, char *argv[])
       p->abort(a);
     switch (exc_type) {
       case EXC_ERRNO:
-       die(1, "unexpected error: %s", exc_i);
+       die(1, "unexpected error: %s", strerror(exc_i));
        break;
       default:
        RETHROW;
@@ -428,7 +526,7 @@ void swrsh_build(sw_remote *r, char *argv[], char *env[])
   int fd[2];
   pid_t kid;
 
-  /* --- Validate arguments --- */
+  /* --- Validate the arguments --- */
 
   if (!argv[0])
     swdie(r, 1, "Usage: build COMMAND [ARG...]");
@@ -452,7 +550,10 @@ void swrsh_build(sw_remote *r, char *argv[], char *env[])
     struct tm *tm;
     char buf[64];
     char **p;
+    struct utsname u;
 
+    if (uname(&u))
+      swdie(r, 1, "couldn't get hostname: %s", strerror(errno));
     if (logfd < 0)
       swdie(r, 1, "couldn't open `.build-log' file: %s", strerror(errno));
     if ((logfp = fdopen(logfd, "a")) == 0) {
@@ -462,7 +563,8 @@ void swrsh_build(sw_remote *r, char *argv[], char *env[])
     t = time(0);
     tm = localtime(&t);
     strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
-    fprintf(logfp, "\n\n*** %s: started build: %s", buf, argv[0]);
+    fprintf(logfp, "\n\n*** %s: %s started build: %s",
+           buf, u.nodename, argv[0]);
     for (p = argv + 1; *p; p++)
       fprintf(logfp, " %s", *p);
     fputs("\n\n", logfp);
@@ -498,7 +600,7 @@ void swrsh_build(sw_remote *r, char *argv[], char *env[])
     if (!n)
       break;
     if (n < 0) {
-      putf(r, logfp, "*** error reading from pipe: %s\n", strerror(errno));
+      putf(r, logfp, "\n*** error reading from pipe: %s\n", strerror(errno));
       kill(kid, SIGTERM);
       break;
     }
@@ -511,15 +613,16 @@ void swrsh_build(sw_remote *r, char *argv[], char *env[])
 
   {
     int status;
-    if (waitpid(kid, &status, 0) < 0)
-      putf(r, logfp, "*** error reading exit status: %s\n", strerror(errno));
-    else {
+    if (waitpid(kid, &status, 0) < 0) {
+      putf(r, logfp, "\n*** error reading exit status: %s\n",
+          strerror(errno));
+    } else {
       if (WIFSIGNALED(status))
-       fprintf(logfp, "*** exited on signal %i\n", WTERMSIG(status));
+       fprintf(logfp, "\n*** exited on signal %i\n", WTERMSIG(status));
       else if (WIFEXITED(status))
-       fprintf(logfp, "*** exited with status %i\n", WEXITSTATUS(status));
+       fprintf(logfp, "\n*** exited with status %i\n", WEXITSTATUS(status));
       else
-       fprintf(logfp, "*** reaped, but didn't exit.  Strange\n");
+       fprintf(logfp, "\n*** reaped, but didn't exit.  Strange\n");
     }
     fclose(logfp);
     swwait(r, status);