1.1 --- a/fsaccess/fsaccess.c Wed Jan 17 18:56:05 2024 +0100
1.2 +++ b/fsaccess/fsaccess.c Thu Jan 18 19:13:14 2024 +0100
1.3 @@ -53,13 +53,16 @@
1.4 script Read operations from a script file (or stdin)\n\
1.5 Execution operations:\n\
1.6 \n\
1.7 + jobs Show initiated programs\n\
1.8 run Run a program from the filesystem\n\
1.9 + wait Wait for a program to finish\n\
1.10 ";
1.11
1.12 /* Operations exposed by the program. */
1.13
1.14 struct operation operations[] = {
1.15 {"copy-in", copy_in},
1.16 + {"jobs", show_programs},
1.17 {"ls", list_objects},
1.18 {"mkdir", make_dirs},
1.19 {"rm", remove_non_dirs},
1.20 @@ -67,6 +70,7 @@
1.21 {"run", run_program},
1.22 {"script", run_script},
1.23 {"stat", stat_objects},
1.24 + {"wait", wait_program},
1.25 {NULL, NULL},
1.26 };
1.27
2.1 --- a/fsaccess/op_run.c Wed Jan 17 18:56:05 2024 +0100
2.2 +++ b/fsaccess/op_run.c Thu Jan 18 19:13:14 2024 +0100
2.3 @@ -1,5 +1,5 @@
2.4 /*
2.5 - * Run a program residing in the filesystem.
2.6 + * Run programs residing in the filesystem.
2.7 *
2.8 * Copyright (C) 2022, 2023, 2024 Paul Boddie <paul@boddie.org.uk>
2.9 *
2.10 @@ -27,6 +27,8 @@
2.11 #include <systypes/format.h>
2.12
2.13 #include <stdio.h>
2.14 +#include <stdlib.h>
2.15 +#include <string.h>
2.16
2.17 #include "ops.h"
2.18
2.19 @@ -38,15 +40,60 @@
2.20
2.21
2.22
2.23 +/* Initiated programs (jobs).
2.24 + NOTE: Arbitrary limit. */
2.25 +
2.26 +#define NUMBER_OF_JOBS 32
2.27 +
2.28 +static file_t *readers[NUMBER_OF_JOBS] = {NULL};
2.29 +static process_t *processes[NUMBER_OF_JOBS] = {NULL};
2.30 +static const char *programs[NUMBER_OF_JOBS] = {NULL};
2.31 +static int next_job = 0;
2.32 +
2.33 +
2.34 +
2.35 +/* Wait for a program to finish, showing its output. */
2.36 +
2.37 +static int _wait_program(file_t *reader, process_t *process)
2.38 +{
2.39 + char buffer[TO_TRANSFER];
2.40 + notify_flags_t flags;
2.41 + notify_values_t values;
2.42 + long err;
2.43 +
2.44 + /* Read until the pipe yields no more data. */
2.45 +
2.46 + while (1)
2.47 + {
2.48 + offset_t nread = client_read(reader, buffer, TO_TRANSFER);
2.49 +
2.50 + if (nread)
2.51 + fwrite(buffer, sizeof(char), nread, stdout);
2.52 + else
2.53 + break;
2.54 + }
2.55 +
2.56 + /* Close the pipe and obtain the process state. */
2.57 +
2.58 + client_close(reader);
2.59 +
2.60 + err = process_wait(process, &flags, &values);
2.61 +
2.62 + printf("End process (flags %" pFMTnotify_flags "x values: %ld, %ld)\n", flags, values.sig, values.val);
2.63 +
2.64 + if (err)
2.65 + return -1;
2.66 +
2.67 + return values.val;
2.68 +}
2.69 +
2.70 /* Run the given program. */
2.71
2.72 int run_program(int argc, char *argv[])
2.73 {
2.74 - char buffer[TO_TRANSFER];
2.75 process_t *process;
2.76 file_t *reader, *writer;
2.77 - notify_flags_t flags;
2.78 - notify_values_t values;
2.79 + int last_job;
2.80 long err;
2.81
2.82 /* Create a pipe for process output. */
2.83 @@ -75,30 +122,71 @@
2.84
2.85 client_close(writer);
2.86
2.87 - /* Read until the pipe yields no more data. */
2.88 + /* Record the output stream. */
2.89
2.90 - while (1)
2.91 + last_job = next_job;
2.92 +
2.93 + while (readers[next_job] != NULL)
2.94 {
2.95 - offset_t nread = client_read(reader, buffer, TO_TRANSFER);
2.96 + next_job++;
2.97 +
2.98 + if (next_job >= NUMBER_OF_JOBS)
2.99 + next_job = 0;
2.100
2.101 - if (nread)
2.102 - fwrite(buffer, sizeof(char), nread, stdout);
2.103 - else
2.104 - break;
2.105 + /* Wait for the process to complete if no more job slots are available. */
2.106 +
2.107 + if (next_job == last_job)
2.108 + return _wait_program(reader, process);
2.109 }
2.110
2.111 - /* Close the pipe and obtain the process state. */
2.112 + readers[next_job] = reader;
2.113 + processes[next_job] = process;
2.114 + programs[next_job] = strdup(argv[0]);
2.115 +
2.116 + return 0;
2.117 +}
2.118
2.119 - client_close(reader);
2.120 +/* Show initiated programs. */
2.121 +
2.122 +int show_programs(int argc, char *argv[])
2.123 +{
2.124 + (void) argc; (void) argv;
2.125 +
2.126 + int job_number;
2.127
2.128 - err = process_wait(process, &flags, &values);
2.129 + for (job_number = 0; job_number < NUMBER_OF_JOBS; job_number++)
2.130 + {
2.131 + if (readers[job_number] != NULL)
2.132 + printf("[%d] %s\n", job_number, programs[job_number]);
2.133 + }
2.134 +
2.135 + return 0;
2.136 +}
2.137
2.138 - printf("End process (flags %" pFMTnotify_flags "x values: %ld, %ld)\n", flags, values.sig, values.val);
2.139 +/* Wait for the indicated program to finish, showing its output. */
2.140
2.141 - if (err)
2.142 +int wait_program(int argc, char *argv[])
2.143 +{
2.144 + int job_number;
2.145 + int exitcode;
2.146 +
2.147 + if (argc < 1)
2.148 return -1;
2.149
2.150 - return values.val;
2.151 + job_number = atoi(argv[0]);
2.152 +
2.153 + if (readers[job_number] == NULL)
2.154 + return -1;
2.155 +
2.156 + exitcode = _wait_program(readers[job_number], processes[job_number]);
2.157 +
2.158 + readers[job_number] = NULL;
2.159 + processes[job_number] = NULL;
2.160 +
2.161 + free(programs[job_number]);
2.162 + programs[job_number] = NULL;
2.163 +
2.164 + return exitcode;
2.165 }
2.166
2.167 /* vim: tabstop=2 expandtab shiftwidth=2
3.1 --- a/fsaccess/ops.h Wed Jan 17 18:56:05 2024 +0100
3.2 +++ b/fsaccess/ops.h Thu Jan 18 19:13:14 2024 +0100
3.3 @@ -52,7 +52,9 @@
3.4 int remove_non_dirs(int argc, char *argv[]);
3.5 int run_program(int argc, char *argv[]);
3.6 int run_script(int argc, char *argv[]);
3.7 +int show_programs(int argc, char *argv[]);
3.8 int stat_objects(int argc, char *argv[]);
3.9 +int wait_program(int argc, char *argv[]);
3.10
3.11 /* vim: tabstop=4 expandtab shiftwidth=4
3.12 */