diff options
Diffstat (limited to 'src/satd-list.c')
-rw-r--r-- | src/satd-list.c | 241 |
1 files changed, 0 insertions, 241 deletions
diff --git a/src/satd-list.c b/src/satd-list.c deleted file mode 100644 index 12c06a7..0000000 --- a/src/satd-list.c +++ /dev/null @@ -1,241 +0,0 @@ -/** - * Copyright © 2015, 2016 Mattias Andrée <maandree@member.fsf.org> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#include "daemon.h" - - - -/** - * Quote a string, in shell (Bash-only if necessary) compatible - * format, if necessary. Here, just adding quotes around all not - * do. The string must be single line, and there must not be - * any invisible characters; it should be possible to copy - * a string from the terminal by marking it, hence all of this - * ugliness. - * - * @param str The string. - * @return Return a safe representation of the string, - * `NULL` on error. - */ -static char * -quote(const char *str) -{ -#define UNSAFE(c) strchr(" \"$()[]{};|&^#!?*~`<>", c) -#define N(I, S, B, Q) (I*in + S*sn + B*bn + Q*qn + rn) - - size_t in = 0; /* < ' ' or 127 */ - size_t sn = 0; /* in UNSAFE */ - size_t bn = 0; /* = '\\' */ - size_t qn = 0; /* = '\'' */ - size_t rn = 0; /* other */ - size_t n, i = 0; - const unsigned char *s; - char *rc = NULL; - - for (s = (const unsigned char *)str; *s; s++) { - if (*s < ' ') in++; - else if (*s == 127) in++; - else if (UNSAFE(*s)) sn++; - else if (*s == '\\') bn++; - else if (*s == '\'') qn++; - else rn++; - } - if (N(1, 1, 1, 1) == rn) - return strdup(rn ? str : "''"); - - n = in ? (N(4, 1, 2, 2) + 3) : (N(0, 1, 1, 4) + 2); - t (!(rc = malloc((n + 1) * sizeof(char)))); - rc[i += !!in] = '$'; - rc[i += 1] = '\''; - if (in == 0) { - for (s = (const unsigned char *)str; *s; s++) { - rc[i++] = (char)*s; - if (*s == '\'') - rc[i++] = '\\', rc[i++] = '\'', rc[i++] = '\''; - } - } else { - for (s = (const unsigned char *)str; *s; s++) { - if ((*s < ' ') || (*s == 127)) { - rc[i++] = '\\'; - rc[i++] = 'x'; - rc[i++] = "0123456789ABCDEF"[(*s >> 4) & 15]; - rc[i++] = "0123456789ABCDEF"[(*s >> 0) & 15]; - } - else if (strchr("\\'", *s)) rc[i++] = '\\', rc[i++] = (char)*s; - else rc[i++] = (char)*s; - } - } - rc[i++] = '\''; - rc[i] = '\0'; -fail: - return rc; -} - - -/** - * Create a textual representation of the a duration. - * - * @param buffer Output buffer, with a size of at least - * 10 `char`:s plus enough to encode a `time_t`. - * @param s The duration in seconds. - */ -static void -strduration(char *buffer, time_t s) -{ - char *buf = buffer; - int secs, mins, hours, sd = 0, md = 0, hd = 0; - secs = (int)(s % 60), s /= 60; - mins = (int)(s % 60), s /= 60; - hours = (int)(s % 24), s /= 24; - if (s) hd++, buf += sprintf(buf, "%llid", (long long int)s); - if (hd | hours) md++, buf += sprintf(buf, "%0*i:", ++hd, hours); - if (md | mins) sd++, buf += sprintf(buf, "%0*i:", ++md, mins); - /*just for alignment*/ buf += sprintf(buf, "%0*i:", ++sd, secs); -} - - -/** - * Dump a job to the socket. - * - * @param job The job. - * @return 0 on success, -1 on error. - */ -static int -send_job_human(struct job *job) -{ -#define FIX_NSEC(T) (((T)->tv_nsec < 0L) ? ((T)->tv_sec -= 1, (T)->tv_nsec += 1000000000L) : 0L) -#define ARRAY(LIST) \ - for (arg = LIST; *arg; arg++) { \ - free(qstr); \ - t (!(qstr = quote(*arg))); \ - t (send_string(SOCK_FILENO, STDOUT_FILENO, " ", qstr, NULL)); \ - } - - struct tm *tm; - struct timespec rem; - 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)]; - char timestr_b[10]; - char **args = NULL; - char **arg; - char **argv = NULL; - char **envp = NULL; - size_t argsn; - int rc = 0, saved_errno; - - /* Get remaining time. */ - if (clock_gettime(job->clk, &rem)) - return errno == EINVAL ? 0 : -1; - rem.tv_sec = job->ts.tv_sec - rem.tv_sec; - rem.tv_nsec = job->ts.tv_nsec - rem.tv_nsec; - FIX_NSEC(&rem); - if (rem.tv_sec < 0) - /* This job will be removed momentarily, do not list it. (To simply things.) */ - return 0; - - /* Get clock name. */ - switch (job->clk) { - case CLOCK_REALTIME: clk = "walltime"; break; - case CLOCK_BOOTTIME: clk = "boottime"; break; - default: clk = "unrecognised"; break; - } - - /* Get textual representation of the remaining time. (Seconds only.) */ - strduration(rem_s, rem.tv_sec); - - /* Get textual representation of the expiration time. */ - if (job->clk == CLOCK_REALTIME) { - t (!(tm = localtime(&(job->ts.tv_sec)))); - strftime(timestr_a, sizeof(timestr_a), "%Y-%m-%d %H:%M:%S", tm); - } else { - strduration(timestr_a, job->ts.tv_sec); - } - sprintf(timestr_b, "%09li", job->ts.tv_nsec); - - /* 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)))); /* 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 wdir: ", wdir, - "\n argv:", NULL)); - free(qstr); - ARRAY(argv); t (send_string(SOCK_FILENO, STDOUT_FILENO, "\n envp:", NULL)); - ARRAY(envp + 1); t (send_string(SOCK_FILENO, STDOUT_FILENO, "\n\n", NULL)); - -done: - saved_errno = errno; - free(qstr), free(args), free(argv), free(wdir), free(envp); - errno = saved_errno; - return rc; -fail: - rc = -1; - goto done; -} - - - -/** - * Subroutine to the sat daemon: list jobs. - * - * @param argc Should be 3. - * @param argv The name of the process, the pathname of the socket, - * and the pathname to the state file. - * @return 0 The process was successful. - * @return 1 The process failed queuing the job. - */ -int -main(int argc, char *argv[]) -{ - size_t n = 0; - char *message = NULL; - struct job **jobs = NULL; - struct job **job; - DAEMON_PROLOGUE; - - /* Receive and validate message. */ - t (readall(SOCK_FILENO, &message, &n) || n); - - /* Perform action. */ - t (!(jobs = get_jobs())); - for (job = jobs; *job; job++) - t (send_job_human(*job)); - - DAEMON_CLEANUP_START; - for (job = jobs; *job; job++) - free(*job); - free(jobs); - free(message); - DAEMON_CLEANUP_END; -} - |