# 2.11BSD#431 - /usr/src/ucb/ex/ex.c

##### Functions

    init              X
    iownit            X
    main              X
    tailpath          X

##### Variables

    copyright         X
    tttrace           X

##### Macros

    tracbuf           X

       1: /*
       2:  * Copyright (c) 1980 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  */
       6:
       7: #if !defined(lint) && defined(DOSCCS)
       8: char *copyright =
       9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
      10:  All rights reserved.\n";
      11:
      12: static char *sccsid = "@(#)ex.c	7.5.1.1 (Berkeley) 8/12/86";
      13: #endif not lint
      14:
      15: #include "ex.h"
      16: #include "ex_argv.h"
      17: #include "ex_temp.h"
      18: #include "ex_tty.h"
      19:
      20: #ifdef TRACE
      21: char    tttrace[]   = { '/','d','e','v','/','t','t','y','x','x',0 };
      22: #endif
      23:
      24: /*
      25:  * The code for ex is divided as follows:
      26:  *
      27:  * ex.c			Entry point and routines handling interrupt, hangup
      28:  *			signals; initialization code.
      29:  *
      30:  * ex_addr.c		Address parsing routines for command mode decoding.
      31:  *			Routines to set and check address ranges on commands.
      32:  *
      33:  * ex_cmds.c		Command mode command decoding.
      34:  *
      35:  * ex_cmds2.c		Subroutines for command decoding and processing of
      36:  *			file names in the argument list.  Routines to print
      37:  *			messages and reset state when errors occur.
      38:  *
      39:  * ex_cmdsub.c		Subroutines which implement command mode functions
      40:  *			such as append, delete, join.
      41:  *
      42:  * ex_data.c		Initialization of options.
      43:  *
      44:  * ex_get.c		Command mode input routines.
      45:  *
      46:  * ex_io.c		General input/output processing: file i/o, unix
      47:  *			escapes, filtering, source commands, preserving
      48:  *			and recovering.
      49:  *
      50:  * ex_put.c		Terminal driving and optimizing routines for low-level
      51:  *			output (cursor-positioning); output line formatting
      52:  *			routines.
      53:  *
      54:  * ex_re.c		Global commands, substitute, regular expression
      55:  *			compilation and execution.
      56:  *
      57:  * ex_set.c		The set command.
      58:  *
      59:  * ex_subr.c		Loads of miscellaneous subroutines.
      60:  *
      61:  * ex_temp.c		Editor buffer routines for main buffer and also
      62:  *			for named buffers (Q registers if you will.)
      63:  *
      64:  * ex_tty.c		Terminal dependent initializations from termcap
      65:  *			data base, grabbing of tty modes (at beginning
      66:  *			and after escapes).
      67:  *
      68:  * ex_unix.c		Routines for the ! command and its variations.
      69:  *
      70:  * ex_v*.c		Visual/open mode routines... see ex_v.c for a
      71:  *			guide to the overall organization.
      72:  */
      73:
      74: /*
      75:  * Main procedure.  Process arguments and then
      76:  * transfer control to the main command processing loop
      77:  * in the routine commands.  We are entered as either "ex", "edit", "vi"
      78:  * or "view" and the distinction is made here.  Actually, we are "vi" if
      79:  * there is a 'v' in our name, "view" is there is a 'w', and "edit" if
      80:  * there is a 'd' in our name.  For edit we just diddle options;
      81:  * for vi we actually force an early visual command.
      82:  */
      83: main(ac, av)
      84:     register int ac;
      85:     register char *av[];
      86: {
      87: #ifndef VMUNIX
      88:     char *erpath = EXSTRINGS;
      89: #endif
      90:     register char *cp;
      91:     register int c;
      92:     bool recov = 0;
      93:     bool ivis;
      94:     bool itag = 0;
      95:     bool fast = 0;
      96:     extern int onemt();
      97: #ifdef TRACE
      98:     register char *tracef;
      99: #endif
     100:
     101:     /*
     102: 	 * Immediately grab the tty modes so that we wont
     103: 	 * get messed up if an interrupt comes in quickly.
     104: 	 */
     105:     gTTY(1);
     106: #ifndef USG3TTY
     107:     normf = tty.sg_flags;
     108: #else
     109:     normf = tty;
     110: #endif
     111:     ppid = getpid();
     112:     /*
     113: 	 * Defend against d's, v's, w's, and a's in directories of
     114: 	 * path leading to our true name.
     115: 	 */
     116:     av[0] = tailpath(av[0]);
     117:
     118:     /*
     119: 	 * Figure out how we were invoked: ex, edit, vi, view.
     120: 	 */
     121:     ivis = any('v', av[0]); /* "vi" */
     122:     if (any('w', av[0]))    /* "view" */
     123:         value(READONLY) = 1;
     124:     if (any('d', av[0])) {  /* "edit" */
     125:         value(OPEN) = 0;
     126:         value(REPORT) = 1;
     127:         value(MAGIC) = 0;
     128:     }
     129:
     130: #ifndef VMUNIX
     131:     /*
     132: 	 * For debugging take files out of . if name is a.out.
     133: 	 */
     134:     if (av[0][0] == 'a')
     135:         erpath = tailpath(erpath);
     136: #endif
     137:     /*
     138: 	 * Open the error message file.
     139: 	 */
     140:     draino();
     141: #ifndef VMUNIX
     142:     erfile = open(erpath+4, 0);
     143:     if (erfile < 0) {
     144:         erfile = open(erpath, 0);
     145:     }
     146: #endif
     147:     pstop();
     148:
     149:     /*
     150: 	 * Initialize interrupt handling.
     151: 	 */
     152:     oldhup = signal(SIGHUP, SIG_IGN);
     153:     if (oldhup == SIG_DFL)
     154:         signal(SIGHUP, onhup);
     155:     oldquit = signal(SIGQUIT, SIG_IGN);
     156:     ruptible = signal(SIGINT, SIG_IGN) == SIG_DFL;
     157:     if (signal(SIGTERM, SIG_IGN) == SIG_DFL)
     158:         signal(SIGTERM, onhup);
     159:     if (signal(SIGEMT, SIG_IGN) == SIG_DFL)
     160:         signal(SIGEMT, onemt);
     161:
     162:     /*
     163: 	 * Process flag arguments.
     164: 	 */
     165:     ac--, av++;
     166:     while (ac && av[0][0] == '-') {
     167:         c = av[0][1];
     168:         if (c == 0) {
     169:             hush = 1;
     170:             value(AUTOPRINT) = 0;
     171:             fast++;
     172:         } else switch (c) {
     173:
     174:         case 'R':
     175:             value(READONLY) = 1;
     176:             break;
     177:
     178: #ifdef TRACE
     179:         case 'T':
     180:             if (av[0][2] == 0)
     181:                 tracef = "trace";
     182:             else {
     183:                 tracef = tttrace;
     184:                 tracef[8] = av[0][2];
     185:                 if (tracef[8])
     186:                     tracef[9] = av[0][3];
     187:                 else
     188:                     tracef[9] = 0;
     189:             }
     190:             trace = fopen(tracef, "w");
     191: #define tracbuf NULL
     192:             if (trace == NULL)
     193:                 printf("Trace create error\n");
     194:             else
     195:                 setbuf(trace, tracbuf);
     196:             break;
     197:
     198: #endif
     199:
     200: #ifdef LISPCODE
     201:         case 'l':
     202:             value(LISP) = 1;
     203:             value(SHOWMATCH) = 1;
     204:             break;
     205: #endif
     206:
     207:         case 'r':
     208:             recov++;
     209:             break;
     210:
     211:         case 't':
     212:             if (ac > 1 && av[1][0] != '-') {
     213:                 ac--, av++;
     214:                 itag = 1;
     215:                 /* BUG: should check for too long tag. */
     216:                 CP(lasttag, av[0]);
     217:             }
     218:             break;
     219:
     220:         case 'v':
     221:             ivis = 1;
     222:             break;
     223:
     224:         case 'w':
     225:             defwind = 0;
     226:             if (av[0][2] == 0) defwind = 3;
     227:             else for (cp = &av[0][2]; isdigit(*cp); cp++)
     228:                 defwind = 10*defwind + *cp - '0';
     229:             break;
     230:
     231:
     232:         default:
     233:             smerror("Unknown option %s\n", av[0]);
     234:             break;
     235:         }
     236:         ac--, av++;
     237:     }
     238:
     239:     /*
     240: 	 * Initialize end of core pointers.
     241: 	 * Normally we avoid breaking back to fendcore after each
     242: 	 * file since this can be expensive (much core-core copying).
     243: 	 * If your system can scatter load processes you could do
     244: 	 * this as ed does, saving a little core, but it will probably
     245: 	 * not often make much difference.
     246: 	 */
     247:     fendcore = (line *) sbrk(0);
     248:     endcore = fendcore - 2;
     249:
     250: #ifdef SIGTSTP
     251:     if (!hush && signal(SIGTSTP, SIG_IGN) == SIG_DFL)
     252:         signal(SIGTSTP, onsusp), dosusp++;
     253: #endif
     254:
     255:     if (ac && av[0][0] == '+') {
     256:         firstpat = &av[0][1];
     257:         ac--, av++;
     258:     }
     259:
     260:
     261:     /*
     262: 	 * If we are doing a recover and no filename
     263: 	 * was given, then execute an exrecover command with
     264: 	 * the -r option to type out the list of saved file names.
     265: 	 * Otherwise set the remembered file name to the first argument
     266: 	 * file name so the "recover" initial command will find it.
     267: 	 */
     268:     if (recov) {
     269:         if (ac == 0) {
     270:             ppid = 0;
     271:             setrupt();
     272:             execl(EXRECOVER, "exrecover", "-r", 0);
     273:             filioerr(EXRECOVER);
     274:             exit(1);
     275:         }
     276:         CP(savedfile, *av++), ac--;
     277:     }
     278:
     279:     /*
     280: 	 * Initialize the argument list.
     281: 	 */
     282:     argv0 = av;
     283:     argc0 = ac;
     284:     args0 = av[0];
     285:     erewind();
     286:
     287:     /*
     288: 	 * Initialize a temporary file (buffer) and
     289: 	 * set up terminal environment.  Read user startup commands.
     290: 	 */
     291:     if (setexit() == 0) {
     292:         setrupt();
     293:         intty = isatty(0);
     294:         value(PROMPT) = intty;
     295:         if (cp = getenv("SHELL"))
     296:             CP(shell, cp);
     297:         if (fast || !intty)
     298:             setterm("dumb");
     299:         else {
     300:             gettmode();
     301:             if ((cp = getenv("TERM")) != 0 && *cp)
     302:                 setterm(cp);
     303:         }
     304:     }
     305:     if (setexit() == 0 && !fast && intty) {
     306:         if ((globp = getenv("EXINIT")) && *globp)
     307:             commands(1,1);
     308:         else {
     309:             globp = 0;
     310:             if ((cp = getenv("HOME")) != 0 && *cp) {
     311:                 (void) strcat(strcpy(genbuf, cp), "/.exrc");
     312:                 if (iownit(genbuf))
     313:                     source(genbuf, 1);
     314:             }
     315:         }
     316:         /*
     317: 		 * Allow local .exrc too.  This loses if . is $HOME,
     318: 		 * but nobody should notice unless they do stupid things
     319: 		 * like putting a version command in .exrc.  Besides,
     320: 		 * they should be using EXINIT, not .exrc, right?
     321: 		 */
     322:          if (iownit(".exrc"))
     323:             source(".exrc", 1);
     324:     }
     325:     init(); /* moved after prev 2 chunks to fix directory option */
     326:
     327:     /*
     328: 	 * Initial processing.  Handle tag, recover, and file argument
     329: 	 * implied next commands.  If going in as 'vi', then don't do
     330: 	 * anything, just set initev so we will do it later (from within
     331: 	 * visual).
     332: 	 */
     333:     if (setexit() == 0) {
     334:         if (recov)
     335:             globp = "recover";
     336:         else if (itag)
     337:             globp = ivis ? "tag" : "tag|p";
     338:         else if (argc)
     339:             globp = "next";
     340:         if (ivis)
     341:             initev = globp;
     342:         else if (globp) {
     343:             inglobal = 1;
     344:             commands(1, 1);
     345:             inglobal = 0;
     346:         }
     347:     }
     348:
     349:     /*
     350: 	 * Vi command... go into visual.
     351: 	 * Strange... everything in vi usually happens
     352: 	 * before we ever "start".
     353: 	 */
     354:     if (ivis) {
     355:         /*
     356: 		 * Don't have to be upward compatible with stupidity
     357: 		 * of starting editing at line $.
     358: 		 */
     359:         if (dol > zero)
     360:             dot = one;
     361:         globp = "visual";
     362:         if (setexit() == 0)
     363:             commands(1, 1);
     364:     }
     365:
     366:     /*
     367: 	 * Clear out trash in state accumulated by startup,
     368: 	 * and then do the main command loop for a normal edit.
     369: 	 * If you quit out of a 'vi' command by doing Q or ^\,
     370: 	 * you also fall through to here.
     371: 	 */
     372:     seenprompt = 1;
     373:     ungetchar(0);
     374:     globp = 0;
     375:     initev = 0;
     376:     setlastchar('\n');
     377:     setexit();
     378:     commands(0, 0);
     379:     cleanup(1);
     380:     exit(0);
     381: }
     382:
     383: /*
     384:  * Initialization, before editing a new file.
     385:  * Main thing here is to get a new buffer (in fileinit),
     386:  * rest is peripheral state resetting.
     387:  */
     388: init()
     389: {
     390:     register int i;
     391:
     392:     fileinit();
     393:     dot = zero = truedol = unddol = dol = fendcore;
     394:     one = zero+1;
     395:     undkind = UNDNONE;
     396:     chng = 0;
     397:     edited = 0;
     398:     for (i = 0; i <= 'z'-'a'+1; i++)
     399:         names[i] = 1;
     400:     anymarks = 0;
     401: }
     402:
     403: /*
     404:  * Return last component of unix path name p.
     405:  */
     406: char *
     407: tailpath(p)
     408: register char *p;
     409: {
     410:     register char *r;
     411:
     412:     for (r=p; *p; p++)
     413:         if (*p == '/')
     414:             r = p+1;
     415:     return(r);
     416: }
     417:
     418: /*
     419:  * Check ownership of file.  Return nonzero if it exists and is owned by the
     420:  * user or the option sourceany is used
     421:  */
     422: iownit(file)
     423: char *file;
     424: {
     425:     struct stat sb;
     426:
     427:     if (stat(file, &sb) == 0 && (value(SOURCEANY) || sb.st_uid == getuid()))
     428:         return(1);
     429:     else
     430:         return(0);
     431: }

#### Defined functions

init defined in line 388; used 3 times

- in line 325
- in /usr/src/ucb/ex/ex_cmds.c line 276, 512

iownit defined in line 422; used 2 times

- in line 312, 322

main defined in line 83; never used
tailpath defined in line 406; used 3 times

- in line 116, 135
- in /usr/src/ucb/ex/ex.h line 347

#### Defined variables

copyright defined in line 8; never used
sccsid defined in line 12; never used
tttrace defined in line 21; used 1 times

- in line 183

#### Defined macros

tracbuf defined in line 191; used 1 times

- in line 195

Last modified: 1991-09-08 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1484 |