perl 4.0 patch 14: patch #11, continued
[p5sagit/p5-mst-13.2.git] / msdos / msdos.c
1 /* $RCSfile: msdos.c,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:37 $
2  *
3  *    (C) Copyright 1989, 1990 Diomidis Spinellis.
4  *
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.
7  *
8  * $Log:        msdos.c,v $
9  * Revision 4.0.1.1  91/06/07  11:22:37  lwall
10  * patch4: new copyright notice
11  * 
12  * Revision 4.0  91/03/20  01:34:46  lwall
13  * 4.0 baseline.
14  * 
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
27 #include "EXTERN.h"
28 #include "perl.h"
29
30 #include <dos.h>
31 #include <process.h>
32
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;
64         srv.h.al = (unsigned char)(function & 0x0F);
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  */
144 #define ROOT_UID        0
145 #define ROOT_GID        0
146 int
147 getuid(void)
148 {
149         return ROOT_UID;
150 }
151
152 int
153 geteuid(void)
154 {
155         return ROOT_UID;
156 }
157
158 int
159 getgid(void)
160 {
161         return ROOT_GID;
162 }
163
164 int
165 getegid(void)
166 {
167         return ROOT_GID;
168 }
169
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
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
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 }