home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d9xx / d902 / less.lha / Less / Source / source.lha / main.c < prev    next >
C/C++ Source or Header  |  1993-02-05  |  17KB  |  642 lines

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