/* -*-c-*-
*
- * $Id: sw_build.c,v 1.1 1999/06/02 16:53:34 mdw Exp $
+ * $Id: sw_build.c,v 1.4 1999/09/16 12:53:46 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.4 1999/09/16 12:53:46 mdw
+ * Some systems have uname(2) return > 0.
+ *
+ * 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.
*
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
+#include <sys/utsname.h>
#ifndef DECL_ENVIRON
extern char **environ;
{
archcons *aa;
+ dstr d = DSTR_INIT;
+ char **av;
+ struct utsname u;
+
+ /* --- Fill in the hostname --- */
+
+ if (uname(&u) < 0)
+ 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));
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 --- */
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);
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;
int fd[2];
pid_t kid;
- /* --- Validate arguments --- */
+ /* --- Validate the arguments --- */
if (!argv[0])
swdie(r, 1, "Usage: build COMMAND [ARG...]");
struct tm *tm;
char buf[64];
char **p;
+ struct utsname u;
+ if (uname(&u) < 0)
+ 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) {
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);
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;
}
{
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);