home *** CD-ROM | disk | FTP | other *** search
/ ftp.uv.es / 2014.11.ftp.uv.es.tar / ftp.uv.es / pub / unix / aix-rs6000 / elm2.3.11.AIX3.1.5.Z / elm2.3.11.AIX3.1.5 / src / file_util.c < prev    next >
C/C++ Source or Header  |  1991-11-26  |  9KB  |  395 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: file_util.c,v 4.1 90/04/28 22:43:04 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1986, 1987 Dave Taylor
  8.  *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log:    file_util.c,v $
  17.  * Revision 4.1  90/04/28  22:43:04  syd
  18.  * checkin of Elm 2.3 as of Release PL0
  19.  * 
  20.  *
  21.  ******************************************************************************/
  22.  
  23. /** File oriented utility routines for ELM 
  24.  
  25. **/
  26.  
  27. #include "headers.h"
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #include <ctype.h>
  31. #include <errno.h>
  32.  
  33. #ifdef BSD
  34. # undef tolower
  35. #endif
  36.  
  37. #include <signal.h>
  38. #include <errno.h>
  39.  
  40. #ifdef BSD
  41. # include <sys/wait.h>
  42. #endif
  43.  
  44. extern int errno;        /* system error number */
  45.  
  46. char *error_name(), *error_description(), /* *strcpy(), */ *getlogin();
  47. long  fsize();
  48.  
  49. long
  50. bytes(name)
  51. char *name;
  52. {
  53.     /** return the number of bytes in the specified file.  This
  54.         is to check to see if new mail has arrived....  (also
  55.         see "fsize()" to see how we can get the same information
  56.         on an opened file descriptor slightly more quickly)
  57.     **/
  58.  
  59.     int ok = 1;
  60.     extern int errno;    /* system error number! */
  61.     struct stat buffer;
  62.  
  63.     if (stat(name, &buffer) != 0)
  64.       if (errno != 2) {
  65.         dprint(1,(debugfile,
  66.              "Error: errno %s on fstat of file %s (bytes)\n", 
  67.              error_name(errno), name));
  68.         Write_to_screen("\n\rError attempting fstat on file %s!\n\r",
  69.              1, name);
  70.         Write_to_screen("** %s - %s. **\n\r", 2, error_name(errno),
  71.           error_description(errno));
  72.         emergency_exit();
  73.       }
  74.       else
  75.         ok = 0;
  76.     
  77.     return(ok ? (long) buffer.st_size : 0L);
  78. }
  79.  
  80. int
  81. can_access(file, mode)
  82. char *file; 
  83. int   mode;
  84. {
  85.     /** returns ZERO iff user can access file or "errno" otherwise **/
  86.  
  87.     int the_stat = 0, pid, w; 
  88.     struct stat stat_buf;
  89.     void _exit(), exit();
  90. #if defined(BSD) && !defined(WEXITSTATUS)
  91.     union wait status;
  92. #else
  93.     int status;
  94. #endif
  95. #ifdef VOIDSIG
  96.     register void (*istat)(), (*qstat)();
  97. #else
  98.     register int (*istat)(), (*qstat)();
  99. #endif
  100.     
  101. #ifdef VFORK
  102.     if ((pid = vfork()) == 0) {
  103. #else
  104.     if ((pid = fork()) == 0) {
  105. #endif
  106.       setgid(groupid);
  107.       setuid(userid);        /** back to normal userid **/
  108.  
  109.       errno = 0;
  110.  
  111.       if (access(file, mode) == 0) 
  112.         _exit(0);
  113.       else 
  114.         _exit(errno != 0? errno : 1);    /* never return zero! */
  115.       _exit(127);
  116.     }
  117.  
  118.     istat = signal(SIGINT, SIG_IGN);
  119.     qstat = signal(SIGQUIT, SIG_IGN);
  120.  
  121.     while ((w = wait(&status)) != pid && w != -1)
  122.         ;
  123.  
  124. #if    defined(WEXITSTATUS)
  125.     /* Use POSIX macro if defined */
  126.     the_stat = WEXITSTATUS(status);
  127. #else
  128. #ifdef BSD
  129.     the_stat = status.w_retcode;
  130. #else
  131.     the_stat = status >> 8;
  132. #endif
  133. #endif    /*WEXITSTATUS*/
  134.  
  135.     signal(SIGINT, istat);
  136.     signal(SIGQUIT, qstat);
  137.     if (the_stat == 0) {
  138.       if (stat(file, &stat_buf) == 0) {
  139.         w = stat_buf.st_mode & S_IFMT;
  140. #ifdef S_IFLNK
  141.         if (w != S_IFREG && w != S_IFLNK)
  142. #else
  143.         if (w != S_IFREG)
  144. #endif
  145.           the_stat = 1;
  146.       }
  147.     }
  148.  
  149.     return(the_stat);
  150. }
  151.  
  152. int
  153. can_open(file, mode)
  154. char *file, *mode;
  155. {
  156.     /** Returns 0 iff user can open the file.  This is not
  157.         the same as can_access - it's used for when the file might
  158.         not exist... **/
  159.  
  160.     FILE *fd;
  161.     int the_stat = 0, pid, w, preexisted = 0; 
  162.     void _exit(), exit();
  163. #if defined(BSD) && !defined(WEXITSTATUS)
  164.     union wait status;
  165. #else
  166.     int status;
  167. #endif
  168. #ifdef VOIDSIG
  169.     register void (*istat)(), (*qstat)();
  170. #else
  171.     register int (*istat)(), (*qstat)();
  172. #endif
  173.     
  174. #ifdef VFORK
  175.     if ((pid = vfork()) == 0) {
  176. #else
  177.     if ((pid = fork()) == 0) {
  178. #endif
  179.       setgid(groupid);
  180.       setuid(userid);        /** back to normal userid **/
  181.       errno = 0;
  182.       if (access(file, ACCESS_EXISTS) == 0)
  183.         preexisted = 1;
  184.       if ((fd = fopen(file, mode)) == NULL)
  185.         _exit(errno);
  186.       else {
  187.         fclose(fd);        /* don't just leave it open! */
  188.         if(!preexisted)    /* don't leave it if this test created it! */
  189.           unlink(file);
  190.         _exit(0);
  191.       }
  192.       _exit(127);
  193.     }
  194.  
  195.     istat = signal(SIGINT, SIG_IGN);
  196.     qstat = signal(SIGQUIT, SIG_IGN);
  197.  
  198.     while ((w = wait(&status)) != pid && w != -1)
  199.         ;
  200.  
  201. #ifdef WEXITSTATUS
  202.     the_stat = WEXITSTATUS(status);
  203. #else
  204. #ifdef BSD
  205.     the_stat = status.w_retcode;
  206. #else
  207.     the_stat = status >> 8;
  208. #endif
  209. #endif /*WEXITSTATUS*/
  210.     
  211.     signal(SIGINT, istat);
  212.     signal(SIGQUIT, qstat);
  213.  
  214.     return(the_stat);
  215. }
  216.  
  217. int
  218. copy(from, to)
  219. char *from, *to;
  220. {
  221.     /** this routine copies a specified file to the destination
  222.         specified.  Non-zero return code indicates that something
  223.         dreadful happened! **/
  224.  
  225.     FILE *from_file, *to_file;
  226.     char buffer[VERY_LONG_STRING];
  227.     
  228.     if ((from_file = fopen(from, "r")) == NULL) {
  229.       dprint(1, (debugfile, "Error: could not open %s for reading (copy)\n",
  230.          from));
  231.       error1("Could not open file %s.", from);
  232.       return(1);
  233.     }
  234.  
  235.     if ((to_file = fopen(to, "w")) == NULL) {
  236.       dprint(1, (debugfile, "Error: could not open %s for writing (copy)\n",
  237.          to));
  238.       error1("Could not open file %s.", to);
  239.       return(1);
  240.     }
  241.  
  242.     while (fgets(buffer, VERY_LONG_STRING, from_file) != NULL)
  243.       if (fputs(buffer, to_file) == EOF) {
  244.           Write_to_screen("\n\rWrite failed to tempfile in copy\n\r", 0);
  245.           perror(to);
  246.           fclose(to_file);
  247.           fclose(from_file);
  248.           return(1);
  249.       }
  250.     fclose(from_file);
  251.         if (fclose(to_file) == EOF) {
  252.       Write_to_screen("\n\rClose failed on tempfile in copy\n\r", 0);
  253.       perror(to);
  254.       return(1);
  255.     }
  256.     chown( to, userid, groupid);
  257.  
  258.     return(0);
  259. }
  260.  
  261. int
  262. append(fd, filename)
  263. FILE *fd;
  264. char *filename;
  265. {
  266.     /** This routine appends the specified file to the already
  267.         open file descriptor.. Returns non-zero if fails.  **/
  268.  
  269.     FILE *my_fd;
  270.     char buffer[VERY_LONG_STRING];
  271.     
  272.     if ((my_fd = fopen(filename, "r")) == NULL) {
  273.       dprint(1, (debugfile,
  274.         "Error: could not open %s for reading (append)\n", filename));
  275.       return(1);
  276.     }
  277.  
  278.     while (fgets(buffer, VERY_LONG_STRING, my_fd) != NULL)
  279.       if (fputs(buffer, fd) == EOF) {
  280.           Write_to_screen("\n\rWrite failed to tempfile in append\n\r", 0);
  281.           perror(filename);
  282.           rm_temps_exit();
  283.       }
  284.  
  285.     if (fclose(my_fd) == EOF) {
  286.       Write_to_screen("\n\rClose failed on tempfile in append\n\r", 0);
  287.       perror(filename);
  288.       rm_temps_exit();
  289.     }
  290.  
  291.     return(0);
  292. }
  293.  
  294. #define FORWARDSIGN    "Forward to "
  295. int
  296. check_mailfile_size(mfile)
  297. char *mfile;
  298. {
  299.     /** Check to ensure we have mail.  Only used with the '-z'
  300.         starting option. So we output a diagnostic if there is
  301.         no mail to read (including  forwarding).
  302.         Return 0 if there is mail,
  303.            <0 if no permission to check,
  304.            1 if no mail,
  305.            2 if no mail because mail is being forwarded.
  306.      **/
  307.  
  308.     char firstline[SLEN];
  309.     int retcode;
  310.     struct stat statbuf;
  311.     FILE *fp;
  312.  
  313.     /* see if file exists first */
  314.     if (access(mfile, ACCESS_EXISTS) != 0)
  315.       retcode = 1;                    /* no file */
  316.  
  317.     /* exists - now see if user has read access */
  318.     else if (can_access(mfile, READ_ACCESS) != 0)
  319.       retcode = -1;                    /* no perm */
  320.  
  321.     /* read access - now see if file has a reasonable size */
  322.     else if ((fp = fopen(mfile, "r")) == NULL)
  323.       retcode = -1;        /* no perm? should have detected this above! */
  324.     else if (fstat(fileno(fp), &statbuf) == -1) 
  325.       retcode = -1;                    /* arg error! */
  326.     else if (statbuf.st_size < 2)        
  327.       retcode = 1;    /* empty or virtually empty, e.g. just a newline */
  328.  
  329.     /* file has reasonable size - see if forwarding */
  330.     else if (fgets (firstline, SLEN, fp) == NULL)
  331.       retcode = 1;         /* empty? should have detected this above! */
  332.     else if (first_word(firstline, FORWARDSIGN))
  333.       retcode = 2;                    /* forwarding */
  334.  
  335.     /* not forwarding - so file must have some mail in it */
  336.     else
  337.       retcode = 0;
  338.  
  339.     /* now display the appropriate message if there isn't mail in it */
  340.     switch(retcode) {
  341.  
  342.     case -1:    printf("You have no permission to read %s!\n\r", mfile);
  343.             break;
  344.     case 1:        printf("You have no mail.\n\r");
  345.             break;
  346.     case 2:        no_ret(firstline) /* remove newline before using */
  347.             printf("Your mail is being forwarded to %s.\n\r",
  348.               firstline + strlen(FORWARDSIGN));
  349.             break;
  350.     }
  351.     return(retcode);
  352. }
  353.  
  354. create_readmsg_file()
  355. {
  356.     /** Creates the file ".current" in the users home directory
  357.         for use with the "readmsg" program.
  358.     **/
  359.  
  360.     FILE *fd;
  361.     char buffer[SLEN];
  362.  
  363.     sprintf(buffer,"%s/%s", home, readmsg_file);
  364.  
  365.     if ((fd = fopen (buffer, "w")) == NULL) {
  366.       dprint(1, (debugfile, 
  367.          "Error: couldn't create file %s - error %s (%s)\n",
  368.          buffer, error_name(errno), "create_readmsg_file"));
  369.       return;    /* no error to user */
  370.     }
  371.  
  372.     if (current)
  373.       fprintf(fd, "%d\n", headers[current-1]->index_number);
  374.     else
  375.       fprintf(fd, "\n");
  376.  
  377.     fclose(fd);
  378.     chown( buffer, userid, groupid);
  379. }
  380.  
  381. long fsize(fd)
  382. FILE *fd;
  383. {
  384.     /** return the size of the current file pointed to by the given
  385.         file descriptor - see "bytes()" for the same function with
  386.         filenames instead of open files...
  387.     **/
  388.  
  389.     struct stat buffer;
  390.  
  391.     (void) fstat(fileno(fd), &buffer);
  392.  
  393.     return( (long) buffer.st_size );
  394. }
  395.