home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / forut062.zip / ForUtil-0.62 / lib / environment.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  11KB  |  437 lines

  1. #ifndef lint
  2. static char rcsId[]="$Header: /usr/local/rcs/ForUtil/lib/RCS/environment.c,v 1.21 1996/08/27 19:19:48 koen Exp koen $";
  3. #endif
  4. /*****
  5. * environment.c : environment scanning routines for libforUtil
  6. *
  7. * This file Version:     $Revision: 1.21 $
  8. *
  9. * Creation date:     03/18/1996 
  10. * Last Modification:    $Date: 1996/08/27 19:19:48 $ 
  11. * By:            $Author: koen $
  12. * Current State:    $State: Exp $
  13. * Author:        koen
  14. * (C)1995 Ripley Software Development
  15. * All Rights Reserved
  16. *****/ 
  17. /*****
  18. * ChangeLog
  19. * $Log: environment.c,v $
  20. * Revision 1.21  1996/08/27 19:19:48  koen
  21. * msdos related updates
  22. *
  23. * Revision 1.20  1996/08/07 21:17:40  koen
  24. * moved all msdos passwd emulation routines to msdospwd.c
  25. *
  26. * Revision 1.19  1996/08/02 14:52:52  koen
  27. * Replaced forLibP.h with forutil.h
  28. *
  29. * Revision 1.18  1996/07/30 02:02:37  koen
  30. * Reordered include files.
  31. *
  32. * Revision 1.17  1996/07/16 09:19:02  koen
  33. * added an extra LOGIN if for msdos implementation of getpwuid. 
  34. * Corrected a bug in make_directory
  35. *
  36. * Revision 1.16  1996/05/06 00:36:43  koen
  37. * Adapted for MSDOS: added bogus getpwent & getpwnam functions.
  38. *
  39. * Revision 1.15  1996/03/08 15:32:11  koen
  40. * Moved all Open Include database stuff to database.c
  41. *
  42. * Revision 1.14  1996/03/06 17:18:04  koen
  43. * Working on open_selected stuff: a version which uses dbm, and a simple one 
  44. * not using dbm. Removed the previously existing XXXXSearch routines 
  45. * completely, the new routines are much faster.
  46. *
  47. * Revision 1.13  1996/02/28 02:55:52  koen
  48. * Added make_directory and string_to_file routines.
  49. *
  50. * Revision 1.12  1996/02/19 01:29:38  koen
  51. * Added lots of #ifdef VERBOSE fprintf... #endif lines.
  52. *
  53. * Revision 1.11  1996/02/14 01:52:58  koen
  54. * Added the scan_for_(home,env_var,environment) routines + stuff to compile 
  55. * misc.c standalone if TEST is defined.
  56. *
  57. * Revision 1.10  1996/02/13 19:21:00  koen
  58. * Removed all x-related stuff to NeditUtils.c and GenUtils.c
  59. * Moved the file-handling routines from GenUtils.c to here.
  60. *
  61. * Revision 1.8  1995/11/24  03:26:17  koen
  62. * Added the XPromptMessage function: a wrapper for the DialogF of type 
  63. * DF_PROMPT.
  64. * Corrected return values for CheckIfSaved.
  65. *
  66. * Revision 1.7  1995/11/22  03:26:09  koen
  67. * Changed CheckIfSaved to use DialogF instead of PostWarningBox. The latter
  68. * doesn't seem to work under Linux.
  69. *
  70. * Revision 1.6  1995/11/17  01:44:45  koen
  71. * Corrected a number of small bugs occuring in lint. Removed all runtime
  72. * tracing information.
  73. *
  74. * Revision 1.5  1995/11/14  04:08:10  koen
  75. * Code clean up.
  76. *
  77. * Revision 1.4  1995/11/12  23:02:41  koen
  78. * modified get_home_dir, user's home directory is now returned in the
  79. * argument **home_dir. Previous form returned a char*, which gave
  80. * a casting warning when used.
  81. *
  82. * Revision 1.2  1995/10/31  17:32:46  koen
  83. * new source file Id record
  84. *
  85. * Revision 1.1  1995/10/09  01:49:43  root
  86. * Initial revision
  87. *
  88. *****/
  89. /* needed to prevent multiple variable decls under MSDOS in sysdeps.h */
  90. #define LIBRARY_OBJECT
  91.  
  92. /* include this before anything else */
  93. #ifdef HAVE_CONFIG_H
  94. #include "autoconf.h"
  95. #endif
  96.  
  97. #include <stdio.h> 
  98. #include <stdlib.h>
  99. #include <ctype.h> 
  100. #include <errno.h>
  101. #include <fcntl.h>
  102. #include <string.h>
  103. #include <sys/types.h>
  104. #include <sys/stat.h>
  105.  
  106. #include "memmacros.h"
  107. #include "forutil.h"
  108. #include "msdospwd.h"
  109.  
  110. /*
  111. * permissions to use for directory creation, rwx for user, 
  112. * rx for group and others. Change if you do not like this.
  113. */
  114. #ifndef __MSDOS__
  115. #define DIR_PERM (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
  116. #endif
  117.  
  118. /****
  119. * Private data and function prototypes
  120. ****/
  121. static struct passwd *user_pwd = NULL;
  122.  
  123. /*****
  124. * get the user id of the current user
  125. * If root is using this, it's gonna get called every time, but what
  126. * the heck, root shouldn't be doing any development as root anyway...
  127. *****/
  128. static uid_t 
  129. get_user_id(void)
  130. {
  131.     static uid_t user_id;
  132.     if(user_id == 0)
  133.         user_id = getuid();
  134.     return(user_id);
  135. }
  136.  
  137. /*****
  138. * return a passwd for the current user.
  139. * If it fails, default to name <unknown> and \tmp as home dir and
  140. * tell the user what will happen.
  141. *****/
  142. static void 
  143. get_user_info(void)
  144. {
  145.     if(user_pwd == NULL)
  146.     {
  147.         /* get the user data from the passwd file */
  148.         user_pwd = getpwuid(get_user_id());
  149.         if(user_pwd == NULL)
  150.         {
  151.             static char *temp_path;
  152.             /*
  153.             * no passwd info found, set name fields to <unknown> and try
  154.             * to figure out what to use as pw_dir: try TMP, TEMP or /tmp 
  155.             */
  156.             if((temp_path = getenv("TMP")) == NULL)
  157.                 if((temp_path = getenv("TEMP")) == NULL)
  158. #ifdef __MSDOS__    /* current directory */
  159.                     temp_path = ".\\";
  160. #else
  161.                     temp_path = "/tmp";
  162. #endif
  163.             fprintf(stderr, "Hmm, I cannot figure out who you are. "
  164.                 "Using %s for temporary storage.\n",
  165.                 temp_path);
  166.             checked_malloc(user_pwd,1,struct passwd);
  167.             user_pwd->pw_name = "<unknown>";
  168.             user_pwd->pw_gecos = "<unknown>";
  169.             user_pwd->pw_dir = temp_path;
  170.         }
  171.     }
  172. }
  173.  
  174. /****
  175. * get the login name of the user
  176. ****/
  177. char 
  178. *get_user_login(void)
  179. {
  180.     get_user_info();
  181.     return(user_pwd->pw_name);
  182. }
  183.  
  184. /****
  185. * get the real name of the user
  186. ****/
  187. char 
  188. *get_user_name(void)
  189. {
  190.     get_user_info();
  191.     return(user_pwd->pw_gecos);
  192. }
  193.  
  194. /****
  195. * get the home directory of the user
  196. ****/
  197. void 
  198. get_home_dir(char **home_dir)
  199. {
  200.     get_user_info();
  201.     *home_dir = user_pwd->pw_dir;
  202.     return;
  203. }
  204.  
  205. /****
  206. * Scan for referenced home directories by the char ~ in a string
  207. ****/
  208. static void
  209. scan_for_home(char *file)
  210. {
  211.     char *newfile;
  212.     struct passwd *user_info = NULL;
  213.     char *chPtr = NULL;
  214.     int i = 0;
  215.  
  216.     /* scratch memory */
  217.     checked_alloca(newfile, MAXPATHLEN, char);
  218.  
  219.     /*
  220.     * Get the name of the user referred to. This scan stops when a separation
  221.     * character is encounterd.
  222.     */
  223.     for(chPtr = file+1, i = 0 ; 
  224.         *chPtr != '\0' && *chPtr != SLASH && *chPtr != ':' ; *chPtr++)
  225.         newfile[i++] = *chPtr;
  226.     newfile[i] = '\0';
  227.  
  228.     if(newfile[0] == '\0')    /* reference to the current user */
  229.     {
  230.         get_user_info();
  231.         sprintf(newfile, "%s%s", user_pwd->pw_dir, chPtr);
  232.     }
  233.     else     /* reference to another user. Get his home directory */
  234.     {
  235.         if((user_info = getpwnam(newfile)) == NULL)
  236.             return;
  237.         sprintf(newfile, "%s%s", user_info->pw_dir, chPtr);
  238.     }
  239.     strcpy(file, newfile);
  240. }
  241.  
  242. /****
  243. * Scan for an environment variable in the given string
  244. ****/
  245. static void
  246. scan_for_env_var(char *file)
  247. {
  248.     char *newfile;
  249.     char *chPtr = NULL, *envPtr = NULL;
  250.     int i;
  251.  
  252.     /* scratch space */
  253.     checked_alloca(newfile, MAXPATHLEN, char);
  254.  
  255.     /*
  256.     * Get the name of the env. var referred to. This scan stops when a 
  257.     * separation character or EOL is encounterd.
  258.     */
  259.     for(chPtr = file+1, i = 0 ; 
  260.         *chPtr != '\0' && *chPtr != SLASH && *chPtr != ':' ; *chPtr++)
  261.         newfile[i++] = *chPtr;
  262.     newfile[i] = '\0';
  263.  
  264.     /* no env. var of this name found, return and don't modify anything */
  265.     if((envPtr = getenv(newfile)) == NULL)
  266.         return;
  267.  
  268.     sprintf(newfile, "%s%s", envPtr, chPtr);
  269.     /* substitute the real value and return the modified string */
  270.     strcpy(file, newfile);
  271. }
  272.  
  273. /****
  274. * Scan for any environment variables or user's home directories
  275. * and replace them with their corresponding value.
  276. * Returns 1 if substitution took place, 0 if not.
  277. ****/
  278. int
  279. scan_for_environment(char *file)
  280. {
  281.     char *chPtr; 
  282.     int changed = 0;
  283.  
  284.     /* first strip out any whitespace */
  285.     stripspaces(file);
  286.  
  287.     for(chPtr = file ; *chPtr != '\0' ; *chPtr++)
  288.     {
  289.         switch(*chPtr)
  290.         {
  291.             case '~':
  292.                 /* home directory of current or other user */
  293.                 scan_for_home(chPtr);
  294.                 changed = 1;
  295.                 break;
  296. #ifdef __MSDOS__    /* msdos environment vars begin with a percent sign */
  297.             case '%':
  298. #else
  299.             case '$':
  300. #endif
  301.                 /* environment variable */
  302.                 scan_for_env_var(chPtr);
  303.                 changed = 1;
  304.                 break;
  305.         }
  306.     }
  307.     return(changed);
  308. }
  309.  
  310. /*****
  311. * make_directory: create a directory dir_to_make
  312. *****/
  313. int
  314. make_directory(char *dir_to_make)
  315. {
  316.     char *temp, *ldir, *chPtr;
  317.     char *curr_dir;
  318.     int r_val;
  319.  
  320.     curr_dir = getcwd(NULL, MAXPATHLEN);    /* getcwd allocates this for us */
  321.  
  322.     checked_alloca(temp, MAXPATHLEN, char);
  323.     checked_alloca(ldir, MAXPATHLEN, char);
  324.  
  325.     /* make a local copy of the given string, we do not want to alter it */
  326.     strncpy(temp, dir_to_make, strlen(dir_to_make)+1);
  327.     /* scan for any environment stuff inside */
  328.     scan_for_environment(temp);
  329.     /* check for a leading directory. If not prepend current path*/
  330.     if(temp[0] != '.' && temp[0] != SLASH)
  331.     {
  332.         sprintf(ldir,"%s%s%s",curr_dir, CHAR_SLASH, temp);
  333.         strncpy(temp,ldir,strlen(ldir)+1);
  334.         strcpy(ldir,"");
  335.     }
  336.     /* test if we can cd to this dir */
  337.     if(((r_val = chdir(temp)) == -1) && errno == ENOENT)
  338.     {
  339.         /* initialise the directory tree, subdirectory by subdirectory. */
  340.         if(temp[0] == SLASH)
  341.             strcpy(ldir, CHAR_SLASH);
  342.         else
  343.             strcpy(ldir,"");
  344.         chPtr = strtok(temp, CHAR_SLASH);
  345.         strcat(ldir, chPtr);
  346.         strcat(ldir, CHAR_SLASH);
  347.         /*
  348.         * recurse through the directories to make. strtok always gives the first
  349.         * part of the directory to create.
  350.         */
  351.         for(chPtr = strtok(NULL, CHAR_SLASH);
  352.             chPtr != NULL; chPtr = strtok(NULL, CHAR_SLASH))
  353.         {
  354.             strcat(ldir, chPtr);
  355.             /* first try to cd to the given dir. */
  356.             if((r_val = chdir(ldir)) == -1 && errno == ENOENT)
  357.             {
  358.                 /* if we fail, create it. */
  359. #ifdef __MSDOS__
  360.                 r_val = mkdir(ldir);
  361. #else
  362.                 r_val = mkdir(ldir, DIR_PERM);
  363. #endif
  364.                 if(r_val)
  365.                 {
  366.                     chdir(curr_dir);
  367.                     free(curr_dir);
  368.                     return(r_val);
  369.                 }
  370.             }
  371.             strcat(ldir, CHAR_SLASH);
  372.         }
  373.     }
  374.     else
  375.     /* directory already exists */
  376.     {
  377.         chdir(curr_dir);
  378.         free(curr_dir);
  379.         return(0); 
  380.     }
  381.     chdir(curr_dir);
  382.     free(curr_dir);
  383.     printf("Created directory %s\n", dir_to_make);
  384.     return(r_val);
  385. }
  386.  
  387. /****
  388. * string_to_file: save the given string to a given file name
  389. * In:
  390. *    text: text to save to file
  391. *    filename: file to save to
  392. * Returns:
  393. *    0 on success, -1 on failure and errno is set 
  394. ****/
  395. int
  396. string_to_file(char *text, char *filename)
  397. {
  398.     int len;
  399.     FILE *fp;
  400.  
  401.     /* scan for any environment variables in here */
  402.     scan_for_environment(filename);
  403.  
  404.     /* try to open a file with the given name */
  405. #ifndef __MSDOS__
  406.     if ((fp = fopen(filename,"w")) == NULL) 
  407. #else
  408.     if ((fp = fopen(filename,"wb")) == NULL) 
  409. #endif
  410.         return(-1);
  411.     /* add a newline to the text if it isn't already there */
  412.     len = strlen(text); 
  413.     if(text[len-1] != '\n')
  414.         text[len++]= '\n'; 
  415.     /* flush the contents of text to the given file */
  416.     fwrite(text, sizeof(char), len, fp);
  417.     /* close the file */
  418.     if (fclose(fp))
  419.         return(-1);
  420.     return(0);
  421. }
  422.  
  423. /****
  424. * Check if file exists by statting it.
  425. * returns 0 on failure, size of file on success.
  426. * This function does not test if the file is writable.
  427. ****/
  428. unsigned long
  429. check_if_file_exists(char *file)
  430. {
  431.     struct stat buf;
  432.     if(stat(file, &buf))
  433.         return(0);
  434.     return((unsigned long)buf.st_size);
  435. }
  436.