perl 4.0 patch 14: patch #11, continued
[p5sagit/p5-mst-13.2.git] / msdos / msdos.c
CommitLineData
352d5a3a 1/* $RCSfile: msdos.c,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:37 $
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 $
352d5a3a 9 * Revision 4.0.1.1 91/06/07 11:22:37 lwall
10 * patch4: new copyright notice
11 *
fe14fcc3 12 * Revision 4.0 91/03/20 01:34:46 lwall
13 * 4.0 baseline.
14 *
b1248f16 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 27#include "EXTERN.h"
28#include "perl.h"
29
fe14fcc3 30#include <dos.h>
31#include <process.h>
32
b1248f16 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 */
57int
58ioctl(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 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 */
131void
132sleep(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 144#define ROOT_UID 0
145#define ROOT_GID 0
b1248f16 146int
147getuid(void)
148{
fe14fcc3 149 return ROOT_UID;
b1248f16 150}
151
152int
153geteuid(void)
154{
fe14fcc3 155 return ROOT_UID;
b1248f16 156}
157
158int
159getgid(void)
160{
fe14fcc3 161 return ROOT_GID;
b1248f16 162}
163
164int
165getegid(void)
166{
fe14fcc3 167 return ROOT_GID;
b1248f16 168}
169
fe14fcc3 170int
171setuid(int uid)
172{ return (uid==ROOT_UID?0:-1); }
173
174int
175setgid(int gid)
176{ return (gid==ROOT_GID?0:-1); }
177
b1248f16 178/*
179 * The following code is based on the do_exec and do_aexec functions
180 * in file doio.c
181 */
182int
183do_aspawn(really,arglast)
184STR *really;
185int *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 214
215int
216do_spawn(cmd)
217char *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}