Rune - Further Object abstraction work
[rune.git] / libruntime / sys_proc.c
1 /*
2  * SYS_PROC.C
3  *
4  * Process-related system support
5  */
6
7 #include "defs.h"
8 #include <sys/wait.h>
9
10 typedef struct ProcStor {
11     runepid_t pid;
12     int32_t xcode;
13     int32_t error;
14 #if LONG_BITS == 64
15     int     pad01;
16 #endif
17 } ProcStor;
18
19 struct exec_args {
20     LValueStor lvs;
21     void    *path;
22     void    *argv;
23     void    *envp;
24     int     fd0;
25     int     fd1;
26     int     fd2;
27 #if LONG_BITS == 64
28     int     pad01;
29 #endif
30 };
31
32 extern char **environ;
33
34 void
35 RUNESYSCALL(exec) (struct exec_args *args, int *rval)
36 {
37     ProcStor *proc = args->lvs.lv_Addr;
38     char  **av;
39     char  **envp;
40     pid_t   pid;
41
42     av = args->argv;
43     envp = args->envp;
44
45     if ((pid = vfork()) == 0) {
46         char  **myenvp;
47         int     fd1 = args->fd1;
48         int     fd2 = args->fd2;
49
50         if (fd1 == 0)
51             fd1 = fcntl(fd1, F_DUPFD_CLOEXEC, 10);
52         if (fd2 == 0 || fd2 == 1)
53             fd2 = fcntl(fd2, F_DUPFD_CLOEXEC, 10);
54
55         if (args->fd0 < 0)
56             close(0);
57         else if (args->fd0 != 0)
58             dup2(args->fd0, 0);
59
60         if (fd1 < 0)
61             close(1);
62         else if (fd1 != 1)
63             dup2(fd1, 1);
64
65         if (fd2 < 0)
66             close(2);
67         else if (fd2 != 2)
68             dup2(fd2, 2);
69
70         fcntl(0, F_SETFD, 0);   /* ignore error */
71         fcntl(1, F_SETFD, 0);   /* ignore error */
72         fcntl(2, F_SETFD, 0);   /* ignore error */
73
74         myenvp = (envp ? envp : environ);
75         execve(args->path, av, myenvp);
76         _exit(99);
77     }
78     if (sizeof(pid) < sizeof(runepid_t))
79         proc->pid = (runepid_t)(int)pid;
80     else
81         proc->pid = pid;
82     if (pid < 0)
83         *rval = -1;
84     else
85         *rval = 0;
86 }
87
88 struct wait_args {
89     LValueStor lvs;
90 #if 0
91     int     ms;
92 #if LONG_BITS == 64
93     int     pad01;
94 #endif
95 #endif
96 };
97
98 void
99 RUNESYSCALL(wait) (struct wait_args *args, int *rval)
100 {
101     ProcStor *proc = args->lvs.lv_Addr;
102     pid_t   pid;
103
104     for (;;) {
105         int     status;
106
107         pid = wait4(proc->pid, &status, WNOHANG, NULL);
108         if (pid < 0) {
109             if (errno == EINTR)
110                 continue;
111             if (errno != EAGAIN) {
112                 proc->error = errno;
113                 *rval = -1;
114                 break;
115             }
116             pid = 0;
117         }
118         if (pid == 0) {
119             threadWaitEvent(proc->pid, THWAIT_PROC);
120             continue;
121         }
122         proc->pid = pid;
123         proc->error = 0;
124         proc->xcode = WEXITSTATUS(status);
125         *rval = 0;
126         break;
127     }
128 }
129
130 struct waitn_args {
131     LValueStor lvs;
132 };
133
134 void
135 RUNESYSCALL(waitn) (struct waitn_args *args, int *rval)
136 {
137     ProcStor *proc = args->lvs.lv_Addr;
138     pid_t   pid;
139
140     for (;;) {
141         int     status;
142         pid = wait4(proc->pid, &status, WNOHANG, NULL);
143         if (pid < 0) {
144             if (errno == EINTR)
145                 continue;
146             proc->error = errno;
147             *rval = -1;
148             break;
149         }
150         if (pid == 0) {
151             proc->error = EAGAIN;
152             *rval = -1;
153             break;
154         }
155         proc->pid = pid;
156         proc->error = 0;
157         proc->xcode = WEXITSTATUS(status);
158         *rval = 0;
159         break;
160     }
161 }