Commit | Line | Data |
4633a7c4 |
1 | #define INCL_DOS |
2 | #define INCL_NOPM |
c0c09dfd |
3 | #ifndef NO_SYS_ALLOC |
4 | # define INCL_DOSMEMMGR |
5 | # define INCL_DOSERRORS |
6 | #endif /* ! defined NO_SYS_ALLOC */ |
4633a7c4 |
7 | #include <os2.h> |
8 | |
9 | /* |
10 | * Various Unix compatibility functions for OS/2 |
11 | */ |
12 | |
13 | #include <stdio.h> |
14 | #include <errno.h> |
15 | #include <limits.h> |
16 | #include <process.h> |
17 | |
18 | #include "EXTERN.h" |
19 | #include "perl.h" |
20 | |
21 | /*****************************************************************************/ |
22 | /* priorities */ |
23 | |
24 | int setpriority(int which, int pid, int val) |
25 | { |
26 | return DosSetPriority((pid < 0) ? PRTYS_PROCESSTREE : PRTYS_PROCESS, |
27 | val >> 8, val & 0xFF, abs(pid)); |
28 | } |
29 | |
30 | int getpriority(int which /* ignored */, int pid) |
31 | { |
32 | TIB *tib; |
33 | PIB *pib; |
34 | DosGetInfoBlocks(&tib, &pib); |
35 | return tib->tib_ptib2->tib2_ulpri; |
36 | } |
37 | |
38 | /*****************************************************************************/ |
39 | /* spawn */ |
40 | |
41 | static int |
42 | result(int flag, int pid) |
43 | { |
44 | int r, status; |
45 | Signal_t (*ihand)(); /* place to save signal during system() */ |
46 | Signal_t (*qhand)(); /* place to save signal during system() */ |
47 | |
c0c09dfd |
48 | if (pid < 0 || flag != 0) |
4633a7c4 |
49 | return pid; |
50 | |
51 | ihand = signal(SIGINT, SIG_IGN); |
52 | qhand = signal(SIGQUIT, SIG_IGN); |
c0c09dfd |
53 | do { |
54 | r = wait4pid(pid, &status, 0); |
55 | } while (r == -1 && errno == EINTR); |
4633a7c4 |
56 | signal(SIGINT, ihand); |
57 | signal(SIGQUIT, qhand); |
58 | |
59 | statusvalue = (U16)status; |
60 | if (r < 0) |
61 | return -1; |
62 | return status & 0xFFFF; |
63 | } |
64 | |
65 | int |
66 | do_aspawn(really,mark,sp) |
67 | SV *really; |
68 | register SV **mark; |
69 | register SV **sp; |
70 | { |
71 | register char **a; |
72 | char *tmps; |
73 | int rc; |
74 | int flag = P_WAIT, trueflag; |
75 | |
76 | if (sp > mark) { |
77 | New(401,Argv, sp - mark + 1, char*); |
78 | a = Argv; |
79 | |
80 | if (mark < sp && SvIOKp(*(mark+1))) { |
81 | ++mark; |
82 | flag = SvIVx(*mark); |
83 | } |
84 | |
85 | while (++mark <= sp) { |
86 | if (*mark) |
87 | *a++ = SvPVx(*mark, na); |
88 | else |
89 | *a++ = ""; |
90 | } |
91 | *a = Nullch; |
92 | |
93 | trueflag = flag; |
94 | if (flag == P_WAIT) |
95 | flag = P_NOWAIT; |
96 | |
c0c09dfd |
97 | if (*Argv[0] != '/' && *Argv[0] != '\\') /* will swawnvp use PATH? */ |
98 | TAINT_ENV(); /* testing IFS here is overkill, probably */ |
4633a7c4 |
99 | if (really && *(tmps = SvPV(really, na))) |
100 | rc = result(trueflag, spawnvp(flag,tmps,Argv)); |
101 | else |
102 | rc = result(trueflag, spawnvp(flag,Argv[0],Argv)); |
103 | |
104 | if (rc < 0 && dowarn) |
105 | warn("Can't spawn \"%s\": %s", Argv[0], Strerror(errno)); |
c0c09dfd |
106 | if (rc < 0) rc = 255 << 8; /* Emulate the fork(). */ |
4633a7c4 |
107 | } else |
108 | rc = -1; |
109 | do_execfree(); |
110 | return rc; |
111 | } |
112 | |
113 | int |
114 | do_spawn(cmd) |
115 | char *cmd; |
116 | { |
117 | register char **a; |
118 | register char *s; |
119 | char flags[10]; |
120 | char *shell, *copt; |
121 | int rc; |
122 | |
c0c09dfd |
123 | #ifdef TRYSHELL |
124 | if ((shell = getenv("EMXSHELL")) != NULL) |
125 | copt = "-c"; |
126 | else if ((shell = getenv("SHELL")) != NULL) |
4633a7c4 |
127 | copt = "-c"; |
128 | else if ((shell = getenv("COMSPEC")) != NULL) |
129 | copt = "/C"; |
130 | else |
131 | shell = "cmd.exe"; |
c0c09dfd |
132 | #else |
133 | /* Consensus on perl5-porters is that it is _very_ important to |
134 | have a shell which will not change between computers with the |
135 | same architecture, to avoid "action on a distance". |
136 | And to have simple build, this shell should be sh. */ |
137 | shell = "sh.exe"; |
138 | copt = "-c"; |
139 | #endif |
140 | |
141 | while (*cmd && isSPACE(*cmd)) |
142 | cmd++; |
4633a7c4 |
143 | |
144 | /* save an extra exec if possible */ |
145 | /* see if there are shell metacharacters in it */ |
146 | |
c0c09dfd |
147 | if (*cmd == '.' && isSPACE(cmd[1])) |
148 | goto doshell; |
149 | |
150 | if (strnEQ(cmd,"exec",4) && isSPACE(cmd[4])) |
151 | goto doshell; |
152 | |
153 | for (s = cmd; *s && isALPHA(*s); s++) ; /* catch VAR=val gizmo */ |
154 | if (*s == '=') |
155 | goto doshell; |
156 | |
4633a7c4 |
157 | for (s = cmd; *s; s++) { |
c0c09dfd |
158 | if (*s != ' ' && !isALPHA(*s) && strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) { |
4633a7c4 |
159 | if (*s == '\n' && !s[1]) { |
160 | *s = '\0'; |
161 | break; |
162 | } |
c0c09dfd |
163 | doshell: |
164 | rc = result(P_WAIT, |
165 | spawnl(P_NOWAIT,shell,shell,copt,cmd,(char*)0)); |
166 | if (rc < 0 && dowarn) |
167 | warn("Can't spawn \"%s\": %s", shell, Strerror(errno)); |
168 | if (rc < 0) rc = 255 << 8; /* Emulate the fork(). */ |
169 | return rc; |
4633a7c4 |
170 | } |
171 | } |
c0c09dfd |
172 | |
4633a7c4 |
173 | New(402,Argv, (s - cmd) / 2 + 2, char*); |
174 | Cmd = savepvn(cmd, s-cmd); |
175 | a = Argv; |
176 | for (s = Cmd; *s;) { |
177 | while (*s && isSPACE(*s)) s++; |
178 | if (*s) |
179 | *(a++) = s; |
180 | while (*s && !isSPACE(*s)) s++; |
181 | if (*s) |
182 | *s++ = '\0'; |
183 | } |
184 | *a = Nullch; |
185 | if (Argv[0]) { |
186 | rc = result(P_WAIT, spawnvp(P_NOWAIT,Argv[0],Argv)); |
187 | if (rc < 0 && dowarn) |
188 | warn("Can't spawn \"%s\": %s", Argv[0], Strerror(errno)); |
c0c09dfd |
189 | if (rc < 0) rc = 255 << 8; /* Emulate the fork(). */ |
4633a7c4 |
190 | } else |
191 | rc = -1; |
192 | do_execfree(); |
193 | return rc; |
194 | } |
195 | |
c0c09dfd |
196 | FILE * |
197 | my_popen(cmd,mode) |
198 | char *cmd; |
199 | char *mode; |
200 | { |
201 | char *shell = getenv("EMXSHELL"); |
202 | FILE *res; |
203 | |
204 | my_setenv("EMXSHELL", "sh.exe"); |
205 | res = popen(cmd, mode); |
206 | my_setenv("EMXSHELL", shell); |
207 | return res; |
208 | } |
209 | |
4633a7c4 |
210 | /*****************************************************************************/ |
211 | |
212 | #ifndef HAS_FORK |
213 | int |
214 | fork(void) |
215 | { |
216 | die(no_func, "Unsupported function fork"); |
217 | errno = EINVAL; |
218 | return -1; |
219 | } |
220 | #endif |
221 | |
222 | /*****************************************************************************/ |
223 | /* not implemented in EMX 0.9a */ |
224 | |
225 | void * ctermid(x) { return 0; } |
eacfb5f1 |
226 | |
227 | #ifdef MYTTYNAME /* was not in emx0.9a */ |
4633a7c4 |
228 | void * ttyname(x) { return 0; } |
eacfb5f1 |
229 | #endif |
4633a7c4 |
230 | |
231 | void * gethostent() { return 0; } |
232 | void * getnetent() { return 0; } |
233 | void * getprotoent() { return 0; } |
234 | void * getservent() { return 0; } |
235 | void sethostent(x) {} |
236 | void setnetent(x) {} |
237 | void setprotoent(x) {} |
238 | void setservent(x) {} |
239 | void endhostent(x) {} |
240 | void endnetent(x) {} |
241 | void endprotoent(x) {} |
242 | void endservent(x) {} |
243 | |
244 | /*****************************************************************************/ |
245 | /* stat() hack for char/block device */ |
246 | |
247 | #if OS2_STAT_HACK |
248 | |
249 | /* First attempt used DosQueryFSAttach which crashed the system when |
250 | used with 5.001. Now just look for /dev/. */ |
251 | |
252 | int |
253 | os2_stat(char *name, struct stat *st) |
254 | { |
255 | static int ino = SHRT_MAX; |
256 | |
257 | if (stricmp(name, "/dev/con") != 0 |
258 | && stricmp(name, "/dev/tty") != 0) |
259 | return stat(name, st); |
260 | |
261 | memset(st, 0, sizeof *st); |
262 | st->st_mode = S_IFCHR|0666; |
263 | st->st_ino = (ino-- & 0x7FFF); |
264 | st->st_nlink = 1; |
265 | return 0; |
266 | } |
267 | |
268 | #endif |
c0c09dfd |
269 | |
270 | #ifndef NO_SYS_ALLOC |
271 | |
272 | static char *old2K; |
273 | |
274 | #define ONE_K (1<<10) |
275 | #define TWO_K (1<<11) |
276 | #define FOUR_K (1<<12) |
277 | #define FOUR_K_FLAG (FOUR_K - 1) |
278 | |
279 | |
280 | void * |
281 | sbrk(int size) |
282 | { |
283 | char *got; |
284 | APIRET rc; |
285 | int is2K = 0; |
286 | |
287 | if (!size) return 0; |
288 | else if (size == TWO_K) { |
289 | is2K = 1; |
290 | if (old2K) { |
291 | char *ret = old2K; |
292 | |
293 | old2K = 0; |
294 | return (void *)ret; |
295 | } |
296 | size = FOUR_K; |
297 | } else if (size & FOUR_K_FLAG) { |
298 | croak("Memory allocation in units %li not multiple to 4K", size); |
299 | } |
300 | rc = DosAllocMem((void **)&got, size, PAG_COMMIT | PAG_WRITE); |
301 | if (rc == ERROR_NOT_ENOUGH_MEMORY) { |
302 | return (void *) -1; |
303 | } else if ( rc ) die("Got an error from DosAllocMem: %li", (long)rc); |
304 | if (is2K) old2K = got + TWO_K; |
305 | return (void *)got; |
306 | } |
307 | #endif /* ! defined NO_SYS_ALLOC */ |
308 | |
309 | /* tmp path */ |
310 | |
311 | char *tmppath = TMPPATH1; |
312 | |
313 | void |
314 | settmppath() |
315 | { |
316 | char *p = getenv("TMP"), *tpath; |
317 | int len; |
318 | |
319 | if (!p) p = getenv("TEMP"); |
320 | if (!p) return; |
321 | len = strlen(p); |
322 | tpath = (char *)malloc(len + strlen(TMPPATH1) + 2); |
323 | strcpy(tpath, p); |
324 | tpath[len] = '/'; |
325 | strcpy(tpath + len + 1, TMPPATH1); |
326 | tmppath = tpath; |
327 | } |