home *** CD-ROM | disk | FTP | other *** search
/ gdead.berkeley.edu / gdead.berkeley.edu.tar / gdead.berkeley.edu / pub / cad-tools / ciftomann.tar / CD / paths.c < prev    next >
C/C++ Source or Header  |  1988-01-28  |  10KB  |  378 lines

  1. /*
  2.  * paths.c
  3.  *
  4.  * Written by John Ousterhout.  Modified for VMS by Gile Billingsley.
  5.  * sccsid "%W%  %G%"
  6.  *
  7.  * This file contains routines that a) implement a path mechanism, whereby
  8.  * several places may be searched for files, and b) provide a defaulting
  9.  * mechanism for file name extensions.
  10.  *
  11.  *     KIC is a graphics editor that was developed by the integrated
  12.  * circuits group of the Electronics Research Laboratory and the
  13.  * Department of Electrical Engineering and Computer Sciences at
  14.  * the University of California, Berkeley, California.  The program
  15.  * KIC is available free of charge to any interested party.
  16.  * The sale, resale, or use of this program for profit without the
  17.  * express written consent of the Department of Electrical Engineering
  18.  * and Computer Sciences, University of California, Berkeley, California,
  19.  * is forbidden.
  20.  */
  21.  
  22. #include <stdio.h>
  23. #ifndef vms
  24. #include <pwd.h>
  25. #endif
  26. #include <ctype.h>
  27.  
  28. #ifdef TEST
  29. main(){
  30.     char buf[100];
  31.     int i,j,k,l,n;
  32.     FILE *POpen();
  33.     char *PGetPath();
  34.     char *prealname;
  35.     PSetPath(" ~ ~.foo dma1:[kic.cells] ");
  36.     printf("PATH? %s\n",PGetPath());
  37.     for(;;){
  38.     scanf("%s",buf);
  39.     POpen(buf, "r", NULL, &prealname);
  40.     printf("%s\n",prealname);
  41.     }
  42.     }
  43. #endif
  44.  
  45. #define    FALSE    0
  46. #define    TRUE    1
  47. #define    TILDA    '~'
  48.  
  49. /* Library routines */
  50.  
  51. char *strcpy(), *strncpy(), *index();
  52.  
  53. /* The following string holds the current path,which consists of a bunch
  54.  * of directory names separated by spaces.
  55.  */
  56.  
  57. #define PATHSIZE 161 
  58. static char path[PATHSIZE];
  59.  
  60. int
  61. PConvertTilde(psource, pdest, size)
  62. char **psource;            /* Pointer to a pointer to the source string */
  63. char **pdest;            /* Pointer to a pointer to the dest. string */
  64. int *size;            /* Pointer to no. bytes available at pdest */
  65.  
  66. /*-----------------------------------------------------------------------------
  67.  *    This routine converts tilde notation into standard directory names.
  68.  *
  69.  *    Results:
  70.  *    If the conversion was done successfully, then TRUE is returned.
  71.  *    If a user name couldn't be found in the password file, then
  72.  *    FALSE is returned.
  73.  *
  74.  *    Side Effects:
  75.  *    If the first character of the string indicated by psource is a
  76.  *    tilde ("~") then the subsequent user name is converted to a login
  77.  *    directory name and stored in the string indicated by pdest.  Then
  78.  *    remaining characters in the file name at psource are copied to
  79.  *    pdest and both pointers are updated.  Upon return, psource points
  80.  *    to the terminating character in the source file name and pdest
  81.  *    points to the next character after the last character in the file
  82.  *    name at that location.  If a tilde cannot be converted because the
  83.  *    user name cannot be found, psource is still advanced past the current
  84.  *    entry, but pdest is unaffected.  At most size characters will be
  85.  *    stored at pdest, and the size is decremented by the number of
  86.  *    characters we actually stored.
  87.  *-----------------------------------------------------------------------------
  88.  */
  89.  
  90.     {
  91.     register char *ps, *pd;
  92.  
  93. #ifndef vms
  94.     struct passwd *passwd, *getpwnam();
  95. #endif
  96.  
  97.     char username[35];
  98.     int i, length;
  99.  
  100.     ps = *psource;
  101.     if (*ps == TILDA){
  102.     /* Copy the user name into a string (at most 34 characters), then
  103.      * read the password file entry for the user, then grab out the
  104.       * login directory.
  105.      */
  106.  
  107. #ifdef vms
  108.     ps++;
  109.     if(getenv("HOME") == NULL)
  110. #else
  111.     pd = username;
  112.     for (i=0; ; i++)
  113.         {
  114.         *pd = *++ps;
  115.         if (isspace(*pd) || (*pd=='\0') || (*pd=='/')) break;
  116.         if (i < 34) pd++;
  117.         }
  118.     *pd = '\0';
  119.     passwd = getpwnam(username);
  120.  
  121.     /* If the entry can't be found, skip the source entry and return */
  122.  
  123.     if (passwd == NULL)
  124. #endif
  125.         {
  126.         while ((*ps != '\0') && !isspace(*ps)) ps++;
  127.         *psource = ps;
  128.         return FALSE;
  129.         }
  130.  
  131. #ifdef vms
  132.     length = strlen(getenv("HOME"));
  133.     /* remove closing bracket */
  134.     --length;
  135.     if (length > *size) length = *size;
  136.     strncpy(*pdest, getenv("HOME"), length);
  137.     *size -= length;
  138.     pd = *pdest+length;
  139. #else
  140.     length = strlen(passwd->pw_dir);
  141.     if (length > *size) length = *size;
  142.     strncpy(*pdest, passwd->pw_dir, length);
  143.     *size -= length;
  144.     pd = *pdest+length;
  145. #endif
  146.     }
  147.     else pd = *pdest;
  148.  
  149.     /* Copy the rest of the directory name from the source to the dest. */
  150.  
  151.     while ((*ps != '\0') && !isspace(*ps))
  152.     if (*size > 0)
  153.         {
  154.         *pd++ = *ps++;
  155.         (*size)--;
  156.         }
  157.     else ps++;
  158. #ifdef vms
  159.     /* insert closing bracket for tilda expansion */
  160.     if (**psource == TILDA) {
  161.     if (*size > 0) {
  162.         *pd++ = ']';
  163.         (*size)--;
  164.         }
  165.     else
  166.         *(pd - 1) = ']';
  167.     }
  168. #endif
  169.     *psource = ps;
  170.     *pdest = pd;
  171.     return TRUE;
  172.     }
  173.  
  174. int
  175. PSetPath(string)
  176. char *string;            /* Pointer to a string that is to become
  177.                  * the new fle search path.  Must consist
  178.                  * of one or more directory names separated
  179.                  * by white space.  ~ notation is ok.
  180.                  */
  181.  
  182. /*-----------------------------------------------------------------------------
  183.  *    PSetPath sets up the current search path.
  184.  *
  185.  *    Results:
  186.  *    FALSE is returned if one or more of the paths contained a tilde
  187.  *    notation that couldn't be converted.  Otherwise TRUE is returned.
  188.  *
  189.  *    Side Effects:
  190.  *    The string is stored as the current path, and all entries with
  191.  *    tilde notation are converted to non-tilde notation.  Tilde entries
  192.  *    that cannot be converted are ignored.  Note:  only PATHSIZE total
  193.  *    bytes of path are stored, after tilde conversion.  Excess bytes
  194.  *    are truncated.
  195.  *-----------------------------------------------------------------------------
  196.  */
  197.  
  198.     {
  199.     int result, spaceleft;
  200.     char *p;
  201.  
  202.     if(string[0] == '\0')
  203.       return(path[0] = '\0');
  204.     result = TRUE;
  205.     spaceleft = PATHSIZE-1;
  206.     p = path;
  207.     while (*string != '\0') {
  208.     if (spaceleft <= 0) break;
  209.     while (isspace(*string)) string++;
  210.     if (!PConvertTilde(&string, &p, &spaceleft)) result = FALSE;
  211.     else if (spaceleft-- > 0) *p++ = ' ';
  212.     }
  213.     *p = '\0';
  214.     return result;
  215.     }
  216.  
  217. char *
  218. PGetPath()
  219.  
  220. /*-----------------------------------------------------------------------------
  221.  *    This routine merely returns a pointer to the current path.
  222.  *
  223.  *    Results:
  224.  *    The address of the current path (with all tildes expanded).
  225.  *
  226.  *    Side Effects:    None.
  227.  *-----------------------------------------------------------------------------
  228.  */
  229.  
  230.     {
  231.     return path;
  232.     }
  233.  
  234. FILE *
  235. POpen(file, mode, ext, prealname)
  236. char *file;            /* Name of the file to be opened. */
  237. char *mode;            /* The file mode, as given to fopen. */
  238. char *ext;            /* The default extension fo the file, or
  239.                  * NULL if there is to be no default extension.
  240.                  */
  241. char **prealname;        /* Pointer to a location that will be filled
  242.                  * in with the address of the real name of
  243.                  * the file that was successfully opened.
  244.                  * If NULL, then nothing is stored.
  245.                  */
  246.  
  247. /*-----------------------------------------------------------------------------
  248.  *    This routine does a file lookup using the current path and
  249.  *    supplying a default extension.
  250.  *
  251.  *    Results:
  252.  *    A pointer to a FILE, or NULL if the file couldn't be found.
  253.  *
  254.  *    Side Effects:
  255.  *    If the file name doesn't contain the first character of ext
  256.  *    then ext is appended to the file name, and this routine is
  257.  *    called recursively with the new name.  If that succeeeds,
  258.  *    then we are done.  Otherwise, if the first character of the
  259.  *    file name is "~" or "/" then we try to look up the file with
  260.  *    the original name, doing tilde expansion of course.  If the
  261.  *    first character isn't one of those two characters, we go through
  262.  *    the current path trying to look up the file once for each path
  263.  *    entry by prepending the path entry to the original file name.
  264.  *    This concatenated name is stored in a static string and made
  265.  *    available to the caller through prealname if the open succeeds.
  266.  *    Note: the static string will be trashed on the next call to this
  267.  *    routine.  Also, note that no individual file name is allowed to
  268.  *    be more than NAMESIZE characters long.  Excess characters are lost.
  269.  *-----------------------------------------------------------------------------
  270.  */
  271.  
  272.     {
  273. #ifdef vms
  274. #define NAMESIZE 129
  275. #else
  276. #define NAMESIZE 50
  277. #endif
  278.     static char realname[NAMESIZE];
  279.     char extendedname[NAMESIZE], *p, *p2;
  280.     int length, spaceleft;
  281.     FILE *f;
  282.  
  283.     if(path[0] == '\0' && file[0] != TILDA)
  284.       return(fopen(file,mode));
  285.  
  286.     /* See if we must supply a default extension.  If so, then do it
  287.      * and call this routine recursively.
  288.      */
  289.  
  290.     if (prealname != NULL) *prealname = realname;
  291.     if (ext != NULL)
  292.     if (index(file, ext[0]) == 0)
  293.         {
  294.         length = strlen(file);
  295.         if (length >= NAMESIZE) length = NAMESIZE-1;
  296.         strncpy(extendedname, file, length);
  297.         p = &extendedname[length];
  298.         length = NAMESIZE-1-length;
  299.         if (length > 0) strncpy(p, ext, length);
  300.         extendedname[NAMESIZE-1] = '\0';
  301.         f = POpen(extendedname, mode, (char *) NULL, prealname);
  302.         if (f != NULL) return f;
  303.         }
  304.  
  305.     /* OK, the default extension either wasn't necessary or didn't work.
  306.      * Now try the original name.  If it starts with a ~ or /, look it
  307.      * up directly.
  308.      */
  309.  
  310. #ifdef vms
  311.     if ((index(file,':') != 0) || (index(file,'[') != 0))
  312. #else
  313.     if (file[0] == '/')
  314. #endif
  315.     {
  316.     strncpy(realname, file, NAMESIZE-1);
  317.     realname[NAMESIZE-1] = '\0';
  318.     return fopen(realname, mode);
  319.     }
  320.  
  321. #ifndef vms
  322.     if (file[0] == TILDA)
  323.     {
  324.     p = realname;
  325.     length = NAMESIZE-1;
  326.     if (!PConvertTilde(&file, &p, &length)) return NULL;
  327.     *p = '\0';
  328.     return fopen(realname, mode);
  329.     }
  330. #endif
  331.  
  332.     /* Last, but not least, try going through the path. */
  333.  
  334.     p = path;
  335.     while (*p != '\0')
  336.     {
  337.     spaceleft = NAMESIZE-1;
  338.     p2 = realname;
  339.     while (isspace(*p)) p++;
  340. #ifdef vms
  341.     if(*p == '.' && (isspace(*(p+1)) || *(p+1) == '\0')){
  342.         ++p;
  343.         if((f = fopen(file, mode)) != NULL)
  344.         return f;
  345.         else
  346.         continue;
  347.         }
  348. #endif
  349.     while ((*p != '\0') && !isspace(*p))
  350.         if (spaceleft-- > 0) *p2++ = *p++;
  351.         else p++;
  352. #ifndef vms
  353.     if (spaceleft-- > 0) *p2++ = '/';
  354. #endif
  355.     if (spaceleft > 0) strncpy(p2, file, spaceleft);
  356.     realname[NAMESIZE-1] = '\0';
  357.     f = fopen(realname, mode);
  358.     if (f != NULL) return f;
  359.     }
  360.     return NULL;
  361.     }
  362.  
  363. #ifdef vms
  364. char *index(s,c)
  365.     char *s,c;
  366.     {
  367.     char buf[2];
  368.     int i,strcspn();
  369.     buf[0] = c;
  370.     buf[1] = NULL;
  371.     i = strcspn(s,buf);
  372.     if(i != strlen(s))
  373.     return( &s[i] );
  374.     else
  375.     return( NULL );
  376.     }
  377. #endif
  378.