Flush out the last dregs in the terminal before quitting when
[unix-history] / usr / src / usr.bin / ex / ex.c
index 0026c8e..874ef9a 100644 (file)
@@ -1,13 +1,31 @@
-/* Copyright (c) 1980 Regents of the University of California */
-static char *sccsid = "@(#)ex.c        6.2 %G%";
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+char *copyright =
+"@(#) Copyright (c) 1980 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif not lint
+
+#ifndef lint
+static char *sccsid = "@(#)ex.c        7.6.1.1 (Berkeley) %G%";
+#endif not lint
+
 #include "ex.h"
 #include "ex_argv.h"
 #include "ex_temp.h"
 #include "ex_tty.h"
 
 #ifdef TRACE
 #include "ex.h"
 #include "ex_argv.h"
 #include "ex_temp.h"
 #include "ex_tty.h"
 
 #ifdef TRACE
+#ifdef vms
+char   tttrace[]       = { 't','r','a','c','e','.','l','i','s' };
+#else
 char   tttrace[]       = { '/','d','e','v','/','t','t','y','x','x',0 };
 #endif
 char   tttrace[]       = { '/','d','e','v','/','t','t','y','x','x',0 };
 #endif
+#endif
 
 /*
  * The code for ex is divided as follows:
 
 /*
  * The code for ex is divided as follows:
@@ -72,7 +90,7 @@ main(ac, av)
        register int ac;
        register char *av[];
 {
        register int ac;
        register char *av[];
 {
-#ifndef VMUNIX
+#ifdef EXSTRINGS
        char *erpath = EXSTRINGS;
 #endif
        register char *cp;
        char *erpath = EXSTRINGS;
 #endif
        register char *cp;
@@ -81,15 +99,24 @@ main(ac, av)
        bool ivis;
        bool itag = 0;
        bool fast = 0;
        bool ivis;
        bool itag = 0;
        bool fast = 0;
+       extern int onemt();
+#ifdef UNIX_SBRK
+       extern char *sbrk();
+#else
+       extern char *malloc();
+#endif
 #ifdef TRACE
        register char *tracef;
 #endif
 #ifdef TRACE
        register char *tracef;
 #endif
+#ifdef vms
+       char termtype[20];
+#endif
 
        /*
         * Immediately grab the tty modes so that we wont
         * get messed up if an interrupt comes in quickly.
         */
 
        /*
         * Immediately grab the tty modes so that we wont
         * get messed up if an interrupt comes in quickly.
         */
-       gTTY(1);
+       ex_gTTY(1);
 #ifndef USG3TTY
        normf = tty.sg_flags;
 #else
 #ifndef USG3TTY
        normf = tty.sg_flags;
 #else
@@ -100,7 +127,21 @@ main(ac, av)
         * Defend against d's, v's, w's, and a's in directories of
         * path leading to our true name.
         */
         * Defend against d's, v's, w's, and a's in directories of
         * path leading to our true name.
         */
+#ifndef        vms
        av[0] = tailpath(av[0]);
        av[0] = tailpath(av[0]);
+#else
+       /*
+        * This program has to be invoked by using the following
+        * string definitions:
+        *
+        * vi == "$dir:ex.exe vi"
+        * view == "$dir:ex.exe view"
+        * ex == "$dir:ex.exe ex"
+        * edit == "$dir:ex.exe edit"
+        */
+       ac--;
+       av++;
+#endif
 
        /*
         * Figure out how we were invoked: ex, edit, vi, view.
 
        /*
         * Figure out how we were invoked: ex, edit, vi, view.
@@ -114,7 +155,7 @@ main(ac, av)
                value(MAGIC) = 0;
        }
 
                value(MAGIC) = 0;
        }
 
-#ifndef VMUNIX
+#ifdef EXSTRINGS
        /*
         * For debugging take files out of . if name is a.out.
         */
        /*
         * For debugging take files out of . if name is a.out.
         */
@@ -125,7 +166,7 @@ main(ac, av)
         * Open the error message file.
         */
        draino();
         * Open the error message file.
         */
        draino();
