home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 531.lha / Less_v1.4Z / src.LZH / src / main.c < prev    next >
C/C++ Source or Header  |  1991-07-03  |  17KB  |  635 lines

  1. /*
  2.  * Entry point, initialization, miscellaneous routines.
  3.  */
  4.  
  5. #ifdef AMIGA
  6. /* Compile with -HPreHeader.q to get "less.h"! */
  7. #else
  8. #include "less.h"
  9. #endif
  10.  
  11. #include "position.h"
  12. #include <setjmp.h>
  13. #include <signal.h>
  14.  
  15. public int      ispipe;
  16. public jmp_buf  main_loop;
  17. public char *   first_cmd;
  18. public char *   every_first_cmd;
  19. public int      new_file;
  20. public int      is_tty;
  21. public char     current_file[FILENAME];
  22. public char     previous_file[FILENAME];
  23. public POSITION prev_pos;
  24. public int      any_display;
  25. public int      ac;
  26. public char **  av;
  27. public int      curr_ac;
  28. #if LOGFILE
  29. public int      logfile = -1;
  30. public int      force_logfile = 0;
  31. public char *   namelogfile = NULL;
  32. #endif
  33. #if EDITOR
  34. public char *   editor;
  35. #endif
  36.  
  37. extern int file;
  38. extern int nbufs;
  39. extern int sigs;
  40. extern int quit_at_eof;
  41. extern int p_nbufs, f_nbufs;
  42. extern int back_scroll;
  43. extern int top_scroll;
  44. extern int sc_height;
  45. extern int errmsgs;
  46.  
  47. /* Prototypes for functions defined in main.c */
  48.  
  49. static void SeekRoot __PROTO((ULONG lock));
  50.  
  51.  
  52. #ifdef AMIGA
  53. /********** amiga **************/
  54. #include <ctype.h>
  55. #include <dos.h>
  56. #include <intuition/intuition.h>
  57. #include <exec/memory.h>
  58. #include <ios1.h>
  59.  
  60. extern struct UFB _ufbs[];
  61.  
  62. /* Used by SeekRoot */
  63. #define MAXPATHSTRING 256
  64. static char    absDir[MAXPATHSTRING];
  65.  
  66. struct IntuitionBase *IntuitionBase;
  67. struct Remember *RememberKey;
  68. int called_from_WB = 0;
  69.  
  70.  
  71. /* max items and chars that *.c can expand to */
  72. #define MAXTEMPLATES 100
  73. public char     *local_argv[MAXTEMPLATES];
  74. public int      local_argc;
  75. #endif
  76.  
  77. /*
  78.  * Edit a new file.
  79.  * Filename "-" means standard input.
  80.  * No filename means the "current" file, from the command line.
  81.  */
  82. #ifdef __STDC__
  83. void edit (register char *filename)
  84. #else
  85.         public void
  86. edit(filename)
  87.         register char *filename;
  88. #endif
  89. {
  90.         register int f;
  91.         register char *m;
  92.         POSITION initial_pos;
  93.         char message[100];
  94.         char tempfile[FILENAME];
  95.         static int didpipe;
  96.  
  97.         initial_pos = NULL_POSITION;
  98.         if (filename == NULL || *filename == '\0')
  99.         {
  100.                 if (curr_ac >= ac)
  101.                 {
  102.                         error("No current file");
  103.                         return;
  104.                 }
  105.                 filename = av[curr_ac];
  106.         }
  107.         if (strcmp(filename, "#") == 0)
  108.         {
  109.                 if (*previous_file == '\0')
  110.                 {
  111.                         error("no previous file");
  112.                         return;
  113.                 }
  114.                 strtcpy(tempfile, previous_file, sizeof(tempfile));
  115.                 filename = tempfile;
  116.                 initial_pos = prev_pos;
  117.         }
  118.         if (strcmp(filename, "-") == 0)
  119.         {
  120.                 /*
  121.                  * Use standard input.
  122.                  */
  123.                 if (didpipe)
  124.                 {
  125.                         error("Can view standard input only once");
  126.                         return;
  127.                 }
  128.                 f = 0;
  129. #ifdef AMIGA
  130.                 /* get standard input */
  131.                 if ( !chkufb(0) ) /* if linked with tinymain, we get no stdin */
  132.                 {
  133.                     _ufbs[0].ufbfh = Input();
  134.                     _ufbs[0].ufbflg |= UFB_RA | O_RAW;
  135.                     if ( !called_from_WB ) _ufbs[0].ufbflg |= UFB_NC;
  136.                 }
  137. #endif
  138.         } else if ((m = bad_file(filename, message, sizeof(message))) != NULL)
  139.         {
  140.                 error(m);
  141.                 return;
  142.         } else if ((f = open(filename, 0)) < 0)
  143.         {
  144.                 error(errno_message(filename, message, sizeof(message)));
  145.                 return;
  146.         }
  147.  
  148. #ifdef AMIGA
  149. /* SAS 5.10a isatty is broken; reports that pipe:x is a tty */
  150.         if (isatty(f) && f==0)
  151. #else
  152.         if (isatty(f))
  153. #endif
  154.         {
  155.                 /*
  156.                  * Not really necessary to call this an error,
  157.                  * but if the control terminal (for commands)
  158.                  * and the input file (for data) are the same,
  159.                  * we get weird results at best.
  160.                  */
  161.                 error("Can't take input from a terminal");
  162.                 if (f > 0)
  163.                         close(f);
  164.                 return;
  165.         }
  166.  
  167. #if LOGFILE
  168.         /*
  169.          * If he asked for a log file and we have opened standard input,
  170.          * create the log file.
  171.          * We take care not to blindly overwrite an existing file.
  172.          */
  173.         end_logfile();
  174.         if (f == 0 && namelogfile != NULL && is_tty)
  175.         {
  176.                 int exists;
  177.                 int answer;
  178.  
  179.                 /*
  180.                  * {{ We could use access() here. }}
  181.                  */
  182.                 exists = open(namelogfile, 0);
  183.                 close(exists);
  184.                 exists = (exists >= 0);
  185.  
  186.                 if (exists && !force_logfile)
  187.                 {
  188.                         static char w[] = "WARNING: log file exists: ";
  189.                         strcpy(message, w);
  190.                         strtcpy(message+sizeof(w)-1, namelogfile,
  191.                                 sizeof(message)-sizeof(w));
  192.                         error(message);
  193.                         answer = 'X';   /* Ask the user what to do */
  194.                 } else
  195.                         answer = 'O';   /* Create the log file */
  196.  
  197.         loop:
  198.                 switch (answer)
  199.                 {
  200.                 case 'O': case 'o':
  201.                         logfile = creat(namelogfile, 0644);
  202.                         break;
  203.                 case 'A': case 'a':
  204.                         logfile = open(namelogfile, 1);
  205.                         if (lseek(logfile, (offset_t)0, 2) < 0)
  206.                         {
  207.                                 close(logfile);
  208.                                 logfile = -1;
  209.                         }
  210.                         break;
  211.                 case 'D': case 'd':
  212.                         answer = 0;     /* Don't print an error message */
  213.                         break;
  214.                 case 'q':
  215.                         quit();
  216.                 default:
  217.                         putstr("\n  Overwrite, Append, or Don't log? ");
  218.                         answer = getchr();
  219.                         putstr("\n");
  220.                         flush();
  221.                         goto loop;
  222.                 }
  223.  
  224.                 if (logfile < 0 && answer != 0)
  225.                 {
  226.                         sprintf(message, "Cannot write to \"%s\"",
  227.                                 namelogfile);
  228.                         error(message);
  229.                 }
  230.         }
  231. #endif
  232.  
  233.         /*
  234.          * We are now committed to using the new file.
  235.          * Close the current input file and set up to use the new one.
  236.          */
  237.         if (file > 0)
  238.                 close(file);
  239.         new_file = 1;
  240.         strtcpy(previous_file, current_file, sizeof(previous_file));
  241.         strtcpy(current_file, filename, sizeof(current_file));
  242.         prev_pos = position(TOP);
  243. #ifdef AMIGA
  244.         /* Some heuristics to determine if we've been given a pipe.
  245.            (there must be a better way...)
  246.         */
  247.         ispipe = ((f == 0) && !called_from_WB)
  248.             || (strnicmp(filename, "pipe:", 5) == 0); /* kludge! */
  249. #else
  250.         ispipe = (f == 0);
  251. #endif
  252.         if (ispipe)
  253.                 didpipe = 1;
  254.         file = f;
  255.         ch_init( (ispipe) ? p_nbufs : f_nbufs );
  256.         init_mark();
  257.  
  258.         if (every_first_cmd != NULL)
  259.                 first_cmd = every_first_cmd;
  260.  
  261.         if (is_tty)
  262.         {
  263.                 int no_display = !any_display;
  264.                 any_display = 1;
  265.                 if (no_display && errmsgs > 0)
  266.                 {
  267.                         /*
  268.                          * We displayed some messages on error output
  269.                          * (file descriptor 2; see error() function).
  270.                          * Before erasing the screen contents,
  271.                          * display the file name and wait for a keystroke.
  272.                          */
  273.                         error(filename);
  274.                 }
  275.                 /*
  276.                  * Indicate there is nothing displayed yet.
  277.                  */
  278.                 pos_clear();
  279.                 if (initial_pos != NULL_POSITION)
  280.                         jump_loc(initial_pos);
  281.         }
  282. }
  283.  
  284. /*
  285.  * Edit the next file in the command line list.
  286.  */
  287. #ifdef __STDC__
  288. void next_file (int n)
  289. #else
  290.         public void
  291. next_file(n)
  292.         int n;
  293. #endif
  294. {
  295.         if (curr_ac + n >= ac)
  296.         {
  297.                 if (quit_at_eof)
  298.                         quit();
  299.                 error("No (N-th) next file");
  300.         } else
  301.                 edit(av[curr_ac += n]);
  302. }
  303.  
  304. /*
  305.  * Edit the previous file in the command line list.
  306.  */
  307. #ifdef __STDC__
  308. void prev_file (int n)
  309. #else
  310.         public void
  311. prev_file(n)
  312.         int n;
  313. #endif
  314. {
  315.         if (curr_ac - n < 0)
  316.                 error("No (N-th) previous file");
  317.         else
  318.                 edit(av[curr_ac -= n]);
  319. }
  320.  
  321. #ifndef AMIGA
  322. /*
  323.  * Copy a file directly to standard output.
  324.  * Used if standard output is not a tty.
  325.  */
  326.         static void
  327. cat_file()
  328. {
  329.         register int c;
  330.  
  331.         while ((c = ch_forw_get()) != EOF)
  332.                 putchr(c);
  333.         flush();
  334. }
  335. #endif
  336.  
  337.  
  338. #ifdef AMIGA
  339. /**************** amiga *****************************/
  340. /* Bob Leivian  4/28/87 fudge up things so it will work
  341.    when called from Work Bench */
  342.  
  343. char argvbuf[80];
  344.  
  345. #include "workbench/startup.h"
  346.  
  347. #ifdef MANX
  348. /* ignore AZTECs wb stuff */
  349. _wb_parse(ignore, ignore2)
  350. char *ignore;
  351. char *ignore2;
  352. {
  353.     return;
  354. }
  355. #endif
  356. #endif
  357.  
  358.  
  359. #ifdef NO_GETENV
  360. /* this requires the workbench disk --
  361.   ignore all environment variables for now */
  362. char * getenv(ignore)
  363. {
  364.         return NULL;
  365. }
  366. #endif
  367.  
  368. /*
  369.  * Entry point.
  370.  */
  371. #ifdef __STDC__
  372. int main (int argc, char **argv)
  373. #else
  374. main(argc, argv)
  375.         int argc;
  376.         char *argv[];
  377. #endif
  378. {
  379.         char *getenv();
  380.  
  381.  
  382. #ifdef AMIGA
  383. /***************** amiga ********************/
  384.         IntuitionBase = OpenLibrary ( "intuition.library", 0 );
  385.         RememberKey = NULL;
  386.         /* if we were called from the workbench we will have no args
  387.            but a pointer to WBstruct, get the filename from this structure */
  388.         if(argc == 0) {
  389.                 struct WBStartup *WBmsg;
  390.                 struct WBArg *p;
  391.                 char *cp, c;
  392.                 BPTR newlock;
  393.  
  394.                 /* the argv is really the work bench structure */
  395.                 WBmsg = (struct WBStartup *) argv;
  396.                 p = WBmsg->sm_ArgList;
  397.  
  398.                 /* fake up the args now */
  399.                 /* argv[0] = p->wa_Name; */
  400.                 p++; /* ignore first parm (name), since Less don't use it */
  401.                 for ( local_argc = 1; local_argc < WBmsg->sm_NumArgs
  402.                     && local_argc < MAXTEMPLATES; local_argc++ )
  403.                 {
  404.                     *absDir = '\0';
  405.                     /* SeekRoot UnLocks its argument */
  406.                     newlock = DupLock ( p->wa_Lock );
  407.                     SeekRoot ( newlock );
  408.                     /* The first part is really a device name */
  409.                     for ( cp=absDir; (c = *cp) && c != '/'; cp++ )
  410.                         /* nothing */;
  411.                     *cp = ':';
  412.                     if ( c == '\0' ) /* root dir of a device */
  413.                         *++cp = '\0';
  414.                     else
  415.                         strcat(cp, "/");
  416.                     if ( !(cp = AllocRemember(&RememberKey,
  417.                         strlen(absDir)+strlen(p->wa_Name)+1, 0L)) )
  418.                         quit();
  419.                     strcpy ( cp, absDir );
  420.                     local_argv[local_argc] = strcat(cp, p->wa_Name);
  421.                     p++;
  422.                 }
  423.                 local_argv[local_argc] = NULL;
  424.  
  425.                 called_from_WB = 1;
  426.         }
  427.  
  428.  
  429. #endif
  430.  
  431.         /*
  432.          * Process command line arguments and LESS environment arguments.
  433.          * Command line arguments override environment arguments.
  434.          */
  435.         init_option();
  436.         scan_option(getenv("LESS"));
  437.         argv++;
  438.         while ( (--argc > 0) &&
  439.                 (argv[0][0] == '-' || argv[0][0] == '+') &&
  440.                  argv[0][1] != '\0')
  441.                 scan_option(*argv++);
  442.  
  443. #if EDITOR
  444.         editor = getenv("EDITOR");
  445.         if (editor == NULL || *editor == '\0')
  446.                 editor = "ed";
  447. #endif
  448.  
  449.         /*
  450.          * Set up list of files to be examined.
  451.          */
  452. #ifdef AMIGA
  453.         if ( called_from_WB )
  454.         {
  455.             ac = local_argc-1;
  456.             av = local_argv+1; /* CLI case did an argv++ */
  457.         }
  458.         else
  459.         {
  460. #endif
  461.         ac = argc;
  462.         av = argv;
  463. #ifdef AMIGA
  464.         }
  465. #endif
  466.  
  467.  
  468.         curr_ac = 0;
  469.  
  470.         /*
  471.          * Set up terminal, etc.
  472.          */
  473. #ifdef AMIGA
  474.         is_tty = 1;
  475.         ttopen();
  476. #else
  477.         is_tty = isatty(1);
  478.         if (!is_tty)
  479.         {
  480.                 /*
  481.                  * Output is not a tty.
  482.                  * Just copy the input file(s) to output.
  483.                  */
  484.                 if (ac < 1)
  485.                 {
  486.                         edit("-");
  487.                         cat_file();
  488.                 } else
  489.                 {
  490.                         do
  491.                         {
  492.                                 edit((char *)NULL);
  493.                                 if (file >= 0)
  494.                                         cat_file();
  495.                         } while (++curr_ac < ac);
  496.                 }
  497.                 quit();
  498.         }
  499. #endif
  500.  
  501.         raw_mode(1);
  502.         get_term();
  503.         open_getchr();
  504.         init();
  505.  
  506.         if (setjmp(main_loop))
  507.                 quit();
  508.         init_signals();
  509.  
  510.         /*
  511.          * Select the first file to examine.
  512.          */
  513.         if (ac < 1)
  514.                 edit("-");      /* Standard input */
  515.         else
  516.         {
  517.                 /*
  518.                  * Try all the files named as command arguments.
  519.                  * We are simply looking for one which can be
  520.                  * opened without error.
  521.                  */
  522.                 do
  523.                 {
  524.                         edit((char *)NULL);
  525.                 } while (file < 0 && ++curr_ac < ac);
  526.         }
  527.  
  528.         if (file >= 0)
  529.                 commands();
  530.         quit();
  531.         /*NOTREACHED*/
  532. }
  533.  
  534. /*
  535.  * Copy a string, truncating to the specified length if necessary.
  536.  * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
  537.  */
  538. #ifdef __STDC__
  539. void strtcpy (char *to, char *from, int len)
  540. #else
  541. strtcpy(to, from, len)
  542.         char *to;
  543.         char *from;
  544.         int len;
  545. #endif
  546. {
  547.         strncpy(to, from, len);
  548.         to[len-1] = '\0';
  549. }
  550.  
  551. /*
  552.  * Exit the program.
  553.  */
  554. #ifdef __STDC__
  555. void quit (void)
  556. #else
  557.         public void
  558. quit()
  559. #endif
  560. {
  561.         /*
  562.          * Put cursor at bottom left corner, clear the line,
  563.          * reset the terminal modes, and exit.
  564.          */
  565. #if LOGFILE
  566.         end_logfile();
  567. #endif
  568. #ifdef AMIGA
  569.         ttclose();
  570.  
  571.         if (IntuitionBase)
  572.         {
  573.             FreeRemember( &RememberKey, 1 );
  574.             CloseLibrary(IntuitionBase);
  575.         }
  576. #else
  577.         lower_left();
  578.         clear_eol();
  579.         deinit();
  580.  
  581.         flush();
  582.         raw_mode(0);
  583.  
  584. #endif
  585.  
  586.         exit(0);
  587. }
  588.  
  589.  
  590. #ifdef AMIGA
  591.  
  592. /* Thanks to Bruce Rogers for a UseNet posting including the following
  593.    useful function...
  594. */
  595.  
  596. /*!*******************************************************************
  597.  * FindRoot by Bruce Rogers 1/20/90
  598.  *********************************************************************/
  599. /*
  600. ------------------------------------------------------          Quantum _\/_
  601. 2727 Eel                   Bruce (6502 RULES!) Rogers        |\  Duck  ( 0 0)
  602. Davis, Ca 95616            Quantum Duck Software,           |\ \______/ / \\\
  603. 916-756-2684               rogers@iris.ucdavis.edu         |\ <  <     |   \/
  604. "My brain is on fire!"                                       \________/ Quark!
  605.  
  606. */
  607.  
  608.  
  609. /*!*******************************************************************
  610.  * Recursively go up parent chain, looking for oldest parent.
  611.  * Create the absolute path string as we go.
  612.  *********************************************************************/
  613. static void SeekRoot(lock)
  614. ULONG   lock;
  615. {
  616. struct  FileInfoBlock   *fileInfo;
  617. ULONG newlock;
  618. char NameEnd[MAXPATHSTRING], sep;
  619.  
  620.     fileInfo=AllocMem(sizeof(struct FileInfoBlock),0);
  621.  
  622.     Examine(lock,fileInfo);
  623.     strcpy ( NameEnd, absDir );
  624.     strcpy ( absDir, fileInfo->fib_FileName );
  625.     sep = 0; if ( *absDir ) sep = absDir[strlen(absDir) - 1];
  626.     if ( sep && *NameEnd && sep != '/' && sep != ':' ) strcat ( absDir, "/" );
  627.     strcat ( absDir, NameEnd );
  628.     newlock = ParentDir(lock);
  629.     UnLock(lock);
  630.     if (newlock!=NULL) SeekRoot(newlock);
  631.  
  632.     FreeMem(fileInfo,sizeof(struct FileInfoBlock));
  633. }
  634. #endif
  635.