kernel: Use hashdestroy() to free hash tables allocated with hashinit().
[dragonfly.git] / usr.bin / doscmd / intff.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1992, 1993, 1996
3 * Berkeley Software Design, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Berkeley Software
16 * Design, Inc.
17 *
18 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * BSDI intff.c,v 2.2 1996/04/08 19:32:56 bostic Exp
1de703da
MD
31 *
32 * $FreeBSD: src/usr.bin/doscmd/intff.c,v 1.7.2.2 2002/04/25 11:04:51 tg Exp $
984263bc
MD
33 */
34
984263bc
MD
35#include <sys/param.h>
36#include <ctype.h>
37#include <unistd.h>
38
39#include "doscmd.h"
40#include "cwd.h"
41#include "dispatch.h"
42
678e8cc6
SW
43static LOL *lol = NULL; /* DOS list-of-lists */
44static SDA *sda = NULL; /* DOS swappable data area */
984263bc
MD
45
46/******************************************************************************
47** redirector functions
48**
49**
50** These are set up on entry to the redirector each time, and are referenced
51** by the functions here.
52*/
53static int r_drive,n_drive = 0;
54static CDS *r_cds;
55static SFT *r_sft;
56
57
58/*
59** 2f:11:0
60**
61** Installation check
62*/
63static int
64int2f11_00(regcontext_t *REGS)
65{
66 R_AL = 0xff;
67 R_AH = 'U'; /* and why not? 8) */
68 return(0);
69}
70
71/*
72** 2f:11:1 2f:11:2 2f:11:3 2f:11:4 2f:11:5 2f:11:11 2f:11:13
73**
74** Directory functions
75*/
76static int
77int2f11_dirfn(regcontext_t *REGS)
78{
79 char fname[PATH_MAX], tname[PATH_MAX];
80 int error;
81
82 error = translate_filename(sda->filename1, fname, &r_drive);
83 if (error)
84 return(error);
85
86 if (dos_readonly(r_drive) && (R_AL != 0x05))
87 return(WRITE_PROT_DISK);
88
89 switch(R_AL) {
90 case 0x01: /* rmdir */
91 case 0x02:
92 debug(D_REDIR,"rmdir(%s)\n",fname);
93 error = rmdir(fname);
94 break;
95 case 0x03: /* mkdir */
96 case 0x04:
97 debug(D_REDIR,"mkdir(%s)\n",fname);
98 error = mkdir(fname,0777);
99 break;
100 case 0x05: /* chdir */
101 debug(D_REDIR,"chdir(%s)\n",fname);
102 /* Note returns DOS error directly */
103 return(dos_setcwd(sda->filename1));
104
105 case 0x11: /* rename */
106 error = translate_filename(sda->filename2, tname, &r_drive);
107 if (!error) {
108 debug(D_REDIR,"rename(%s,%s)\n",fname,tname);
109 error = rename(fname, tname);
110 }
111 break;
112
113 case 0x13: /* unlink */
114 debug(D_REDIR,"unlink(%s)\n",fname);
115 error = unlink(fname);
116 break;
117
118 default:
119 fatal("called int2f11_dirfn on unknown function %x\n",R_AL);
120 }
121
122 if (error < 0) {
123 switch(errno) {
124 case ENOTDIR:
125 case ENOENT:
126 return(PATH_NOT_FOUND);
127 case EXDEV:
128 return(NOT_SAME_DEV);
129 default:
130 return(ACCESS_DENIED);
131 }
132 }
133 return(0);
134}
135
136/*
137** 2f:11:6
138**
139** Close
140*/
141static int
142int2f11_close(regcontext_t *REGS __unused)
143{
144 int fd;
145
146 fd = r_sft->fd;
147 debug(D_REDIR, "close(%d)\n", fd);
148
149 r_sft->nfiles--;
150 if (r_sft->nfiles) {
151 debug(D_REDIR, "not last close\n");
152 return(0);
153 }
154 if (close(fd) < 0)
155 return(HANDLE_INVALID);
156 return(0);
157}
158
159/*
160** 2f:11:8 2f:11:9
161**
162** read/write
163*/
164static int
165int2f11_rdwr(regcontext_t *REGS __unused)
166{
167 int fd;
168 char *addr;
169 int nbytes;
a62ce081 170 int n = 0;
984263bc
MD
171
172 fd = r_sft->fd;
173 if (lseek(fd, r_sft->offset, SEEK_SET) < 0)
174 return(SEEK_ERROR);
175
176 addr = (char *)MAKEPTR(sda->dta_seg, sda->dta_off);
177 nbytes = R_CX;
178
179 switch(R_AL) {
180 case 0x08: /* read */
181 debug(D_REDIR, "read(%d, %d)\n", fd, nbytes);
182 n = read(fd, addr, nbytes);
183 if (n < 0)
184 return(READ_FAULT);
185 break;
186 case 0x09:
187 debug(D_REDIR, "write(%d, %d)\n", fd, nbytes);
188 n = write(fd, addr, nbytes);
189 if (n < 0)
190 return(WRITE_FAULT);
191 break;
192 default:
193 fatal("called int2f11_rdwr on unknown function %x\n",R_AL);
194 }
195
196 R_CX = n; /* report count */
197 r_sft->offset += n;
198 if (r_sft->offset > r_sft->size)
199 r_sft->size = r_sft->offset;
200 debug(D_REDIR, "offset now %ld\n", r_sft->offset);
201 return(0);
202}
203
204/*
205** 2f:11:c
206**
207** Get free space (like 21:36)
208*/
209static int
210int2f11_free(regcontext_t *REGS __unused)
211{
212 fsstat_t fs;
213 int error;
214
215 error = get_space(r_drive, &fs);
216 if (error)
217 return (error);
218 R_AX = fs.sectors_cluster;
219 R_BX = fs.total_clusters;
220 R_CX = fs.bytes_sector;
221 R_DX = fs.avail_clusters;
222 return(0);
223}
224
225/*
226** 2f:11:f
227**
228** get size and mode
229*/
230static int
231int2f11_stat(regcontext_t *REGS __unused)
232{
233 char fname[PATH_MAX];
234 struct stat sb;
235 int error;
236
237 error = translate_filename(sda->filename1, fname, &r_drive);
238 if (error)
239 return(error);
240
241 if (stat(fname, &sb) < 0)
242 return(FILE_NOT_FOUND);
243
244 R_AX = to_dos_attr(sb.st_mode);
245 R_BX = sb.st_size >> 16;
246 R_DI = sb.st_size & 0xffff;
247 return(0);
248}
249
250/*
251** 2f:11:16 2f:11:17 2f:11:18 2f:11:2e
252**
253** Open/create a file, closely resembles int21_open.
254*/
255static int
256int2f11_open(regcontext_t *REGS)
257{
258 char fname[PATH_MAX];
259 struct stat sb;
260 int error;
a62ce081 261 int mode = 0; /* open mode */
984263bc 262 int attr; /* attributes of created file */
a62ce081 263 int action = 0; /* what to do about file */
984263bc
MD
264 u_char *p, *e;
265 int i;
a62ce081 266 int omode = 0; /* mode to say we opened in */
984263bc
MD
267 int status;
268 int fd;
269
270 error = translate_filename(sda->filename1, fname, &r_drive);
271 if (error)
272 return(error);
273
274 /*
275 ** get attributes/access mode off stack : low byte is attribute, high
276 ** byte is (sometimes) used in conjunction with 'action'
277 */
278 attr = *(u_short *)MAKEPTR(R_SS, R_SP) & 0xff;
279
280 /* which style? */
281 switch(R_AL) {
282 case 0x16: /* open */
283 action = 0x01; /* fail if does not exist */
284 switch (sda->open_mode & 3) {
285 case 0:
286 mode = O_RDONLY;
287 break;
288 case 1:
289 mode = O_WRONLY;
290 break;
291 case 2:
292 mode = O_RDWR;
293 break;
294 default:
295 return (FUNC_NUM_IVALID);
296 }
297 omode = sda->open_mode & 0x7f;
298 debug(D_REDIR,"open");
299 break;
300
301 case 0x17: /* creat/creat new */
302 case 0x18: /* creat/creat new (no CDS, but we don't care)*/
303 mode = O_RDWR;
304 omode = 3;
305 if (attr & 0x100) { /* creat new */
306 action = 0x10; /* create if not exist, fail if exists */
307 debug(D_REDIR, "creat_new");
308 } else { /* creat */
309 action = 0x12; /* create and destroy */
310 debug(D_REDIR, "creat");
311 }
312 break;
313
314 case 0x2e: /* multipurpose */
315 attr = sda->ext_attr;
316 action = sda->ext_action;
317 switch (sda->ext_mode & 3) {
318 case 0:
319 mode = O_RDONLY;
320 break;
321 case 1:
322 mode = O_WRONLY;
323 break;
324 case 2:
325 mode = O_RDWR;
326 break;
327 default:
328 return (FUNC_NUM_IVALID);
329 }
330 omode = sda->ext_mode & 0x7f;
331 debug(D_REDIR,"mopen");
332 break;
333
334 default:
335 fatal("called int2f11_open for unknown function %x\n",R_AL);
336 }
337 if (action & 0x02) /* replace/open mode */
338 mode |= O_TRUNC;
339 debug(D_REDIR, "(%s) action 0x%x mode 0x%x attr 0x%x omode 0x%x \n",
340 fname, action, mode, attr, omode);
341
342 if (ustat(fname, &sb) < 0) { /* file does not exist */
343 if ((action & 0x10) || (attr & 0x100)) { /* create it */
344 sb.st_ino = 0;
345 mode |= O_CREAT; /* have to create as we go */
346 status = 0x02; /* file created */
347 } else {
348 return(FILE_NOT_FOUND); /* fail */
349 }
350 } else {
351 if (S_ISDIR(sb.st_mode))
352 return(ACCESS_DENIED);
353 if ((action & 0x03) && !(attr & 0x100)) { /* exists, work with it */
354 if (action & 0x02) {
355 if (!S_ISREG(sb.st_mode)) { /* only allowed for files */
356 debug(D_FILE_OPS,"attempt to truncate non-regular file\n");
357 return(ACCESS_DENIED);
358 }
359 status = 0x03; /* we're going to truncate it */
360 } else {
361 status = 0x01; /* just open it */
362 }
363 } else {
364 return(FILE_ALREADY_EXISTS); /* exists, fail */
365 }
366 }
367
368 if ((fd = open(fname, mode, from_dos_attr(attr))) < 0) {
369 debug(D_FILE_OPS,"failed to open %s : %s\n",fname,strerror(errno));
370 return (ACCESS_DENIED);
371 }
372
373 if (R_AL == 0x2e) /* extended wants status returned */
374 R_CX = status;
375
376 /* black magic to populate the SFT */
377
378 e = p = sda->filename1 + 2; /* parse name */
379 while (*p) {
380 if (*p++ == '\\') /* look for beginning of filename */
381 e = p;
382 }
383
384 for (i = 0; i < 8; ++i) { /* copy name and pad with spaces */
385 if (*e && *e != '.')
386 r_sft->name[i] = *e++;
387 else
388 r_sft->name[i] = ' ';
389 }
390
391 if (*e == '.') /* skip period on short names */
392 ++e;
393
394 for (i = 0; i < 3; ++i) { /* copy extension and pad with spaces */
395 if (*e)
396 r_sft->ext[i] = *e++;
397 else
398 r_sft->ext[i] = ' ';
399 }
400
401 if (ustat(fname, &sb) < 0) /* re-stat to be accurate */
402 return(WRITE_FAULT); /* any better ideas?! */
403
404 r_sft->open_mode = omode; /* file open mode */
405 *(u_long *)r_sft->ddr_dpb = 0; /* no parameter block */
406 r_sft->size = sb.st_size; /* current size */
407 r_sft->fd = fd; /* our fd for it (hidden in starting cluster number) */
408 r_sft->offset = 0; /* current offset is 0 */
409 *(u_short *)r_sft->dir_sector = 0; /* not local file, ignored */
410 r_sft->dir_entry = 0; /* not local file, ignored */
411 r_sft->attribute = attr & 0xff; /* file attributes as requested */
412 r_sft->info = r_drive + 0x8040; /* hide drive number here for later reference */
413 encode_dos_file_time(sb.st_mtime, &r_sft->date, &r_sft->time);
414 debug(D_REDIR,"success, fd %d status %x\n", fd, status);
415 return(0);
416}
417
418/*
419** 2f:11:19 2f:11:1b
420**
421** find first
422*/
423static int
424int2f11_findfirst(regcontext_t *REGS __unused)
425{
426 return(find_first(sda->filename1,sda->attrmask,
427 (dosdir_t *)sda->foundentry,
428 (find_block_t *)sda->findfirst));
429}
430
431/*
432** 2f:11:1c
433**
434** find next
435*/
436static int
437int2f11_findnext(regcontext_t *REGS __unused)
438{
439 return(find_next((dosdir_t *)sda->foundentry,
440 (find_block_t *)sda->findfirst));
441}
442
443/*
444** 2f:11:21
445**
446** lseek
447*/
448static int
449int2f11_lseek(regcontext_t *REGS)
450{
451 int fd;
452 off_t offset;
453
454 fd = r_sft->fd;
455 offset = (off_t) ((int) ((R_CX << 16) + R_DX));
456
457 debug(D_REDIR,"lseek(%d, 0x%qx, SEEK_END)\n", fd, offset);
458
459 if ((offset = lseek(fd, offset, SEEK_END)) < 0) {
460 if (errno == EBADF)
461 return(HANDLE_INVALID);
462 else
463 return(SEEK_ERROR);
464 }
465 r_sft->offset = offset; /* update offset in SFT */
466 R_DX = offset >> 16;
467 R_AX = offset;
468 return(0);
469}
470
471/*
472** 2f:11:23
473**
474** qualify filename
475*/
476static int
477int2f11_fnqual(regcontext_t *REGS)
478{
479 char *fname;
480 char *tname;
481 static char errmsg[] = "(failed)";
482 int savedrive;
483 int error;
484
485 return(PATH_NOT_FOUND);
486
487 savedrive = diskdrive; /* to get CWD for network drive */
488 diskdrive = n_drive;
489 fname = (char *)MAKEPTR(R_DS, R_SI); /* path pointers */
490 tname = (char *)MAKEPTR(R_ES, R_DI);
491
492 error = dos_makepath(fname, tname);
493 if (error)
494 tname = errmsg;
495
496 diskdrive = savedrive; /* restore correct drive */
497
498 debug(D_REDIR, "qualify '%s' -> '%s'\n", fname, tname);
499 return(error);
500}
501
502/*
503** 2f:11:??
504**
505** Null function - we know about it but do nothing
506*/
507static int
508int2f11_NULLFUNC(regcontext_t *REGS __unused)
509{
510 return(0);
511}
512
513/*
514** 2f:11:??
515**
516** no function - not handled here (error)
517*/
518static int
519int2f11_NOFUNC(regcontext_t *REGS __unused)
520{
521 return(-1);
522}
523
524struct intfunc_table int2f11_table[] = {
525 { 0x00, IFT_NOSUBFUNC, int2f11_00, "installation check"},
526 { 0x01, IFT_NOSUBFUNC, int2f11_dirfn, "rmdir"},
527 { 0x02, IFT_NOSUBFUNC, int2f11_dirfn, "rmdir"},
528 { 0x03, IFT_NOSUBFUNC, int2f11_dirfn, "mkdir"},
529 { 0x04, IFT_NOSUBFUNC, int2f11_dirfn, "mkdir"},
530 { 0x05, IFT_NOSUBFUNC, int2f11_dirfn, "chdir"},
531 { 0x06, IFT_NOSUBFUNC, int2f11_close, "close"},
532 { 0x07, IFT_NOSUBFUNC, int2f11_NULLFUNC, "commit file"},
533 { 0x08, IFT_NOSUBFUNC, int2f11_rdwr, "read"},
534 { 0x09, IFT_NOSUBFUNC, int2f11_rdwr, "write"},
535 { 0x0a, IFT_NOSUBFUNC, int2f11_NULLFUNC, "lock region"},
536 { 0x0b, IFT_NOSUBFUNC, int2f11_NULLFUNC, "unlock region"},
537 { 0x0c, IFT_NOSUBFUNC, int2f11_free, "free space"},
538 { 0x0e, IFT_NOSUBFUNC, int2f11_NULLFUNC, "chmod"},
539 { 0x0f, IFT_NOSUBFUNC, int2f11_stat, "stat"},
540 { 0x11, IFT_NOSUBFUNC, int2f11_dirfn, "rename"},
541 { 0x13, IFT_NOSUBFUNC, int2f11_dirfn, "unlink"},
542 { 0x16, IFT_NOSUBFUNC, int2f11_open, "open"},
543 { 0x17, IFT_NOSUBFUNC, int2f11_open, "creat"},
544 { 0x18, IFT_NOSUBFUNC, int2f11_open, "creat"},
545 { 0x19, IFT_NOSUBFUNC, int2f11_findfirst, "find first"},
546 { 0x1b, IFT_NOSUBFUNC, int2f11_findfirst, "find first"},
547 { 0x1c, IFT_NOSUBFUNC, int2f11_findnext, "find next"},
548 { 0x1d, IFT_NOSUBFUNC, int2f11_NULLFUNC, "close all (abort)"},
549 { 0x1e, IFT_NOSUBFUNC, int2f11_NULLFUNC, "do redirection"},
550 { 0x1f, IFT_NOSUBFUNC, int2f11_NULLFUNC, "printer setup"},
551 { 0x20, IFT_NOSUBFUNC, int2f11_NULLFUNC, "flush all buffers"},
552 { 0x21, IFT_NOSUBFUNC, int2f11_lseek, "lseek"},
553 { 0x22, IFT_NOSUBFUNC, int2f11_NULLFUNC, "process terminated"},
554 { 0x23, IFT_NOSUBFUNC, int2f11_fnqual, "qualify filename"},
555 { 0x24, IFT_NOSUBFUNC, int2f11_NOFUNC, "turn off printer"},
556 { 0x25, IFT_NOSUBFUNC, int2f11_NOFUNC, "printer mode"},
557 { 0x2d, IFT_NOSUBFUNC, int2f11_NOFUNC, "extended attributes"},
558 { 0x2e, IFT_NOSUBFUNC, int2f11_open, "extended open/create"},
559 { -1, 0, NULL, NULL}
560};
561
562static int int2f11_fastlookup[256];
563
564/******************************************************************************
565** 2f:11
566**
567** The DOS redirector interface.
568*/
569
570/*
571** Verify that the drive being referenced is one we are handling, and
572** establish some state for upcoming functions.
573**
574** Returns 1 if we should handle this request.
575**
576** XXX this is rather inefficient, but much easier to read than the previous
577** incarnation 8(
578*/
579static int
580int2f11_validate(regcontext_t *REGS)
581{
582 int func = R_AL;
583 const char *path = NULL;
584 int doit = 0;
585
586 /* defaults may help trap problems */
587 r_cds = NULL;
588 r_sft = NULL;
589 r_drive = -1;
590
591 /* some functions we accept regardless */
592 switch (func) {
593 case 0x00: /* installation check */
594 case 0x23: /* qualify path */
595 case 0x1c: /* XXX really only valid if a search already started... */
596 return(1);
597 }
598
599 /* Where's the CDS? */
600 switch(func) {
601 case 0x01: /* referenced by the SDA */
602 case 0x02:
603 case 0x03:
604 case 0x04:
605 case 0x05:
606 case 0x0e:
607 case 0x0f:
608 case 0x11:
609 case 0x13:
610 case 0x17:
611 case 0x1b:
612 r_cds = (CDS *)MAKEPTR(sda->cds_seg, sda->cds_off);
613 break;
614
615 case 0x0c: /* in es:di */
616 case 0x1c:
617 r_cds = (CDS *)MAKEPTR(R_ES, R_DI);
618 break;
619 }
620
621 /* Where's the SFT? */
622 switch(func) {
623 case 0x06: /* in es:di */
624 case 0x07:
625 case 0x08:
626 case 0x09:
627 case 0x0a:
628 case 0x0b:
629 case 0x16:
630 case 0x17:
631 case 0x18:
632 case 0x21:
633 case 0x2d:
634 case 0x2e:
635 r_sft = (SFT *)MAKEPTR(R_ES, R_DI);
636 break;
637 }
638
639 /* What drive? */
640 switch(func) {
641 case 0x01: /* get drive from fully-qualified path in SDA */
642 case 0x02:
643 case 0x03:
644 case 0x04:
645 case 0x05:
646 case 0x0c:
647 case 0x0e:
648 case 0x0f:
649 case 0x11:
650 case 0x13:
651 case 0x16:
652 case 0x17:
653 case 0x18:
654 case 0x19:
655 case 0x1b:
656 case 0x2e:
657 path = sda->filename1;
658 break;
659
660 case 0x06: /* get drive from SFT (we put it here when file was opened) */
661 case 0x07:
662 case 0x08:
663 case 0x09:
664 case 0x0a:
665 case 0x0b:
666 case 0x21:
667 case 0x2d:
668 r_drive = r_sft->info & 0x1f;
669 break;
670 }
671
672 if (path) { /* we have a path and need to determine the drive it refers to */
673
674 if (path[1] != ':') { /* must be fully qualified; we cannot handle this */
675 debug(D_REDIR,"attempt to work non-absolute path %s\n",path);
676 return(0);
677 }
678
679 /* translate letter to drive number */
680 r_drive = drlton(path[0]);
681 } else {
682 path = "(no path)";
683 }
684
685 /* do we handle this drive? */
686 if (dos_getcwd(r_drive)) {
687 n_drive = r_drive; /* XXX GROSTIC HACK ALERT */
688 doit = 1;
689 }
690
691 debug(D_REDIR,"%s -> drive %c func %x (%sus)\n",
692 path, drntol(r_drive), func, doit?"":"not ");
693
694 /* so do we deal with this one? */
695 return(doit);
696}
697
698
699int
700int2f_11(regcontext_t *REGS)
701{
702 int idx;
703 int error;
704
705 if (!sda) { /* not initialised yet */
706 error = FUNC_NUM_IVALID;
707 } else {
708
709 idx = intfunc_find(int2f11_table, int2f11_fastlookup, R_AL, 0);
710 if (idx == -1) {
711 debug(D_ALWAYS,"no handler for int2f:11:%x\n", R_AL);
712 return(0);
713 }
714 reset_poll();
715
716
717 if (!int2f11_validate(REGS)) { /* determine whether we handle this request */
718 error = -1; /* not handled by us */
719 } else {
720 debug(D_REDIR, "REDIR: %02x (%s)\n",
721 int2f11_table[idx].func, int2f11_table[idx].desc);
722 /* call the handler */
723 error = int2f11_table[idx].handler(REGS);
724 if (error != -1)
725 debug(D_REDIR, "REDIR: returns %d (%s)\n",
726 error, ((error >= 0) && (error <= dos_ret_size)) ? dos_return[error] : "unknown");
727 }
728 }
729
730 if (error == -1)
731 return (0);
732 if (error) {
733 R_AX = error;
734 R_FLAGS |= PSL_C;
735 } else
736 R_FLAGS &= ~PSL_C;
737 return (1);
738}
739
740/******************************************************************************
741** intff handler.
742**
743** intff is the (secret, proprietary, internal, evil) call to
744** initialise the redirector.
745*/
746static void
747install_drive(int drive, u_char *path)
748{
749 CDS *cds;
750
751 /* check that DOS considers this a valid drive */
752 if (drive < 0 || drive >= lol->lastdrive) {
753 debug(D_REDIR, "Drive %c beyond limit of %c\n",
754 drntol(drive), drntol(lol->lastdrive - 1));
755 return;
756 }
757
758 /* get the CDS for this drive */
759 cds = (CDS *)MAKEPTR(lol->cds_seg, lol->cds_offset);
760 cds += drive;
761
762#if 0 /* XXX looks OK to me - mjs */
763 if (cds->flag & (CDS_remote | CDS_ready)) {
764 debug(D_REDIR, "Drive %c already installed\n", drntol(drive));
765 return;
766 }
767#endif
768
769 debug(D_REDIR, "Installing %c: as %s\n", drntol(drive), path);
770
771 cds->flag |= CDS_remote | CDS_ready | CDS_notnet;
772 cds->path[0] = drntol(drive);
773 cds->path[1] = ':';
774 cds->path[2] = '\\';
775 cds->path[3] = '\0';
776 cds->offset = 2; /* offset of \ in current path field */
777}
778
779static void
780init_drives(void)
781{
782 int drive;
783 u_char *path;
784
785 /* for all possible drives */
786 for (drive = 0; drive < 26; ++drive) {
678e8cc6 787 if ((path = dos_getpath(drive)) != NULL) /* assigned to a path? */
984263bc
MD
788 install_drive(drive, path); /* make it visible to DOS */
789 }
790}
791
792
793void
794intff(regcontext_t *REGS)
795{
796
797 if (lol && sda) { /* already been called? */
798 debug(D_REDIR, "redirector duplicate install ignored");
799 return;
800 }
801 lol = (LOL *)MAKEPTR(R_BX, R_DX); /* where DOS keeps its goodies */
802 sda = (SDA *)MAKEPTR(R_DI, R_SI);
803 init_drives();
804
805 /* initialise dispatcher */
806 intfunc_init(int2f11_table, int2f11_fastlookup);
807}