aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@member.fsf.org>2015-12-31 23:45:15 +0100
committerMattias Andrée <maandree@member.fsf.org>2015-12-31 23:45:15 +0100
commit2edfa688d51080305a7c300bc10e4649bc5f484e (patch)
treed12a839c87aea5ff322feefb50a19d0ad8b31e6d
parentm (diff)
downloadsat-2edfa688d51080305a7c300bc10e4649bc5f484e.tar.gz
sat-2edfa688d51080305a7c300bc10e4649bc5f484e.tar.bz2
sat-2edfa688d51080305a7c300bc10e4649bc5f484e.tar.xz
preserve working directory
Signed-off-by: Mattias Andrée <maandree@member.fsf.org>
-rw-r--r--TODO2
-rw-r--r--doc/info/chap/invoking.texinfo9
-rw-r--r--doc/info/chap/output.texinfo8
-rw-r--r--doc/man/sat.112
-rw-r--r--doc/man/satq.16
-rw-r--r--src/daemon.c5
-rw-r--r--src/sat.c40
-rw-r--r--src/satd-list.c17
8 files changed, 64 insertions, 35 deletions
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 <errno.h>
+#include <unistd.h>
@@ -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;