Commit | Line | Data |
---|---|---|
352d5a3a | 1 | /* $RCSfile: msdos.c,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:37 $ |
b1248f16 LW |
2 | * |
3 | * (C) Copyright 1989, 1990 Diomidis Spinellis. | |
4 | * | |
352d5a3a LW |
5 | * You may distribute under the terms of either the GNU General Public |
6 | * License or the Artistic License, as specified in the README file. | |
b1248f16 LW |
7 | * |
8 | * $Log: msdos.c,v $ | |
352d5a3a LW |
9 | * Revision 4.0.1.1 91/06/07 11:22:37 lwall |
10 | * patch4: new copyright notice | |
11 | * | |
fe14fcc3 LW |
12 | * Revision 4.0 91/03/20 01:34:46 lwall |
13 | * 4.0 baseline. | |
14 | * | |
b1248f16 LW |
15 | * Revision 3.0.1.1 90/03/27 16:10:41 lwall |
16 | * patch16: MSDOS support | |
17 | * | |
18 | * Revision 1.1 90/03/18 20:32:01 dds | |
19 | * Initial revision | |
20 | * | |
21 | */ | |
22 | ||
23 | /* | |
24 | * Various Unix compatibility functions for MS-DOS. | |
25 | */ | |
26 | ||
b1248f16 LW |
27 | #include "EXTERN.h" |
28 | #include "perl.h" | |
29 | ||
fe14fcc3 LW |
30 | #include <dos.h> |
31 | #include <process.h> | |
32 | ||
b1248f16 LW |
33 | /* |
34 | * Interface to the MS-DOS ioctl system call. | |
35 | * The function is encoded as follows: | |
36 | * The lowest nibble of the function code goes to AL | |
37 | * The two middle nibbles go to CL | |
38 | * The high nibble goes to CH | |
39 | * | |
40 | * The return code is -1 in the case of an error and if successful | |
41 | * for functions AL = 00, 09, 0a the value of the register DX | |
42 | * for functions AL = 02 - 08, 0e the value of the register AX | |
43 | * for functions AL = 01, 0b - 0f the number 0 | |
44 | * | |
45 | * Notice that this restricts the ioctl subcodes stored in AL to 00-0f | |
46 | * In the Ralf Borwn interrupt list 90.1 there are no subcodes above AL=0f | |
47 | * so we are ok. | |
48 | * Furthermore CH is also restriced in the same area. Where CH is used as a | |
49 | * code it always is between 00-0f. In the case where it forms a count | |
50 | * together with CL we arbitrarily set the highest count limit to 4095. It | |
51 | * sounds reasonable for an ioctl. | |
52 | * The other alternative would have been to use the pointer argument to | |
53 | * point the the values of CX. The problem with this approach is that | |
54 | * of accessing wild regions when DX is used as a number and not as a | |
55 | * pointer. | |
56 | */ | |
57 | int | |
58 | ioctl(int handle, unsigned int function, char *data) | |
59 | { | |
60 | union REGS srv; | |
61 | struct SREGS segregs; | |
62 | ||
63 | srv.h.ah = 0x44; | |
fe14fcc3 | 64 | srv.h.al = (unsigned char)(function & 0x0F); |
b1248f16 LW |
65 | srv.x.bx = handle; |
66 | srv.x.cx = function >> 4; | |
67 | segread(&segregs); | |
68 | #if ( defined(M_I86LM) || defined(M_I86CM) || defined(M_I86HM) ) | |
69 | segregs.ds = FP_SEG(data); | |
70 | srv.x.dx = FP_OFF(data); | |
71 | #else | |
72 | srv.x.dx = (unsigned int) data; | |
73 | #endif | |
74 | intdosx(&srv, &srv, &segregs); | |
75 | if (srv.x.cflag & 1) { | |
76 | switch(srv.x.ax ){ | |
77 | case 1: | |
78 | errno = EINVAL; | |
79 | break; | |
80 | case 2: | |
81 | case 3: | |
82 | errno = ENOENT; | |
83 | break; | |
84 | case 4: | |
85 | errno = EMFILE; | |
86 | break; | |
87 | case 5: | |
88 | errno = EPERM; | |
89 | break; | |
90 | case 6: | |
91 | errno = EBADF; | |
92 | break; | |
93 | case 8: | |
94 | errno = ENOMEM; | |
95 | break; | |
96 | case 0xc: | |
97 | case 0xd: | |
98 | case 0xf: | |
99 | errno = EINVAL; | |
100 | break; | |
101 | case 0x11: | |
102 | errno = EXDEV; | |
103 | break; | |
104 | case 0x12: | |
105 | errno = ENFILE; | |
106 | break; | |
107 | default: | |
108 | errno = EZERO; | |
109 | break; | |
110 | } | |
111 | return -1; | |
112 | } else { | |
113 | switch (function & 0xf) { | |
114 | case 0: case 9: case 0xa: | |
115 | return srv.x.dx; | |
116 | case 2: case 3: case 4: case 5: | |
117 | case 6: case 7: case 8: case 0xe: | |
118 | return srv.x.ax; | |
119 | case 1: case 0xb: case 0xc: case 0xd: | |
120 | case 0xf: | |
121 | default: | |
122 | return 0; | |
123 | } | |
124 | } | |
125 | } | |
126 | ||
127 | ||
128 | /* | |
129 | * Sleep function. | |
130 | */ | |
131 | void | |
132 | sleep(unsigned len) | |
133 | { | |
134 | time_t end; | |
135 | ||
136 | end = time((time_t *)0) + len; | |
137 | while (time((time_t *)0) < end) | |
138 | ; | |
139 | } | |
140 | ||
141 | /* | |
142 | * Just pretend that everyone is a superuser | |
143 | */ | |
fe14fcc3 LW |
144 | #define ROOT_UID 0 |
145 | #define ROOT_GID 0 | |
b1248f16 LW |
146 | int |
147 | getuid(void) | |
148 | { | |
fe14fcc3 | 149 | return ROOT_UID; |
b1248f16 LW |
150 | } |
151 | ||
152 | int | |
153 | geteuid(void) | |
154 | { | |
fe14fcc3 | 155 | return ROOT_UID; |
b1248f16 LW |
156 | } |
157 | ||
158 | int | |
159 | getgid(void) | |
160 | { | |
fe14fcc3 | 161 | return ROOT_GID; |
b1248f16 LW |
162 | } |
163 | ||
164 | int | |
165 | getegid(void) | |
166 | { | |
fe14fcc3 | 167 | return ROOT_GID; |
b1248f16 LW |
168 | } |
169 | ||
fe14fcc3 LW |
170 | int |
171 | setuid(int uid) | |
172 | { return (uid==ROOT_UID?0:-1); } | |
173 | ||
174 | int | |
175 | setgid(int gid) | |
176 | { return (gid==ROOT_GID?0:-1); } | |
177 | ||
b1248f16 LW |
178 | /* |
179 | * The following code is based on the do_exec and do_aexec functions | |
180 | * in file doio.c | |
181 | */ | |
182 | int | |
183 | do_aspawn(really,arglast) | |
184 | STR *really; | |
185 | int *arglast; | |
186 | { | |
187 | register STR **st = stack->ary_array; | |
188 | register int sp = arglast[1]; | |
189 | register int items = arglast[2] - sp; | |
190 | register char **a; | |
191 | char **argv; | |
192 | char *tmps; | |
193 | int status; | |
194 | ||
195 | if (items) { | |
196 | New(1101,argv, items+1, char*); | |
197 | a = argv; | |
198 | for (st += ++sp; items > 0; items--,st++) { | |
199 | if (*st) | |
200 | *a++ = str_get(*st); | |
201 | else | |
202 | *a++ = ""; | |
203 | } | |
204 | *a = Nullch; | |
205 | if (really && *(tmps = str_get(really))) | |
206 | status = spawnvp(P_WAIT,tmps,argv); | |
207 | else | |
208 | status = spawnvp(P_WAIT,argv[0],argv); | |
209 | Safefree(argv); | |
210 | } | |
211 | return status; | |
212 | } | |
213 | ||
b1248f16 LW |
214 | |
215 | int | |
216 | do_spawn(cmd) | |
217 | char *cmd; | |
218 | { | |
219 | register char **a; | |
220 | register char *s; | |
221 | char **argv; | |
222 | char flags[10]; | |
223 | int status; | |
224 | char *shell, *cmd2; | |
225 | ||
226 | /* save an extra exec if possible */ | |
227 | if ((shell = getenv("COMSPEC")) == 0) | |
228 | shell = "\\command.com"; | |
229 | ||
230 | /* see if there are shell metacharacters in it */ | |
231 | if (strchr(cmd, '>') || strchr(cmd, '<') || strchr(cmd, '|')) | |
232 | doshell: | |
233 | return spawnl(P_WAIT,shell,shell,"/c",cmd,(char*)0); | |
234 | ||
235 | New(1102,argv, strlen(cmd) / 2 + 2, char*); | |
236 | ||
237 | New(1103,cmd2, strlen(cmd) + 1, char); | |
238 | strcpy(cmd2, cmd); | |
239 | a = argv; | |
240 | for (s = cmd2; *s;) { | |
241 | while (*s && isspace(*s)) s++; | |
242 | if (*s) | |
243 | *(a++) = s; | |
244 | while (*s && !isspace(*s)) s++; | |
245 | if (*s) | |
246 | *s++ = '\0'; | |
247 | } | |
248 | *a = Nullch; | |
249 | if (argv[0]) | |
250 | if ((status = spawnvp(P_WAIT,argv[0],argv)) == -1) { | |
251 | Safefree(argv); | |
252 | Safefree(cmd2); | |
253 | goto doshell; | |
254 | } | |
255 | Safefree(cmd2); | |
256 | Safefree(argv); | |
257 | return status; | |
258 | } |