home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lpathext.zip / lpathext.c < prev    next >
C/C++ Source or Header  |  2001-12-10  |  8KB  |  260 lines

  1. /* Subroutine library to manipulate OS/2 LIBPATH extensions.          */
  2.  
  3. /* You may use this code freely, and redistribute it provided the     */
  4. /* original copyright caveat is retained and no charge is levied      */
  5. /* beyond the price of its distribution medium.                       */
  6.  
  7. /* No warranty is expressed or implied as to the suitability of this  */
  8. /* software to perform any given task, nor will the author accept     */
  9. /* liability for any damage or loss incurred by its use.              */
  10.  
  11. /* Copyright (C) 2001, David W. Noon.  All rights reserved.           */
  12.  
  13. /* To switch off the BIN/DLL directory swap, set this macro to 0. */
  14. #define FIDDLE_BIN_TO_DLL 1
  15.  
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #if FIDDLE_BIN_TO_DLL
  19. #include <locale.h>
  20. #endif
  21.  
  22. #define INCL_NOPMAPI
  23. #define INCL_DOSPROCESS
  24. #define INCL_DOSMODULEMGR
  25. #define INCL_DOSMISC
  26. #define INCL_DOSERRORS
  27. #include <os2.h>
  28.  
  29. #include "lpathext.h"
  30.  
  31. /* Private subroutine to set either LIBPATH extension. */
  32. static APIRET set_eitherlibpath(ULONG begin_end_flag)
  33. {
  34.    PPIB pib_ptr;
  35.    PTIB tib_ptr;
  36.    APIRET rc;
  37.    PUCHAR first_slash, final_slash, previous_slash;
  38.    UCHAR exe_path[CCHMAXPATH];
  39.  
  40.    /* Get the address of the thread and process information blocks. */
  41.    DosGetInfoBlocks(&tib_ptr, &pib_ptr);
  42.  
  43.    /* Get the full path/filename of the executable that started this process. */
  44.    if ((rc = DosQueryModuleName(pib_ptr->pib_hmte, sizeof exe_path, exe_path)) != NO_ERROR)
  45.       return rc;
  46.  
  47.    /* The path/filename returned will be X:\dir\subdir\...\progname.exe in format. */
  48.    first_slash = &exe_path[2];
  49.  
  50.    /* Scan the string from right to left for the final '\' or '/', until we hit the first '\' or '/'. */
  51.    final_slash = &exe_path[strlen(exe_path)];
  52.    do
  53.    {
  54.       --final_slash;
  55.    } while (final_slash > first_slash && *final_slash != '\\' && *final_slash != '/');
  56.  
  57.    /* Check if we hit the left edge of the directory path. */
  58.    if (final_slash == first_slash)
  59.    {
  60.       /* The root directory of a drive is left as is. */
  61.       exe_path[3] = '\0';
  62.    }
  63.    else
  64.    {
  65.       /* Make the final slash before the program name into the end of string. */
  66.       *final_slash = '\0';
  67.  
  68.       #if FIDDLE_BIN_TO_DLL
  69.       /* See if we should "fiddle" the final node of the path from "BIN" to "DLL". */
  70.       for (previous_slash = final_slash - 1; previous_slash >= first_slash; --previous_slash)
  71.       {
  72.          if (*previous_slash == '\\' || *previous_slash == '/')
  73.          {
  74.             /* Save user's locale. */
  75.             const char * const old_locale = setlocale(LC_CTYPE, NULL);
  76.  
  77.             /* Ensure a C locale for the strnicmp() call. */
  78.             setlocale(LC_CTYPE, "C");
  79.             if (final_slash - previous_slash == 4 &&
  80.                   strnicmp(previous_slash+1, "bin", 3) == 0)
  81.             {
  82.                const size_t final_node_offset = previous_slash - exe_path + 1;
  83.                UCHAR DLL_path[CCHMAXPATH];
  84.  
  85.                /* Make the DLL directory name in the new string. */
  86.                strcpy(DLL_path, exe_path);
  87.                DLL_path[final_node_offset] = 'D';
  88.                DLL_path[final_node_offset+1] = 'L';
  89.                DLL_path[final_node_offset+2] = 'L';
  90.  
  91.                /* See if the DLL directory exists. */
  92.                if (DosQueryPathInfo(DLL_path, FIL_QUERYFULLNAME, DLL_path, sizeof DLL_path)
  93.                      == NO_ERROR)
  94.                   strcpy(exe_path, DLL_path);
  95.             }
  96.             /* Restore user's locale. */
  97.             setlocale(LC_CTYPE, old_locale);
  98.  
  99.             /* Terminate the surrounding for-loop. */
  100.             break;
  101.          }
  102.       }
  103.       #endif /* FIDDLE_BIN_TO_DLL */
  104.    }
  105.  
  106.    /* Set the specified LIBPATH extension. */
  107.    return DosSetExtLIBPATH(exe_path, begin_end_flag);
  108. }
  109.  
  110. /* Private subroutine to append to either LIBPATH extension */
  111. static APIRET append_eitherlibpath(PCSZ path, ULONG begin_end_flag)
  112. {
  113.    const size_t path_len = strlen(path);
  114.    size_t old_path_len;
  115.    APIRET rc;
  116.    UCHAR old_libpath[1024];
  117.  
  118.    if (path_len == 0)
  119.       return ERROR_INVALID_PARAMETER;
  120.  
  121.    if (path_len > 1023)
  122.       return ERROR_NOT_ENOUGH_MEMORY;
  123.  
  124.    if ((rc = DosQueryExtLIBPATH(old_libpath, begin_end_flag)) != NO_ERROR)
  125.       return rc;
  126.  
  127.    if (old_libpath[0] == '\0')
  128.    {
  129.       memcpy(old_libpath, path, path_len+1);
  130.       old_path_len = path_len - 1;
  131.    }
  132.    else
  133.    {
  134.       /* Use lengths instead of NUL terminators after this. */
  135.       old_path_len = strlen(old_libpath);
  136.  
  137.       /* Check if the new size is too large. */
  138.       if (path_len + old_path_len > 1022)
  139.          return ERROR_NOT_ENOUGH_MEMORY;
  140.  
  141.       /* Concatenate the new path, separated by a semi-colon, on the end of the existing paths. */
  142.       if (old_libpath[old_path_len-1] != ';')
  143.          old_libpath[old_path_len++] = ';';
  144.       memcpy(&old_libpath[old_path_len], path, path_len+1);
  145.       old_path_len += path_len - 1;
  146.    }
  147.  
  148.    /* Erase any trailing semi-colon. */
  149.    if (old_libpath[old_path_len] == ';')
  150.       old_libpath[old_path_len] = '\0';
  151.  
  152.    return DosSetExtLIBPATH(old_libpath, begin_end_flag);
  153. }
  154.  
  155. /* Private subroutine to prepend to either LIBPATH extension */
  156. static APIRET prepend_eitherlibpath(PCSZ path, ULONG begin_end_flag)
  157. {
  158.    size_t path_len = strlen(path);
  159.    APIRET rc;
  160.    UCHAR old_libpath[1024], new_libpath[1024];
  161.  
  162.    if (path_len == 0)
  163.       return ERROR_INVALID_PARAMETER;
  164.  
  165.    if (path_len > 1023)
  166.       return ERROR_NOT_ENOUGH_MEMORY;
  167.  
  168.    if ((rc = DosQueryExtLIBPATH(old_libpath, begin_end_flag)) != NO_ERROR)
  169.       return rc;
  170.  
  171.    memcpy(new_libpath, path, path_len);
  172.    if (old_libpath[0] == '\0')
  173.    {
  174.       /* Remove any trailing semi-colon. */
  175.       if (path[path_len-1] == ';')
  176.          --path_len;
  177.  
  178.       new_libpath[path_len] = '\0';
  179.    }
  180.    else
  181.    {
  182.       register size_t old_path_len = strlen(old_libpath);
  183.  
  184.       /* Adjust for any trailing semi-colon returned by API. */
  185.       if (old_libpath[old_path_len-1] == ';')
  186.          old_libpath[--old_path_len] = '\0';
  187.  
  188.       /* Ensure we have a semi-colon separator. */
  189.       if (path[path_len-1] != ';')
  190.          new_libpath[path_len++] = ';';
  191.  
  192.       if (path_len + old_path_len > 1023)
  193.          return ERROR_NOT_ENOUGH_MEMORY;
  194.  
  195.       memcpy(&new_libpath[path_len], old_libpath, old_path_len+1);
  196.    }
  197.  
  198.    return DosSetExtLIBPATH(new_libpath, begin_end_flag);
  199. }
  200.  
  201. /* Entry point to set the BEGINLIBPATH extension. */
  202. unsigned long set_beginlibpath(void)
  203. {
  204.    return set_eitherlibpath(BEGIN_LIBPATH);
  205. }
  206.  
  207. /* Entry point to set the ENDLIBPATH extension. */
  208. unsigned long set_endlibpath(void)
  209. {
  210.    return set_eitherlibpath(END_LIBPATH);
  211. }
  212.  
  213. /* Entry to clear the BEGINLIBPATH extension */
  214. unsigned long clear_beginlibpath(void)
  215. {
  216.    return DosSetExtLIBPATH("", BEGIN_LIBPATH);
  217. }
  218.  
  219. /* Entry to clear the ENDLIBPATH extension */
  220. unsigned long clear_endlibpath(void)
  221. {
  222.    return DosSetExtLIBPATH("", END_LIBPATH);
  223. }
  224.  
  225. /* Entry to append to the BEGINLIBPATH extension */
  226. unsigned long append_beginlibpath(const char * path)
  227. {
  228.    return append_eitherlibpath(path, BEGIN_LIBPATH);
  229. }
  230.  
  231. /* Entry to append to the ENDLIBPATH extension */
  232. unsigned long append_endlibpath(const char * path)
  233. {
  234.    return append_eitherlibpath(path, END_LIBPATH);
  235. }
  236.  
  237. /* Entry to prepend to the BEGINLIBPATH extension */
  238. unsigned long prepend_beginlibpath(const char * path)
  239. {
  240.    return prepend_eitherlibpath(path, BEGIN_LIBPATH);
  241. }
  242.  
  243. /* Entry to prepend to the ENDLIBPATH extension */
  244. unsigned long prepend_endlibpath(const char * path)
  245. {
  246.    return prepend_eitherlibpath(path, END_LIBPATH);
  247. }
  248.  
  249. /* Entry to query to the BEGINLIBPATH extension */
  250. unsigned long query_beginlibpath(char * path_list)
  251. {
  252.    return DosQueryExtLIBPATH(path_list, BEGIN_LIBPATH);
  253. }
  254.  
  255. /* Entry to query to the ENDLIBPATH extension */
  256. unsigned long query_endlibpath(char * path_list)
  257. {
  258.    return DosQueryExtLIBPATH(path_list, END_LIBPATH);
  259. }
  260.