diff -ur -x'*.d' -x'*.o' 1157pr/src/dosext/mfs/lfn.h 1157/src/dosext/mfs/lfn.h --- 1157pr/src/dosext/mfs/lfn.h 1970-01-01 10:00:00.000000000 +1000 +++ 1157/src/dosext/mfs/lfn.h 2003-09-14 15:26:56.000000000 +1000 @@ -0,0 +1,10 @@ +/* + * All modifications in this file to the original code are + * (C) Copyright 1992, ..., 2003 the "DOSEMU-Development-Team". + * + * for details see file COPYING in the DOSEMU distribution + */ + +void make_unmake_dos_mangled_path(char *dest, char *fpath, + int current_drive, int alias); + diff -ur -x'*.d' -x'*.o' 1157pr/src/dosext/mfs/lfn.c 1157/src/dosext/mfs/lfn.c --- 1157pr/src/dosext/mfs/lfn.c 2003-09-14 12:44:30.000000000 +1000 +++ 1157/src/dosext/mfs/lfn.c 2003-09-19 18:29:14.000000000 +1000 @@ -24,6 +24,7 @@ #include "mfs.h" #include "mangle.h" #include "bios.h" +#include "lfn.h" #define EOS '\0' #define BACKSLASH '\\' @@ -78,7 +79,7 @@ alias=1: mangle, alias=0: don't mangle output: dest = DOS path */ -static void make_unmake_dos_mangled_path(char *dest, char *fpath, +void make_unmake_dos_mangled_path(char *dest, char *fpath, int current_drive, int alias) { char *src; diff -ur -x'*.d' -x'*.o' 1157pr/src/dosext/mfs/mfs.c 1157/src/dosext/mfs/mfs.c --- 1157pr/src/dosext/mfs/mfs.c 2003-09-14 12:44:30.000000000 +1000 +++ 1157/src/dosext/mfs/mfs.c 2003-09-14 17:04:07.000000000 +1000 @@ -264,18 +264,6 @@ #define SFT_FDEVICE 0x0080 #define SFT_FEOF 0x0040 -/* #define MAX_PATH_LENGTH 57 */ -/* 2001/01/05 Manfred Scherer - * With the value 57 I can create pathlength until 54. - * In native DOS I can create pathlength until 63. - * With the value 66 it should be possible to create - * paths with length 63. - * I've tested it on my own system, and I found the value 66 - * is right for me. - */ - -#define MAX_PATH_LENGTH 66 - struct file_fd { char *name; @@ -2417,12 +2405,12 @@ int GetRedirectionRoot(int dsk, char **resourceName,int *ro_flag) { - if (!drives[dsk].root) return (TRUE); + if (!drives[dsk].root) return 1; *resourceName = malloc(MAXPATHLEN + 1); - if (*resourceName == NULL) return (TRUE); + if (*resourceName == NULL) return 1; strcpy(*resourceName, drives[dsk].root ); *ro_flag=drives[dsk].read_only; - return (FALSE); + return 0; } diff -ur -x'*.d' -x'*.o' 1157pr/src/dosext/mfs/mfs.h 1157/src/dosext/mfs/mfs.h --- 1157pr/src/dosext/mfs/mfs.h 2003-09-14 12:44:30.000000000 +1000 +++ 1157/src/dosext/mfs/mfs.h 2003-09-14 17:06:49.000000000 +1000 @@ -14,7 +14,6 @@ #include #include -#ifdef DOSEMU /* definitions to make mach emu code compatible with dosemu */ #include "emu.h" @@ -67,7 +66,6 @@ #define SETHIGH(x,y) (*(x) = (*(x) & ~0xff00) | ((MASK8(y))<<8)) #define SETLOW(x,y) (*(x) = (*(x) & ~0xff) | (MASK8(y))) #define SETWORD(x,y) (*(x) = (*(x) & ~0xffff) | (MASK16(y))) -#endif /* * Copyright (c) 1991 Carnegie Mellon University @@ -471,6 +469,20 @@ #define CANCEL_REDIRECTION 4 #define EXTENDED_GET_REDIRECTION 5 + +/* #define MAX_PATH_LENGTH 57 */ +/* 2001/01/05 Manfred Scherer + * With the value 57 I can create pathlength until 54. + * In native DOS I can create pathlength until 63. + * With the value 66 it should be possible to create + * paths with length 63. + * I've tested it on my own system, and I found the value 66 + * is right for me. + */ + +#define MAX_PATH_LENGTH 66 + + extern int build_ufs_path_(char *ufs, const char *path, int drive, int lowercase); extern boolean_t find_file(char *fpath, struct stat *st, int drive); diff -ur -x'*.d' -x'*.o' 1157pr/src/plugin/commands/builtins.c 1157/src/plugin/commands/builtins.c --- 1157pr/src/plugin/commands/builtins.c 2003-09-14 12:44:22.000000000 +1000 +++ 1157/src/plugin/commands/builtins.c 2003-09-14 16:06:13.000000000 +1000 @@ -377,6 +377,37 @@ return(argcx); } +int com_dosgetdrive(void) +{ + HI(ax) = 0x19; + call_msdos(); /* call MSDOS */ + return LO(ax); /* 0=A, 1=B, ... */ +} + +int com_dossetdrive(int drive) +{ + HI(ax) = 0x0e; + LO(dx) = drive; /* 0=A, 1=B, ... */ + call_msdos(); /* call MSDOS */ + return LO(ax); /* number of available logical drives */ +} + +int com_dossetcurrentdir(char *path) +{ + /*struct com_starter_seg *ctcb = owntcb->params;*/ + char *s = com_strdup(path); + + com_errno = 8; + if (!s) return -1; + HI(ax) = 0x3b; + LWORD(ds) = FP_SEG32 (s) /*COM_SEG*/; + LWORD(edx) = FP_OFF32 (s) /*COM_OFFS_OF(s)*/; + call_msdos(); /* call MSDOS */ + com_strfree(s); + if (LWORD(eflags) & CF) return -1; + return 0; +} + struct REGPACK regs_to_regpack(struct vm86_regs *regs) { struct REGPACK regpack; diff -ur -x'*.d' -x'*.o' 1157pr/src/plugin/commands/builtins.h 1157/src/plugin/commands/builtins.h --- 1157pr/src/plugin/commands/builtins.h 2003-09-14 12:44:22.000000000 +1000 +++ 1157/src/plugin/commands/builtins.h 2003-09-14 15:47:59.000000000 +1000 @@ -63,6 +63,9 @@ char * com_strdup(char *s); unsigned short get_dos_ver(void); void com_strfree(char *s); +int com_dosgetdrive(void); +int com_dossetdrive(int drive); +int com_dossetcurrentdir(char *path); void com_intr(int intno, struct REGPACK *regpack); int com_int86x(int intno, union com_REGS *inregs, union com_REGS *outregs, struct SREGS *segregs); diff -ur -x'*.d' -x'*.o' 1157pr/src/plugin/commands/unix.c 1157/src/plugin/commands/unix.c --- 1157pr/src/plugin/commands/unix.c 2003-09-14 12:44:22.000000000 +1000 +++ 1157/src/plugin/commands/unix.c 2003-09-19 19:22:39.000000000 +1000 @@ -13,6 +13,7 @@ ************************************************/ +#include #include #include #include @@ -22,6 +23,9 @@ #include "memory.h" #include "doshelpers.h" #include "builtins.h" +#include "redirect.h" +#include "../../dosext/mfs/lfn.h" +#include "../../dosext/mfs/mfs.h" #include "msetenv.h" #include "unix.h" @@ -41,7 +45,7 @@ static int usage (void); static int send_command (char **argv); #if CAN_EXECUTE_DOS -static int do_execute_dos (int argc, char **argv); +static int do_execute_dos (int argc, char **argv, int isLiteralCommand); #endif static int do_set_dosenv (int agrc, char **argv); @@ -61,7 +65,11 @@ case 'e': case 'E': /* EXECUTE dos command*/ - return do_execute_dos (argc-2, argv+2); + return do_execute_dos (argc-2, argv+2, 1/*literal DOS cmd*/); + case 'c': + case 'C': + /* EXECUTE dos program*/ + return do_execute_dos (argc-2, argv+2, 0/*not literal DOS cmd - is Linux path*/); #endif case 's': case 'S': @@ -83,8 +91,11 @@ printf ("Run Linux commands from DOSEMU\n\n"); #if CAN_EXECUTE_DOS printf ("UNIX -e [ENVVAR]\n"); - printf (" Execute the DOS command given in the Linux environment variable \"ENVVAR\"\n"); - printf (" and then exit DOSEMU.\n"); + printf (" Execute the DOS command given in the Linux environment variable \"ENVVAR\".\n"); + printf (" If not given, use the argument to the -E flag of DOSEMU\n\n"); + printf ("UNIX -c [ENVVAR]\n"); + printf (" Execute the DOS program whose Linux path is given in the Linux environment\n"); + printf (" variable \"ENVVAR\".\n"); printf (" If not given, use the argument to the -E flag of DOSEMU\n\n"); #endif printf ("UNIX -s ENVVAR\n"); @@ -92,7 +103,7 @@ printf ("UNIX command [arg1 ...]\n"); printf (" Execute the Linux command with the arguments given.\n\n"); printf ("UNIX\n"); - printf (" show this help screen\n\n\n"); + printf (" show this help screen\n\n"); printf ("Note: Use UNIX only to run Linux commands that terminates without user\n"); printf (" interaction. Otherwise it will start and wait forever!\n"); @@ -126,7 +137,169 @@ } #if CAN_EXECUTE_DOS -static int do_execute_dos (int argc, char **argv) + +static char *makeEndInBackslash (char *s) +{ + int len = strlen (s); + if (len && s [len - 1] != '/') + strcpy (s + len, "/"); + return s; +} + +/* + * Return the drive from which is accessible. + * If there is no such redirection, it returns the next available drive * -1. + * If there are no available drives (from >= 2 aka "C:"), it returns -26. + * If an error occurs, it returns -27. + * + * In addition, if a drive is available, is modified + * to have the drive's uncannonicalized linux root as its prefix. This is + * necessary as make_unmake_dos_mangled_path() will not work with a resolved + * path if the drive was LREDIR'ed by the user to a unresolved path. + */ +static int findDrive (char *linux_path_resolved) +{ + int freeDrive = -26; + + j_printf ("findDrive (linux_path='%s')\n", linux_path_resolved); + + int drive; + for (drive = 0; drive < 26; drive++) { + char *drive_linux_root = NULL; + int drive_ro; + char drive_linux_root_resolved [PATH_MAX]; + + if (GetRedirectionRoot (drive, &drive_linux_root, &drive_ro) == 0/*success*/) { + if (!realpath (drive_linux_root, drive_linux_root_resolved)) { + fprintf (stderr, "ERROR: Cannot canonicalize drive root path (%s)\n", strerror (errno)); + return -27; + } + + /* make sure drive root ends in / */ + makeEndInBackslash (drive_linux_root_resolved); + + j_printf ("CMP: drive=%i drive_linux_root='%s' (resolved='%s')\n", + drive, drive_linux_root, drive_linux_root_resolved); + + /* TODO: handle case insensitive filesystems (e.g. VFAT) + * - can we just strlwr() both paths before comparing them? */ + if (strstr (linux_path_resolved, drive_linux_root_resolved) == linux_path_resolved) { + char old_linux_path_resolved [PATH_MAX]; + + j_printf ("\tFound drive!\n"); + strcpy (old_linux_path_resolved, linux_path_resolved); + snprintf (linux_path_resolved, PATH_MAX, "%s%s", + drive_linux_root/*unresolved*/, + old_linux_path_resolved + strlen (drive_linux_root_resolved)); + j_printf ("\t\tModified root; linux path='%s'\n", linux_path_resolved); + + free (drive_linux_root); + return drive; + } + + free (drive_linux_root); + } else { + if (drive >= 2 && freeDrive == -26) { + freeDrive = -drive; + } + } + } + + j_printf ("findDrive() returning free drive: %i\n", -freeDrive); + return freeDrive; +} + +/* + * Given a , change to its corresponding drive and directory + * in DOS (redirecting a new drive if neccessary). The DOS command is + * returned through . + * + * Returns 0 on success, nonzero on failure. + */ +static int setupDOSCommand (char *linux_path) +{ + char linux_path_resolved[PATH_MAX]; + char dos_path [MAX_PATH_LENGTH]; + int drive; + + char *b; + + + if (!realpath (linux_path, linux_path_resolved)) { + fprintf (stderr, "ERROR: Cannot canonicalize path (%s)\n", strerror (errno)); + return (1); + } + + + drive = findDrive (linux_path_resolved); + if (drive < 0) { + drive = -drive; + + if (drive >= 26) { + if (drive == 26) { + fprintf (stderr, "ERROR: Cannot find a free DOS drive to use for LREDIR\n"); + } + + return (1); + } + + /* try mounting / on this DOS drive + (this won't work nice with "long" Linux paths > approx. 66 + but at least programs that try to access ..\DATA\BLAH.DAT + will work) + */ + + j_printf ("Redirecting %c: to /\n", drive + 'A'); + if (RedirectDisk (drive, LINUX_RESOURCE "/", 0/*rw*/) != 0/*success*/) { + fprintf (stderr, "ERROR: Could not redirect %c: to /\n", drive + 'A'); + return (1); + } + } + + + /* switch to the drive */ + j_printf ("Switching to drive %i (%c:)\n", drive, drive + 'A'); + com_dossetdrive (drive); + if (com_dosgetdrive () != drive) { + fprintf (stderr, "ERROR: Could not change to %c:\n", drive + 'A'); + + if (com_dossetdrive (com_dosgetdrive ()) < 26) + fprintf (stderr, "Try 'LASTDRIVE=Z' in CONFIG.SYS.\n"); + + return (1); + } + + + make_unmake_dos_mangled_path (dos_path, linux_path_resolved, + drive, 1/*alias*/); + j_printf ("DOS path: '%s' (from linux '%s')\n", + dos_path, linux_path_resolved); + + + /* switch to the directory */ + if (strlen (dos_path) >= 3 && (b = strrchr (dos_path, '\\')) != NULL) { + char *dos_dir = dos_path + 2; + *b++ = 0; + + j_printf ("Changing to directory '%s'\n", dos_dir); + if (com_dossetcurrentdir (dos_dir)) { + fprintf (stderr, "ERROR: Could not change to directory: %s\n", dos_dir); + return (1); + } + } else { + fprintf (stderr, "INTERNAL ERROR: no backslash in DOS path\n"); + return (1); + } + + + /* return the 8.3 EXE name */ + strcpy (linux_path/*arg as return value*/, b); + + + return (0); +} + +static int do_execute_dos (int argc, char **argv, int isLiteralCommand) { char *data = lowmem_alloc(256); struct REGPACK preg = REGPACK_INIT; @@ -148,16 +321,23 @@ if (! preg.r_ax) { /* SUCCESSFUL */ - printf ("About to Execute : %s\n", data); - - - if (system (data)) { - /* SYSTEM failed ... */ - fprintf (stderr, "SYSTEM failed ....(%d)\n", errno); - return (1); - } + if (!isLiteralCommand && setupDOSCommand (data)) + return (1); + + if (*data) { + printf ("About to Execute : %s\n", data); + + if (system (data)) { + /* SYSTEM failed ... */ + fprintf (stderr, "SYSTEM failed ....(%d)\n", errno); + return (1); + } - return (0); + return (0); + } else { + /* empty string */ + return (1); + } } else { /* UNSUCCESSFUL */ diff -ur -x'*.d' -x'*.o' 1157pr/src/plugin/coopthreads/coopthreads.c 1157/src/plugin/coopthreads/coopthreads.c --- 1157pr/src/plugin/coopthreads/coopthreads.c 2003-09-14 12:44:22.000000000 +1000 +++ 1157/src/plugin/coopthreads/coopthreads.c 2003-09-14 16:02:42.000000000 +1000 @@ -994,21 +994,6 @@ return 0; } -int com_dosgetdrive(void) -{ - HI(ax) = 0x19; - call_msdos(); /* call MSDOS */ - return LO(ax); /* 0=A, 1=B, ... */ -} - -int com_dossetdrive(int drive) -{ - HI(ax) = 0x0e; - LO(dx) = drive; /* 0=A, 1=B, ... */ - call_msdos(); /* call MSDOS */ - return LO(ax); /* number of available logical drives */ -} - int com_dosgetcurrentdir(int drive, char *buf) { struct com_starter_seg *ctcb = owntcb->params; @@ -1031,22 +1016,6 @@ return 0; } -int com_dossetcurrentdir(char *path) -{ - struct com_starter_seg *ctcb = owntcb->params; - char *s = com_strdup(path); - - com_errno = 8; - if (!s) return -1; - HI(ax) = 0x3b; - LWORD(ds) = COM_SEG; - LWORD(edx) = COM_OFFS_OF(s); - call_msdos(); /* call MSDOS */ - com_strfree(s); - if (LWORD(eflags) & CF) return -1; - return 0; -} - int com_dosgetsetfilestamp(int fd, int ftime) { if (ftime) {