1 /* 2 * A test of executing code in new tasks and threads. 3 * 4 * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/sys/err.h> 23 24 #include <fsclient/client.h> 25 #include <fsclient/process.h> 26 #include <systypes/fcntl.h> 27 #include <systypes/format.h> 28 29 #include <stdio.h> 30 31 32 33 /* Transfer size for communication. */ 34 35 const offset_t TO_TRANSFER = 1024; 36 37 38 39 /* Test process initiation and interaction. */ 40 41 static long test_process(int argc, const char *argv[]) 42 { 43 process_t *process; 44 file_t *reader, *writer; 45 long err; 46 47 /* Obtain the common notifier. */ 48 49 notifier_t *notifier = client_notifier_task(); 50 51 /* Create a pipe for process output. */ 52 53 err = client_pipe(&reader, &writer, O_NONBLOCK); 54 55 if (err) 56 { 57 printf("Could not obtain pipe: %s\n", l4sys_errtostr(err)); 58 return err; 59 } 60 61 err = client_subscribe(reader, NOTIFY_CONTENT_AVAILABLE | NOTIFY_PEER_CLOSED, notifier); 62 63 if (err) 64 { 65 printf("Could not subscribe to pipe notifications: %s\n", l4sys_errtostr(err)); 66 return err; 67 } 68 69 /* Start the process. */ 70 71 err = process_spawn(argc, argv, writer, &process); 72 73 if (err) 74 { 75 printf("Could not start process: %s\n", l4sys_errtostr(err)); 76 return err; 77 } 78 79 printf("Finished program initiation.\n"); 80 81 /* Wait for a signal from the process or input from the process. */ 82 83 err = notify_subscribe(process_notifiable(process), NOTIFY_TASK_ALL, notifier); 84 85 if (err) 86 { 87 printf("Could not subscribe to task notifications: %s\n", l4sys_errtostr(err)); 88 return err; 89 } 90 91 notifiable_t *notifiable; 92 93 while (1) 94 { 95 err = notify_wait_many(¬ifiable, notifier); 96 97 if (err) 98 { 99 printf("Could not wait for process: %s\n", l4sys_errtostr(err)); 100 return err; 101 } 102 103 /* Handle any signal. */ 104 105 if (notifiable == process_notifiable(process)) 106 break; 107 108 /* Handle any input. */ 109 110 else if (notifiable == file_notifiable(reader)) 111 { 112 char buffer[TO_TRANSFER]; 113 offset_t nread = client_read(reader, buffer, TO_TRANSFER); 114 115 while (nread) 116 { 117 fwrite(buffer, sizeof(char), nread, stdout); 118 nread = client_read(reader, buffer, TO_TRANSFER); 119 } 120 } 121 } 122 123 notify_flags_t flags = process_notifications(process); 124 notify_values_t values = process_notification_values(process); 125 126 printf("End process (flags %" pFMTnotify_flags "x values: %ld, %ld)\n", flags, values.sig, values.val); 127 128 err = process_error(process); 129 130 client_close(reader); 131 process_free(process); 132 client_notifier_close(notifier); 133 134 return err; 135 } 136 137 138 139 int main(int argc, char *argv[]) 140 { 141 long err; 142 143 if (argc < 2) 144 { 145 printf("Need the program to run.\n"); 146 return 1; 147 } 148 149 /* Start a process for a non-existent program. */ 150 151 printf("Start non-existent program...\n"); 152 153 const char *bad_argv[] = {"non_existent_program"}; 154 155 err = test_process(1, bad_argv); 156 157 if (!err) 158 { 159 printf("Non-existent program was apparently successfully started.\n"); 160 return 1; 161 } 162 163 printf("Non-existent program result: %s\n", l4sys_errtostr(err)); 164 165 /* Start a process for the given program. */ 166 167 printf("Start process...\n"); 168 169 err = test_process(argc - 1, (const char **) argv + 1); 170 171 if (err) 172 return 1; 173 174 printf("End of test.\n"); 175 return 0; 176 } 177 178 /* vim: tabstop=2 expandtab shiftwidth=2 179 */