home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 1998 November / Dppcpro1198.iso / Nov / Intelcad / Install / Data.Z / Lispcmds.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-19  |  30.1 KB  |  817 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //  LISPCMDS.CPP
  3. //
  4. //    Release 1.0   
  5. //    
  6. //    .............................................................................
  7. //    
  8. //    Copyright (c) 1998 by Visio Corporation.  All rights reserved.
  9. //    
  10. //    The Software is subject to the license agreement that accompanies 
  11. //    or is included with the Software, which specifies the permitted 
  12. //    and prohibited uses of the Software. Any unauthorized duplication 
  13. //    or use of Visio Corporation Software, in whole or in part, in print, 
  14. //    or in any other storage and retrieval system is prohibited.
  15. //    
  16. //    To the maximum extent permitted by applicable law, Visio Corporation
  17. //    and its suppliers disclaim any and all warranties and conditions,
  18. //    either express or implied, including, without limitation, implied
  19. //    warranties of merchantability, fitness for a particular purpose,
  20. //    title, and non-infringement, and those arising out of usage of trade
  21. //    or course of dealing, concerning these materials.  These materials
  22. //    are provided "as is" without warranty of any kind.
  23. //    .............................................................................
  24. //
  25. //  Description:
  26. //  This SDS program contains LISP extension functions to enhance LISP functionality.
  27. //
  28. ///////////////////////////////////////////////////////////////////////////////
  29.  
  30.  
  31.  
  32. #include "afx.h"
  33. #include "afxwin.h"
  34. #include <io.h>
  35. #include <direct.h>     // Directory stuff
  36. #include <errno.h>
  37. #include <sds.h>
  38.  
  39.  
  40. #define EOS                     '\0'
  41. #define BACKWARD                1
  42. #define FORWARD                 0
  43. #define MAXBUFFER               255
  44. #define MINBUFFER               50
  45. #define FORWARDSLASHCHAR        '/'
  46. #define FORWARDSLASHSTRING      "/"
  47. #define BACKWARDSLASHCHAR       '\\'
  48. #define BACKWARDSLASHSTRING     "\\"
  49.  
  50. #define ARRAYCOUNT(array) (sizeof(array)/sizeof((array)[0]))
  51.  
  52. // Functions declarations;
  53. int deletefile     (struct sds_resbuf *rb = NULL);
  54. int deltree        (struct sds_resbuf *rb = NULL);
  55. int filexists      (struct sds_resbuf *rb = NULL);
  56. int listfiles      (struct sds_resbuf *rb = NULL);
  57. int getcwd         (struct sds_resbuf *rb = NULL);
  58. int chelp          (struct sds_resbuf *rb = NULL);
  59. int makedir        (struct sds_resbuf *rb = NULL);
  60. int renamedir      (struct sds_resbuf *rb = NULL);
  61. int renamefile     (struct sds_resbuf *rb = NULL);
  62. int copyfile       (struct sds_resbuf *rb = NULL);
  63.  
  64. // A few structures used.
  65. struct functionDef{ char *function_name; int (*function) (struct sds_resbuf *); };
  66. struct directoryList{ char* sourceDir; char* targetDir; struct directoryList* dir_next;};
  67. static struct functionDef funcTable[] =        
  68. {
  69.   // Allow for these functions to be call with parens. Note that the functions
  70.   // take care of situation where no arguments are supplied.
  71.   {"deletefile",        deletefile},
  72.   {"deltree",           deltree},
  73.   {"filexists",         filexists},
  74.   {"listfiles",         listfiles},
  75.   {"getcwd",            getcwd},
  76.   {"chelp",             chelp},
  77.   {"makedir",           makedir},
  78.   {"renamedir",         renamedir},
  79.   {"renamefile",        renamefile},
  80.   {"copyfile",          copyfile},
  81.  
  82.   // Allow for these fuctions to be called from the command line
  83.   // without parens.
  84.   {"c:deletefile",      deletefile},
  85.   {"c:deltree",           deltree},
  86.   {"c:filexists",         filexists},
  87.   {"c:listfiles",         listfiles},
  88.   {"c:getcwd",            getcwd},
  89.   {"c:chelp",             chelp},
  90.   {"c:makedir",           makedir},
  91.   {"c:renamedir",         renamedir},
  92.   {"c:renamefile",        renamefile},
  93.   {"c:copyfile",          copyfile}
  94. };
  95.  
  96. // Global declarations
  97. struct directoryList*   DirectoryList       = NULL;
  98. struct directoryList*   TopDirectoryList    = NULL;
  99. struct sds_resbuf*      TopOfLList          = NULL;
  100. struct sds_resbuf*      returnLList         = NULL;
  101.  
  102. //  Local support function declarations.
  103. static int    funcload         (void);
  104. static int    funcunload       (void);
  105. static int    invokefun        (void);
  106. static int    DirsList         (char* Root, char* Target);
  107. static void   CorrectSlashes   (char* fName, int slashDirection);
  108. static BOOL   CreateNestedDirs (const char* directoryBeingCreated);
  109.  
  110. int    main                     (int, char **);
  111.  
  112. ///////////////////////////////////////////////////////////////////////////////
  113. ///////////////////////////////////////////////////////////////////////////////
  114. // MAIN - the main entry point 
  115. ///////////////////////////////////////////////////////////////////////////////
  116. int main(int argc, char** argv)
  117. {
  118.    int status;
  119.    char errorstr[80];
  120.    short scode = RSRSLT;             
  121.  
  122.    sds_init(argc, argv);             // Start communications with lisp
  123.  
  124.    for ( ;; ) {                      // Communication loop
  125.        if ((status = sds_link(scode)) < 0) {
  126.            sprintf(errorstr, "Lisp extension commands: bad status from sds_link() = %d\n", status);
  127.            sds_printf(errorstr);
  128.            sds_exit(0);
  129.        }
  130.        scode = RSRSLT;               
  131.  
  132.        switch (status) {
  133.        case SDS_RQXLOAD:                 // Load & define functions
  134.            scode = funcload() == RTNORM ? RSRSLT : RSERR;
  135.            sds_printf("Lisp extension commands - loaded\nEnter \"(chelp)\" for function list\n");
  136.            break;
  137.        case SDS_RQXUNLD:                 // Load & define functions
  138.        case SDS_RQQUIT:
  139.            scode = funcunload() == RTNORM ? RSRSLT : RSERR;
  140.            sds_printf("Lisp extension commands - unloaded\n");
  141.            break;
  142.        case SDS_RQSUBR:                  
  143.            scode = invokefun() == RTNORM ? RSRSLT : RSERR;
  144.            break;
  145.        default:
  146.            break;
  147.        }
  148.    }
  149.    return 1;
  150. }
  151.  
  152. ///////////////////////////////////////////////////////////////////////////////
  153. // FUNCLOAD  --  Defun extension functions.  
  154. ///////////////////////////////////////////////////////////////////////////////
  155. static int funcload()
  156. {
  157.     short i;
  158.  
  159.     // Loop through the array and defun each command.
  160.     for (i = 0; i < ARRAYCOUNT(funcTable); i++) {
  161.         if (!sds_defun(funcTable[i].function_name, i))
  162.             return RTERROR;
  163.     }
  164.     return RTNORM;
  165. }
  166.  
  167. ///////////////////////////////////////////////////////////////////////////////
  168. // FUNCUNLOAD  --  Defun extension functions.  
  169. ///////////////////////////////////////////////////////////////////////////////
  170. static int funcunload()
  171. {
  172.     short i;
  173.  
  174.     // Loop through the array and defun each command.
  175.     for (i = 0; i < ARRAYCOUNT(funcTable); i++) {
  176.         if (!sds_undef(funcTable[i].function_name, i))
  177.             return RTERROR;
  178.     }
  179.     return RTNORM;
  180. }
  181.  
  182. ///////////////////////////////////////////////////////////////////////////////
  183. // invokefun -- Execute extension functions.
  184. ///////////////////////////////////////////////////////////////////////////////
  185. static int invokefun()
  186. {
  187.     struct sds_resbuf *rb;
  188.     int val;
  189.  
  190.     // Verify that function code is valid.
  191.     if ((val = sds_getfuncode()) < 0 || val >= ARRAYCOUNT(funcTable)) {
  192.         sds_fail("Invalid function code.");
  193.         return RTERROR;
  194.     }
  195.  
  196.     // Get any arguments.
  197.     rb = sds_getargs();
  198.  
  199.     // Call the function and return is return value
  200.     val = (*funcTable[val].function)(rb);
  201.     sds_relrb(rb);
  202.  
  203.     return val;
  204. }
  205.  
  206. ///////////////////////////////////////////////////////////////////////////////
  207. // deletefile -- Deletes a file using lisp syntax 
  208. // usage; (deletefile "f:/somefile.exe")
  209. ///////////////////////////////////////////////////////////////////////////////
  210. static int deletefile(struct sds_resbuf *rb)
  211. {
  212.    char tmpBuffer[MAXBUFFER];
  213.  
  214.    // If rb is NULL, prompt for needed information.
  215.    if (rb == NULL) {
  216.        int result = sds_getstring(TRUE, "Enter file name to delete: ", tmpBuffer);
  217.        if (result != RTNORM) {
  218.            sds_retnil();
  219.            return RTERROR;
  220.        }
  221.    } else if (rb->restype == RTSTR) {
  222.        // We have a string.
  223.        strcpy(tmpBuffer,rb->resval.rstring);
  224.   } else {
  225.        // Bad Argument type, return nil to lisp.
  226.        sds_retnil();
  227.        return RTERROR;
  228.    }
  229.  
  230.    sds_retint(unlink(tmpBuffer) == 0);
  231.    return RTNORM;
  232. }
  233.  
  234. ///////////////////////////////////////////////////////////////////////////////
  235. // deltree -- deletes a directory tree 
  236. // usage; (deltree "d:\\somedir")
  237. ///////////////////////////////////////////////////////////////////////////////
  238. static int deltree(struct sds_resbuf *rb)
  239. {
  240.    char tmpBuffer[MAXBUFFER], TmpFile[MAXBUFFER];
  241.    struct _finddata_t c_file;
  242.    struct sds_resbuf tmpResBuf;
  243.    long hFile;
  244.  
  245.    // If the user doesn't add args, prompt.
  246.    if (rb == NULL) {
  247.        int result = sds_getstring(TRUE, "Enter directory name to delete: ", tmpBuffer);
  248.        if (result != RTNORM) {
  249.            sds_retnil();
  250.            return RTERROR;
  251.        }
  252.    } else if (rb->restype == RTSTR) {
  253.        // We have a string.
  254.        strcpy(tmpBuffer,rb->resval.rstring);
  255.    } else {
  256.        // Bad Argument type, return nil to lisp.
  257.        sds_retnil();
  258.        return RTERROR;
  259.    }
  260.  
  261.    CorrectSlashes(tmpBuffer, BACKWARD);
  262.    strcpy(TmpFile, tmpBuffer);
  263.  
  264.    if (TmpFile[strlen(TmpFile) - 1] != BACKWARDSLASHCHAR)
  265.            strcat(TmpFile, "\\*.*");
  266.    else
  267.            strcat(TmpFile, "*.*");
  268.  
  269.    tmpResBuf.restype = RTSTR;
  270.    tmpResBuf.resval.rstring = (char*)malloc(MAXBUFFER);
  271.  
  272.    // Find first *.* file in the directory.
  273.    if( (hFile = _findfirst( TmpFile, &c_file )) != -1L ) {
  274.        if (c_file.name[0] != '.') {
  275.            // if this is a directory, step into it and remove everything.
  276.            if ((c_file.attrib & _A_SUBDIR)) {
  277.                sprintf(tmpResBuf.resval.rstring, "%s%s%s%s", tmpBuffer, BACKWARDSLASHSTRING, c_file.name);
  278.                deltree(&tmpResBuf);
  279.                RemoveDirectory(tmpResBuf.resval.rstring);
  280.            }
  281.            sprintf(TmpFile, "%s%s%s", tmpBuffer, BACKWARDSLASHSTRING,  c_file.name);
  282.            SetFileAttributes(TmpFile, FILE_ATTRIBUTE_ARCHIVE);
  283.            DeleteFile(TmpFile);
  284.        }
  285.        // Find the other files.
  286.        while( _findnext( hFile, &c_file ) == 0 )  {
  287.            if (c_file.name[0] != '.') {
  288.                // if this is a directory, step into it and remove everything.
  289.                if (c_file.attrib & _A_SUBDIR) {
  290.                    sprintf(tmpResBuf.resval.rstring, "%s%s%s", tmpBuffer, BACKWARDSLASHSTRING, c_file.name);
  291.                    deltree(&tmpResBuf);
  292.                    RemoveDirectory(tmpResBuf.resval.rstring);
  293.                }
  294.                sprintf(TmpFile, "%s%s%s", tmpBuffer, BACKWARDSLASHSTRING,  c_file.name);
  295.                SetFileAttributes(TmpFile, FILE_ATTRIBUTE_ARCHIVE);
  296.                DeleteFile(TmpFile);
  297.            }
  298.        }
  299.        _findclose( hFile );
  300.    }
  301.  
  302.    BOOL res = RemoveDirectory(tmpBuffer);
  303.  
  304.    if (res == 0) {       
  305.        if (GetLastError() == (DWORD)32/*Sharing violation*/)
  306.            ads_printf("Share violation: Can't remove %s\n", tmpBuffer);           
  307.        else
  308.            ads_printf("Directory \'%s\' not found!\n", tmpBuffer);   
  309.        
  310.        ads_retint(0); 
  311.     } else
  312.        sds_retint(1);
  313.    return RTNORM;
  314. }
  315.  
  316. ///////////////////////////////////////////////////////////////////////////////
  317. // filexists(const char* FileName)
  318. // usage; (filexists "f:/somedir/somefile.ext") 
  319. ///////////////////////////////////////////////////////////////////////////////
  320. static int filexists(struct sds_resbuf *rb)
  321. {
  322.     OFSTRUCT ofstruct;
  323.  
  324.     // Bail if the resbuf isn't the right type.
  325.     if (rb->restype != RTSTR) {
  326.         sds_printf("error: bad arguent type\n");
  327.         return RTERROR;
  328.     }
  329.  
  330.     if (!(OpenFile(rb->resval.rstring, &ofstruct, OF_EXIST) == HFILE_ERROR))
  331.         ads_rett();
  332.     else
  333.         ads_retnil();
  334.  
  335.     return RTNORM;
  336.  
  337. }
  338.  
  339. ///////////////////////////////////////////////////////////////////////////////
  340. // listfiles -- create a list of files in a given directory 
  341. // usage; (listfiles "f:/somdir/*.ext")
  342. ///////////////////////////////////////////////////////////////////////////////
  343. static int listfiles(struct sds_resbuf *rb)
  344. {
  345.    char tmpBuffer[MAXBUFFER];
  346.    char fileName[MAXBUFFER];
  347.    struct _finddata_t c_file;
  348.    long hFile;
  349.    struct sds_resbuf* returnLList = NULL;
  350.  
  351.    TopOfLList = NULL;
  352.  
  353.    // If the user doesn't add args, prompt.
  354.    if (rb == NULL) {
  355.        int result = sds_getstring(TRUE, "Enter directory and file type specification: ", tmpBuffer);
  356.        if (result != RTNORM) {
  357.            sds_retnil();
  358.            return RTERROR;
  359.        }
  360.    } else if (rb->restype == RTSTR) {
  361.        // We have a string.
  362.        strcpy(tmpBuffer,rb->resval.rstring);
  363.   } else {
  364.        // Bad Argument type, return nil to lisp.
  365.        sds_retnil();
  366.        return RTERROR;
  367.    }
  368.  
  369.    CorrectSlashes(tmpBuffer, BACKWARD);
  370.  
  371.    // Find first file that matches the file description..
  372.    if( (hFile = _findfirst(tmpBuffer, &c_file )) != -1L ) {
  373.        if (!(c_file.attrib & _A_SUBDIR)) {
  374.            // Since this is the first time through we can allocate the buffer.
  375.            if ((returnLList = sds_newrb(RTSTR)) == NULL) {
  376.                sds_fail("Unable to allocate linked list buffer\n");
  377.                sds_retnil();
  378.                return RTERROR;
  379.            } else {
  380.                // First time through save off pointer to the top of the linked list.
  381.                if (TopOfLList == NULL)
  382.                    TopOfLList = returnLList;
  383.            }
  384.  
  385.            strcpy(fileName, tmpBuffer);
  386.  
  387.            // Strip off the wild card and replace it with the file name.
  388.            if (strstr(fileName, BACKWARDSLASHSTRING) != NULL)
  389.                strcpy(strrchr(fileName, BACKWARDSLASHCHAR) + 1, c_file.name);
  390.            else
  391.                strcpy(fileName, c_file.name);
  392.                
  393.            // Allocate string space and save the file name into the linked list.
  394.            if ((returnLList->resval.rstring = (char*)malloc(sizeof(fileName) + 1)) == NULL) {
  395.                sds_fail("Unable to allocate string buffer.\n");
  396.                sds_retnil();
  397.                return RTERROR;
  398.            }
  399.  
  400.            strcpy(returnLList->resval.rstring, strlwr(fileName));
  401.            returnLList->rbnext = NULL;
  402.        } 
  403.  
  404.        // Now find any other files that match the wildcard.
  405.        while( _findnext( hFile, &c_file ) == 0 )  {
  406.            if (!(c_file.attrib & _A_SUBDIR)) {
  407.                // If returnLList is NULL, the first pass above didn't find anything
  408.                // to match the wild card, so we will need to allocate a new buffer.
  409.                // If it's not NULL, then we need to allocate a new buffer on the 
  410.                // ->rbnext and move to it.
  411.                if (returnLList == NULL) {
  412.                    if ((returnLList = sds_newrb(RTSTR)) == NULL) {
  413.                        sds_fail("Unable to allocate linked list buffer\n");
  414.                        sds_retnil();
  415.                        return RTERROR;
  416.                    }
  417.                } else {
  418.                    if ((returnLList->rbnext = sds_newrb(RTSTR)) == NULL) {
  419.                        sds_fail("Unable to allocate linked list buffer\n");
  420.                        sds_retnil();
  421.                        return RTERROR;
  422.                    }
  423.                    returnLList = returnLList->rbnext;
  424.                }
  425.                // Again checking to make sure we can get to the top of the linked list.
  426.                if (TopOfLList == NULL)
  427.                    TopOfLList = returnLList;
  428.  
  429.                strcpy(fileName, tmpBuffer);
  430.  
  431.                // Strip off the wild card and replace it with the file name.
  432.                if (strstr(fileName, BACKWARDSLASHSTRING) != NULL)
  433.                    strcpy(strrchr(fileName, BACKWARDSLASHCHAR) + 1, c_file.name);
  434.                else
  435.                    strcpy(fileName, c_file.name);
  436.  
  437.                // Allocate string space and save the file name into the linked list.
  438.                if ((returnLList->resval.rstring = (char*)malloc(sizeof(fileName) + 1)) == NULL) {
  439.                    sds_fail("Unable to allocate string buffer.\n");
  440.                    sds_retnil();
  441.                    return RTERROR;
  442.                }
  443.  
  444.                strcpy(returnLList->resval.rstring, strlwr(fileName));
  445.                returnLList->rbnext = NULL;
  446.            }
  447.        }
  448.        _findclose( hFile );
  449.        if (TopOfLList == NULL && returnLList == NULL) {
  450.             ads_printf("File type specification must be supplied.\n");
  451.             return RTNORM;
  452.        } else {
  453.            // Now return what we have found to LISP. If anything.
  454.            if (TopOfLList != NULL)
  455.                sds_retlist(TopOfLList);
  456.            else 
  457.                sds_retnil();
  458.        }
  459.    }
  460.    // If all this has happened, then the user passed in a bogus directory.
  461.    if (hFile == -1 && TopOfLList == NULL && returnLList == NULL) {
  462.        ads_printf("Directory \'%s\' not found.\n", tmpBuffer);
  463.        ads_retnil();
  464.    } else {
  465.         // Now clean up after ourselves.
  466.         returnLList = TopOfLList;
  467.         while (returnLList != NULL) {
  468.             // Need to manually free up the string space allocated.
  469.             free(returnLList->resval.rstring);
  470.             returnLList->resval.rstring = NULL;
  471.             returnLList = returnLList->rbnext;
  472.         }
  473.         // Now we can release the resbuf chain.
  474.         sds_relrb(returnLList);
  475.    }
  476.    return RTNORM;
  477. }
  478.  
  479. ///////////////////////////////////////////////////////////////////////////////
  480. // getcwd -- get the current working directory. 
  481. ///////////////////////////////////////////////////////////////////////////////
  482. static int getcwd(struct sds_resbuf *rb)
  483. {
  484.    char tmpBuffer[MAXBUFFER];
  485.  
  486.    getcwd(tmpBuffer, MAXBUFFER);
  487.  
  488.    sds_retstr(tmpBuffer);
  489.  
  490.     return RTNORM;
  491. }
  492.  
  493. //-----------------------------------------------------------------------------
  494. // chelp -- Displays help screen.
  495. //
  496. static int chelp(struct sds_resbuf *rb)
  497. {
  498.  
  499.    sds_textscr();
  500.    sds_printf("\nCommand:    Syntax:                           Return value:\n");
  501.    sds_printf("----------------------------------------------------------------------\n");
  502.    sds_printf("deletefile    (deletefile \"sFilename\")           1 = success.\n");
  503.    sds_printf("deltree       (deltree \"sDirectory\")             1 = success.\n");
  504.    sds_printf("filexists     (filexists \"sFilename\")            T = success.\n");
  505.    sds_printf("listfiles     (listfiles \"path\\*.*\")             (list) = success.\n");
  506.    sds_printf("getcwd        (getcwd)                           path = success.\n");
  507.    sds_printf("makedir       (makedir \"drive:\\dir\")             1 = success.\n");
  508.    sds_printf("renamedir     (renamedir \"source\" \"target\")      1 = success.\n");
  509.    sds_printf("renamefile    (renamefile \"source\" \"target\")     1 = success.\n");
  510.    sds_printf("copyfile      (copyfile \"sFrom\" \"sTo\" [\"/s\"])    number of files = success.\n");
  511.    sds_printf("----------------------------------------------------------------------\n");
  512.    sds_printf("    NOTE:\n");
  513.    sds_printf("    All extension commands can be called with or without arguments.\n");
  514.    sds_printf("    If no arguments are supplied, the command will prompt you for any\n");
  515.    sds_printf("    information it needs to complete the task. Also all output will be\n");
  516.    sds_printf("    echoed to the history window, and can be used as return values for setq.\n\n");
  517.  
  518.    sds_retvoid();
  519.    return RTNORM;
  520. }
  521.  
  522. ///////////////////////////////////////////////////////////////////////////////
  523. // makedir -- create a directory usage; (makedir "f:/junk")
  524. ///////////////////////////////////////////////////////////////////////////////
  525. static int makedir(struct sds_resbuf *rb)
  526. {
  527.    char tmpBuffer[MAXBUFFER];
  528.  
  529.    // If rb is NULL, prompt for needed information.
  530.    if (rb == NULL) {
  531.        int result = sds_getstring(TRUE, "Enter directory name: ", tmpBuffer);
  532.        if (result != RTNORM) {
  533.            sds_retnil();
  534.            return RTERROR;
  535.        }
  536.    } else if (rb->restype == RTSTR) {
  537.        // We have a string.
  538.        strcpy(tmpBuffer,rb->resval.rstring);
  539.    } else {
  540.        // Bad Argument type, return nil to lisp.
  541.        sds_retnil();
  542.        return RTERROR;
  543.    }
  544.  
  545.    CorrectSlashes(tmpBuffer, BACKWARD);
  546.  
  547.    sds_retint(CreateNestedDirs(tmpBuffer));
  548.  
  549.    return RTNORM;
  550. }
  551.  
  552. ///////////////////////////////////////////////////////////////////////////////
  553. // renamedir -- rename a directory usage; (renamedir "f:/junk" "f:/mbjunk").
  554. ///////////////////////////////////////////////////////////////////////////////
  555. static int renamedir(struct sds_resbuf *rb)
  556. {
  557.    return renamefile(rb);
  558. }
  559.  
  560. ///////////////////////////////////////////////////////////////////////////////
  561. // renamefile -- rename a file usage; (renamefile "f:/junk" "f:/mbjunk").
  562. ///////////////////////////////////////////////////////////////////////////////
  563. static int renamefile(struct sds_resbuf *rb)
  564. {
  565.    char oldfname[MAXBUFFER], newfname[MAXBUFFER];
  566.  
  567.    // If rb is NULL, prompt for needed information.
  568.    if (rb == NULL) {
  569.        int result = sds_getstring(TRUE, "Enter old file name: ", oldfname);
  570.        if (result != RTNORM) {
  571.            sds_retnil();
  572.            return RTERROR;
  573.        }
  574.        result = sds_getstring(TRUE, "Enter new file name: ", newfname);
  575.        if (result != RTNORM) {
  576.            sds_retnil();
  577.            return RTERROR;
  578.        }
  579.    } else if (rb->restype == RTSTR && rb->rbnext->restype == RTSTR) {
  580.        // We have a string.
  581.        strcpy(oldfname,rb->resval.rstring);
  582.        strcpy(newfname,rb->rbnext->resval.rstring);
  583.    } else {
  584.        // Bad Argument type, return nil to lisp.
  585.        sds_retnil();
  586.        return RTERROR;
  587.    }
  588.  
  589.    CorrectSlashes(oldfname, BACKWARD);
  590.    CorrectSlashes(newfname, BACKWARD);
  591.  
  592.    if (!rename(oldfname, newfname)) {
  593.        sds_retint(1);
  594.        return RTNORM;
  595.    } else {
  596.       sds_retnil();
  597.       return RTERROR;
  598.    }
  599. }
  600.  
  601. ///////////////////////////////////////////////////////////////////////////////
  602. // copyfile -- copies a directory tree usage; (copyfile "d:\\junk\file.txt "g:/junk")
  603. ///////////////////////////////////////////////////////////////////////////////
  604. static int copyfile(struct sds_resbuf *rb)
  605. {
  606.    char source[MAXBUFFER], target[MAXBUFFER], tmpBuffer[MINBUFFER];
  607.  
  608.    // If the user doesn't add args, prompt.
  609.    if (rb == NULL) {
  610.        int result = sds_getstring(TRUE, "Enter source file name: ", source);
  611.        if (result != RTNORM) {
  612.            sds_retnil();
  613.            return RTERROR;
  614.        }
  615.        result = sds_getstring(TRUE, "Enter target directory: ", target);
  616.        if (result != RTNORM) {
  617.            sds_retnil();
  618.            return RTERROR;
  619.        }
  620.    } else if (rb->restype == RTSTR && rb->rbnext->restype == RTSTR) {
  621.        // We have a string.
  622.        strncpy(source,rb->resval.rstring, MAXBUFFER - 1);
  623.        strncpy(target,rb->rbnext->resval.rstring, MAXBUFFER - 1);
  624.    } else {
  625.         // Bad Argument type, return nil to lisp.
  626.         sds_retnil();
  627.         return RTERROR;
  628.    }
  629.  
  630.    CorrectSlashes(source, BACKWARD);
  631.    CorrectSlashes(target, BACKWARD);
  632.  
  633.    // I'm going to assume that if there is no '.' in the target name that it is
  634.    // a directory.
  635.    if (strstr(target, ".") == NULL) {
  636.       // Just in case the user has a trailing back slash on the output path.
  637.       if(target[strlen(target) - 1] == '\\')
  638.           *(strrchr(target, '\\')) = '\0';
  639.  
  640.       
  641.       CreateNestedDirs(target);
  642.       // Here the user has not given the output file a name which means it should have
  643.       // the same name as the source file. So we will append the file name to the output
  644.       // path.
  645.  
  646.       strcat(target, strrchr(source, '\\'));
  647.    } else {
  648.       // Here the user gave us a file name for the target file. So we will use it.
  649.       strcpy(tmpBuffer, target);
  650.       *(strrchr(tmpBuffer, '\\')) = '\0';
  651.       CreateNestedDirs(tmpBuffer);
  652.    }
  653.  
  654.    if (CopyFile(source, target, FALSE) == TRUE) {
  655.        sds_rett();
  656.        return RTNORM;
  657.    } else {
  658.        sds_printf("Unable to copy %s to %s, verify file names.\n",source, target);
  659.        sds_retnil();
  660.        return RTERROR;
  661.    }
  662.  
  663.    return RTNORM;
  664. }
  665.  
  666. ///////////////////////////////////////////////////////////////////////////////
  667. // Helper functions.
  668. ///////////////////////////////////////////////////////////////////////////////
  669. ///////////////////////////////////////////////////////////////////////////////
  670. // CorrectSlashes -- Reverses forward slashes.
  671. ///////////////////////////////////////////////////////////////////////////////
  672. void CorrectSlashes(char* fName, int slashDirection)
  673. {
  674.     char* tmpPtr = NULL;
  675.     if (slashDirection == BACKWARD) {
  676.         // Change forward slashes to backslashes.
  677.         while ((tmpPtr = strstr(fName, FORWARDSLASHSTRING)) != NULL) {
  678.             *tmpPtr = BACKWARDSLASHCHAR;
  679.         }
  680.     } else {
  681.         // Change backward slashes to forwardslashes.
  682.         while ((tmpPtr = strstr(fName, BACKWARDSLASHSTRING)) != NULL) {
  683.             *tmpPtr = FORWARDSLASHCHAR;
  684.         }
  685.     }
  686. }
  687.  
  688. ///////////////////////////////////////////////////////////////////////////////
  689. // CreateNestedDirs -- Loops down path creating each directory in turn.
  690. ///////////////////////////////////////////////////////////////////////////////
  691. BOOL CreateNestedDirs(const char* directoryBeingCreated)
  692. {
  693.    char subDirectory[MAXBUFFER];
  694.    char tmpBuffer[MAXBUFFER];
  695.    char *Ptr;
  696.    int Len = 0, i;
  697.    BOOL bFirstTime = TRUE;
  698.  
  699.    strcpy(tmpBuffer, directoryBeingCreated);
  700.    Ptr = tmpBuffer;
  701.    Len = strlen(tmpBuffer);
  702.  
  703.    for (i = 0; i < Len; i++) {
  704.        if (*(Ptr) != BACKWARDSLASHCHAR) {
  705.            subDirectory[i] = *Ptr;
  706.        } else {
  707.            subDirectory[i] = EOS;
  708.  
  709.            if (_mkdir(subDirectory) == -1) {
  710.                if (bFirstTime == TRUE) {
  711.                    bFirstTime = FALSE;
  712.                } else {
  713.                    if (errno != EEXIST && errno != EACCES) {
  714.                        sprintf(tmpBuffer,   "Cannot create this directory %s:\n"
  715.                                             "This is probably a permissions error, or\n"
  716.                                             "you may be experiencing network problems.\n"
  717.                                             "Abort.\n",
  718.                                        subDirectory);
  719.                        MessageBox(NULL, tmpBuffer, "Directory Creation Problem!", MB_OK | MB_ICONHAND | MB_TASKMODAL);
  720.                        return (FALSE);
  721.                    }
  722.                }
  723.            }
  724.        subDirectory[i] = *Ptr;
  725.        }
  726.        ++Ptr;
  727.    }
  728.    subDirectory[i] = EOS;
  729.    if (_mkdir(subDirectory) == -1) {
  730.        if (errno != EEXIST  && errno != EACCES) {
  731.            sprintf(tmpBuffer,   "Cannot create this directory %s:\n"
  732.                                 "This is probably a permissions error, or\n"
  733.                                 "you may be experiencing network problems.\n"
  734.                                 "Abort.\n",
  735.                           subDirectory);
  736.            MessageBox(NULL, tmpBuffer, "Directory Creation Problem!", MB_OK | MB_ICONHAND | MB_TASKMODAL);
  737.            return (FALSE);
  738.        }
  739.    }
  740.    return (TRUE);
  741. }
  742.  
  743. ///////////////////////////////////////////////////////////////////////////////
  744. // DirsList -- Creates linked list of directories to be copied.
  745. ///////////////////////////////////////////////////////////////////////////////
  746. static int  DirsList(char* Root, char* Target)
  747. {
  748.    char tmpBuffer[MAXBUFFER];
  749.    char dirName[MAXBUFFER], targenName[MAXBUFFER];
  750.    struct _finddata_t c_file;
  751.    long hFile;
  752.  
  753.    strcpy(tmpBuffer, Root);
  754.    strcat(tmpBuffer, "\\*.*");
  755.  
  756.  
  757.    // Find first *.* file in requested directory.
  758.    if( (hFile = _findfirst(tmpBuffer, &c_file )) != -1L ) {
  759.  
  760.        if (c_file.attrib & _A_SUBDIR && c_file.name[0] != '.') {
  761.            strcpy(dirName, tmpBuffer);
  762.            strcpy(strrchr(dirName, '\\') + 1, c_file.name);
  763.            if ((DirectoryList->sourceDir = (char*)malloc(sizeof(dirName) + 1)) == NULL) {
  764.                ads_fail("Unable to allocate string buffer.\n");
  765.                ads_retnil();
  766.             return RTERROR;
  767.            }
  768.            if ((DirectoryList->targetDir = (char*)malloc(sizeof(dirName) + 1)) == NULL) {
  769.                ads_fail("Unable to allocate string buffer.\n");
  770.                ads_retnil();
  771.             return RTERROR;
  772.            }
  773.  
  774.            strcpy(DirectoryList->sourceDir, strlwr(dirName));
  775.            strcpy(DirectoryList->targetDir, strlwr(Target));
  776.            DirectoryList->dir_next = NULL;
  777.            DirsList(DirectoryList->sourceDir, DirectoryList->targetDir);
  778.       }
  779.  
  780.       // Find the rest of the files.
  781.       while( _findnext( hFile, &c_file ) == 0 )  {
  782.            if (c_file.attrib & _A_SUBDIR && c_file.name[0] != '.') {
  783.                if ((DirectoryList->dir_next = (struct directoryList*)malloc(sizeof(struct directoryList))) == NULL) {
  784.                    ads_fail("Unable to allocate buffer\n");
  785.                    ads_retnil();
  786.                    return RTERROR;
  787.                }
  788.                DirectoryList = DirectoryList->dir_next;
  789.                DirectoryList->sourceDir = DirectoryList->targetDir = NULL;
  790.                DirectoryList->dir_next = NULL;
  791.  
  792.                strcpy(dirName, tmpBuffer);
  793.                strcpy(strrchr(dirName, BACKWARDSLASHCHAR) + 1, c_file.name);
  794.  
  795.                if ((DirectoryList->sourceDir = (char*)malloc(sizeof(dirName) + 1)) == NULL) {
  796.                    ads_fail("Unable to allocate string buffer.\n");
  797.                    ads_retnil();
  798.                    return RTERROR;
  799.                }
  800.                if ((DirectoryList->targetDir = (char*)malloc(sizeof(dirName) + 1)) == NULL) {
  801.                    ads_fail("Unable to allocate string buffer.\n");
  802.                    ads_retnil();
  803.                    return RTERROR;
  804.                }
  805.                sprintf(targenName, "%s%s%s", Target, BACKWARDSLASHSTRING, c_file.name);
  806.  
  807.                strcpy(DirectoryList->sourceDir , strlwr(dirName));
  808.                strcpy(DirectoryList->targetDir , strlwr(targenName));
  809.                DirectoryList->dir_next = NULL;
  810.                DirsList(DirectoryList->sourceDir, DirectoryList->targetDir);
  811.            }
  812.       }
  813.       _findclose( hFile );
  814.    }
  815.    return RTNORM;
  816. }
  817.