"Fossies" - the Fresh Open Source Software Archive

Member "dosemu-1.4.0/src/plugin/commands/lredir.c" (4 May 2007, 17209 Bytes) of package /linux/misc/old/dosemu-1.4.0.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "lredir.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Written: 10/29/93 by Tim Bird (original code)
    3  * All modifications in this file to the original code are
    4  * (C) Copyright 1992, ..., 2007 the "DOSEMU-Development-Team".
    5  *
    6  * for details see file COPYING.DOSEMU in the DOSEMU distribution
    7  */
    8 
    9 /***********************************************
   10  * File: LREDIR.C
   11  *  Program for Linux DOSEMU disk redirector functions
   12  * Fixes: 1/7/95 by Tim Josling TEJ: check correct # args
   13  *      :                            display read/write status correctly
   14  * Changes: 3/19/95 by Kang-Jin Lee
   15  *  Removed unused variables
   16  *  Changes to eliminate warnings
   17  *  Display read/write status when redirecting drive
   18  *  Usage information is more verbose
   19  *
   20  * Changes: 11/27/97 Hans Lermen
   21  *  new detection stuff,
   22  *  rewrote to use plain C and intr(), instead of asm and fiddling with
   23  *  (maybe used) machine registers.
   24  *
   25  * Changes: 990703 Hans Lermen
   26  *  Checking for DosC and exiting with error, if not redirector capable.
   27  *  Printing DOS errors in clear text.
   28  *
   29  * Changes: 010211 Bart Oldeman
   30  *   Make it possible to "reredirect": LREDIR drive filepath
   31  *   can overwrite the direction for the drive.
   32  *
   33  * Changes: 20010402 Hans Lermen
   34  *   Ported to buildin_apps, compiled directly into dosemu
   35  *
   36  *
   37  * NOTES:
   38  *  LREDIR supports the following commands:
   39  *  LREDIR drive filepath
   40  *    redirects the indicated drive to the specified linux filepath
   41  *    drive = the drive letter followed by a colon (ex. 'E:')
   42  *    filepath has linux, fs and a file path (ex. 'LINUX\FS\USR\SRC')
   43  *  LREDIR DEL drive
   44  *    cancels redirection of the indicated drive
   45  *  LREDIR
   46  *    shows drives that are currently redirected (mapped)
   47  *  LREDIR HELP or LREDIR ?
   48  *    show usage information for LREDIR
   49  ***********************************************/
   50 
   51 
   52 #include <ctype.h>    /* toupper */
   53 #include <stdio.h>    /* printf  */
   54 #include <stdlib.h>
   55 #include <string.h>
   56 
   57 #include "config.h"
   58 #include "emu.h"
   59 #include "memory.h"
   60 #include "msetenv.h"
   61 #include "doshelpers.h"
   62 #include "utilities.h"
   63 #include "lredir.h"
   64 #include "builtins.h"
   65 #include "disks.h"
   66 
   67 #define printf  com_printf
   68 #define intr    com_intr
   69 #define strncmpi strncasecmp
   70 #define FP_OFF(x) FP_OFF32(x)
   71 #define FP_SEG(x) FP_SEG32(x)
   72 
   73 typedef unsigned char uint8;
   74 typedef unsigned int uint16;
   75 
   76 #define CARRY_FLAG    1 /* carry bit in flags register */
   77 #define CC_SUCCESS    0
   78 
   79 #define DOS_GET_LIST_OF_LISTS  0x5200
   80 #define DOS_GET_SDA_POINTER    0x5D06
   81 #define DOS_GET_REDIRECTION    0x5F02
   82 #define DOS_REDIRECT_DEVICE    0x5F03
   83 #define DOS_CANCEL_REDIRECTION 0x5F04
   84 
   85 #define MAX_RESOURCE_STRING_LENGTH  36  /* 16 + 16 + 3 for slashes + 1 for NULL */
   86 #define MAX_RESOURCE_PATH_LENGTH   128  /* added to support Linux paths */
   87 #define MAX_DEVICE_STRING_LENGTH     5  /* enough for printer strings */
   88 
   89 #define REDIR_PRINTER_TYPE    3
   90 #define REDIR_DISK_TYPE       4
   91 
   92 #define READ_ONLY_DRIVE_ATTRIBUTE 1  /* same as NetWare Lite */
   93 
   94 #define KEYWORD_DEL   "DELETE"
   95 #define KEYWORD_DEL_COMPARE_LENGTH  3
   96 
   97 #define KEYWORD_HELP   "HELP"
   98 #define KEYWORD_HELP_COMPARE_LENGTH  4
   99 
  100 #define DEFAULT_REDIR_PARAM   0
  101 
  102 #include "doserror.h"
  103 
  104 static FAR_PTR /* char far * */
  105 GetListOfLists(void)
  106 {
  107     FAR_PTR LOL;
  108     struct REGPACK preg = REGPACK_INIT;
  109 
  110     preg.r_ax = DOS_GET_LIST_OF_LISTS;
  111     intr(0x21, &preg);
  112     LOL = MK_FP(preg.r_es, preg.r_bx);
  113     return (LOL);
  114 }
  115 
  116 static FAR_PTR /* char far * */
  117 GetSDAPointer(void)
  118 {
  119     FAR_PTR SDA;
  120     struct REGPACK preg = REGPACK_INIT;
  121 
  122     preg.r_ax = DOS_GET_SDA_POINTER;
  123     intr(0x21, &preg);
  124     SDA = MK_FP(preg.r_ds, preg.r_si);
  125 
  126     return (SDA);
  127 }
  128 
  129 /********************************************
  130  * InitMFS - call Emulator to initialize MFS
  131  ********************************************/
  132 /* tej - changed return type to void as nothing returned */
  133 static void InitMFS(void)
  134 {
  135     FAR_PTR LOL;
  136     FAR_PTR SDA;
  137     unsigned char _osmajor;
  138     unsigned char _osminor;
  139     state_t preg;
  140 
  141     LOL = GetListOfLists();
  142     SDA = GetSDAPointer();
  143 
  144     /* now get the DOS version */
  145     HI(ax) = 0x30;
  146     call_msdos();
  147     _osmajor = LO(ax);
  148     _osminor = HI(ax);
  149 
  150     /* get DOS version into CX */
  151     preg.ecx = _osmajor | (_osminor <<8);
  152 
  153     preg.edx = FP_OFF16(LOL);
  154     preg.es = FP_SEG16(LOL);
  155     preg.esi = FP_OFF16(SDA);
  156     preg.ds = FP_SEG16(SDA);
  157     preg.ebx = 0x500;
  158     mfs_helper(&preg);
  159 }
  160 
  161 /********************************************
  162  * RedirectDevice - redirect a device to a remote resource
  163  * ON ENTRY:
  164  *  deviceStr has a string with the device name:
  165  *    either disk or printer (ex. 'D:' or 'LPT1')
  166  *  resourceStr has a string with the server and name of resource
  167  *    (ex. 'TIM\TOOLS')
  168  *  deviceType indicates the type of device being redirected
  169  *    3 = printer, 4 = disk
  170  *  deviceParameter is a value to be saved with this redirection
  171  *  which will be returned on GetRedirectionList
  172  * ON EXIT:
  173  *  returns CC_SUCCESS if the operation was successful,
  174  *  otherwise returns the DOS error code
  175  * NOTES:
  176  *  deviceParameter is used in DOSEMU to return the drive attribute
  177  *  It is not actually saved and returned as specified by the redirector
  178  *  specification.  This type of usage is common among commercial redirectors.
  179  ********************************************/
  180 static uint16 RedirectDevice(char *deviceStr, char *resourceStr, uint8 deviceType,
  181                       uint16 deviceParameter)
  182 {
  183     char slashedResourceStr[MAX_RESOURCE_PATH_LENGTH];
  184     struct REGPACK preg = REGPACK_INIT;
  185     char *dStr, *sStr;
  186 
  187     /* prepend the resource string with slashes */
  188     strcpy(slashedResourceStr, "\\\\");
  189     strcat(slashedResourceStr, resourceStr);
  190 
  191     /* should verify strings before sending them down ??? */
  192     dStr = com_strdup(deviceStr);
  193     preg.r_ds = FP_SEG(dStr);
  194     preg.r_si = FP_OFF(dStr);
  195     sStr = com_strdup(slashedResourceStr);
  196     preg.r_es = FP_SEG(sStr);
  197     preg.r_di = FP_OFF(sStr);
  198     preg.r_cx = deviceParameter;
  199     preg.r_bx = deviceType;
  200     preg.r_ax = DOS_REDIRECT_DEVICE;
  201     intr(0x21, &preg);
  202     com_strfree(dStr);
  203     com_strfree(sStr);
  204 
  205     if (preg.r_flags & CARRY_FLAG) {
  206       return (preg.r_ax);
  207     }
  208     else {
  209       return (CC_SUCCESS);
  210     }
  211 }
  212 
  213 /********************************************
  214  * GetRedirection - get next entry from list of redirected devices
  215  * ON ENTRY:
  216  *  redirIndex has the index of the next device to return
  217  *    this should start at 0, and be incremented between calls
  218  *    to retrieve all elements of the redirection list
  219  * ON EXIT:
  220  *  returns CC_SUCCESS if the operation was successful, and
  221  *  deviceStr has a string with the device name:
  222  *    either disk or printer (ex. 'D:' or 'LPT1')
  223  *  resourceStr has a string with the server and name of resource
  224  *    (ex. 'TIM\TOOLS')
  225  *  deviceType indicates the type of device which was redirected
  226  *    3 = printer, 4 = disk
  227  *  deviceParameter has my rights to this resource
  228  * NOTES:
  229  *
  230  ********************************************/
  231 static uint16 GetRedirection(uint16 redirIndex, char *deviceStr, char *resourceStr,
  232                       uint8 * deviceType, uint16 * deviceParameter)
  233 {
  234     uint16 ccode;
  235     uint8 deviceTypeTemp;
  236     char slashedResourceStr[MAX_RESOURCE_PATH_LENGTH];
  237     struct REGPACK preg = REGPACK_INIT;
  238     char *dStr, *sStr;
  239 
  240     dStr = lowmem_alloc(16);
  241     preg.r_ds = FP_SEG(dStr);
  242     preg.r_si = FP_OFF(dStr);
  243     sStr = lowmem_alloc(128);
  244     preg.r_es = FP_SEG(sStr);
  245     preg.r_di = FP_OFF(sStr);
  246     preg.r_bx = redirIndex;
  247     preg.r_ax = DOS_GET_REDIRECTION;
  248     intr(0x21, &preg);
  249     strcpy(deviceStr,dStr);
  250     lowmem_free(dStr, 16);
  251     strcpy(slashedResourceStr,sStr);
  252     lowmem_free(sStr, 128);
  253 
  254     ccode = preg.r_ax;
  255     deviceTypeTemp = preg.r_bx & 0xff;       /* save device type before C ruins it */
  256     *deviceType = deviceTypeTemp;
  257     *deviceParameter = preg.r_cx;
  258 
  259     /* copy back unslashed portion of resource string */
  260     if (preg.r_flags & CARRY_FLAG) {
  261       return (ccode);
  262     }
  263     else {
  264       /* eat the leading slashes */
  265       strcpy(resourceStr, slashedResourceStr + 2);
  266       return (CC_SUCCESS);
  267     }
  268 }
  269 
  270 /********************************************
  271  * CancelRedirection - delete a device mapped to a remote resource
  272  * ON ENTRY:
  273  *  deviceStr has a string with the device name:
  274  *    either disk or printer (ex. 'D:' or 'LPT1')
  275  * ON EXIT:
  276  *  returns CC_SUCCESS if the operation was successful,
  277  *  otherwise returns the DOS error code
  278  * NOTES:
  279  *
  280  ********************************************/
  281 static uint16 CancelRedirection(char *deviceStr)
  282 {
  283     struct REGPACK preg = REGPACK_INIT;
  284     char *dStr;
  285 
  286     dStr = com_strdup(deviceStr);
  287     preg.r_ds = FP_SEG(dStr);
  288     preg.r_si = FP_OFF(dStr);
  289     preg.r_ax = DOS_CANCEL_REDIRECTION;
  290     intr(0x21, &preg);
  291     com_strfree(dStr);
  292 
  293     if (preg.r_flags & CARRY_FLAG) {
  294       return (preg.r_ax);
  295     }
  296     else {
  297       return (CC_SUCCESS);
  298     }
  299 }
  300 
  301 /*************************************
  302  * ShowMyRedirections
  303  *  show my current drive redirections
  304  * NOTES:
  305  *  I show the read-only attribute for each drive
  306  *    which is returned in deviceParam.
  307  *************************************/
  308 static void
  309 ShowMyRedirections(void)
  310 {
  311     int driveCount;
  312     uint16 redirIndex, deviceParam, ccode;
  313     uint8 deviceType;
  314 
  315     char deviceStr[MAX_DEVICE_STRING_LENGTH];
  316     char resourceStr[MAX_RESOURCE_PATH_LENGTH];
  317 
  318     redirIndex = 0;
  319     driveCount = 0;
  320 
  321     while ((ccode = GetRedirection(redirIndex, deviceStr, resourceStr,
  322                            &deviceType, &deviceParam)) == CC_SUCCESS) {
  323       /* only print disk redirections here */
  324       if (deviceType == REDIR_DISK_TYPE) {
  325         if (driveCount == 0) {
  326           printf("Current Drive Redirections:\n");
  327         }
  328         driveCount++;
  329         printf("%-2s = %-20s ", deviceStr, resourceStr);
  330 
  331         /* read attribute is returned in the device parameter */
  332         if (deviceParam & 0x80) {
  333       if ((deviceParam & 0x7f) > 1)
  334         printf("CDROM:%d ", (deviceParam & 0x7f) - 1);
  335           switch ((deviceParam & 0x7f) != 0) {
  336             case READ_ONLY_DRIVE_ATTRIBUTE:
  337               printf("attrib = READ ONLY\n");
  338               break;
  339             default:
  340               printf("attrib = READ/WRITE\n");
  341               break;
  342           }
  343         }
  344       }
  345 
  346       redirIndex++;
  347     }
  348 
  349     if (driveCount == 0) {
  350       printf("No drives are currently redirected to Linux.\n");
  351     }
  352 }
  353 
  354 static void
  355 DeleteDriveRedirection(char *deviceStr)
  356 {
  357     uint16 ccode;
  358 
  359     /* convert device string to upper case */
  360     strupr(deviceStr);
  361     ccode = CancelRedirection(deviceStr);
  362     if (ccode) {
  363       printf("Error %x (%s)\ncanceling redirection on drive %s\n",
  364              ccode, decode_DOS_error(ccode), deviceStr);
  365       }
  366     else {
  367       printf("Redirection for drive %s was deleted.\n", deviceStr);
  368     }
  369 }
  370 
  371 static int FindRedirectionByDevice(char *deviceStr, char *resourceStr)
  372 {
  373     uint16 redirIndex = 0, deviceParam, ccode;
  374     uint8 deviceType;
  375     char dStr[MAX_DEVICE_STRING_LENGTH];
  376     char dStrSrc[MAX_DEVICE_STRING_LENGTH];
  377 
  378     snprintf(dStrSrc, MAX_DEVICE_STRING_LENGTH, "%s", deviceStr);
  379     strupr(dStrSrc);
  380     while ((ccode = GetRedirection(redirIndex, dStr, resourceStr,
  381                            &deviceType, &deviceParam)) == CC_SUCCESS) {
  382       if (strcmp(dStrSrc, dStr) == 0)
  383         break;
  384       redirIndex++;
  385     }
  386 
  387     return ccode;
  388 }
  389 
  390 static int FindFATRedirectionByDevice(char *deviceStr, char *resourceStr)
  391 {
  392     struct DINFO *di;
  393     char *dir;
  394     fatfs_t *f;
  395     unsigned long serial;
  396     if (!(di = (struct DINFO *)lowmem_alloc(sizeof(struct DINFO))))
  397     return 0;
  398     LWORD(eax) = 0x6900;
  399     LWORD(ebx) = toupper(deviceStr[0]) - 'A' + 1;
  400     REG(ds) = FP_SEG32(di);
  401     LWORD(edx) = FP_OFF32(di);
  402     call_msdos();
  403     if (REG(eflags) & CF) {
  404     lowmem_free((void *)di, sizeof(struct DINFO));
  405     printf("error retrieving serial, %#x\n", LWORD(eax));
  406     return -1;
  407     }
  408     serial = READ_DWORD(&di->serial);
  409     lowmem_free((void *)di, sizeof(struct DINFO));
  410     f = get_fat_fs_by_serial(serial);
  411     if (!f || !(dir = f->dir)) {
  412     printf("error identifying FAT volume\n");
  413     return -1;
  414     }
  415     strcpy(resourceStr, "LINUX\\FS");
  416     strcat(resourceStr, dir);
  417     return CC_SUCCESS;
  418 }
  419 
  420 /********************************************
  421  * Check wether we are running DosC (FreeDos)
  422  * and check wether this version can cope with redirection
  423  * ON ENTRY:
  424  *  nothing
  425  * ON EXIT:
  426  *  returns 0 if not running DosC
  427  *  otherwise returns the DosC 'build' number
  428  *
  429  ********************************************/
  430 /* no longer used -- Bart */
  431 #if 0
  432 static uint16 CheckForDosc(void)
  433 {
  434     struct REGPACK preg = REGPACK_INIT;
  435 
  436     preg.r_ax = 0xdddc;
  437     dos_helper_r(&preg);
  438 
  439     if (preg.r_ax == 0xdddc) {
  440       return 0;
  441     }
  442     else {
  443       return (preg.r_bx);
  444     }
  445 }
  446 #endif
  447 
  448 int lredir_main(int argc, char **argv)
  449 {
  450     uint16 ccode;
  451     uint16 deviceParam;
  452     int carg;
  453 #if 0
  454     unsigned long dversion;
  455 #endif
  456 
  457     char deviceStr[MAX_DEVICE_STRING_LENGTH];
  458     char resourceStr[MAX_RESOURCE_PATH_LENGTH];
  459 
  460 
  461     /* initialize the MFS, just in case the user didn't run EMUFS.SYS */
  462     InitMFS();
  463 
  464     /* need to parse the command line */
  465     /* if no parameters, then just show current mappings */
  466     if (argc == 1) {
  467       ShowMyRedirections();
  468       return(0);
  469     }
  470 
  471     /* tej one parm is either error or HELP/-help etc */
  472     if (argc == 2 && strncmpi(argv[1], KEYWORD_HELP, KEYWORD_HELP_COMPARE_LENGTH) == 0) {
  473       printf("Usage: LREDIR [[drive:] LINUX\\FS\\path [R] | [C [n]] | HELP]\n");
  474       printf("Redirect a drive to the Linux file system.\n\n");
  475       printf("LREDIR X: LINUX\\FS\\tmp\n");
  476       printf("  Redirect drive X: to /tmp of Linux file system for read/write\n");
  477       printf("  If R is specified, the drive will be read-only\n");
  478       printf("  If C is specified, (read-only) CDROM n is used (n=1 by default)\n");
  479       printf("  ${home} represents user's home directory\n\n");
  480       printf("  If drive is not specified, the next available drive will be used.");
  481       printf("LREDIR X: Y:\n");
  482       printf("  Redirect drive X: to where the drive Y: is redirected.\n");
  483       printf("  If F is specified, the path for Y: is taken from its emulated "
  484              "FAT volume.\n\n");
  485       printf("LREDIR DEL drive:\n");
  486       printf("  delete a drive redirection\n\n");
  487       printf("LREDIR\n");
  488       printf("  show current drive redirections\n\n");
  489       printf("LREDIR HELP\n");
  490       printf("  show this help screen\n");
  491       return(0);
  492     }
  493 
  494     if (strncmpi(argv[1], KEYWORD_DEL, KEYWORD_DEL_COMPARE_LENGTH) == 0) {    
  495       DeleteDriveRedirection(argv[2]);
  496       return(0);
  497     }
  498 
  499     /* assume the command is to redirect a drive */
  500     /* read the drive letter and resource string */
  501     carg = 3;
  502     if (argc > 2 && argv[2][1] == ':') {
  503       /* lredir c: d: */
  504       strcpy(deviceStr, argv[1]);
  505       if ((argc > 3 && toupper(argv[3][0]) == 'F') ||
  506         ((ccode = FindRedirectionByDevice(argv[2], resourceStr)) != CC_SUCCESS)) {
  507         if ((ccode = FindFATRedirectionByDevice(argv[2], resourceStr)) != CC_SUCCESS) {
  508           printf("Error: unable to find redirection for drive %s\n", argv[2]);
  509       goto MainExit;
  510     }
  511       }
  512     } else {
  513       if (argc > 1 && argv[1][1] != ':') {
  514     int nextDrive;
  515         strcpy(resourceStr, argv[1]);
  516     nextDrive = find_drive(resourceStr);
  517     if (nextDrive == -26) {
  518         printf("Cannot redirect (maybe no drives available).");
  519         return(0);
  520     } else if (nextDrive == -27) {
  521         printf("Cannot canonicalize drive root path.\n");
  522         return(0);
  523     }
  524         deviceStr[0] = -nextDrive + 'A';
  525     deviceStr[1] = ':';
  526     deviceStr[2] = '\0';
  527     carg = 2;
  528       } else if (argc > 2) {
  529         strcpy(deviceStr, argv[1]);
  530         strcpy(resourceStr, argv[2]);
  531       }
  532     }
  533     deviceParam = DEFAULT_REDIR_PARAM;
  534 
  535     if (argc > carg) {
  536       if (toupper(argv[carg][0]) == 'R') {
  537         deviceParam = 1;
  538       }
  539       if (toupper(argv[carg][0]) == 'C') {
  540     int cdrom = 1;
  541     if (argc > carg+1 && argv[carg+1][0] >= '1' && argv[carg+1][0] <= '4')
  542       cdrom = argv[carg+1][0] - '0';
  543         deviceParam = 1 + cdrom;
  544       }
  545     }
  546 
  547     /* upper-case both strings */
  548     strupr(deviceStr);
  549     strupr(resourceStr);
  550 
  551     /* now actually redirect the drive */
  552     ccode = RedirectDevice(deviceStr, resourceStr, REDIR_DISK_TYPE,
  553                            deviceParam);
  554 
  555     /* duplicate redirection: try to reredirect */
  556     if (ccode == 0x55) {
  557       DeleteDriveRedirection(deviceStr);     
  558       ccode = RedirectDevice(deviceStr, resourceStr, REDIR_DISK_TYPE,
  559                              deviceParam);
  560     }
  561 
  562     if (ccode) {
  563       printf("Error %x (%s)\nwhile redirecting drive %s to %s\n",
  564              ccode, decode_DOS_error(ccode), deviceStr, resourceStr);
  565       goto MainExit;
  566     }
  567     if ((argc <= 2 || argv[2][1] != ':') && argc >= 2 && argv[1][1] != ':')
  568     msetenv("DOSEMU_LASTREDIR", deviceStr);
  569 
  570     printf("%s = %s", deviceStr, resourceStr);
  571     if (deviceParam > 1)
  572       printf(" CDROM:%d", deviceParam - 1);
  573     printf(" attrib = ");
  574     switch (deviceParam != 0) {
  575       case READ_ONLY_DRIVE_ATTRIBUTE:
  576         printf("READ ONLY\n");
  577         break;
  578       default:
  579         printf("READ/WRITE\n");
  580         break;
  581     }
  582 
  583 MainExit:
  584     return (ccode);
  585 }