home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume17 / e2 / part03 / read_hist.c < prev   
C/C++ Source or Header  |  1989-02-08  |  6KB  |  198 lines

  1. #include "e.h"
  2.  
  3. /*
  4.  * read_hist()
  5.  *
  6.  * Do some initialization type things such as finding out if the user has a
  7.  * uid, password entry, home directory etc. Then find out where the history
  8.  * is kept and check to see if it's there. If it's not just indicate this by
  9.  * returning -1 and let other functions deal with this problem as they see
  10.  * fit.
  11.  *
  12.  * If the history exists then read it. The format of the history file is
  13.  *
  14.  
  15. /absolute/path/name/for/some/directory
  16. \tfilename_1
  17. \tfilename_2
  18. \tfilename_3
  19. \tfilename_4
  20. /absolute/path/of/some/other/directory
  21. \tsome_filename_or_other
  22. \tanother_filename
  23.  
  24.  *
  25.  * Where \t is of course a single TAB.
  26.  * The files for a directory are kept in least recently used order. So in
  27.  * the above example, 'filename_1' was used before 'filename_2' and so on.
  28.  * There may be a maximum of HIST_LINES file names associated with each 
  29.  * directory.
  30.  *
  31.  * If the history is used and needs to be updated, then we will have to create
  32.  * a new file that looks pretty much like the current one. Unfortunately we
  33.  * will have to read and write the whole of the old file.
  34.  *
  35.  * Seeing as we are going to have to write the new history file, it doesn't
  36.  * make much sense to try and find the relevant directory in a clever manner
  37.  * (e.g. by keeping the history sorted by directory). The point is that
  38.  * we HAVE to read and write the whole file once so it doesn't really matter
  39.  * where we encounter the directory we want (if at all).
  40.  *
  41.  *
  42.  * We return the number of history items found after setting the pointers in
  43.  * hist[] to point to them. hist[0] points to the oldest filename, hist[1]
  44.  * to the next oldest etc etc... hist[hist_count - 1] to the most recently
  45.  * used.
  46.  *
  47.  */
  48.  
  49. int
  50. read_hist()
  51. {
  52.     static char line[MAXPATHLEN]; /* Static, as saved_line may point at it. */
  53.     int h_index = 0;              /* # of history items found so far.       */
  54.     register int cwd_len;         /* # of chars in the current dir name.    */
  55.     struct stat sbuf;
  56.  
  57.     cwd_len = strlen(cwd);
  58.  
  59.     if (stat(ehist, &sbuf) == -1){
  60.         return -1;
  61.     }
  62.  
  63.     emode = (int)sbuf.st_mode;
  64.  
  65.     hist_fp = fopen(ehist, "r");
  66.     if (!hist_fp){
  67.         e_error("Could not open history '%s'.", ehist);
  68.     }
  69.  
  70.     /*
  71.      * Open a new history file that will renamed to the old one once
  72.      * we update. (If we update.)
  73.      *
  74.      */
  75.  
  76.     get_temp();
  77.  
  78.     /*
  79.      * Make sure that the first line of the history starts with a '/'
  80.      * This way we know we are not dealing with an old-style (pre version 1.3)
  81.      * history file. The error message here is unsatisfactory - it should make
  82.      * a better attempt to find out what's wrong and point them to the 
  83.      * script for converting to the new format etc etc. Fortunately I'm the
  84.      * only person in the world who uses e and so it's not a problem.
  85.      *
  86.      */
  87.  
  88.     if (!fgets(line, MAXPATHLEN, hist_fp)){
  89.         e_error("Could not read first line of '%s'.\n", ehist);
  90.     }
  91.  
  92.     if (line[0] != '/'){
  93.         e_error("The history (%s) is munged. It is not in version %s format.",
  94.             ehist, VERSION);
  95.     }
  96.  
  97.     ok_fprintf(tmp_fp, "%s", line);
  98.  
  99.     /*
  100.      * Get lines and write them to the new history until you see one that 
  101.      * matches the directory we are in.
  102.      *
  103.      */
  104.     while (fgets(line, MAXPATHLEN, hist_fp)){
  105.  
  106.         register char *tmp = line;
  107.         int room_left = HIST_LINES * MAXPATHLEN;
  108.         char *room;
  109.  
  110.         /* 
  111.          * If it's not a path starting with a '/' then continue. 
  112.          * We have a filename. Keep going until the next directory entry.
  113.          *
  114.          */
  115.         if (line[0] != '/'){
  116.             ok_fprintf(tmp_fp, "%s", line);
  117.             continue;
  118.         }
  119.  
  120.         zap_nl(tmp);
  121.  
  122.         /*
  123.          * Test to see if this is the directory we want. tmp - line is the
  124.          * length of the name of the found directory. Do a length test first
  125.          * up to avoid a strcmp if possible.
  126.          *
  127.          */
  128.         if (tmp - line != cwd_len || strcmp(line, cwd)){
  129.             ok_fprintf(tmp_fp, "%s\n", line);
  130.             continue;
  131.         }
  132.  
  133.         /* 
  134.          * So we have found the directory we were looking for. Allocate a
  135.          * hunk of space to read all the filenames. 
  136.          */
  137.         room = sbrk(room_left);
  138.         if (room == (char *)-1){
  139.             e_error("Could not sbrk().");
  140.         }
  141.  
  142.         /*
  143.          * Read the filenames. If we reach a line that starts with a '/'
  144.          * then we are onto the next directory in the history and we save
  145.          * a pointer to this line to emit it later.
  146.          *
  147.          */
  148.         while (fgets(room, room_left, hist_fp)){
  149.             char *cp = hist[h_index] = room + 1;
  150.             zap_nl(cp);
  151.             room_left -= (cp - room);
  152.  
  153.             /*
  154.              * In theory we should never run out of space, but in case we do
  155.              * we might as well try to grab some more rather than just dying.
  156.              *
  157.              */
  158.             if (room_left <= MAXPATHLEN){
  159.                 room_left = HIST_LINES * MAXPATHLEN;
  160.                 room = sbrk(room_left);
  161.                 if (room == (char *)-1){
  162.                     e_error("Could not sbrk().");
  163.                 }
  164.             }
  165.             
  166.             if (*room == '/'){
  167.                 saved_line = room; /* Read one too many! */
  168.                 return h_index;
  169.             }
  170.  
  171.             room = cp + 1;
  172.             h_index++;
  173.  
  174.             /*
  175.              * Check to see if we have read HIST_LINES filenames. If we have,
  176.              * make sure that the next line is in fact a directory (by
  177.              * verifying that it starts with a '/'.
  178.              *
  179.              */
  180.             if (h_index == HIST_LINES){
  181.                 if (fgets(line, MAXPATHLEN, hist_fp)){
  182.                     if (line[0] != '/'){
  183.                         e_error("History contains too many entries!");
  184.                     }
  185.                     else{
  186.                         tmp = line;
  187.                         zap_nl(tmp);
  188.                         saved_line = line;
  189.                     }
  190.                 }
  191.                 return HIST_LINES;
  192.             }
  193.         }
  194.         return h_index;
  195.     }
  196.     return h_index;
  197. }
  198.