From 2edfa688d51080305a7c300bc10e4649bc5f484e Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Thu, 31 Dec 2015 23:45:15 +0100 Subject: preserve working directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- TODO | 2 -- doc/info/chap/invoking.texinfo | 9 +++++++-- doc/info/chap/output.texinfo | 8 ++++++++ doc/man/sat.1 | 12 ++++++++++-- doc/man/satq.1 | 6 ++++++ src/daemon.c | 5 +++-- src/sat.c | 40 ++++++++++++++++++++-------------------- src/satd-list.c | 17 ++++++++++------- 8 files changed, 64 insertions(+), 35 deletions(-) delete mode 100644 TODO diff --git a/TODO b/TODO deleted file mode 100644 index bef866e..0000000 --- a/TODO +++ /dev/null @@ -1,2 +0,0 @@ -We probably shall save the working directory too. - diff --git a/doc/info/chap/invoking.texinfo b/doc/info/chap/invoking.texinfo index 65c62b3..6afa45d 100644 --- a/doc/info/chap/invoking.texinfo +++ b/doc/info/chap/invoking.texinfo @@ -51,8 +51,13 @@ kill the parent. @command{sat} runs the specified command (@code{COMMAND...}) at a specified time (@code{TIME}). The job will run with -the same environment as @command{sat} has when it queues -the job. +the same environment and the same working directory as +@command{sat} has when it queues the job. The working +directory is determined by its absolute pathname@footnote{Most +probably the canonical pathname}, if no such directory +exists when the job is executed, the job's working directory +will be that of @command{satd}, which is always @file{/} +unless it was started with @option{-f}. @command{satq} lists all queued jobs to standard output. diff --git a/doc/info/chap/output.texinfo b/doc/info/chap/output.texinfo index d475706..4671dfb 100644 --- a/doc/info/chap/output.texinfo +++ b/doc/info/chap/output.texinfo @@ -14,6 +14,7 @@ The output for each job is formatted @example job: JOB-ID clock: CLOCK argc: ARGC remaining: REM argv[0]: ARGV0 time: TIME + wdir: WDIR argv: ARGV envp: ENVP @end example @@ -54,6 +55,13 @@ is @code{boottime}, this is formatted in the say way as formatted @code{YEAR-MM-DD HH:MM:SS} in 24-hour clock, local time. +@item WDIR +is the working directory the job will have. If that +directory does not exist when the job is executed, +the job's working directory will be that if this +daemon, which is always @file{/} unless @command{satd} +was started with @option{-f}. + @item ARGV is all arguments in the job's command line, including @code{ARGV0}. Each argument is quoted as necssary. diff --git a/doc/man/sat.1 b/doc/man/sat.1 index 77b1d77..93854b6 100644 --- a/doc/man/sat.1 +++ b/doc/man/sat.1 @@ -22,9 +22,17 @@ unless it is already running, and queue a specified to be executed at a selected .IR TIME . The job shall be executed with the same environment -variables as +variables and the same working directory (by +pathname) as .BR sat (1) -had when the job was queued. +had when the job was queued. However, if there is no +directory will the pathname matching the working +directory, when the job executes, the working directory +will be /, or whatever the working directory of +.BR satd (1) +(if +.BR satd (1) +is running in the foreground.) .PP The .I TIME diff --git a/doc/man/satq.1 b/doc/man/satq.1 index 630b5a2..082a7ac 100644 --- a/doc/man/satq.1 +++ b/doc/man/satq.1 @@ -17,6 +17,7 @@ indented. The output for each job is formatted .nf job: \fIJOB-ID\fP clock: \fICLOCK\fP argc: \fIARGC\fP remaining: \fIREM\fP argv[0]: \fIARGV0\fP time: \fITIME\fP + wdir: \fIWDIR\fP argv: \fIARGV\fP envp: \fIENVP\fP .fi @@ -75,6 +76,11 @@ it is formatted .IB YEAR - MM - DD \ HH : MM : SS in 24-hour clock, local time. .TP +.I WDIR +is the working directory the job will have. However, +if that directory one longer exists, its working +directory will be /. +.TP .I ARGV is all arguments in the job's command line, including .IR ARGV0 . diff --git a/src/daemon.c b/src/daemon.c index 12c1aea..e9c79d9 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -279,7 +279,7 @@ run_job_or_hook(struct job *job, const char *hook) t (!(args = restore_array(job->payload, job->n, &argsn))); t (!(argv = sublist(args, (size_t)(job->argc)))); - t (!(envp = sublist(args + job->argc, argsn - (size_t)(job->argc)))); + t (!(envp = sublist(args + job->argc, argsn - (size_t)(job->argc)))); /* Includes wdir. */ free(args), args = NULL; if (hook) { @@ -298,7 +298,8 @@ run_job_or_hook(struct job *job, const char *hook) close(STATE_FILENO); close(BOOT_FILENO); close(REAL_FILENO); - environ = envp; + (void)(status = chdir(envp[0])); + environ = envp + 1; execvp(*argv, argv); exit(1); default: diff --git a/src/sat.c b/src/sat.c index 2cc4f09..e3e1e84 100644 --- a/src/sat.c +++ b/src/sat.c @@ -23,6 +23,7 @@ #include "client.h" #include "common.h" #include +#include @@ -50,10 +51,13 @@ USAGE("TIME COMMAND...") int main(int argc, char *argv[], char *envp[]) { +#define E(CASE, DESC) case CASE: return fprintf(stderr, "%s: %s: %s\n", argv0, DESC, argv[1]), 2 + struct timespec ts; clockid_t clk; char *msg = NULL; - size_t n; + void *new; + size_t n, size = 64; if ((argc < 3) || (argv[1][0] == '-')) usage(); @@ -63,33 +67,29 @@ main(int argc, char *argv[], char *envp[]) /* Parse the time argument. */ if (parse_time(argv[1], &ts, &clk)) { switch (errno) { - case EINVAL: - fprintf(stderr, - "%s: time parameter cound not be parsed, perhaps " - "you need an external parser: %s\n", argv0, argv[1]); - return 2; - case ERANGE: - fprintf(stderr, - "%s: the specified time is beyond the limit of what " - "can be represented by `struct timespec`: %s\n", argv0, argv[1]); - return 2; - case EDOM: - fprintf(stderr, - "%s: the specified time is in past, and more than " - "a day ago: %s\n", argv0, argv[1]); - return 2; - default: - goto fail; + E (EINVAL, "time parameter cound not be parsed, perhaps you need an external parser"); + E (ERANGE, "the specified time is beyond the limit of what can be stored"); + E (EDOM, "the specified time is in past, and more than a day ago"); + default: goto fail; } } argc -= 2; argv += 2; +retry: + /* Get the size of the current working directory's pathname. */ + t (!(new = realloc(msg, size <<= 1))); + if (!getcwd(msg = new, size)) { + t (errno != ERANGE); + goto retry; + } + size = strlen(getcwd(msg, size)) + 1, free(msg); + /* Construct message to send to the daemon. */ - n = measure_array(argv) + measure_array(envp); + n = measure_array(argv) + size + measure_array(envp); t (!(msg = malloc(n + sizeof(int) + sizeof(clk) + sizeof(ts)))); - store_array(store_array(msg, argv), envp); + store_array(getcwd(store_array(msg, argv), size) + size, envp); memcpy(msg + n, &argc, sizeof(int)), n += sizeof(int); memcpy(msg + n, &clk, sizeof(clk)), n += sizeof(clk); memcpy(msg + n, &ts, sizeof(ts)), n += sizeof(ts); diff --git a/src/satd-list.c b/src/satd-list.c index 0591368..75f7996 100644 --- a/src/satd-list.c +++ b/src/satd-list.c @@ -73,7 +73,6 @@ quote(const char *str) rc[i++] = (char)*s; if (*s == '\'') rc[i++] = '\\', rc[i++] = '\'', rc[i++] = '\''; - } break; default: @@ -146,6 +145,7 @@ send_job_human(struct job *job) const char *clk; char rem_s[3 * sizeof(time_t) + sizeof("d00:00:00")]; char *qstr = NULL; + char *wdir = NULL; char line[sizeof("job: %zu clock: unrecognised argc: %i remaining: , argv[0]: ") + 3 * sizeof(size_t) + 3 * sizeof(int) + sizeof(rem_s) + 9]; char timestr_a[sizeof("-00-00 00:00:00") + 3 * sizeof(time_t)]; @@ -195,17 +195,19 @@ send_job_human(struct job *job) /* Get arguments. */ t (!(args = restore_array(job->payload, job->n, &argsn))); t (!(argv = sublist(args, (size_t)(job->argc)))); - t (!(envp = sublist(args + job->argc, argsn - (size_t)(job->argc)))); + t (!(envp = sublist(args + job->argc, argsn - (size_t)(job->argc)))); /* Includes wdir. */ /* Send message. */ t (!(qstr = quote(args[0]))); + t (!(wdir = quote(envp[0]))); sprintf(line, "job: %zu clock: %s argc: %i remaining: %s.%09li argv[0]: ", job->no, clk, job->argc, rem_s, rem.tv_nsec); t (send_string(SOCK_FILENO, STDOUT_FILENO, - line, qstr, "\n", - " time: ", timestr_a, ".", timestr_b, "\n", - " argv:", - NULL)); + line, qstr, "\n", + " time: ", timestr_a, ".", timestr_b, "\n", + " wdir:", wdir, "\n", + " argv:", + NULL)); for (arg = argv; *arg; arg++) { free(qstr); t (!(qstr = quote(*arg))); @@ -213,7 +215,7 @@ send_job_human(struct job *job) } free(qstr), qstr = NULL; t (send_string(SOCK_FILENO, STDOUT_FILENO, "\n envp:", NULL)); - for (arg = envp; *arg; arg++) { + for (arg = envp + 1; *arg; arg++) { t (!(qstr = quote(*arg))); t (send_string(SOCK_FILENO, STDOUT_FILENO, " ", qstr, NULL)); free(qstr); @@ -226,6 +228,7 @@ done: free(qstr); free(args); free(argv); + free(wdir); free(envp); errno = saved_errno; return rc; -- cgit v1.2.3-70-g09d2