1.1 --- a/fsaccess/fsaccess.c Thu Jan 25 00:05:40 2024 +0100
1.2 +++ b/fsaccess/fsaccess.c Fri Jan 26 00:32:35 2024 +0100
1.3 @@ -56,8 +56,9 @@
1.4 file Send a file to a program\n\
1.5 jobs Show initiated programs\n\
1.6 pipe Connect a running program to a new program\n\
1.7 - run Run a program from the filesystem\n\
1.8 - wait Wait for a program to finish\n\
1.9 + run Run a program from the filesystem and wait for it to finish\n\
1.10 + spawn Run a program in the background\n\
1.11 + wait Wait for a spawned program to finish\n\
1.12 ";
1.13
1.14 /* Operations exposed by the program. */
1.15 @@ -72,6 +73,7 @@
1.16 {"rm", remove_non_dirs},
1.17 {"rmdir", remove_dirs},
1.18 {"run", run_program},
1.19 + {"spawn", spawn_program},
1.20 {"script", run_script},
1.21 {"stat", stat_objects},
1.22 {"wait", wait_program},
2.1 --- a/fsaccess/op_run.c Thu Jan 25 00:05:40 2024 +0100
2.2 +++ b/fsaccess/op_run.c Fri Jan 26 00:32:35 2024 +0100
2.3 @@ -52,6 +52,45 @@
2.4
2.5
2.6
2.7 +/* Find the given program in the job list. */
2.8 +
2.9 +static int _find_program(process_t *process)
2.10 +{
2.11 + int job_number;
2.12 +
2.13 + for (job_number = 0; job_number < NUMBER_OF_JOBS; job_number++)
2.14 + {
2.15 + if (processes[job_number] == process)
2.16 + return job_number;
2.17 + }
2.18 +
2.19 + return -1;
2.20 +}
2.21 +
2.22 +/* Remove the details of a program from the job list. */
2.23 +
2.24 +static void _remove_program(int job_number)
2.25 +{
2.26 + readers[job_number] = NULL;
2.27 + processes[job_number] = NULL;
2.28 +
2.29 + free(programs[job_number]);
2.30 + programs[job_number] = NULL;
2.31 +}
2.32 +
2.33 +/* Show the details of a running program. */
2.34 +
2.35 +static void _show_program(int job_number)
2.36 +{
2.37 + /* Employ the Unix convention of a "+" for the default job to be restored upon
2.38 + the appropriate command. */
2.39 +
2.40 + printf("[%d]%s %s%s\n", job_number, job_number == next_job ? "+" : " ",
2.41 + programs[job_number], readers[job_number] != NULL ? " [!]" : "");
2.42 +}
2.43 +
2.44 +
2.45 +
2.46 /* Show output from a program. */
2.47
2.48 static void _show_output(file_t *reader)
2.49 @@ -63,11 +102,26 @@
2.50 fwrite(buffer, sizeof(char), nread, stdout);
2.51 }
2.52
2.53 +/* Show the exit status of a program. */
2.54 +
2.55 +static void _show_status(notifiable_t *notifiable)
2.56 +{
2.57 + printf("Completed with");
2.58 +
2.59 + if (notifiable->notifications & NOTIFY_TASK_ERROR)
2.60 + printf(" error");
2.61 +
2.62 + if (notifiable->notifications & NOTIFY_TASK_SIGNAL)
2.63 + printf(" signal %ld", notifiable->values.sig);
2.64 +
2.65 + printf(" value %ld\n", notifiable->values.val);
2.66 +}
2.67 +
2.68 /* Wait for a program to finish, showing its output. */
2.69
2.70 static int _wait_program(file_t *reader, process_t *process)
2.71 {
2.72 - notifier_t *notifier = client_notifier_local();
2.73 + notifier_t *notifier = client_notifier_task();
2.74 notifiable_t *notifiable;
2.75 int exitcode;
2.76 long err;
2.77 @@ -81,7 +135,6 @@
2.78 if (err)
2.79 {
2.80 printf("Could not subscribe to pipe notifications: %s\n", l4sys_errtostr(err));
2.81 - client_notifier_close(notifier);
2.82 return -1;
2.83 }
2.84 }
2.85 @@ -92,7 +145,6 @@
2.86 {
2.87 printf("Could not subscribe to process notifications: %s\n", l4sys_errtostr(err));
2.88 client_unsubscribe(reader, notifier);
2.89 - client_notifier_close(notifier);
2.90 return -1;
2.91 }
2.92
2.93 @@ -110,7 +162,6 @@
2.94 client_unsubscribe(reader, notifier);
2.95
2.96 notify_unsubscribe(process_notifiable(process), notifier);
2.97 - client_notifier_close(notifier);
2.98 return -1;
2.99 }
2.100
2.101 @@ -123,19 +174,22 @@
2.102
2.103 if (process_terminated(notifiable))
2.104 {
2.105 - if (reader != NULL)
2.106 + if ((reader != NULL) && ((process_t *) notifiable->base == process))
2.107 _show_output(reader);
2.108
2.109 - printf("Completed with");
2.110 + _show_status(notifiable);
2.111
2.112 - if (notifiable->notifications & NOTIFY_TASK_ERROR)
2.113 - printf(" error");
2.114 + /* If explicitly waiting for this process, remove it from the job list and
2.115 + return. Otherwise, just remove it from the job list and keep waiting
2.116 + for the indicated process. */
2.117
2.118 - if (notifiable->notifications & NOTIFY_TASK_SIGNAL)
2.119 - printf(" signal %ld", notifiable->values.sig);
2.120 -
2.121 - printf(" value %ld\n", notifiable->values.val);
2.122 - break;
2.123 + if ((process_t *) notifiable->base == process)
2.124 + {
2.125 + _remove_program(next_job);
2.126 + break;
2.127 + }
2.128 + else
2.129 + _remove_program(_find_program((process_t *) notifiable->base));
2.130 }
2.131 }
2.132
2.133 @@ -148,7 +202,6 @@
2.134
2.135 /* Close the process and pipe. */
2.136
2.137 - client_notifier_close(notifier);
2.138 process_free(process);
2.139
2.140 if (reader != NULL)
2.141 @@ -203,10 +256,13 @@
2.142 if (next_job >= NUMBER_OF_JOBS)
2.143 next_job = 0;
2.144
2.145 - /* Wait for the process to complete if no more job slots are available. */
2.146 + /* Return an error if no more job slots are available. */
2.147
2.148 if (next_job == last_job)
2.149 - return _wait_program(output_reader, process);
2.150 + {
2.151 + printf("No job slots available.\n");
2.152 + return -1;
2.153 + }
2.154 }
2.155
2.156 readers[next_job] = output_reader;
2.157 @@ -253,7 +309,10 @@
2.158 if (argc < 1)
2.159 return -1;
2.160
2.161 - job_number = atoi(argv[0]);
2.162 + if (!strcmp(argv[0], "+"))
2.163 + job_number = next_job;
2.164 + else
2.165 + job_number = atoi(argv[0]);
2.166
2.167 if (readers[job_number] == NULL)
2.168 {
2.169 @@ -269,14 +328,23 @@
2.170 client_close(readers[job_number]);
2.171 readers[job_number] = NULL;
2.172
2.173 + /* Subscribe to signals from the process. */
2.174 +
2.175 + notify_subscribe(process_notifiable(processes[job_number]), NOTIFY_TASK_ALL, client_notifier_task());
2.176 +
2.177 return exitcode;
2.178 }
2.179
2.180 -/* Run the given program. */
2.181 +/* Run the given program and wait for it to finish. */
2.182
2.183 int run_program(int argc, char *argv[])
2.184 {
2.185 - return _run_program(argc, argv, NULL);
2.186 + int exitcode = _run_program(argc, argv, NULL);
2.187 +
2.188 + if (exitcode)
2.189 + return exitcode;
2.190 +
2.191 + return _wait_program(readers[next_job], processes[next_job]);
2.192 }
2.193
2.194 /* Show initiated programs. */
2.195 @@ -290,24 +358,37 @@
2.196 for (job_number = 0; job_number < NUMBER_OF_JOBS; job_number++)
2.197 {
2.198 if (processes[job_number] != NULL)
2.199 - printf("[%d] %s%s\n", job_number, programs[job_number],
2.200 - readers[job_number] != NULL ? " [!]" : "");
2.201 + _show_program(job_number);
2.202 }
2.203
2.204 return 0;
2.205 }
2.206
2.207 -/* Wait for the indicated program to finish, showing its output. */
2.208 +/* Run the given program but do not wait for it to finish, instead allowing the
2.209 + program to produce output and potentially block until an operation to wait
2.210 + for its completion is performed. */
2.211 +
2.212 +int spawn_program(int argc, char *argv[])
2.213 +{
2.214 + int exitcode = _run_program(argc, argv, NULL);
2.215 +
2.216 + if (!exitcode)
2.217 + _show_program(next_job);
2.218 +
2.219 + return exitcode;
2.220 +}
2.221 +
2.222 +/* Wait for the indicated program (or the last program to be spawned) to finish,
2.223 + showing its output. */
2.224
2.225 int wait_program(int argc, char *argv[])
2.226 {
2.227 int job_number;
2.228 - int exitcode;
2.229
2.230 if (argc < 1)
2.231 - return -1;
2.232 -
2.233 - job_number = atoi(argv[0]);
2.234 + job_number = next_job;
2.235 + else
2.236 + job_number = atoi(argv[0]);
2.237
2.238 if (processes[job_number] == NULL)
2.239 {
2.240 @@ -315,15 +396,7 @@
2.241 return -1;
2.242 }
2.243
2.244 - exitcode = _wait_program(readers[job_number], processes[job_number]);
2.245 -
2.246 - readers[job_number] = NULL;
2.247 - processes[job_number] = NULL;
2.248 -
2.249 - free(programs[job_number]);
2.250 - programs[job_number] = NULL;
2.251 -
2.252 - return exitcode;
2.253 + return _wait_program(readers[job_number], processes[job_number]);
2.254 }
2.255
2.256 /* vim: tabstop=2 expandtab shiftwidth=2
3.1 --- a/fsaccess/ops.h Thu Jan 25 00:05:40 2024 +0100
3.2 +++ b/fsaccess/ops.h Fri Jan 26 00:32:35 2024 +0100
3.3 @@ -53,6 +53,7 @@
3.4 int remove_dirs(int argc, char *argv[]);
3.5 int remove_non_dirs(int argc, char *argv[]);
3.6 int run_program(int argc, char *argv[]);
3.7 +int spawn_program(int argc, char *argv[]);
3.8 int run_script(int argc, char *argv[]);
3.9 int show_programs(int argc, char *argv[]);
3.10 int stat_objects(int argc, char *argv[]);