-#ifndef VMUNIX
+#ifdef EXSTRINGS
        erfile = open(erpath+4, 0);
        if (erfile < 0) {
                erfile = open(erpath, 0);
        erfile = open(erpath+4, 0);
        if (erfile < 0) {
                erfile = open(erpath, 0);
@@ -143,17 +184,8 @@ main(ac, av)
        ruptible = signal(SIGINT, SIG_IGN) == SIG_DFL;
        if (signal(SIGTERM, SIG_IGN) == SIG_DFL)
                signal(SIGTERM, onhup);
        ruptible = signal(SIGINT, SIG_IGN) == SIG_DFL;
        if (signal(SIGTERM, SIG_IGN) == SIG_DFL)
                signal(SIGTERM, onhup);
-
-       /*
-        * Initialize end of core pointers.
-        * Normally we avoid breaking back to fendcore after each
-        * file since this can be expensive (much core-core copying).
-        * If your system can scatter load processes you could do
-        * this as ed does, saving a little core, but it will probably
-        * not often make much difference.
-        */
-       fendcore = (line *) sbrk(0);
-       endcore = fendcore - 2;
+       if (signal(SIGEMT, SIG_IGN) == SIG_DFL)
+               signal(SIGEMT, onemt);
 
        /*
         * Process flag arguments.
 
        /*
         * Process flag arguments.
@@ -184,9 +216,11 @@ main(ac, av)
                                        tracef[9] = 0;
                        }
                        trace = fopen(tracef, "w");
                                        tracef[9] = 0;
                        }
                        trace = fopen(tracef, "w");
+#define tracbuf NULL
                        if (trace == NULL)
                        if (trace == NULL)
-                               printf("Trace create error\n");
-                       setbuf(trace, tracbuf);
+                               ex_printf("Trace create error\n");
+                       else
+                               setbuf(trace, tracbuf);
                        break;
 
 #endif
                        break;
 
 #endif
@@ -222,12 +256,6 @@ main(ac, av)
                                defwind = 10*defwind + *cp - '0';
                        break;
 
                                defwind = 10*defwind + *cp - '0';
                        break;
 
-#ifdef CRYPT
-               case 'x':
-                       /* -x: encrypted mode */
-                       xflag = 1;
-                       break;
-#endif
 
                default:
                        smerror("Unknown option %s\n", av[0]);
 
                default:
                        smerror("Unknown option %s\n", av[0]);
@@ -246,12 +274,6 @@ main(ac, av)
                ac--, av++;
        }
 
                ac--, av++;
        }
 
-#ifdef CRYPT
-       if(xflag){
-               key = getpass(KEYPROMPT);
-               kflag = crinit(key, perm);
-       }
-#endif
 
        /*
         * If we are doing a recover and no filename
 
        /*
         * If we are doing a recover and no filename
@@ -266,7 +288,7 @@ main(ac, av)
                        setrupt();
                        execl(EXRECOVER, "exrecover", "-r", 0);
                        filioerr(EXRECOVER);
                        setrupt();
                        execl(EXRECOVER, "exrecover", "-r", 0);
                        filioerr(EXRECOVER);
-                       exit(1);
+                       ex_exit(1);
                }
                CP(savedfile, *av++), ac--;
        }
                }
                CP(savedfile, *av++), ac--;
        }
@@ -287,24 +309,87 @@ main(ac, av)
                setrupt();
                intty = isatty(0);
                value(PROMPT) = intty;
                setrupt();
                intty = isatty(0);
                value(PROMPT) = intty;
+#ifndef        vms
                if (cp = getenv("SHELL"))
                if (cp = getenv("SHELL"))
+#else
+               if (cp = getlog("SHELL"))
+#endif
                        CP(shell, cp);
                if (fast || !intty)
                        setterm("dumb");
                else {
                        gettmode();
                        CP(shell, cp);
                if (fast || !intty)
                        setterm("dumb");
                else {
                        gettmode();
+#ifndef        vms
                        if ((cp = getenv("TERM")) != 0 && *cp)
                                setterm(cp);
                        if ((cp = getenv("TERM")) != 0 && *cp)
                                setterm(cp);
+#else
+                       if ((cp = getlog("TERM")) != 0 && *cp) {
+                               /*
+                                * Can't just use it directly since getlog
+                                * returns a pointer to a static buffer that
+                                * tgetent() will eventually use
+                                */
+                               CP(termtype, cp);
+                               setterm(termtype);
+                       }
+#endif
                }
        }
                }
        }
