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

Defined functions

init defined in line 384; used 3 times
main defined in line 71; never used
tailpath defined in line 408; used 3 times

Defined variables

sccsid defined in line 2; never used
tttrace defined in line 9; used 1 times

Defined macros

tracbuf defined in line 190; used 1 times
Last modified: 1981-07-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1113
Valid CSS Valid XHTML 1.0 Strict