Phasor 3.3.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
IO.c
Go to the documentation of this file.
1#include "IO.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#ifdef _WIN32
6#include <windows.h>
7#else
8#include <unistd.h>
9#include <sys/wait.h>
10#endif
11
12static char **parse_argv(const char *cmd, int *argc)
13{
14 if (!cmd || !*cmd)
15 return NULL;
16 size_t len = strlen(cmd);
17 char *copy = malloc(len + 1);
18 if (!copy)
19 return NULL;
20
21#ifdef _WIN32
22 strcpy_s(copy, len + 1, cmd);
23#else
24 strcpy(copy, cmd);
25#endif
26
27 *argc = 0;
28#ifdef _WIN32
29 char *context = NULL;
30 char *token = strtok_s(copy, " ", &context);
31#else
32 char *token = strtok(copy, " ");
33#endif
34 while (token)
35 {
36 (*argc)++;
37#ifdef _WIN32
38 token = strtok_s(NULL, " ", &context);
39#else
40 token = strtok(NULL, " ");
41#endif
42 }
43
44#ifdef _WIN32
45 strcpy_s(copy, len + 1, cmd);
46#else
47 strcpy(copy, cmd);
48#endif
49
50 char **argv = malloc((*argc + 1) * sizeof(char *));
51 if (!argv)
52 {
53 free(copy);
54 return NULL;
55 }
56
57 int i = 0;
58#ifdef _WIN32
59 token = strtok_s(copy, " ", &context);
60#else
61 token = strtok(copy, " ");
62#endif
63 while (token)
64 {
65 argv[i] = malloc(strlen(token) + 1);
66 if (!argv[i])
67 {
68 for (int j = 0; j < i; j++)
69 free(argv[j]);
70 free(argv);
71 free(copy);
72 return NULL;
73 }
74#ifdef _WIN32
75 strcpy_s(argv[i], strlen(token) + 1, token);
76#else
77 strcpy(argv[i], token);
78#endif
79 i++;
80#ifdef _WIN32
81 token = strtok_s(NULL, " ", &context);
82#else
83 token = strtok(NULL, " ");
84#endif
85 }
86 argv[i] = NULL;
87 free(copy);
88 return argv;
89}
90
91static void free_argv(char **argv)
92{
93 if (!argv)
94 return;
95 for (int i = 0; argv[i]; i++)
96 free(argv[i]);
97 free(argv);
98}
99
100void c_print_stdout(const char *s, int64_t len)
101{
102 fwrite(s, 1, (size_t)len, stdout);
103}
104
105void c_print_stderr(const char *s, int64_t len)
106{
107 fwrite(s, 1, (size_t)len, stderr);
108}
109
110int64_t c_system(const char *cmd)
111{
112 return (int64_t)system(cmd);
113}
114
115char *c_system_out(const char *cmd)
116{
117 int argc;
118 char **argv = parse_argv(cmd, &argc);
119 if (!argv)
120 return NULL;
121 char *output = NULL;
122 size_t output_size = 0;
123 size_t output_capacity = 1024;
124 output = malloc(output_capacity);
125 if (!output)
126 {
127 free_argv(argv);
128 return NULL;
129 }
130#ifdef _WIN32
131 SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
132 HANDLE hRead, hWrite;
133 if (!CreatePipe(&hRead, &hWrite, &sa, 0))
134 {
135 free(output);
136 free_argv(argv);
137 return NULL;
138 }
139 STARTUPINFO si = {0};
140 si.cb = sizeof(si);
141 si.dwFlags = STARTF_USESTDHANDLES;
142 si.hStdOutput = hWrite; // capture stdout
143 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
144 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
145 PROCESS_INFORMATION pi;
146 if (!CreateProcess(NULL, (char *)cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
147 {
148 CloseHandle(hRead);
149 CloseHandle(hWrite);
150 free(output);
151 free_argv(argv);
152 return NULL;
153 }
154 CloseHandle(hWrite);
155 DWORD bytesRead;
156 char buffer[1024];
157 while (ReadFile(hRead, buffer, sizeof(buffer), &bytesRead, NULL) && bytesRead > 0)
158 {
159 if (output_size + bytesRead >= output_capacity)
160 {
161 output_capacity *= 2;
162 char *new_output = realloc(output, output_capacity);
163 if (!new_output)
164 {
165 CloseHandle(hRead);
166 CloseHandle(pi.hProcess);
167 CloseHandle(pi.hThread);
168 free(output);
169 free_argv(argv);
170 return NULL;
171 }
172 output = new_output;
173 }
174 memcpy(output + output_size, buffer, bytesRead);
175 output_size += bytesRead;
176 }
177 output[output_size] = '\0';
178 CloseHandle(hRead);
179 WaitForSingleObject(pi.hProcess, INFINITE);
180 CloseHandle(pi.hProcess);
181 CloseHandle(pi.hThread);
182#else
183 int pipefd[2];
184 if (pipe(pipefd) == -1)
185 {
186 free(output);
187 free_argv(argv);
188 return NULL;
189 }
190 pid_t pid = fork();
191 if (pid == -1)
192 {
193 close(pipefd[0]);
194 close(pipefd[1]);
195 free(output);
196 free_argv(argv);
197 return NULL;
198 }
199 if (pid == 0)
200 {
201 close(pipefd[0]);
202 dup2(pipefd[1], STDOUT_FILENO);
203 close(pipefd[1]);
204 execvp(argv[0], argv);
205 _exit(1);
206 }
207 else
208 {
209 close(pipefd[1]);
210 ssize_t bytesRead;
211 char buffer[1024];
212 while ((bytesRead = read(pipefd[0], buffer, sizeof(buffer))) > 0)
213 {
214 if (output_size + bytesRead >= output_capacity)
215 {
216 output_capacity *= 2;
217 char *new_output = realloc(output, output_capacity);
218 if (!new_output)
219 {
220 close(pipefd[0]);
221 free(output);
222 free_argv(argv);
223 return NULL;
224 }
225 output = new_output;
226 }
227 memcpy(output + output_size, buffer, bytesRead);
228 output_size += bytesRead;
229 }
230 output[output_size] = '\0';
231 close(pipefd[0]);
232 int status;
233 waitpid(pid, &status, 0);
234 }
235#endif
236 free_argv(argv);
237 return output;
238}
239
240char *c_system_err(const char *cmd)
241{
242 int argc;
243 char **argv = parse_argv(cmd, &argc);
244 if (!argv)
245 return NULL;
246 char *output = NULL;
247 size_t output_size = 0;
248 size_t output_capacity = 1024;
249 output = malloc(output_capacity);
250 if (!output)
251 {
252 free_argv(argv);
253 return NULL;
254 }
255#ifdef _WIN32
256 SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
257 HANDLE hRead, hWrite;
258 if (!CreatePipe(&hRead, &hWrite, &sa, 0))
259 {
260 free(output);
261 free_argv(argv);
262 return NULL;
263 }
264 STARTUPINFO si = {0};
265 si.cb = sizeof(si);
266 si.dwFlags = STARTF_USESTDHANDLES;
267 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
268 si.hStdError = hWrite;
269 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
270 PROCESS_INFORMATION pi;
271 if (!CreateProcess(NULL, (char *)cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
272 {
273 CloseHandle(hRead);
274 CloseHandle(hWrite);
275 free(output);
276 free_argv(argv);
277 return NULL;
278 }
279 CloseHandle(hWrite);
280 DWORD bytesRead;
281 char buffer[1024];
282 while (ReadFile(hRead, buffer, sizeof(buffer), &bytesRead, NULL) && bytesRead > 0)
283 {
284 if (output_size + bytesRead >= output_capacity)
285 {
286 output_capacity *= 2;
287 char *new_output = realloc(output, output_capacity);
288 if (!new_output)
289 {
290 CloseHandle(hRead);
291 CloseHandle(pi.hProcess);
292 CloseHandle(pi.hThread);
293 free(output);
294 free_argv(argv);
295 return NULL;
296 }
297 output = new_output;
298 }
299 memcpy(output + output_size, buffer, bytesRead);
300 output_size += bytesRead;
301 }
302 output[output_size] = '\0';
303 CloseHandle(hRead);
304 WaitForSingleObject(pi.hProcess, INFINITE);
305 CloseHandle(pi.hProcess);
306 CloseHandle(pi.hThread);
307#else
308 int pipefd[2];
309 if (pipe(pipefd) == -1)
310 {
311 free(output);
312 free_argv(argv);
313 return NULL;
314 }
315 pid_t pid = fork();
316 if (pid == -1)
317 {
318 close(pipefd[0]);
319 close(pipefd[1]);
320 free(output);
321 free_argv(argv);
322 return NULL;
323 }
324 if (pid == 0)
325 {
326 close(pipefd[0]);
327 dup2(pipefd[1], STDERR_FILENO);
328 close(pipefd[1]);
329 execvp(argv[0], argv);
330 _exit(1);
331 }
332 else
333 {
334 close(pipefd[1]);
335 ssize_t bytesRead;
336 char buffer[1024];
337 while ((bytesRead = read(pipefd[0], buffer, sizeof(buffer))) > 0)
338 {
339 if (output_size + bytesRead >= output_capacity)
340 {
341 output_capacity *= 2;
342 char *new_output = realloc(output, output_capacity);
343 if (!new_output)
344 {
345 close(pipefd[0]);
346 free(output);
347 free_argv(argv);
348 return NULL;
349 }
350 output = new_output;
351 }
352 memcpy(output + output_size, buffer, bytesRead);
353 output_size += bytesRead;
354 }
355 output[output_size] = '\0';
356 close(pipefd[0]);
357 int status;
358 waitpid(pid, &status, 0);
359 }
360#endif
361 free_argv(argv);
362 return output;
363}
void c_print_stderr(const char *s, int64_t len)
Native print error function.
Definition IO.c:105
static void free_argv(char **argv)
Definition IO.c:91
int64_t c_system(const char *cmd)
CRT system call.
Definition IO.c:110
void c_print_stdout(const char *s, int64_t len)
Native print function.
Definition IO.c:100
static char ** parse_argv(const char *cmd, int *argc)
Definition IO.c:12
char * c_system_out(const char *cmd)
CRT system call, get out.
Definition IO.c:115
char * c_system_err(const char *cmd)
CRT system call, get err.
Definition IO.c:240
static uint64_t s[2]
Definition random.cpp:6