1 /*
2
3 Copyright (c) 2009-2013 uim Project https://github.com/uim/uim
4
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of authors nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31
32 */
33
34 #include <config.h>
35
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <sys/wait.h>
40
41 #include "uim.h"
42 #include "uim-internal.h"
43 #include "uim-scm.h"
44 #include "uim-scm-abbrev.h"
45 #include "uim-posix.h"
46 #include "uim-notify.h"
47 #include "gettext.h"
48 #include "dynlib.h"
49
50 typedef struct {
51 int flag;
52 char *arg;
53 } opt_args;
54
55 static uim_lisp
make_arg_cons(const opt_args * arg)56 make_arg_cons(const opt_args *arg)
57 {
58 return CONS(MAKE_SYM(arg->arg), MAKE_INT(arg->flag));
59 }
60
61 static uim_lisp
make_arg_list(const opt_args * list)62 make_arg_list(const opt_args *list)
63 {
64 uim_lisp ret_;
65 int i = 0;
66
67 ret_ = uim_scm_null();
68 while (list[i].arg != 0) {
69 ret_ = CONS((uim_lisp)uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)make_arg_cons,
70 (void *)&list[i]), ret_);
71 i++;
72 }
73 return ret_;
74 }
75
76 static uim_lisp
c_current_process_id(void)77 c_current_process_id(void)
78 {
79 return MAKE_INT(getpid());
80 }
81 static uim_lisp
c_parent_process_id(void)82 c_parent_process_id(void)
83 {
84 return MAKE_INT(getppid());
85 }
86 static uim_lisp
c_process_fork(void)87 c_process_fork(void)
88 {
89 return MAKE_INT(fork());
90 }
91 static uim_lisp
c__exit(uim_lisp status_)92 c__exit(uim_lisp status_)
93 {
94 _exit(C_INT(status_));
95 return uim_scm_t();
96 }
97
98 const static opt_args waitpid_options[] = {
99 #ifdef WCONTINUED
100 { WCONTINUED, "$WCONTINUED" },
101 #endif
102 #ifdef WNOHANG
103 { WNOHANG, "$WNOHANG" },
104 #endif
105 #ifdef WUNTRACED
106 { WUNTRACED, "$WUNTRACED" },
107 #endif
108 { 0, 0 }
109 };
110 static uim_lisp uim_lisp_process_waitpid_options;
111 static uim_lisp
c_process_waitpid_options(void)112 c_process_waitpid_options(void)
113 {
114 return uim_lisp_process_waitpid_options;
115 }
116 static uim_lisp
c_process_waitpid(uim_lisp pid_,uim_lisp options_)117 c_process_waitpid(uim_lisp pid_, uim_lisp options_)
118 {
119 uim_lisp ret_ = uim_scm_null();
120 int status;
121
122 ret_ = MAKE_INT(waitpid(C_INT(pid_), &status, C_INT(options_)));
123 if (WIFEXITED(status))
124 return LIST5(ret_, uim_scm_t(), uim_scm_f(), uim_scm_f(), MAKE_INT(WEXITSTATUS(status)));
125 else if (WIFSIGNALED(status))
126 return LIST5(ret_, uim_scm_f(), uim_scm_t(), uim_scm_f(), MAKE_INT(WTERMSIG(status)));
127 #ifdef WIFSTOPPED
128 else if (WIFSTOPPED(status))
129 return LIST5(ret_, uim_scm_f(), uim_scm_f(), uim_scm_t(), MAKE_INT(WSTOPSIG(status)));
130 #endif
131
132 return LIST5(ret_, uim_scm_f(), uim_scm_f(), uim_scm_f(), MAKE_INT(status));
133 }
134
135 static uim_lisp
c_daemon(uim_lisp nochdir_,uim_lisp noclose_)136 c_daemon(uim_lisp nochdir_, uim_lisp noclose_)
137 {
138 return MAKE_INT(daemon(C_BOOL(nochdir_), C_BOOL(noclose_)));
139 }
140
141 static uim_lisp
c_execve(uim_lisp file_,uim_lisp argv_,uim_lisp envp_)142 c_execve(uim_lisp file_, uim_lisp argv_, uim_lisp envp_)
143 {
144 char **argv;
145 char **envp;
146 int i;
147 int argv_len = uim_scm_length(argv_);
148 int envp_len;
149 uim_lisp ret_;
150
151 if (argv_len < 1)
152 return uim_scm_f();
153
154 argv = uim_malloc(sizeof(char *) * (argv_len + 1));
155
156 for (i = 0; i < argv_len; i++) {
157 argv[i] = uim_strdup(REFER_C_STR(CAR(argv_)));
158 argv_ = CDR(argv_);
159 }
160 argv[argv_len] = NULL;
161
162 if (FALSEP(envp_) || NULLP(envp_)) {
163 envp_len = 0;
164 envp = NULL;
165 } else {
166 envp_len = uim_scm_length(envp_);
167 envp = uim_malloc(sizeof(char *) * (envp_len + 1));
168
169 for (i = 0; i < envp_len; i++) {
170 uim_lisp env_ = CAR(envp_);
171
172 uim_asprintf(&envp[i], "%s=%s", REFER_C_STR(CAR(env_)), REFER_C_STR(CDR(env_)));
173 envp_ = CDR(envp_);
174 }
175 envp[envp_len] = NULL;
176 }
177
178 ret_ = MAKE_INT(execve(REFER_C_STR(file_), argv, envp));
179
180 for (i = 0; i < argv_len; i++)
181 free(argv[i]);
182 free(argv);
183
184 for (i = 0; i < envp_len; i++)
185 free(envp[i]);
186 free(envp);
187
188 return ret_;
189 }
190
191 static uim_lisp
c_execvp(uim_lisp file_,uim_lisp argv_)192 c_execvp(uim_lisp file_, uim_lisp argv_)
193 {
194 char **argv;
195 int i;
196 int len = uim_scm_length(argv_);
197 uim_lisp ret_;
198
199 if (len < 1)
200 return uim_scm_f();
201
202 argv = uim_malloc(sizeof(char *) * (len + 1));
203
204 for (i = 0; i < len; i++) {
205 argv[i] = uim_strdup(REFER_C_STR(CAR(argv_)));
206 argv_ = CDR(argv_);
207 }
208 argv[len] = NULL;
209
210 ret_ = MAKE_INT(execvp(REFER_C_STR(file_), argv));
211
212 for (i = 0; i < len; i++)
213 free(argv[i]);
214 free(argv);
215
216 return ret_;
217 }
218
219 void
uim_plugin_instance_init(void)220 uim_plugin_instance_init(void)
221 {
222 uim_scm_init_proc0("current-process-id", c_current_process_id);
223 uim_scm_init_proc0("parent-process-id", c_parent_process_id);
224 uim_scm_init_proc0("process-fork", c_process_fork);
225 uim_scm_init_proc1("_exit", c__exit);
226 uim_scm_init_proc2("process-waitpid", c_process_waitpid);
227 uim_scm_init_proc0("process-waitpid-options?", c_process_waitpid_options);
228 uim_lisp_process_waitpid_options = make_arg_list(waitpid_options);
229 uim_scm_gc_protect(&uim_lisp_process_waitpid_options);
230 uim_scm_eval_c_string("(define process-waitpid-options-alist (process-waitpid-options?))");
231
232 uim_scm_init_proc2("daemon", c_daemon);
233
234 uim_scm_init_proc3("execve", c_execve);
235 uim_scm_init_proc2("execvp", c_execvp);
236 }
237
238 void
uim_plugin_instance_quit(void)239 uim_plugin_instance_quit(void)
240 {
241 uim_scm_gc_unprotect(&uim_lisp_process_waitpid_options);
242 }
243