Phasor 3.1.1
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 asm_print_stdout(const char *s, int64_t len)
101{
102 fwrite(s, 1, (size_t)len, stdout);
103 fflush(stdout);
104}
105
106void asm_print_stderr(const char *s, int64_t len)
107{
108 fwrite(s, 1, (size_t)len, stderr);
109 fflush(stderr);
110}
111
112int64_t asm_system(const char *cmd)
113{
114 return (int64_t)system(cmd);
115}
116
117char *asm_system_out(const char *cmd)
118{
119 int argc;
120 char **argv = parse_argv(cmd, &argc);
121 if (!argv)
122 return NULL;
123 char *output = NULL;
124 size_t output_size = 0;
125 size_t output_capacity = 1024;
126 output = malloc(output_capacity);
127 if (!output)
128 {
129 free_argv(argv);
130 return NULL;
131 }
132#ifdef _WIN32
133 SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
134 HANDLE hRead, hWrite;
135 if (!CreatePipe(&hRead, &hWrite, &sa, 0))
136 {
137 free(output);
138 free_argv(argv);
139 return NULL;
140 }
141 STARTUPINFO si = {sizeof(STARTUPINFO)};
142 si.dwFlags = STARTF_USESTDHANDLES;
143 si.hStdOutput = hWrite; // capture stdout
144 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
145 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
146 PROCESS_INFORMATION pi;
147 if (!CreateProcess(NULL, (char *)cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
148 {
149 CloseHandle(hRead);
150 CloseHandle(hWrite);
151 free(output);
152 free_argv(argv);
153 return NULL;
154 }
155 CloseHandle(hWrite);
156 DWORD bytesRead;
157 char buffer[1024];
158 while (ReadFile(hRead, buffer, sizeof(buffer), &bytesRead, NULL) && bytesRead > 0)
159 {
160 if (output_size + bytesRead >= output_capacity)
161 {
162 output_capacity *= 2;
163 char *new_output = realloc(output, output_capacity);
164 if (!new_output)
165 {
166 CloseHandle(hRead);
167 CloseHandle(pi.hProcess);
168 CloseHandle(pi.hThread);
169 free(output);
170 free_argv(argv);
171 return NULL;
172 }
173 output = new_output;
174 }
175 memcpy(output + output_size, buffer, bytesRead);
176 output_size += bytesRead;
177 }
178 output[output_size] = '\0';
179 CloseHandle(hRead);
180 WaitForSingleObject(pi.hProcess, INFINITE);
181 CloseHandle(pi.hProcess);
182 CloseHandle(pi.hThread);
183#else
184 int pipefd[2];
185 if (pipe(pipefd) == -1)
186 {
187 free(output);
188 free_argv(argv);
189 return NULL;
190 }
191 pid_t pid = fork();
192 if (pid == -1)
193 {
194 close(pipefd[0]);
195 close(pipefd[1]);
196 free(output);
197 free_argv(argv);
198 return NULL;
199 }
200 if (pid == 0)
201 {
202 close(pipefd[0]);
203 dup2(pipefd[1], STDOUT_FILENO);
204 close(pipefd[1]);
205 execvp(argv[0], argv);
206 _exit(1);
207 }
208 else
209 {
210 close(pipefd[1]);
211 ssize_t bytesRead;
212 char buffer[1024];
213 while ((bytesRead = read(pipefd[0], buffer, sizeof(buffer))) > 0)
214 {
215 if (output_size + bytesRead >= output_capacity)
216 {
217 output_capacity *= 2;
218 char *new_output = realloc(output, output_capacity);
219 if (!new_output)
220 {
221 close(pipefd[0]);
222 free(output);
223 free_argv(argv);
224 return NULL;
225 }
226 output = new_output;
227 }
228 memcpy(output + output_size, buffer, bytesRead);
229 output_size += bytesRead;
230 }
231 output[output_size] = '\0';
232 close(pipefd[0]);
233 int status;
234 waitpid(pid, &status, 0);
235 }
236#endif
237 free_argv(argv);
238 return output;
239}
240
241char *asm_system_err(const char *cmd)
242{
243 int argc;
244 char **argv = parse_argv(cmd, &argc);
245 if (!argv)
246 return NULL;
247 char *output = NULL;
248 size_t output_size = 0;
249 size_t output_capacity = 1024;
250 output = malloc(output_capacity);
251 if (!output)
252 {
253 free_argv(argv);
254 return NULL;
255 }
256#ifdef _WIN32
257 SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
258 HANDLE hRead, hWrite;
259 if (!CreatePipe(&hRead, &hWrite, &sa, 0))
260 {
261 free(output);
262 free_argv(argv);
263 return NULL;
264 }
265 STARTUPINFO si = {sizeof(STARTUPINFO)};
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}
char * asm_system_err(const char *cmd)
CRT system call, get err.
Definition IO.c:241
void asm_print_stdout(const char *s, int64_t len)
Native print function.
Definition IO.c:100
int64_t asm_system(const char *cmd)
CRT system call.
Definition IO.c:112
static void free_argv(char **argv)
Definition IO.c:91
void asm_print_stderr(const char *s, int64_t len)
Native print error function.
Definition IO.c:106
static char ** parse_argv(const char *cmd, int *argc)
Definition IO.c:12
char * asm_system_out(const char *cmd)
CRT system call, get out.
Definition IO.c:117