home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume16 / less5 / part03 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-09-22  |  7.5 KB  |  455 lines

  1. /*
  2.  * Entry point, initialization, miscellaneous routines.
  3.  */
  4.  
  5. #include "less.h"
  6. #include "position.h"
  7.  
  8. public int    ispipe;
  9. public char *    first_cmd;
  10. public char *    every_first_cmd;
  11. public int    new_file;
  12. public int    is_tty;
  13. public char     *current_file;
  14. public char     *previous_file;
  15. public POSITION    prev_pos;
  16. public int    any_display;
  17. public int    scroll;
  18. public int    ac;
  19. public char **    av;
  20. public int     curr_ac;
  21. public int    quitting;
  22.  
  23. extern int    file;
  24. extern int    quit_at_eof;
  25. extern int    cbufs;
  26. extern int    errmsgs;
  27.  
  28. #if LOGFILE
  29. public int    logfile = -1;
  30. public int    force_logfile = 0;
  31. public char *    namelogfile = NULL;
  32. #endif
  33.  
  34. #if EDITOR
  35. public char *    editor;
  36. #endif
  37.  
  38. #if TAGS
  39. extern char *    tagfile;
  40. extern char *    tagpattern;
  41. extern int    tagoption;
  42. #endif
  43.  
  44.  
  45. /*
  46.  * Edit a new file.
  47.  * Filename "-" means standard input.
  48.  * No filename means the "current" file, from the command line.
  49.  */
  50.     public void
  51. edit(filename)
  52.     register char *filename;
  53. {
  54.     register int f;
  55.     register char *m;
  56.     POSITION initial_pos;
  57.     char message[100];
  58.     static int didpipe;
  59.  
  60.     initial_pos = NULL_POSITION;
  61.     if (filename == NULL || *filename == '\0')
  62.     {
  63.         if (curr_ac >= ac)
  64.         {
  65.             error("No current file");
  66.             return;
  67.         }
  68.         filename = save(av[curr_ac]);
  69.     } else if (strcmp(filename, "#") == 0)
  70.     {
  71.         if (*previous_file == '\0')
  72.         {
  73.             error("no previous file");
  74.             return;
  75.         }
  76.         filename = save(previous_file);
  77.         initial_pos = prev_pos;
  78.     } else
  79.         filename = save(filename);
  80.  
  81.     if (strcmp(filename, "-") == 0)
  82.     {
  83.         /* 
  84.          * Use standard input.
  85.          */
  86.         if (didpipe)
  87.         {
  88.             error("Can view standard input only once");
  89.             return;
  90.         }
  91.         f = 0;
  92.     } else if ((m = bad_file(filename, message, sizeof(message))) != NULL)
  93.     {
  94.         error(m);
  95.         free(filename);
  96.         return;
  97.     } else if ((f = open(filename, 0)) < 0)
  98.     {
  99.         error(errno_message(filename, message, sizeof(message)));
  100.         free(filename);
  101.         return;
  102.     }
  103.  
  104.     if (isatty(f))
  105.     {
  106.         /*
  107.          * Not really necessary to call this an error,
  108.          * but if the control terminal (for commands)
  109.          * and the input file (for data) are the same,
  110.          * we get weird results at best.
  111.          */
  112.         error("Can't take input from a terminal");
  113.         if (f > 0)
  114.             close(f);
  115.         free(filename);
  116.         return;
  117.     }
  118.  
  119. #if LOGFILE
  120.     if (f == 0 && namelogfile != NULL && is_tty)
  121.         use_logfile();
  122. #endif
  123.  
  124.     /*
  125.      * We are now committed to using the new file.
  126.      * Close the current input file and set up to use the new one.
  127.      */
  128.     if (file > 0)
  129.         close(file);
  130.     new_file = 1;
  131.     if (previous_file != NULL)
  132.         free(previous_file);
  133.     previous_file = current_file;
  134.     current_file = filename;
  135.     prev_pos = position(TOP);
  136.     ispipe = (f == 0);
  137.     if (ispipe)
  138.         didpipe = 1;
  139.     file = f;
  140.     ch_init(cbufs, 0);
  141.     init_mark();
  142.  
  143.     if (every_first_cmd != NULL)
  144.         first_cmd = every_first_cmd;
  145.  
  146.     if (is_tty)
  147.     {
  148.         int no_display = !any_display;
  149.         any_display = 1;
  150.         if (no_display && errmsgs > 0)
  151.         {
  152.             /*
  153.              * We displayed some messages on error output
  154.              * (file descriptor 2; see error() function).
  155.              * Before erasing the screen contents,
  156.              * display the file name and wait for a keystroke.
  157.              */
  158.             error(filename);
  159.         }
  160.         /*
  161.          * Indicate there is nothing displayed yet.
  162.          */
  163.         pos_clear();
  164.         if (initial_pos != NULL_POSITION)
  165.             jump_loc(initial_pos);
  166.         clr_linenum();
  167.     }
  168. }
  169.  
  170. /*
  171.  * Edit the next file in the command line list.
  172.  */
  173.     public void
  174. next_file(n)
  175.     int n;
  176. {
  177.     if (curr_ac + n >= ac)
  178.     {
  179.         if (quit_at_eof)
  180.             quit();
  181.         error("No (N-th) next file");
  182.     } else
  183.         edit(av[curr_ac += n]);
  184. }
  185.  
  186. /*
  187.  * Edit the previous file in the command line list.
  188.  */
  189.     public void
  190. prev_file(n)
  191.     int n;
  192. {
  193.     if (curr_ac - n < 0)
  194.         error("No (N-th) previous file");
  195.     else
  196.         edit(av[curr_ac -= n]);
  197. }
  198.  
  199. /*
  200.  * Copy a file directly to standard output.
  201.  * Used if standard output is not a tty.
  202.  */
  203.     static void
  204. cat_file()
  205. {
  206.     register int c;
  207.  
  208.     while ((c = ch_forw_get()) != EOI)
  209.         putchr(c);
  210.     flush();
  211. }
  212.  
  213. #if LOGFILE
  214.  
  215. use_logfile()
  216. {
  217.     int exists;
  218.     int answer;
  219.     char message[100];
  220.  
  221.     /*
  222.      * If he asked for a log file and we have opened standard input,
  223.      * create the log file.  
  224.      * We take care not to blindly overwrite an existing file.
  225.      */
  226.     end_logfile();
  227.  
  228.     /*
  229.      * {{ We could use access() here. }}
  230.      */
  231.     exists = open(namelogfile, 0);
  232.     close(exists);
  233.     exists = (exists >= 0);
  234.  
  235.     if (exists && !force_logfile)
  236.     {
  237.         static char w[] = "WARNING: log file exists: ";
  238.         strcpy(message, w);
  239.         strtcpy(message+sizeof(w)-1, namelogfile,
  240.             sizeof(message)-sizeof(w));
  241.         error(message);
  242.         answer = 'X';    /* Ask the user what to do */
  243.     } else
  244.         answer = 'O';    /* Create the log file */
  245.  
  246. loop:
  247.     switch (answer)
  248.     {
  249.     case 'O': case 'o':
  250.         logfile = creat(namelogfile, 0644);
  251.         break;
  252.     case 'A': case 'a':
  253.         logfile = open(namelogfile, 1);
  254.         if (lseek(logfile, (offset_t)0, 2) < 0)
  255.         {
  256.             close(logfile);
  257.             logfile = -1;
  258.         }
  259.         break;
  260.     case 'D': case 'd':
  261.         answer = 0;    /* Don't print an error message */
  262.         break;
  263.     case 'q':
  264.         quit();
  265.     default:
  266.         putstr("\n  Overwrite, Append, or Don't log? ");
  267.         answer = getchr();
  268.         putstr("\n");
  269.         flush();
  270.         goto loop;
  271.     }
  272.  
  273.     if (logfile < 0 && answer != 0)
  274.     {
  275.         sprintf(message, "Cannot write to \"%s\"", 
  276.             namelogfile);
  277.         error(message);
  278.     }
  279. }
  280.  
  281. #endif
  282.  
  283. /*
  284.  * Entry point.
  285.  */
  286. main(argc, argv)
  287.     int argc;
  288.     char *argv[];
  289. {
  290.     char *getenv();
  291.  
  292.  
  293.     /*
  294.      * Process command line arguments and LESS environment arguments.
  295.      * Command line arguments override environment arguments.
  296.      */
  297.     init_prompt();
  298.     init_option();
  299.     scan_option(getenv("LESS"));
  300.     argv++;
  301.     while ( (--argc > 0) && 
  302.         (argv[0][0] == '-' || argv[0][0] == '+') && 
  303.         argv[0][1] != '\0')
  304.         scan_option(*argv++);
  305.  
  306. #if EDITOR
  307.     editor = getenv("EDITOR");
  308.     if (editor == NULL || *editor == '\0')
  309.         editor = EDIT_PGM;
  310. #endif
  311.  
  312.     /*
  313.      * Set up list of files to be examined.
  314.      */
  315.     ac = argc;
  316.     av = argv;
  317.     curr_ac = 0;
  318.  
  319.     /*
  320.      * Set up terminal, etc.
  321.      */
  322.     is_tty = isatty(1);
  323.     if (!is_tty)
  324.     {
  325.         /*
  326.          * Output is not a tty.
  327.          * Just copy the input file(s) to output.
  328.          */
  329.         if (ac < 1)
  330.         {
  331.             edit("-");
  332.             cat_file();
  333.         } else
  334.         {
  335.             do
  336.             {
  337.                 edit((char *)NULL);
  338.                 if (file >= 0)
  339.                     cat_file();
  340.             } while (++curr_ac < ac);
  341.         }
  342.         exit(0);
  343.     }
  344.  
  345.     raw_mode(1);
  346.     get_term();
  347.     open_getchr();
  348.     init();
  349.     init_cmd();
  350.  
  351.     init_signals(1);
  352.  
  353.     /*
  354.      * Select the first file to examine.
  355.      */
  356. #if TAGS
  357.     if (tagoption)
  358.     {
  359.         /*
  360.          * A -t option was given.
  361.          * Verify that no filenames were also given.
  362.          * Edit the file selected by the "tags" search,
  363.          * and search for the proper line in the file.
  364.          */
  365.         if (ac > 0)
  366.         {
  367.             error("No filenames allowed with -t option");
  368.             quit();
  369.         }
  370.         if (tagfile == NULL)
  371.             quit();
  372.         edit(tagfile);
  373.         if (file < 0)
  374.             quit();
  375.         if (tagsearch())
  376.             quit();
  377.     } else
  378. #endif
  379.     if (ac < 1)
  380.         edit("-");    /* Standard input */
  381.     else 
  382.     {
  383.         /*
  384.          * Try all the files named as command arguments.
  385.          * We are simply looking for one which can be
  386.          * opened without error.
  387.          */
  388.         do
  389.         {
  390.             edit((char *)NULL);
  391.         } while (file < 0 && ++curr_ac < ac);
  392.     }
  393.  
  394.     if (file >= 0)
  395.         commands();
  396.     quit();
  397.     /*NOTREACHED*/
  398. }
  399.  
  400. /*
  401.  * Copy a string, truncating to the specified length if necessary.
  402.  * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
  403.  */
  404.     public void
  405. strtcpy(to, from, len)
  406.     char *to;
  407.     char *from;
  408.     unsigned int len;
  409. {
  410.     strncpy(to, from, len);
  411.     to[len-1] = '\0';
  412. }
  413.  
  414. /*
  415.  * Copy a string to a "safe" place
  416.  * (that is, to a buffer allocated by calloc).
  417.  */
  418.     public char *
  419. save(s)
  420.     char *s;
  421. {
  422.     register char *p;
  423.  
  424.     p = calloc(strlen(s)+1, sizeof(char));
  425.     if (p == NULL)
  426.     {
  427.         error("cannot allocate memory");
  428.         quit();
  429.     }
  430.     strcpy(p, s);
  431.     return (p);
  432. }
  433.  
  434. /*
  435.  * Exit the program.
  436.  */
  437.     public void
  438. quit()
  439. {
  440.     /*
  441.      * Put cursor at bottom left corner, clear the line,
  442.      * reset the terminal modes, and exit.
  443.      */
  444.     quitting = 1;
  445. #if LOGFILE
  446.     end_logfile();
  447. #endif
  448.     lower_left();
  449.     clear_eol();
  450.     deinit();
  451.     flush();
  452.     raw_mode(0);
  453.     exit(0);
  454. }
  455.