home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / elvis184.zip / src / elvprsv.c < prev    next >
C/C++ Source or Header  |  1995-04-23  |  8KB  |  335 lines

  1. /* elvprsv.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    1500 SW Park #326
  6.  *    Portland OR, 97201
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the portable sources for the "elvprsv" program.
  12.  * "Elvprsv" is run by Elvis when Elvis is about to die.  It is also
  13.  * run when the computer boots up.  It is not intended to be run directly
  14.  * by the user, ever.
  15.  *
  16.  * Basically, this program does the following four things:
  17.  *    - It extracts the text from the temporary file, and places the text in
  18.  *    a file in the /usr/preserve directory.
  19.  *    - It adds a line to the /usr/preserve/Index file, describing the file
  20.  *    that it just preserved.
  21.  *    - It removes the temporary file.
  22.  *    -    It sends mail to the owner of the file, saying that the file was
  23.  *    preserved, and how it can be recovered.
  24.  *
  25.  * The /usr/preserve/Index file is a log file that contains one line for each
  26.  * file that has ever been preserved.  Each line of this file describes one
  27.  * preserved file.  The first word on the line is the name of the file that
  28.  * contains the preserved text.  The second word is the full pathname of the
  29.  * file that was being edited; for anonymous buffers, this is the directory
  30.  * name plus "/foo".
  31.  *
  32.  * If elvprsv's first argument (after the command name) starts with a hyphen,
  33.  * then the characters after the hyphen are used as a description of when
  34.  * the editor went away.  This is optional.
  35.  *
  36.  * The remaining arguments are all the names of temporary files that are
  37.  * to be preserved.  For example, on a UNIX system, the /etc/rc file might
  38.  * invoke it this way:
  39.  *
  40.  *    elvprsv "-the system went down" /tmp/elv_*.*
  41.  *
  42.  * This file contains only the portable parts of the preserve program.
  43.  * It must #include a system-specific file.  The system-specific file is
  44.  * expected to define the following functions:
  45.  *
  46.  *    char *ownername(char *filename)    - returns name of person who owns file
  47.  *
  48.  *    void mail(char *user, char *name, char *when, char *tmp)
  49.  *                    - tell user that file was preserved
  50.  */
  51.  
  52. /* OS/2, emx+gcc 0.9a */
  53. #ifdef OS2
  54. # include <sys/emx.h>   /* sigh...emx insists this be the first header file */
  55. #endif                  /* (used in wildcard.c, included below) */
  56.  
  57. #include <stdio.h>
  58. #include "config.h"
  59. #include "vi.h"
  60.  
  61. /* We include ctype.c here (instead of including just ctype.h and linking
  62.  * with ctype.o) because on some systems ctype.o will have been compiled in
  63.  * "large model" and the elvprsv program is to be compiled in "small model" 
  64.  * You can't mix models.  By including ctype.c here, we can avoid linking
  65.  * with ctype.o.
  66.  */
  67. #include "ctype.c"
  68.  
  69. void preserve P_((char *, char *));
  70. void main P_((int, char **));
  71.  
  72. #if AMIGA
  73. BLK tmpblk;
  74. # include "amiwild.c"
  75. # include "amiprsv.c"
  76. #endif
  77.  
  78. #if OSK
  79. # undef sprintf
  80. #endif
  81.  
  82. #if ANY_UNIX || OSK
  83. # include "prsvunix.c"
  84. #endif
  85.  
  86. #if MSDOS || TOS || OS2
  87. # include "prsvdos.c"
  88. # define WILDCARD_NO_MAIN
  89. # include "wildcard.c"
  90. #endif
  91.  
  92.  
  93. BLK    buf;
  94. BLK    hdr;
  95. BLK    name;
  96. int    rewrite_now;    /* boolean: should we send text directly to orig file? */
  97.  
  98.  
  99.  
  100. /* This function preserves a single file, and announces its success/failure
  101.  * via an e-mail message.
  102.  */
  103. void preserve(tname, when)
  104.     char    *tname;        /* name of a temp file to be preserved */
  105.     char    *when;        /* description of when the editor died */
  106. {
  107.     int    infd;        /* fd used for reading from the temp file */
  108.     FILE    *outfp;        /* fp used for writing to the recovery file */
  109.     FILE    *index;        /* fp used for appending to index file */
  110.     char    outname[100];    /* the name of the recovery file */
  111.     char    *user;        /* name of the owner of the temp file */
  112. #if AMIGA
  113.     char    *prsvdir;
  114. #endif
  115.     int    i;
  116.  
  117.     /* open the temp file */
  118.     infd = open(tname, O_RDONLY|O_BINARY);
  119.     if (infd < 0)
  120.     {
  121.         /* if we can't open the file, then we should assume that
  122.          * the filename contains wildcard characters that weren't
  123.          * expanded... and also assume that they weren't expanded
  124.          * because there are no files that need to be preserved.
  125.          * THEREFORE... we should silently ignore it.
  126.          * (Or loudly ignore it if the user was using -R)
  127.          */
  128.         if (rewrite_now)
  129.         {
  130.             perror(tname);
  131.         }
  132.         return;
  133.     }
  134.  
  135.     /* read the header and name from the file */
  136.     if (read(infd, hdr.c, BLKSIZE) != BLKSIZE
  137.      || read(infd, name.c, BLKSIZE) != BLKSIZE)
  138.     {
  139.         /* something wrong with the file - sorry */
  140.         fprintf(stderr, "%s: truncated header blocks\n", tname);
  141.         close(infd);
  142.         return;
  143.     }
  144.  
  145.     /* If the filename block contains an empty string, then Elvis was
  146.      * only keeping the temp file around because it contained some text
  147.      * that was needed for a named cut buffer.  The user doesn't care
  148.      * about that kind of temp file, so we should silently delete it.
  149.      */
  150.     if (name.c[0] == '\0' && name.c[1] == '\177')
  151.     {
  152.         close(infd);
  153.         unlink(tname);
  154.         return;
  155.     }
  156.  
  157.     /* If there are no text blocks in the file, then we must've never
  158.      * really started editing.  Discard the file.
  159.      */
  160.     if (hdr.n[1] == 0)
  161.     {
  162.         close(infd);
  163.         unlink(tname);
  164.         return;
  165.     }
  166.  
  167.     if (rewrite_now)
  168.     {
  169.         /* we don't need to open the index file */
  170.         index = (FILE *)0;
  171.  
  172.         /* make sure we can read every block! */
  173.         for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
  174.         {
  175.             lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
  176.             if (read(infd, buf.c, BLKSIZE) != BLKSIZE
  177.              || buf.c[0] == '\0')
  178.             {
  179.                 /* messed up header */
  180.                 fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
  181.                 close(infd);
  182.                 return;
  183.             }
  184.         }
  185.  
  186.         /* open the user's file for writing */
  187.         outfp = fopen(name.c, "w");
  188.         if (!outfp)
  189.         {
  190.             perror(name.c);
  191.             close(infd);
  192.             return;
  193.         }
  194.     }
  195.     else
  196.     {
  197.         /* open/create the index file */
  198.         index = fopen(PRSVINDEX, "a");
  199.         if (!index)
  200.         {
  201.             perror(PRSVINDEX);
  202.             mail(ownername(tname), name.c, when, tname);
  203.             exit(2);
  204.         }
  205.  
  206.         /* should be at the end of the file already, but MAKE SURE */
  207.         fseek(index, 0L, 2);
  208.  
  209.         /* create the recovery file in the PRESVDIR directory */
  210. #if AMIGA
  211.         prsvdir = &PRSVDIR[strlen(PRSVDIR) - 1];
  212.         if (*prsvdir == '/' || *prsvdir == ':')
  213.         {
  214.             sprintf(outname, "%sp%ld", PRSVDIR, ftell(index));
  215.         }
  216.         else
  217. #endif
  218.         sprintf(outname, "%s%cp%ld", PRSVDIR, SLASH, ftell(index));
  219.         outfp = fopen(outname, "w");
  220.         if (!outfp)
  221.         {
  222.             perror(outname);
  223.             close(infd);
  224.             fclose(index);
  225.             mail(ownername(tname), name.c, when, tname);
  226.             return;
  227.         }
  228.     }
  229.  
  230.     /* write the text of the file out to the recovery file */
  231.     for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
  232.     {
  233.         lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
  234.         if (read(infd, buf.c, BLKSIZE) != BLKSIZE
  235.          || buf.c[0] == '\0')
  236.         {
  237.             /* messed up header */
  238.             fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
  239.             fclose(outfp);
  240.             close(infd);
  241.             if (index)
  242.             {
  243.                 fclose(index);
  244.             }
  245.             unlink(outname);
  246.             return;
  247.         }
  248.         fputs(buf.c, outfp);
  249.     }
  250.  
  251.     /* add a line to the index file */
  252.     if (index)
  253.     {
  254.         fprintf(index, "%s %s\n", outname, name.c);
  255.     }
  256.  
  257.     /* close everything */
  258.     close(infd);
  259.     fclose(outfp);
  260.     if (index)
  261.     {
  262.         fclose(index);
  263.     }
  264.  
  265.     /* Are we doing this due to something more frightening than just
  266.      * a ":preserve" command?
  267.      */
  268.     if (*when)
  269.     {
  270.         /* send a mail message */
  271.         mail(ownername(tname), name.c, when, (char *)0);
  272.  
  273.         /* remove the temp file -- the editor has died already */
  274.         unlink(tname);
  275.     }
  276. }
  277.  
  278. void main(argc, argv)
  279.     int    argc;
  280.     char    **argv;
  281. {
  282.     int    i;
  283.     char    *when = "the editor went away";
  284.  
  285. #ifdef __EMX__
  286.     _wildcard(&argc, &argv);
  287. #else
  288. # if MSDOS || TOS || OS2
  289.     /* expand any wildcards in the command line */
  290.     _ct_init("");
  291.     argv = wildexpand(&argc, argv);
  292. # endif
  293. #endif
  294.  
  295.     /* do we have a "-c", "-R", or "-when elvis died" argument? */
  296.     i = 1;
  297.     if (argc >= i + 1 && !strcmp(argv[i], "-R"))
  298.     {
  299.         rewrite_now = 1;
  300.         when = "";
  301.         i++;
  302. #if ANY_UNIX
  303.         setuid(geteuid());
  304. #endif
  305.     }
  306. #if OSK
  307.     else
  308.     {
  309.         setuid(0);
  310.     }
  311. #endif
  312.     if (argc >= i + 1 && argv[i][0] == '-')
  313.     {
  314.         when = argv[i] + 1;
  315.         i++;
  316.     }
  317.  
  318.     /* preserve everything we're supposed to */
  319.     while (i < argc)
  320.     {
  321.         char *p = argv[i] - 1;
  322.  
  323.         /* reconvert any converted spaces */
  324.         while (*++p)
  325.         {
  326.             if ((unsigned char)(*p) == SPACEHOLDER)
  327.             {
  328.                 *p = ' ';
  329.             }
  330.         }
  331.         preserve(argv[i], when);
  332.         i++;
  333.     }
  334. }
  335.