summaryrefslogtreecommitdiffstats
path: root/usr.bin/doscmd/intff.c
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1997-08-09 01:43:15 +0000
committerdyson <dyson@FreeBSD.org>1997-08-09 01:43:15 +0000
commit305573cb2990c5d329d149cef5a3b5533b1e8fd9 (patch)
treedf06304b637358dbe8a006fdb7a6ea5955fee179 /usr.bin/doscmd/intff.c
parentdede28832bba6a9de7a428ff58df92439bddbc9c (diff)
downloadFreeBSD-src-305573cb2990c5d329d149cef5a3b5533b1e8fd9.zip
FreeBSD-src-305573cb2990c5d329d149cef5a3b5533b1e8fd9.tar.gz
Add our doscmd to the tree. This is a result of work from BSDI, and
a group of dos emulator developers. Submitted by: Jonathan Lemon <jlemon@americantv.com> Obtained from: BSDI
Diffstat (limited to 'usr.bin/doscmd/intff.c')
-rw-r--r--usr.bin/doscmd/intff.c805
1 files changed, 805 insertions, 0 deletions
diff --git a/usr.bin/doscmd/intff.c b/usr.bin/doscmd/intff.c
new file mode 100644
index 0000000..e27ac0e
--- /dev/null
+++ b/usr.bin/doscmd/intff.c
@@ -0,0 +1,805 @@
+/*
+ * Copyright (c) 1992, 1993, 1996
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Berkeley Software
+ * Design, Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * BSDI intff.c,v 2.2 1996/04/08 19:32:56 bostic Exp
+ *
+ * $Id: intff.c,v 1.8 1996/09/23 09:59:25 miff Exp $
+ */
+
+#include "doscmd.h"
+#include <sys/param.h>
+#include <ctype.h>
+
+#include "dispatch.h"
+
+static LOL *lol = 0; /* DOS list-of-lists */
+static SDA *sda = 0; /* DOS swappable data area */
+
+/******************************************************************************
+** redirector functions
+**
+**
+** These are set up on entry to the redirector each time, and are referenced
+** by the functions here.
+*/
+static int r_drive,n_drive = 0;
+static CDS *r_cds;
+static SFT *r_sft;
+
+
+/*
+** 2f:11:0
+**
+** Installation check
+*/
+static int
+int2f11_00(regcontext_t *REGS)
+{
+ R_AL = 0xff;
+ R_AH = 'U'; /* and why not? 8) */
+ return(0);
+}
+
+/*
+** 2f:11:1 2f:11:2 2f:11:3 2f:11:4 2f:11:5 2f:11:11 2f:11:13
+**
+** Directory functions
+*/
+static int
+int2f11_dirfn(regcontext_t *REGS)
+{
+ char fname[PATH_MAX], tname[PATH_MAX];
+ int error;
+
+ error = translate_filename(sda->filename1, fname, &r_drive);
+ if (error)
+ return(error);
+
+ if (dos_readonly(r_drive) && (R_AL != 0x05))
+ return(WRITE_PROT_DISK);
+
+ switch(R_AL) {
+ case 0x01: /* rmdir */
+ case 0x02:
+ debug(D_REDIR,"rmdir(%s)\n",fname);
+ error = rmdir(fname);
+ break;
+ case 0x03: /* mkdir */
+ case 0x04:
+ debug(D_REDIR,"mkdir(%s)\n",fname);
+ error = mkdir(fname,0777);
+ break;
+ case 0x05: /* chdir */
+ debug(D_REDIR,"chdir(%s)\n",fname);
+ /* Note returns DOS error directly */
+ return(dos_setcwd(sda->filename1));
+
+ case 0x11: /* rename */
+ error = translate_filename(sda->filename2, tname, &r_drive);
+ if (!error) {
+ debug(D_REDIR,"rename(%s,%s)\n",fname,tname);
+ error = rename(fname, tname);
+ }
+ break;
+
+ case 0x13: /* unlink */
+ debug(D_REDIR,"unlink(%s)\n",fname);
+ error = unlink(fname);
+ break;
+
+ default:
+ fatal("called int2f11_dirfn on unknown function %x\n",R_AL);
+ }
+
+ if (error < 0) {
+ switch(errno) {
+ case ENOTDIR:
+ case ENOENT:
+ return(PATH_NOT_FOUND);
+ case EXDEV:
+ return(NOT_SAME_DEV);
+ default:
+ return(ACCESS_DENIED);
+ }
+ }
+ return(0);
+}
+
+/*
+** 2f:11:6
+**
+** Close
+*/
+static int
+int2f11_close(regcontext_t *REGS)
+{
+ int fd;
+
+ fd = r_sft->fd;
+ debug(D_REDIR, "close(%d)\n", fd);
+
+ r_sft->nfiles--;
+ if (r_sft->nfiles) {
+ debug(D_REDIR, "not last close\n");
+ return(0);
+ }
+ if (close(fd) < 0)
+ return(HANDLE_INVALID);
+ return(0);
+}
+
+/*
+** 2f:11:8 2f:11:9
+**
+** read/write
+*/
+static int
+int2f11_rdwr(regcontext_t *REGS)
+{
+ int fd;
+ char *addr;
+ int nbytes;
+ int n;
+
+ fd = r_sft->fd;
+ if (lseek(fd, r_sft->offset, SEEK_SET) < 0)
+ return(SEEK_ERROR);
+
+ addr = (char *)MAKEPTR(sda->dta_seg, sda->dta_off);
+ nbytes = R_CX;
+
+ switch(R_AL) {
+ case 0x08: /* read */
+ debug(D_REDIR, "read(%d, %d)\n", fd, nbytes);
+ n = read(fd, addr, nbytes);
+ if (n < 0)
+ return(READ_FAULT);
+ break;
+ case 0x09:
+ debug(D_REDIR, "write(%d, %d)\n", fd, nbytes);
+ n = write(fd, addr, nbytes);
+ if (n < 0)
+ return(WRITE_FAULT);
+ break;
+ default:
+ fatal("called int2f11_rdwr on unknown function %x\n",R_AL);
+ }
+
+ R_CX = n; /* report count */
+ r_sft->offset += n;
+ if (r_sft->offset > r_sft->size)
+ r_sft->size = r_sft->offset;
+ debug(D_REDIR, "offset now %d\n", r_sft->offset);
+ return(0);
+}
+
+/*
+** 2f:11:c
+**
+** Get free space (like 21:36)
+*/
+static int
+int2f11_free(regcontext_t *REGS)
+{
+ fsstat_t fs;
+ int error;
+
+ error = get_space(r_drive, &fs);
+ if (error)
+ return (error);
+ R_AX = fs.sectors_cluster;
+ R_BX = fs.total_clusters;
+ R_CX = fs.bytes_sector;
+ R_DX = fs.avail_clusters;
+ return(0);
+}
+
+/*
+** 2f:11:f
+**
+** get size and mode
+*/
+static int
+int2f11_stat(regcontext_t *REGS)
+{
+ char fname[PATH_MAX];
+ struct stat sb;
+ int error;
+
+ error = translate_filename(sda->filename1, fname, &r_drive);
+ if (error)
+ return(error);
+
+ if (stat(fname, &sb) < 0)
+ return(FILE_NOT_FOUND);
+
+ R_AX = to_dos_attr(sb.st_mode);
+ R_BX = sb.st_size >> 16;
+ R_DI = sb.st_size & 0xffff;
+ return(0);
+}
+
+/*
+** 2f:11:16 2f:11:17 2f:11:18 2f:11:2e
+**
+** Open/create a file, closely resembles int21_open.
+*/
+static int
+int2f11_open(regcontext_t *REGS)
+{
+ char fname[PATH_MAX];
+ struct stat sb;
+ int error;
+ int mode; /* open mode */
+ int attr; /* attributes of created file */
+ int action; /* what to do about file */
+ u_char *p, *e;
+ int i;
+ int omode; /* mode to say we opened in */
+ int status;
+ int fd;
+
+ error = translate_filename(sda->filename1, fname, &r_drive);
+ if (error)
+ return(error);
+
+ /*
+ ** get attributes/access mode off stack : low byte is attribute, high
+ ** byte is (sometimes) used in conjunction with 'action'
+ */
+ attr = *(u_short *)N_GETPTR(R_SS, R_SP) & 0xff;
+
+ /* which style? */
+ switch(R_AL) {
+ case 0x16: /* open */
+ action = 0x01; /* fail if does not exist */
+ switch (sda->open_mode & 3) {
+ case 0:
+ mode = O_RDONLY;
+ break;
+ case 1:
+ mode = O_WRONLY;
+ break;
+ case 2:
+ mode = O_RDWR;
+ break;
+ default:
+ return (FUNC_NUM_IVALID);
+ }
+ omode = sda->open_mode & 0x7f;
+ debug(D_REDIR,"open");
+ break;
+
+ case 0x17: /* creat/creat new */
+ case 0x18: /* creat/creat new (no CDS, but we don't care)*/
+ mode = O_RDWR;
+ omode = 3;
+ if (attr & 0x100) { /* creat new */
+ action = 0x10; /* create if not exist, fail if exists */
+ debug(D_REDIR, "creat_new");
+ } else { /* creat */
+ action = 0x12; /* create and destroy */
+ debug(D_REDIR, "creat");
+ }
+ break;
+
+ case 0x2e: /* multipurpose */
+ attr = sda->ext_attr;
+ action = sda->ext_action;
+ switch (sda->ext_mode & 3) {
+ case 0:
+ mode = O_RDONLY;
+ break;
+ case 1:
+ mode = O_WRONLY;
+ break;
+ case 2:
+ mode = O_RDWR;
+ break;
+ default:
+ return (FUNC_NUM_IVALID);
+ }
+ omode = sda->ext_mode & 0x7f;
+ debug(D_REDIR,"mopen");
+ break;
+
+ default:
+ fatal("called int2f11_open for unknown function %x\n",R_AL);
+ }
+ if (action & 0x02) /* replace/open mode */
+ mode |= O_TRUNC;
+ debug(D_REDIR, "(%s) action 0x%x mode 0x%x attr 0x%x omode 0x%x \n",
+ fname, action, mode, attr, omode);
+
+ if (ustat(fname, &sb) < 0) { /* file does not exist */
+ if ((action & 0x10) || (attr & 0x100)) { /* create it */
+ sb.st_ino = 0;
+ mode |= O_CREAT; /* have to create as we go */
+ status = 0x02; /* file created */
+ } else {
+ return(FILE_NOT_FOUND); /* fail */
+ }
+ } else {
+ if (S_ISDIR(sb.st_mode))
+ return(ACCESS_DENIED);
+ if ((action & 0x03) && !(attr & 0x100)) { /* exists, work with it */
+ if (action & 0x02) {
+ if (!S_ISREG(sb.st_mode)) { /* only allowed for files */
+ debug(D_FILE_OPS,"attempt to truncate non-regular file\n");
+ return(ACCESS_DENIED);
+ }
+ status = 0x03; /* we're going to truncate it */
+ } else {
+ status = 0x01; /* just open it */
+ }
+ } else {
+ return(FILE_ALREADY_EXISTS); /* exists, fail */
+ }
+ }
+
+ if ((fd = open(fname, mode, from_dos_attr(attr))) < 0) {
+ debug(D_FILE_OPS,"failed to open %s : %s\n",fname,strerror(errno));
+ return (ACCESS_DENIED);
+ }
+
+ if (R_AL == 0x2e) /* extended wants status returned */
+ R_CX = status;
+
+ /* black magic to populate the SFT */
+
+ e = p = sda->filename1 + 2; /* parse name */
+ while (*p) {
+ if (*p++ == '\\') /* look for beginning of filename */
+ e = p;
+ }
+
+ for (i = 0; i < 8; ++i) { /* copy name and pad with spaces */
+ if (*e && *e != '.')
+ r_sft->name[i] = *e++;
+ else
+ r_sft->name[i] = ' ';
+ }
+
+ if (*e == '.') /* skip period on short names */
+ ++e;
+
+ for (i = 0; i < 3; ++i) { /* copy extension and pad with spaces */
+ if (*e)
+ r_sft->ext[i] = *e++;
+ else
+ r_sft->ext[i] = ' ';
+ }
+
+ if (ustat(fname, &sb) < 0) /* re-stat to be accurate */
+ return(WRITE_FAULT); /* any better ideas?! */
+
+ r_sft->open_mode = omode; /* file open mode */
+ *(u_long *)r_sft->ddr_dpb = 0; /* no parameter block */
+ r_sft->size = sb.st_size; /* current size */
+ r_sft->fd = fd; /* our fd for it (hidden in starting cluster number) */
+ r_sft->offset = 0; /* current offset is 0 */
+ *(u_short *)r_sft->dir_sector = 0; /* not local file, ignored */
+ r_sft->dir_entry = 0; /* not local file, ignored */
+ r_sft->attribute = attr & 0xff; /* file attributes as requested */
+ r_sft->info = r_drive + 0x8040; /* hide drive number here for later reference */
+ encode_dos_file_time(sb.st_mtime, &r_sft->date, &r_sft->time);
+ debug(D_REDIR,"success, fd %d status %x\n", fd, status);
+ return(0);
+}
+
+/*
+** 2f:11:19 2f:11:1b
+**
+** find first
+*/
+static int
+int2f11_findfirst(regcontext_t *REGS)
+{
+ return(find_first(sda->filename1,sda->attrmask,
+ (dosdir_t *)sda->foundentry,
+ (find_block_t *)sda->findfirst));
+}
+
+/*
+** 2f:11:1c
+**
+** find next
+*/
+static int
+int2f11_findnext(regcontext_t *REGS)
+{
+ return(find_next((dosdir_t *)sda->foundentry,
+ (find_block_t *)sda->findfirst));
+}
+
+/*
+** 2f:11:21
+**
+** lseek
+*/
+static int
+int2f11_lseek(regcontext_t *REGS)
+{
+ int fd;
+ off_t offset;
+
+ fd = r_sft->fd;
+ offset = (R_CX << 16) + R_DX;
+
+ debug(D_REDIR,"lseek(%d, 0x%qx, SEEK_END)\n", fd, offset);
+
+ if ((offset = lseek(fd, offset, SEEK_END)) < 0) {
+ if (errno == EBADF)
+ return(HANDLE_INVALID);
+ else
+ return(SEEK_ERROR);
+ }
+ r_sft->offset = offset; /* update offset in SFT */
+ R_DX = offset >> 16;
+ R_AX = offset;
+ return(0);
+}
+
+/*
+** 2f:11:23
+**
+** qualify filename
+*/
+static int
+int2f11_fnqual(regcontext_t *REGS)
+{
+ char *fname,*tname;
+ int savedrive;
+ int error;
+
+ return(PATH_NOT_FOUND);
+
+ savedrive = diskdrive; /* to get CWD for network drive */
+ diskdrive = n_drive;
+ fname = (char *)N_GETPTR(R_DS, R_SI); /* path pointers */
+ tname = (char *)N_GETPTR(R_ES, R_DI);
+
+ error = dos_makepath(fname, tname);
+ if (error)
+ tname = "(failed)";
+
+ diskdrive = savedrive; /* restore correct drive */
+
+ debug(D_REDIR, "qualify '%s' -> '%s'\n", fname, tname);
+ return(error);
+}
+
+/*
+** 2f:11:??
+**
+** Null function - we know about it but do nothing
+*/
+static int
+int2f11_NULLFUNC(regcontext_t *REGS)
+{
+ return(0);
+}
+
+/*
+** 2f:11:??
+**
+** no function - not handled here (error)
+*/
+static int
+int2f11_NOFUNC(regcontext_t *REGS)
+{
+ return(-1);
+}
+
+struct intfunc_table int2f11_table[] = {
+ { 0x00, IFT_NOSUBFUNC, int2f11_00, "installation check"},
+ { 0x01, IFT_NOSUBFUNC, int2f11_dirfn, "rmdir"},
+ { 0x02, IFT_NOSUBFUNC, int2f11_dirfn, "rmdir"},
+ { 0x03, IFT_NOSUBFUNC, int2f11_dirfn, "mkdir"},
+ { 0x04, IFT_NOSUBFUNC, int2f11_dirfn, "mkdir"},
+ { 0x05, IFT_NOSUBFUNC, int2f11_dirfn, "chdir"},
+ { 0x06, IFT_NOSUBFUNC, int2f11_close, "close"},
+ { 0x07, IFT_NOSUBFUNC, int2f11_NULLFUNC, "commit file"},
+ { 0x08, IFT_NOSUBFUNC, int2f11_rdwr, "read"},
+ { 0x09, IFT_NOSUBFUNC, int2f11_rdwr, "write"},
+ { 0x0a, IFT_NOSUBFUNC, int2f11_NULLFUNC, "lock region"},
+ { 0x0b, IFT_NOSUBFUNC, int2f11_NULLFUNC, "unlock region"},
+ { 0x0c, IFT_NOSUBFUNC, int2f11_free, "free space"},
+ { 0x0e, IFT_NOSUBFUNC, int2f11_NULLFUNC, "chmod"},
+ { 0x0f, IFT_NOSUBFUNC, int2f11_stat, "stat"},
+ { 0x11, IFT_NOSUBFUNC, int2f11_dirfn, "rename"},
+ { 0x13, IFT_NOSUBFUNC, int2f11_dirfn, "unlink"},
+ { 0x16, IFT_NOSUBFUNC, int2f11_open, "open"},
+ { 0x17, IFT_NOSUBFUNC, int2f11_open, "creat"},
+ { 0x18, IFT_NOSUBFUNC, int2f11_open, "creat"},
+ { 0x19, IFT_NOSUBFUNC, int2f11_findfirst, "find first"},
+ { 0x1b, IFT_NOSUBFUNC, int2f11_findfirst, "find first"},
+ { 0x1c, IFT_NOSUBFUNC, int2f11_findnext, "find next"},
+ { 0x1d, IFT_NOSUBFUNC, int2f11_NULLFUNC, "close all (abort)"},
+ { 0x1e, IFT_NOSUBFUNC, int2f11_NULLFUNC, "do redirection"},
+ { 0x1f, IFT_NOSUBFUNC, int2f11_NULLFUNC, "printer setup"},
+ { 0x20, IFT_NOSUBFUNC, int2f11_NULLFUNC, "flush all buffers"},
+ { 0x21, IFT_NOSUBFUNC, int2f11_lseek, "lseek"},
+ { 0x22, IFT_NOSUBFUNC, int2f11_NULLFUNC, "process terminated"},
+ { 0x23, IFT_NOSUBFUNC, int2f11_fnqual, "qualify filename"},
+ { 0x24, IFT_NOSUBFUNC, int2f11_NOFUNC, "turn off printer"},
+ { 0x25, IFT_NOSUBFUNC, int2f11_NOFUNC, "printer mode"},
+ { 0x2d, IFT_NOSUBFUNC, int2f11_NOFUNC, "extended attributes"},
+ { 0x2e, IFT_NOSUBFUNC, int2f11_open, "extended open/create"},
+ { -1, 0, NULL, NULL}
+};
+
+static int int2f11_fastlookup[256];
+
+/******************************************************************************
+** 2f:11
+**
+** The DOS redirector interface.
+*/
+
+/*
+** Verify that the drive being referenced is one we are handling, and
+** establish some state for upcoming functions.
+**
+** Returns 1 if we should handle this request.
+**
+** XXX this is rather inefficient, but much easier to read than the previous
+** incarnation 8(
+*/
+static int
+int2f11_validate(regcontext_t *REGS)
+{
+ int func = R_AL;
+ char *path = NULL;
+ int doit = 0;
+
+ /* defaults may help trap problems */
+ r_cds = NULL;
+ r_sft = NULL;
+ r_drive = -1;
+
+ /* some functions we accept regardless */
+ switch (func) {
+ case 0x00: /* installation check */
+ case 0x23: /* qualify path */
+ case 0x1c: /* XXX really only valid if a search already started... */
+ return(1);
+ }
+
+ /* Where's the CDS? */
+ switch(func) {
+ case 0x01: /* referenced by the SDA */
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x0e:
+ case 0x0f:
+ case 0x11:
+ case 0x13:
+ case 0x17:
+ case 0x1b:
+ r_cds = (CDS *)MAKEPTR(sda->cds_seg, sda->cds_off);
+ break;
+
+ case 0x0c: /* in es:di */
+ case 0x1c:
+ r_cds = (CDS *)N_GETPTR(R_ES, R_DI);
+ break;
+ }
+
+ /* Where's the SFT? */
+ switch(func) {
+ case 0x06: /* in es:di */
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x21:
+ case 0x2d:
+ case 0x2e:
+ r_sft = (SFT *)N_GETPTR(R_ES, R_DI);
+ break;
+ }
+
+ /* What drive? */
+ switch(func) {
+ case 0x01: /* get drive from fully-qualified path in SDA */
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x0c:
+ case 0x0e:
+ case 0x0f:
+ case 0x11:
+ case 0x13:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1b:
+ case 0x2e:
+ path = sda->filename1;
+ break;
+
+ case 0x06: /* get drive from SFT (we put it here when file was opened) */
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x21:
+ case 0x2d:
+ r_drive = r_sft->info & 0x1f;
+ break;
+ }
+
+ if (path) { /* we have a path and need to determine the drive it refers to */
+
+ if (path[1] != ':') { /* must be fully qualified; we cannot handle this */
+ debug(D_REDIR,"attempt to work non-absolute path %s\n",path);
+ return(0);
+ }
+
+ /* translate letter to drive number */
+ r_drive = toupper(path[0]) - 'A';
+ } else {
+ path = "(no path)";
+ }
+
+ /* do we handle this drive? */
+ if (dos_getcwd(r_drive)) {
+ n_drive = r_drive; /* XXX GROSTIC HACK ALERT */
+ doit = 1;
+ }
+
+ debug(D_REDIR,"%s -> drive %c func %x (%sus)\n",
+ path, 'A'+r_drive, func, doit?"":"not ");
+
+ /* so do we deal with this one? */
+ return(doit);
+}
+
+
+int
+int2f_11(regcontext_t *REGS)
+{
+ int index;
+ int error;
+ char *fname;
+
+
+ if (!sda) { /* not initialised yet */
+ error = FUNC_NUM_IVALID;
+ } else {
+
+ index = intfunc_find(int2f11_table, int2f11_fastlookup, R_AL, 0);
+ if (index == -1) {
+ debug(D_ALWAYS,"no handler for int2f:11:%x\n", R_AL);
+ return(0);
+ }
+ reset_poll();
+
+
+ if (!int2f11_validate(REGS)) { /* determine whether we handle this request */
+ error = -1; /* not handled by us */
+ } else {
+ debug(D_REDIR, "REDIR: %02x (%s)\n",
+ int2f11_table[index].func, int2f11_table[index].desc);
+ /* call the handler */
+ error = int2f11_table[index].handler(REGS);
+ if (error != -1)
+ debug(D_REDIR, "REDIR: returns %d (%s)\n",
+ error, ((error >= 0) && (error <= dos_ret_size)) ? dos_return[error] : "unknown");
+ }
+ }
+
+ if (error == -1)
+ return (0);
+ if (error) {
+ R_AX = error;
+ R_FLAGS |= PSL_C;
+ } else
+ R_FLAGS &= ~PSL_C;
+ return (1);
+}
+
+/******************************************************************************
+** intff handler.
+**
+** intff is the (secret, proprietary, internal, evil) call to
+** initialise the redirector.
+*/
+static void
+install_drive(int drive, u_char *path)
+{
+ CDS *cds;
+
+ /* check that DOS considers this a valid drive */
+ if (drive < 0 || drive >= lol->lastdrive) {
+ debug(D_REDIR, "Drive %c beyond limit of %c)\n",
+ drive + 'A', lol->lastdrive - 1 + 'A');
+ return;
+ }
+
+ /* get the CDS for this drive */
+ cds = (CDS *)MAKEPTR(lol->cds_seg, lol->cds_offset);
+ cds += drive;
+
+#if 0 /* XXX looks OK to me - mjs */
+ if (cds->flag & (CDS_remote | CDS_ready)) {
+ debug(D_REDIR, "Drive %c already installed\n", drive + 'A');
+ return;
+ }
+#endif
+
+ debug(D_REDIR, "Installing %c: as %s\n", drive + 'A', path);
+
+ cds->flag |= CDS_remote | CDS_ready | CDS_notnet;
+ cds->path[0] = drive + 'A';
+ cds->path[1] = ':';
+ cds->path[2] = '\\';
+ cds->path[3] = '\0';
+ cds->offset = 2; /* offset of \ in current path field */
+}
+
+static void
+init_drives(void)
+{
+ int drive;
+ u_char *path;
+
+ /* for all possible drives */
+ for (drive = 0; drive < 26; ++drive) {
+ if (path = dos_getpath(drive)) /* assigned to a path? */
+ install_drive(drive, path); /* make it visible to DOS */
+ }
+}
+
+void
+intff(regcontext_t *REGS)
+{
+
+ if (lol && sda) { /* already been called? */
+ debug(D_REDIR, "redirector duplicate install ignored\n");
+ return;
+ }
+ lol = (LOL *)N_GETPTR(R_ES, R_DI); /* where DOS keeps its goodies */
+ sda = (SDA *)N_GETPTR(R_DS, R_SI);
+
+ init_drives();
+
+ /* initialise dispatcher */
+ intfunc_init(int2f11_table, int2f11_fastlookup);
+}
OpenPOWER on IntegriCloud