1.1 --- a/fsaccess/op_run.c Wed Jan 17 18:56:05 2024 +0100
1.2 +++ b/fsaccess/op_run.c Thu Jan 18 19:13:14 2024 +0100
1.3 @@ -1,5 +1,5 @@
1.4 /*
1.5 - * Run a program residing in the filesystem.
1.6 + * Run programs residing in the filesystem.
1.7 *
1.8 * Copyright (C) 2022, 2023, 2024 Paul Boddie <paul@boddie.org.uk>
1.9 *
1.10 @@ -27,6 +27,8 @@
1.11 #include <systypes/format.h>
1.12
1.13 #include <stdio.h>
1.14 +#include <stdlib.h>
1.15 +#include <string.h>
1.16
1.17 #include "ops.h"
1.18
1.19 @@ -38,15 +40,60 @@
1.20
1.21
1.22
1.23 +/* Initiated programs (jobs).
1.24 + NOTE: Arbitrary limit. */
1.25 +
1.26 +#define NUMBER_OF_JOBS 32
1.27 +
1.28 +static file_t *readers[NUMBER_OF_JOBS] = {NULL};
1.29 +static process_t *processes[NUMBER_OF_JOBS] = {NULL};
1.30 +static const char *programs[NUMBER_OF_JOBS] = {NULL};
1.31 +static int next_job = 0;
1.32 +
1.33 +
1.34 +
1.35 +/* Wait for a program to finish, showing its output. */
1.36 +
1.37 +static int _wait_program(file_t *reader, process_t *process)
1.38 +{
1.39 + char buffer[TO_TRANSFER];
1.40 + notify_flags_t flags;
1.41 + notify_values_t values;
1.42 + long err;
1.43 +
1.44 + /* Read until the pipe yields no more data. */
1.45 +
1.46 + while (1)
1.47 + {
1.48 + offset_t nread = client_read(reader, buffer, TO_TRANSFER);
1.49 +
1.50 + if (nread)
1.51 + fwrite(buffer, sizeof(char), nread, stdout);
1.52 + else
1.53 + break;
1.54 + }
1.55 +
1.56 + /* Close the pipe and obtain the process state. */
1.57 +
1.58 + client_close(reader);
1.59 +
1.60 + err = process_wait(process, &flags, &values);
1.61 +
1.62 + printf("End process (flags %" pFMTnotify_flags "x values: %ld, %ld)\n", flags, values.sig, values.val);
1.63 +
1.64 + if (err)
1.65 + return -1;
1.66 +
1.67 + return values.val;
1.68 +}
1.69 +
1.70 /* Run the given program. */
1.71
1.72 int run_program(int argc, char *argv[])
1.73 {
1.74 - char buffer[TO_TRANSFER];
1.75 process_t *process;
1.76 file_t *reader, *writer;
1.77 - notify_flags_t flags;
1.78 - notify_values_t values;
1.79 + int last_job;
1.80 long err;
1.81
1.82 /* Create a pipe for process output. */
1.83 @@ -75,30 +122,71 @@
1.84
1.85 client_close(writer);
1.86
1.87 - /* Read until the pipe yields no more data. */
1.88 + /* Record the output stream. */
1.89
1.90 - while (1)
1.91 + last_job = next_job;
1.92 +
1.93 + while (readers[next_job] != NULL)
1.94 {
1.95 - offset_t nread = client_read(reader, buffer, TO_TRANSFER);
1.96 + next_job++;
1.97 +
1.98 + if (next_job >= NUMBER_OF_JOBS)
1.99 + next_job = 0;
1.100
1.101 - if (nread)
1.102 - fwrite(buffer, sizeof(char), nread, stdout);
1.103 - else
1.104 - break;
1.105 + /* Wait for the process to complete if no more job slots are available. */
1.106 +
1.107 + if (next_job == last_job)
1.108 + return _wait_program(reader, process);
1.109 }
1.110
1.111 - /* Close the pipe and obtain the process state. */
1.112 + readers[next_job] = reader;
1.113 + processes[next_job] = process;
1.114 + programs[next_job] = strdup(argv[0]);
1.115 +
1.116 + return 0;
1.117 +}
1.118
1.119 - client_close(reader);
1.120 +/* Show initiated programs. */
1.121 +
1.122 +int show_programs(int argc, char *argv[])
1.123 +{
1.124 + (void) argc; (void) argv;
1.125 +
1.126 + int job_number;
1.127
1.128 - err = process_wait(process, &flags, &values);
1.129 + for (job_number = 0; job_number < NUMBER_OF_JOBS; job_number++)
1.130 + {
1.131 + if (readers[job_number] != NULL)
1.132 + printf("[%d] %s\n", job_number, programs[job_number]);
1.133 + }
1.134 +
1.135 + return 0;
1.136 +}
1.137
1.138 - printf("End process (flags %" pFMTnotify_flags "x values: %ld, %ld)\n", flags, values.sig, values.val);
1.139 +/* Wait for the indicated program to finish, showing its output. */
1.140
1.141 - if (err)
1.142 +int wait_program(int argc, char *argv[])
1.143 +{
1.144 + int job_number;
1.145 + int exitcode;
1.146 +
1.147 + if (argc < 1)
1.148 return -1;
1.149
1.150 - return values.val;
1.151 + job_number = atoi(argv[0]);
1.152 +
1.153 + if (readers[job_number] == NULL)
1.154 + return -1;
1.155 +
1.156 + exitcode = _wait_program(readers[job_number], processes[job_number]);
1.157 +
1.158 + readers[job_number] = NULL;
1.159 + processes[job_number] = NULL;
1.160 +
1.161 + free(programs[job_number]);
1.162 + programs[job_number] = NULL;
1.163 +
1.164 + return exitcode;
1.165 }
1.166
1.167 /* vim: tabstop=2 expandtab shiftwidth=2