This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 3.0 patch #17 patch #16, continued
[perl5.git] / msdos / msdos.c
CommitLineData
b1248f16
LW
1/* $Header: msdos.c,v 3.0.1.1 90/03/27 16:10:41 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 3.0.1.1 90/03/27 16:10:41 lwall
10 * patch16: MSDOS support
11 *
12 * Revision 1.1 90/03/18 20:32:01 dds
13 * Initial revision
14 *
15 */
16
17/*
18 * Various Unix compatibility functions for MS-DOS.
19 */
20
21#include <stdio.h>
22#include <errno.h>
23#include <dos.h>
24#include <time.h>
25#include <process.h>
26
27#include "EXTERN.h"
28#include "perl.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 */
54int
55ioctl(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 = function & 0xf;
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 */
128void
129sleep(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 */
141int
142getuid(void)
143{
144 return 0;
145}
146
147int
148geteuid(void)
149{
150 return 0;
151}
152
153int
154getgid(void)
155{
156 return 0;
157}
158
159int
160getegid(void)
161{
162 return 0;
163}
164
165/*
166 * The following code is based on the do_exec and do_aexec functions
167 * in file doio.c
168 */
169int
170do_aspawn(really,arglast)
171STR *really;
172int *arglast;
173{
174 register STR **st = stack->ary_array;
175 register int sp = arglast[1];
176 register int items = arglast[2] - sp;
177 register char **a;
178 char **argv;
179 char *tmps;
180 int status;
181
182 if (items) {
183 New(1101,argv, items+1, char*);
184 a = argv;
185 for (st += ++sp; items > 0; items--,st++) {
186 if (*st)
187 *a++ = str_get(*st);
188 else
189 *a++ = "";
190 }
191 *a = Nullch;
192 if (really && *(tmps = str_get(really)))
193 status = spawnvp(P_WAIT,tmps,argv);
194 else
195 status = spawnvp(P_WAIT,argv[0],argv);
196 Safefree(argv);
197 }
198 return status;
199}
200
201char *getenv(char *name);
202
203int
204do_spawn(cmd)
205char *cmd;
206{
207 register char **a;
208 register char *s;
209 char **argv;
210 char flags[10];
211 int status;
212 char *shell, *cmd2;
213
214 /* save an extra exec if possible */
215 if ((shell = getenv("COMSPEC")) == 0)
216 shell = "\\command.com";
217
218 /* see if there are shell metacharacters in it */
219 if (strchr(cmd, '>') || strchr(cmd, '<') || strchr(cmd, '|'))
220 doshell:
221 return spawnl(P_WAIT,shell,shell,"/c",cmd,(char*)0);
222
223 New(1102,argv, strlen(cmd) / 2 + 2, char*);
224
225 New(1103,cmd2, strlen(cmd) + 1, char);
226 strcpy(cmd2, cmd);
227 a = argv;
228 for (s = cmd2; *s;) {
229 while (*s && isspace(*s)) s++;
230 if (*s)
231 *(a++) = s;
232 while (*s && !isspace(*s)) s++;
233 if (*s)
234 *s++ = '\0';
235 }
236 *a = Nullch;
237 if (argv[0])
238 if ((status = spawnvp(P_WAIT,argv[0],argv)) == -1) {
239 Safefree(argv);
240 Safefree(cmd2);
241 goto doshell;
242 }
243 Safefree(cmd2);
244 Safefree(argv);
245 return status;
246}