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