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