aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rcynic/rcynic.c95
1 files changed, 59 insertions, 36 deletions
diff --git a/rcynic/rcynic.c b/rcynic/rcynic.c
index 09add560..1a44a184 100644
--- a/rcynic/rcynic.c
+++ b/rcynic/rcynic.c
@@ -66,9 +66,10 @@ typedef struct certinfo {
* Program context that would otherwise be a mess of global variables.
*/
typedef struct rcynic_ctx {
- char *jane, *rsync, *authenticated, *old_authenticated, *unauthenticated;
+ char *authenticated, *old_authenticated, *unauthenticated;
+ char *jane, *rsync_program;
STACK *rsync_cache;
- int indent;
+ int indent, rsync_timeout;
int rsync_verbose, mkdir_verbose, err_verbose;
} rcynic_ctx_t;
@@ -390,6 +391,17 @@ static int rm_rf(const char *name)
* log stream into lines without fgets() is a pain, maybe setting
* nonblocking I/O before calling fdopen() would suffice to let us use
* select()? If we time out, we need to kill() the rsync process.
+ *
+ * Ok, this is a PITA. I don't see any portable way to use fgets()
+ * with non-blocking I/O, so we have to revert to raw read()/write()
+ * calls (after setting fcntl(fd, O_NONBLOCK)), look for the newline
+ * ourselves, and perhaps even copy remainig text from the buffer down
+ * to the bottom (or do some kind of ringbuffer thing, hmmm...no that
+ * doesn't work well with null terminated strings, oh well).
+ *
+ * Type signature of execvp() is weird, hence the cast. Well, ok
+ * ANSI/ISO const is weird to begin with, but even once one gets past
+ * the bizzare syntax, execvp()'s type signature is still weird.
*/
static int rsync_cmp(const char * const *a, const char * const *b)
@@ -397,39 +409,41 @@ static int rsync_cmp(const char * const *a, const char * const *b)
return strcmp(*a, *b);
}
-static int rsync(const rcynic_ctx_t *rc, ...)
+static int rsync(const rcynic_ctx_t *rc,
+ const char * const *args,
+ const char *uri)
{
static char *rsync_cmd[] = {
"rsync", "--update", "--times", "--copy-links", "--itemize-changes"
};
- char *s, *argv[100], buffer[URI_MAX * 4], *uri = 0, path[FILENAME_MAX];
- int i, argc, pipe_fds[2], pid_status = -1;
- va_list ap;
+ const char *argv[100];
+ char *s, buffer[URI_MAX * 4], path[FILENAME_MAX];
+ int i, ret, pipe_fds[2], argc = 0, pid_status = -1;
+#if 0
+ struct timeval tv;
+ fd_set rfds;
+ int n;
+#endif
pid_t pid;
FILE *f;
+ assert(rc && uri);
+
memset(argv, 0, sizeof(argv));
- va_start(ap, rc);
- for (argc = 0; argc < sizeof(rsync_cmd)/sizeof(*rsync_cmd); argc++) {
+ for (i = 0; i < sizeof(rsync_cmd)/sizeof(*rsync_cmd); i++) {
assert(argc < sizeof(argv)/sizeof(*argv));
- argv[argc] = rsync_cmd[argc];
+ argv[argc++] = rsync_cmd[i];
}
- while ((s = va_arg(ap, char *)) != NULL) {
- assert(argc < sizeof(argv)/sizeof(*argv));
- argv[argc++] = s;
- if (!uri && *s != '-')
- uri = s;
+ if (args) {
+ for (i = 0; args[i]; i++) {
+ assert(argc < sizeof(argv)/sizeof(*argv));
+ argv[argc++] = args[i];
+ }
}
- va_end(ap);
- if (rc->rsync)
- argv[0] = rc->rsync;
-
- if (!uri) {
- logmsg(rc, "Couldn't extract URI from rsync command");
- return 0;
- }
+ if (rc->rsync_program)
+ argv[0] = rc->rsync_program;
if (!uri_to_filename(uri, path, sizeof(path), rc->unauthenticated)) {
logmsg(rc, "Couldn't extract filename from URI: %s", uri);
@@ -437,6 +451,9 @@ static int rsync(const rcynic_ctx_t *rc, ...)
}
assert(argc < sizeof(argv)/sizeof(*argv));
+ argv[argc++] = uri;
+
+ assert(argc < sizeof(argv)/sizeof(*argv));
argv[argc++] = path;
assert(rc->rsync_cache != NULL);
@@ -491,7 +508,7 @@ static int rsync(const rcynic_ctx_t *rc, ...)
whine("dup2(1) failed\n");
else if (dup2(pipe_fds[1], 2) < 0)
whine("dup2(2) failed\n");
- else if (execvp(argv[0], argv) < 0)
+ else if (execvp(argv[0], (char * const *) argv) < 0)
whine("execvp() failed\n");
whine("last system error: ");
write(2, strerror(errno), strlen(strerror(errno)));
@@ -508,30 +525,33 @@ static int rsync(const rcynic_ctx_t *rc, ...)
logmsg(rc, "%s", buffer);
}
- strcpy(buffer, uri);
- if ((s = strrchr(buffer + SIZEOF_RSYNC, '/')) != NULL && s[1] == '\0')
- *s = '\0';
- if ((s = strdup(buffer)) == NULL || !sk_push(rc->rsync_cache, s))
- logmsg(rc, "Couldn't cache URI %s, oh well", uri);
-
waitpid(pid, &pid_status, 0);
if (WEXITSTATUS(pid_status)) {
logmsg(rc, "rsync exited with status %d", pid_status);
- return 0;
+ ret = 0;
} else {
- return 1;
+ ret = 1;
}
+
+ strcpy(buffer, uri);
+ if ((s = strrchr(buffer + SIZEOF_RSYNC, '/')) != NULL && s[1] == '\0')
+ *s = '\0';
+ if ((s = strdup(buffer)) == NULL || !sk_push(rc->rsync_cache, s))
+ logmsg(rc, "Couldn't cache URI %s, oh well", uri);
+
+ return ret;
}
static int rsync_crl(const rcynic_ctx_t *rc, const char *uri)
{
- return rsync(rc, uri, NULL);
+ return rsync(rc, NULL, uri);
}
static int rsync_sia(const rcynic_ctx_t *rc, const char *uri)
{
- return rsync(rc, "--recursive", "--delete", uri, NULL);
+ static const char * const rsync_args[] = { "--recursive", "--delete", NULL };
+ return rsync(rc, rsync_args, uri);
}
@@ -1092,8 +1112,11 @@ int main(int argc, char *argv[])
else if (!name_cmp(val->name, "err-verbose"))
rc.err_verbose = atoi(val->value);
+ else if (!name_cmp(val->name, "rsync-timeout"))
+ rc.rsync_timeout = atoi(val->value);
+
else if (!name_cmp(val->name, "rsync-program"))
- rc.rsync = strdup(val->value);
+ rc.rsync_program = strdup(val->value);
}
if (!rm_rf(rc.old_authenticated)) {
@@ -1185,8 +1208,8 @@ int main(int argc, char *argv[])
free(rc.authenticated);
free(rc.old_authenticated);
free(rc.unauthenticated);
- if (rc.rsync)
- free(rc.rsync);
+ if (rc.rsync_program)
+ free(rc.rsync_program);
finish = time(0);