-       if (setexit() == 0 && !fast && intty)
+       if (setexit() == 0 && !fast && intty) {
+#ifndef        vms
                if ((globp = getenv("EXINIT")) && *globp)
                if ((globp = getenv("EXINIT")) && *globp)
+#else
+               if ((globp = getlog("EXINIT")) && *globp)
+#endif
                        commands(1,1);
                else {
                        globp = 0;
                        commands(1,1);
                else {
                        globp = 0;
-                       if ((cp = getenv("HOME")) != 0 && *cp)
-                               source(strcat(strcpy(genbuf, cp), "/.exrc"), 1);
+                       if ((cp = getenv("HOME")) != 0 && *cp) {
+                               (void) strcat(strcpy(genbuf, cp), "/.exrc");
+                               if (iownit(genbuf))
+                                       source(genbuf, 1);
+                       }
                }
                }
+               /*
+                * Allow local .exrc too.  This loses if . is $HOME,
+                * but nobody should notice unless they do stupid things
+                * like putting a version command in .exrc.  Besides,
+                * they should be using EXINIT, not .exrc, right?
+                */
+                if (iownit(".exrc"))
+                       source(".exrc", 1);
+       }
+#ifdef UNIX_SBRK
+       /*
+        * Initialize end of core pointers.
+        * Normally we avoid breaking back to fendcore after each
+        * file since this can be expensive (much core-core copying).
+        * If your system can scatter load processes you could do
+        * this as ed does, saving a little core, but it will probably
+        * not often make much difference.
+        */
+       fendcore = (line *) sbrk(0);
+       endcore = fendcore - 2;
+#else
+       /*
+        * Allocate all the memory we will ever use in one chunk.
+        * This is for system such as VMS where sbrk() does not
+        * guarantee that the memory allocated beyond the end is
+        * consecutive.  VMS's RMS does all sorts of memory allocation
+        * and screwed up ex royally because ex assumes that all
+        * memory up to "endcore" belongs to it and RMS has different
+        * ideas.
+        */
+       fendcore = (line *) malloc((unsigned)
+               value(LINELIMIT) * sizeof (line *));
+       if (fendcore == NULL) {
+               lprintf("ex: cannot handle %d lines\n", value(LINELIMIT));
+               lprintf("ex: set \"linelimit\" lower\n");
+               flush();
+               ex_exit(1);
+       }
+       endcore = fendcore + (value(LINELIMIT) - 1);
+#endif
        init(); /* moved after prev 2 chunks to fix directory option */
 
        /*
        init(); /* moved after prev 2 chunks to fix directory option */
 
        /*
@@ -360,7 +445,7 @@ main(ac, av)
        setexit();
        commands(0, 0);
        cleanup(1);
        setexit();
        commands(0, 0);
        cleanup(1);
-       exit(0);
+       ex_exit(0);
 }
 
 /*
 }
 
 /*
@@ -381,130 +466,8 @@ init()
        for (i = 0; i <= 'z'-'a'+1; i++)
                names[i] = 1;
        anymarks = 0;
        for (i = 0; i <= 'z'-'a'+1; i++)
                names[i] = 1;
        anymarks = 0;
-#ifdef CRYPT
-        if(xflag) {
-                xtflag = 1;
-                makekey(key, tperm);
-        }
-#endif
-}
-
-/*
- * When a hangup occurs our actions are similar to a preserve
- * command.  If the buffer has not been [Modified], then we do
- * nothing but remove the temporary files and exit.
- * Otherwise, we sync the temp file and then attempt a preserve.
- * If the preserve succeeds, we unlink our temp files.
- * If the preserve fails, we leave the temp files as they are
- * as they are a backup even without preservation if they
- * are not removed.
- */
-onhup()
-{
-
-       /*
-        * USG tty driver can send multiple HUP's!!
-        */
-       signal(SIGINT, SIG_IGN);
-       signal(SIGHUP, SIG_IGN);
-       if (chng == 0) {
-               cleanup(1);
-               exit(0);
-       }
-       if (setexit() == 0) {
-               if (preserve()) {
-                       cleanup(1);
-                       exit(0);
-               }
-       }
-       exit(1);
-}
-
-/*
- * An interrupt occurred.  Drain any output which
- * is still in the output buffering pipeline.
- * Catch interrupts again.  Unless we are in visual
- * reset the output state (out of -nl mode, e.g).
- * Then like a normal error (with the \n before Interrupt
- * suppressed in visual mode).
- */
-onintr()
-{
-
-#ifndef CBREAK
-       signal(SIGINT, onintr);
-#else
-       signal(SIGINT, inopen ? vintr : onintr);
-#endif
-       draino();
-       if (!inopen) {
-               pstop();
-               setlastchar('\n');
-#ifdef CBREAK
-       }
-#else
-       } else
-               vraw();
-#endif
-       error("\nInterrupt" + inopen);
-}
-
-/*
- * If we are interruptible, enable interrupts again.
- * In some critical sections we turn interrupts off,
- * but not very often.
- */
-setrupt()
-{
-
-       if (ruptible) {
-#ifndef CBREAK
-               signal(SIGINT, onintr);
-#else
-               signal(SIGINT, inopen ? vintr : onintr);
-#endif
-#ifdef SIGTSTP
-               if (dosusp)
-                       signal(SIGTSTP, onsusp);
-#endif
-       }
 }
 
 }
 
-preserve()
-{
-
-#ifdef VMUNIX
-       tflush();
-#endif
-       synctmp();
-       pid = fork();
-       if (pid < 0)
-               return (0);
-       if (pid == 0) {
-               close(0);
-               dup(tfile);
-               execl(EXPRESERVE, "expreserve", (char *) 0);
-               exit(1);
-       }
-       waitfor();
-       if (rpid == pid && status == 0)
-               return (1);
-       return (0);
-}
-
-#ifndef V6
-exit(i)
-       int i;
-{
-
-# ifdef TRACE
-       if (trace)
-               fclose(trace);
-# endif
-       _exit(i);
-}
-#endif
-
 /*
  * Return last component of unix path name p.
  */
 /*
  * Return last component of unix path name p.
  */
@@ -519,3 +482,18 @@ register char *p;
                        r = p+1;
        return(r);
 }
                        r = p+1;
        return(r);
 }
+
+/*
+ * Check ownership of file.  Return nonzero if it exists and is owned by the
+ * user or the option sourceany is used
+ */
+iownit(file)
+char *file;
+{
+       struct stat sb;
+
+       if (stat(file, &sb) == 0 && (value(SOURCEANY) || sb.st_uid == getuid()))
+               return(1);
+       else
+               return(0);
+}