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 /* Release the writing end of the pipe. */ 82 83 client_close(writer); 84 85 /* Wait for a signal from the process or input from the process. */ 86 87 err = notify_subscribe(process_notifiable(process), NOTIFY_TASK_ALL, notifier); 88 89 if (err) 90 { 91 printf("Could not subscribe to task notifications: %s\n", l4sys_errtostr(err)); 92 return err; 93 } 94 95 notifiable_t *notifiable; 96 97 while (1) 98 { 99 err = notify_wait_many(¬ifiable, notifier); 100 101 if (err) 102 { 103 printf("Could not wait for process: %s\n", l4sys_errtostr(err)); 104 return err; 105 } 106 107 /* Handle any signal. */ 108 109 if (notifiable == process_notifiable(process)) 110 break; 111 112 /* Handle any input. */ 113 114 else if (notifiable == file_notifiable(reader)) 115 { 116 char buffer[TO_TRANSFER]; 117 offset_t nread = client_read(reader, buffer, TO_TRANSFER); 118 119 while (nread) 120 { 121 fwrite(buffer, sizeof(char), nread, stdout); 122 nread = client_read(reader, buffer, TO_TRANSFER); 123 } 124 } 125 } 126 127 notify_flags_t flags = process_notifications(process); 128 notify_values_t values = process_notification_values(process); 129 130 printf("End process (flags %" pFMTnotify_flags "x values: %ld, %ld)\n", flags, values.sig, values.val); 131 printf("End reader (flags %" pFMTnotify_flags "x)\n", file_notifications(reader)); 132 133 err = process_error(process); 134 135 client_close(reader); 136 process_free(process); 137 client_notifier_close(notifier); 138 139 return err; 140 } 141 142 143 144 int main(int argc, char *argv[]) 145 { 146 long err; 147 148 if (argc < 2) 149 { 150 printf("Need the program to run.\n"); 151 return 1; 152 } 153 154 /* Start a process for a non-existent program. */ 155 156 printf("Start non-existent program...\n"); 157 158 const char *bad_argv[] = {"non_existent_program"}; 159 160 err = test_process(1, bad_argv); 161 162 if (!err) 163 { 164 printf("Non-existent program was apparently successfully started.\n"); 165 return 1; 166 } 167 168 printf("Non-existent program result: %s\n", l4sys_errtostr(err)); 169 170 /* Start a process for the given program. */ 171 172 printf("Start process...\n"); 173 174 err = test_process(argc - 1, (const char **) argv + 1); 175 176 if (err) 177 return 1; 178 179 printf("End of test.\n"); 180 return 0; 181 } 182 183 /* vim: tabstop=2 expandtab shiftwidth=2 184 */