Subversion Repositories planix.SVN

Rev

Rev 115 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
105 7u83 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
static char *sccsid = "@(#)ex_io.c	7.11.1.1 (Berkeley) 8/12/86";
9
#endif
10
 
11
#include "ex.h"
12
#include "ex_argv.h"
13
#include "ex_temp.h"
14
#include "ex_tty.h"
15
#include "ex_vis.h"
16
 
17
/*
18
 * File input/output, source, preserve and recover
19
 */
20
 
21
/*
22
 * Following remember where . was in the previous file for return
23
 * on file switching.
24
 */
25
int	altdot;
26
int	oldadot;
27
bool	wasalt;
28
short	isalt;
29
 
30
long	cntch;			/* Count of characters on unit io */
31
#ifndef VMUNIX
32
short	cntln;			/* Count of lines " */
33
#else
34
int	cntln;
35
#endif
36
long	cntnull;		/* Count of nulls " */
37
long	cntodd;			/* Count of non-ascii characters " */
38
 
39
/*
40
 * Parse file name for command encoded by comm.
41
 * If comm is E then command is doomed and we are
42
 * parsing just so user won't have to retype the name.
43
 */
44
filename(comm)
45
	int comm;
46
{
47
	register int c = comm, d;
48
	register int i;
49
 
50
	d = getchar();
51
	if (endcmd(d)) {
52
		if (savedfile[0] == 0 && comm != 'f')
53
			error("No file|No current filename");
115 7u83 54
		CP(file, savedfile);
105 7u83 55
		wasalt = (isalt > 0) ? isalt-1 : 0;
56
		isalt = 0;
57
		oldadot = altdot;
58
		if (c == 'e' || c == 'E')
59
			altdot = lineDOT();
60
		if (d == EOF)
61
			ungetchar(d);
62
	} else {
63
		ungetchar(d);
64
		getone();
65
		eol();
66
		if (savedfile[0] == 0 && c != 'E' && c != 'e') {
67
			c = 'e';
68
			edited = 0;
69
		}
70
		wasalt = strcmp(file, altfile) == 0;
71
		oldadot = altdot;
72
		switch (c) {
73
 
74
		case 'f':
75
			edited = 0;
76
			/* fall into ... */
77
 
78
		case 'e':
79
			if (savedfile[0]) {
80
				altdot = lineDOT();
115 7u83 81
				CP(altfile, savedfile);
105 7u83 82
			}
115 7u83 83
			CP(savedfile, file);
105 7u83 84
			break;
85
 
86
		default:
87
			if (file[0]) {
88
				if (c != 'E')
89
					altdot = lineDOT();
115 7u83 90
				CP(altfile, file);
105 7u83 91
			}
92
			break;
93
		}
94
	}
95
	if (hush && comm != 'f' || comm == 'E')
96
		return;
97
	if (file[0] != 0) {
98
		lprintf("\"%s\"", file);
99
		if (comm == 'f') {
100
			if (value(READONLY))
101
				printf(" [Read only]");
102
			if (!edited)
103
				printf(" [Not edited]");
104
			if (tchng)
105
				printf(" [Modified]");
106
		}
107
		flush();
108
	} else
109
		printf("No file ");
110
	if (comm == 'f') {
111
		if (!(i = lineDOL()))
112
			i++;
113
		printf(" line %d of %d --%ld%%--", lineDOT(), lineDOL(),
114
		    (long) 100 * lineDOT() / i);
115
	}
116
}
117
 
118
/*
119
 * Get the argument words for a command into genbuf
120
 * expanding # and %.
121
 */
122
getargs()
123
{
124
	register int c;
125
	register char *cp, *fp;
126
	static char fpatbuf[32];	/* hence limit on :next +/pat */
127
 
128
	pastwh();
129
	if (peekchar() == '+') {
130
		for (cp = fpatbuf;;) {
131
			c = *cp++ = getchar();
132
			if (cp >= &fpatbuf[sizeof(fpatbuf)])
133
				error("Pattern too long");
134
			if (c == '\\' && isspace(peekchar()))
135
				c = getchar();
136
			if (c == EOF || isspace(c)) {
137
				ungetchar(c);
138
				*--cp = 0;
139
				firstpat = &fpatbuf[1];
140
				break;
141
			}
142
		}
143
	}
144
	if (skipend())
145
		return (0);
115 7u83 146
	CP(genbuf, "echo "); cp = &genbuf[5];
105 7u83 147
	for (;;) {
148
		c = getchar();
149
		if (endcmd(c)) {
150
			ungetchar(c);
151
			break;
152
		}
153
		switch (c) {
154
 
155
		case '\\':
156
			if (any(peekchar(), "#%|"))
157
				c = getchar();
158
			/* fall into... */
159
 
160
		default:
161
			if (cp > &genbuf[LBSIZE - 2])
162
flong:
163
				error("Argument buffer overflow");
164
			*cp++ = c;
165
			break;
166
 
167
		case '#':
168
			fp = altfile;
169
			if (*fp == 0)
170
				error("No alternate filename@to substitute for #");
171
			goto filexp;
172
 
173
		case '%':
174
			fp = savedfile;
175
			if (*fp == 0)
176
				error("No current filename@to substitute for %%");
177
filexp:
178
			while (*fp) {
179
				if (cp > &genbuf[LBSIZE - 2])
180
					goto flong;
181
				*cp++ = *fp++;
182
			}
183
			break;
184
		}
185
	}
186
	*cp = 0;
187
	return (1);
188
}
189
 
190
/*
191
 * Glob the argument words in genbuf, or if no globbing
192
 * is implied, just split them up directly.
193
 */
194
glob(gp)
195
	struct glob *gp;
196
{
197
	int pvec[2];
198
	register char **argv = gp->argv;
199
	register char *cp = gp->argspac;
200
	register int c;
201
	char ch;
202
	int nleft = NCARGS;
203
 
204
	gp->argc0 = 0;
205
	if (gscan() == 0) {
206
		register char *v = genbuf + 5;		/* strlen("echo ") */
207
 
208
		for (;;) {
209
			while (isspace(*v))
210
				v++;
211
			if (!*v)
212
				break;
213
			*argv++ = cp;
214
			while (*v && !isspace(*v))
215
				*cp++ = *v++;
216
			*cp++ = 0;
217
			gp->argc0++;
218
		}
219
		*argv = 0;
220
		return;
221
	}
222
	if (pipe(pvec) < 0)
223
		error("Can't make pipe to glob");
224
	pid = fork();
225
	io = pvec[0];
226
	if (pid < 0) {
227
		close(pvec[1]);
228
		error("Can't fork to do glob");
229
	}
230
	if (pid == 0) {
231
		int oerrno;
232
 
233
		close(1);
234
		dup(pvec[1]);
235
		close(pvec[0]);
236
		close(2);	/* so errors don't mess up the screen */
237
		open("/dev/null", 1);
238
		execl(svalue(SHELL), "sh", "-c", genbuf, 0);
239
		oerrno = errno; close(1); dup(2); errno = oerrno;
240
		filioerr(svalue(SHELL));
241
	}
242
	close(pvec[1]);
243
	do {
244
		*argv = cp;
245
		for (;;) {
246
			if (read(io, &ch, 1) != 1) {
247
				close(io);
248
				c = -1;
249
			} else
250
#ifndef	ISO
251
				c = ch & TRIM;
252
#else
253
			{
254
				if (niso(ch))
255
					c = ch & TRIM;
256
				else
257
					c = ch;
258
			}
259
#endif
260
			if (c <= 0 || isspace(c))
261
				break;
262
			*cp++ = c;
263
			if (--nleft <= 0)
264
				error("Arg list too long");
265
		}
266
		if (cp != *argv) {
267
			--nleft;
268
			*cp++ = 0;
269
			gp->argc0++;
270
			if (gp->argc0 >= NARGS)
271
				error("Arg list too long");
272
			argv++;
273
		}
274
	} while (c >= 0);
275
	waitfor();
276
	if (gp->argc0 == 0)
277
		error("No match");
278
}
279
 
280
/*
281
 * Scan genbuf for shell metacharacters.
282
 * Set is union of v7 shell and csh metas.
283
 */
284
gscan()
285
{
286
	register char *cp;
287
 
288
	for (cp = genbuf; *cp; cp++)
289
		if (any(*cp, "~{[*?$`'\"\\"))
290
			return (1);
291
	return (0);
292
}
293
 
294
/*
295
 * Parse one filename into file.
296
 */
297
struct glob G;
298
getone()
299
{
300
	register char *str;
301
 
302
	if (getargs() == 0)
303
		error("Missing filename");
304
	glob(&G);
305
	if (G.argc0 > 1)
306
		error("Ambiguous|Too many file names");
307
	str = G.argv[G.argc0 - 1];
308
	if (strlen(str) > FNSIZE - 4)
309
		error("Filename too long");
310
samef:
115 7u83 311
	CP(file, str);
105 7u83 312
}
313
 
314
/*
315
 * Read a file from the world.
316
 * C is command, 'e' if this really an edit (or a recover).
317
 */
318
rop(c)
319
	int c;
320
{
321
	register int i;
322
	struct stat stbuf;
323
	short magic;
324
	static int ovro;	/* old value(READONLY) */
325
	static int denied;	/* 1 if READONLY was set due to file permissions */
326
 
327
	io = open(file, 0);
328
	if (io < 0) {
329
		if (c == 'e' && errno == ENOENT) {
330
			edited++;
331
			/*
332
			 * If the user just did "ex foo" he is probably
333
			 * creating a new file.  Don't be an error, since
334
			 * this is ugly, and it screws up the + option.
335
			 */
336
			if (!seenprompt) {
337
				printf(" [New file]");
338
				noonl();
339
				return;
340
			}
341
		}
342
		syserror();
343
	}
344
	if (fstat(io, &stbuf))
345
		syserror();
346
	switch (stbuf.st_mode & S_IFMT) {
347
 
348
	case S_IFBLK:
349
		error(" Block special file");
350
 
351
	case S_IFCHR:
352
		if (isatty(io))
353
			error(" Teletype");
354
		if (samei(&stbuf, "/dev/null"))
355
			break;
356
		error(" Character special file");
357
 
358
	case S_IFDIR:
359
		error(" Directory");
360
 
361
	case S_IFREG:
362
		i = read(io, (char *) &magic, sizeof(magic));
363
		lseek(io, 0l, 0);
364
		if (i != sizeof(magic))
365
			break;
366
#if !defined (BIT8) && !defined(ISO)
367
		switch (magic) {
368
 
369
		case 0405:	/* data overlay on exec */
370
		case 0407:	/* unshared */
371
		case 0410:	/* shared text */
372
		case 0411:	/* separate I/D */
373
		case 0413:	/* VM/Unix demand paged */
374
		case 0430:	/* PDP-11 Overlay shared */
375
		case 0431:	/* PDP-11 Overlay sep I/D */
376
			error(" Executable");
377
 
378
		/*
379
		 * We do not forbid the editing of portable archives
380
		 * because it is reasonable to edit them, especially
381
		 * if they are archives of text files.  This is
382
		 * especially useful if you archive source files together
383
		 * and copy them to another system with ~%take, since
384
		 * the files sometimes show up munged and must be fixed.
385
		 */
386
		case 0177545:
387
		case 0177555:
388
			error(" Archive");
389
 
390
		default:
391
#ifdef mbb
392
			/* C/70 has a 10 bit byte */
393
			if (magic & 03401600)
394
#else
395
			/* Everybody else has an 8 bit byte */
396
			if (magic & 0100200)
397
#endif
398
				error(" Non-ascii file");
399
			break;
400
		}
401
#endif /* !BIT8 */
402
	}
403
	if (c != 'r') {
404
		if (value(READONLY) && denied) {
405
			value(READONLY) = ovro;
406
			denied = 0;
407
		}
408
		if ((stbuf.st_mode & 0222) == 0 || access(file, 2) < 0) {
409
			ovro = value(READONLY);
410
			denied = 1;
411
			value(READONLY) = 1;
412
		}
413
	}
414
	if (value(READONLY)) {
415
		printf(" [Read only]");
416
		flush();
417
	}
418
	if (c == 'r')
419
		setdot();
420
	else
421
		setall();
422
	if (FIXUNDO && inopen && c == 'r')
423
		undap1 = undap2 = dot + 1;
424
	rop2();
425
	rop3(c);
426
}
427
 
428
rop2()
429
{
430
	line *first, *last, *a;
431
	struct stat statb;
432
 
433
	deletenone();
434
	clrstats();
435
	first = addr2 + 1;
106 7u83 436
 
437
/*	if (fstat(io, &statb) < 0)
105 7u83 438
		bsize = LBSIZE;
439
	else {
440
		bsize = statb.st_blksize;
441
		if (bsize <= 0)
442
			bsize = LBSIZE;
443
	}
106 7u83 444
*/
445
	bsize=LBSIZE;	
446
 
105 7u83 447
	ignore(append(getfile, addr2));
448
	last = dot;
449
	/*
450
	 *	if the modeline variable is set,
451
	 *	check the first and last five lines of the file
452
	 *	for a mode line.
453
	 */
454
	if (value(MODELINE)) {
455
		for (a=first; a<=last; a++) {
456
			if (a==first+5 && last-first > 10)
457
				a = last - 4;
118 7u83 458
			ex_getline(*a);
105 7u83 459
			checkmodeline(linebuf);
460
		}
461
	}
462
}
463
 
464
rop3(c)
465
	int c;
466
{
467
 
468
	if (iostats() == 0 && c == 'e')
469
		edited++;
470
	if (c == 'e') {
471
		if (wasalt || firstpat) {
472
			register line *addr = zero + oldadot;
473
 
474
			if (addr > dol)
475
				addr = dol;
476
			if (firstpat) {
477
				globp = (*firstpat) ? firstpat : "$";
478
				commands(1,1);
479
				firstpat = 0;
480
			} else if (addr >= one) {
481
				if (inopen)
482
					dot = addr;
483
				markpr(addr);
484
			} else
485
				goto other;
486
		} else
487
other:
488
			if (dol > zero) {
489
				if (inopen)
490
					dot = one;
491
				markpr(one);
492
			}
493
		if(FIXUNDO)
494
			undkind = UNDNONE;
495
		if (inopen) {
496
			vcline = 0;
497
			vreplace(0, LINES, lineDOL());
498
		}
499
	}
500
}
501
 
502
/*
503
 * Are these two really the same inode?
504
 */
505
samei(sp, cp)
506
	struct stat *sp;
507
	char *cp;
508
{
509
	struct stat stb;
510
 
511
	if (stat(cp, &stb) < 0 || sp->st_dev != stb.st_dev)
512
		return (0);
513
	return (sp->st_ino == stb.st_ino);
514
}
515
 
516
/* Returns from edited() */
517
#define	EDF	0		/* Edited file */
518
#define	NOTEDF	-1		/* Not edited file */
519
#define	PARTBUF	1		/* Write of partial buffer to Edited file */
520
 
521
/*
522
 * Write a file.
523
 */
524
wop(dofname)
525
bool dofname;	/* if 1 call filename, else use savedfile */
526
{
527
	register int c, exclam, nonexist;
528
	line *saddr1, *saddr2;
529
	struct stat stbuf;
530
 
531
	c = 0;
532
	exclam = 0;
533
	if (dofname) {
534
		if (peekchar() == '!')
535
			exclam++, ignchar();
536
		ignore(skipwh());
537
		while (peekchar() == '>')
538
			ignchar(), c++, ignore(skipwh());
539
		if (c != 0 && c != 2)
540
			error("Write forms are 'w' and 'w>>'");
541
		filename('w');
542
	} else {
543
		if (savedfile[0] == 0)
544
			error("No file|No current filename");
545
		saddr1=addr1;
546
		saddr2=addr2;
547
		addr1=one;
548
		addr2=dol;
115 7u83 549
		CP(file, savedfile);
105 7u83 550
		if (inopen) {
551
			vclrech(0);
552
			splitw++;
553
		}
554
		lprintf("\"%s\"", file);
555
	}
556
	nonexist = stat(file, &stbuf);
557
	switch (c) {
558
 
559
	case 0:
560
		if (!exclam && (!value(WRITEANY) || value(READONLY)))
561
		switch (edfile()) {
562
 
563
		case NOTEDF:
564
			if (nonexist)
565
				break;
566
			if ((stbuf.st_mode & S_IFMT) == S_IFCHR) {
567
				if (samei(&stbuf, "/dev/null"))
568
					break;
569
				if (samei(&stbuf, "/dev/tty"))
570
					break;
571
			}
572
			io = open(file, 1);
573
			if (io < 0)
574
				syserror();
575
			if (!isatty(io))
576
				serror(" File exists| File exists - use \"w! %s\" to overwrite", file);
577
			close(io);
578
			break;
579
 
580
		case EDF:
581
			if (value(READONLY))
582
				error(" File is read only");
583
			break;
584
 
585
		case PARTBUF:
586
			if (value(READONLY))
587
				error(" File is read only");
588
			error(" Use \"w!\" to write partial buffer");
589
		}
590
cre:
591
/*
592
		synctmp();
593
*/
594
#ifdef V6
595
		io = creat(file, 0644);
596
#else
597
		io = creat(file, 0666);
598
#endif
599
		if (io < 0)
600
			syserror();
601
		writing = 1;
602
		if (hush == 0)
603
			if (nonexist)
604
				printf(" [New file]");
605
			else if (value(WRITEANY) && edfile() != EDF)
606
				printf(" [Existing file]");
607
		break;
608
 
609
	case 2:
610
		io = open(file, 1);
611
		if (io < 0) {
612
			if (exclam || value(WRITEANY))
613
				goto cre;
614
			syserror();
615
		}
616
		lseek(io, 0l, 2);
617
		break;
618
	}
619
	putfile(0);
620
	ignore(iostats());
621
	if (c != 2 && addr1 == one && addr2 == dol) {
622
		if (eq(file, savedfile))
623
			edited = 1;
624
		sync();
625
	}
626
	if (!dofname) {
627
		addr1 = saddr1;
628
		addr2 = saddr2;
629
	}
630
	writing = 0;
631
}
632
 
633
/*
634
 * Is file the edited file?
635
 * Work here is that it is not considered edited
636
 * if this is a partial buffer, and distinguish
637
 * all cases.
638
 */
639
edfile()
640
{
641
 
642
	if (!edited || !eq(file, savedfile))
643
		return (NOTEDF);
644
	return (addr1 == one && addr2 == dol ? EDF : PARTBUF);
645
}
646
 
647
/*
648
 * Extract the next line from the io stream.
649
 */
650
char *nextip;
651
 
652
getfile()
653
{
654
	register short c;
655
	register char *lp, *fp;
656
 
657
	lp = linebuf;
658
	fp = nextip;
659
	do {
660
		if (--ninbuf < 0) {
661
			ninbuf = read(io, genbuf, bsize) - 1;
662
			if (ninbuf < 0) {
663
				if (lp != linebuf) {
664
					lp++;
665
					printf(" [Incomplete last line]");
666
					break;
667
				}
668
				return (EOF);
669
			}
670
			fp = genbuf;
671
			cntch += ninbuf+1;
672
		}
673
		if (lp >= &linebuf[LBSIZE]) {
674
			error(" Line too long");
675
		}
676
		c = *fp++;
677
		if (c == 0) {
678
			cntnull++;
679
			continue;
680
		}
681
#ifndef	BIT8
682
#ifndef	ISO
683
		if (c & QUOTE) {
684
#else
685
		if (niso(c)) {
686
#endif
687
			cntodd++;
688
			c &= TRIM;
689
			if (c == 0)
690
				continue;
691
		}
692
#endif
693
		*lp++ = c;
694
	} while (c != '\n');
695
	*--lp = 0;
696
	nextip = fp;
697
	cntln++;
698
	return (0);
699
}
700
 
701
/*
702
 * Write a range onto the io stream.
703
 */
704
putfile(isfilter)
705
int isfilter;
706
{
707
	line *a1;
708
	register char *fp, *lp;
709
	register int nib;
710
	struct stat statb;
711
 
712
	a1 = addr1;
713
	clrstats();
714
	cntln = addr2 - a1 + 1;
715
	if (cntln == 0)
716
		return;
106 7u83 717
 
718
	bsize = LBSIZE;
719
 
720
/*	if (fstat(io, &statb) < 0)
105 7u83 721
		bsize = LBSIZE;
722
	else {
723
		bsize = statb.st_blksize;
724
		if (bsize <= 0)
725
			bsize = LBSIZE;
726
	}
106 7u83 727
	*/
728
 
105 7u83 729
	nib = bsize;
730
	fp = genbuf;
731
	do {
118 7u83 732
		ex_getline(*a1++);
105 7u83 733
		lp = linebuf;
734
		for (;;) {
735
			if (--nib < 0) {
736
				nib = fp - genbuf;
737
				if (write(io, genbuf, nib) != nib) {
738
					wrerror();
739
				}
740
				cntch += nib;
741
				nib = bsize - 1;
742
				fp = genbuf;
743
			}
744
			if ((*fp++ = *lp++) == 0) {
745
				fp[-1] = '\n';
746
				break;
747
			}
748
		}
749
	} while (a1 <= addr2);
750
	nib = fp - genbuf;
751
	if (write(io, genbuf, nib) != nib) {
752
		wrerror();
753
	}
754
	cntch += nib;
755
}
756
 
757
/*
758
 * A write error has occurred;  if the file being written was
759
 * the edited file then we consider it to have changed since it is
760
 * now likely scrambled.
761
 */
762
wrerror()
763
{
764
 
765
	if (eq(file, savedfile) && edited)
766
		change();
767
	syserror();
768
}
769
 
770
/*
771
 * Source command, handles nested sources.
772
 * Traps errors since it mungs unit 0 during the source.
773
 */
774
short slevel;
775
short ttyindes;
776
 
777
source(fil, okfail)
778
	char *fil;
779
	bool okfail;
780
{
781
	jmp_buf osetexit;
782
	register int saveinp, ointty, oerrno;
783
	char *saveglobp;
784
	short savepeekc;
785
 
786
	signal(SIGINT, SIG_IGN);
787
	saveinp = dup(0);
788
	savepeekc = peekc;
789
	saveglobp = globp;
790
	peekc = 0; globp = 0;
791
	if (saveinp < 0)
792
		error("Too many nested sources");
793
	if (slevel <= 0)
794
		ttyindes = saveinp;
795
	close(0);
796
	if (open(fil, 0) < 0) {
797
		oerrno = errno;
798
		setrupt();
799
		dup(saveinp);
800
		close(saveinp);
801
		errno = oerrno;
802
		if (!okfail)
803
			filioerr(fil);
804
		return;
805
	}
806
	slevel++;
807
	ointty = intty;
808
	intty = isatty(0);
809
	oprompt = value(PROMPT);
810
	value(PROMPT) &= intty;
811
	getexit(osetexit);
812
	setrupt();
813
	if (setexit() == 0)
814
		commands(1, 1);
815
	else if (slevel > 1) {
816
		close(0);
817
		dup(saveinp);
818
		close(saveinp);
819
		slevel--;
820
		resexit(osetexit);
821
		reset();
822
	}
823
	intty = ointty;
824
	value(PROMPT) = oprompt;
825
	close(0);
826
	dup(saveinp);
827
	close(saveinp);
828
	globp = saveglobp;
829
	peekc = savepeekc;
830
	slevel--;
831
	resexit(osetexit);
832
}
833
 
834
/*
835
 * Clear io statistics before a read or write.
836
 */
837
clrstats()
838
{
839
 
840
	ninbuf = 0;
841
	cntch = 0;
842
	cntln = 0;
843
	cntnull = 0;
844
	cntodd = 0;
845
}
846
 
847
/*
848
 * Io is finished, close the unit and print statistics.
849
 */
850
iostats()
851
{
852
 
853
	(void) fsync(io);
854
	close(io);
855
	io = -1;
856
	if (hush == 0) {
857
		if (value(TERSE))
858
			printf(" %d/%D", cntln, cntch);
859
		else
860
			printf(" %d line%s, %D character%s", cntln, plural((long) cntln),
861
			    cntch, plural(cntch));
862
		if (cntnull || cntodd) {
863
			printf(" (");
864
			if (cntnull) {
865
				printf("%D null", cntnull);
866
				if (cntodd)
867
					printf(", ");
868
			}
869
			if (cntodd)
870
#ifndef	ISO
871
				printf("%D non-ASCII", cntodd);
872
#else
873
				printf("%D non-ISO", cntodd);
874
#endif
875
			putchar(')');
876
		}
877
		noonl();
878
		flush();
879
	}
880
	return (cntnull != 0 || cntodd != 0);
881
}
882
 
883
#if USG | USG3TTY
884
/* It's so wonderful how we all speak the same language... */
885
# define index strchr
886
# define rindex strrchr
887
#endif
888
 
889
checkmodeline(li_ne)
890
char *li_ne;
891
{
892
	char *beg, *end;
893
	char cmdbuf[1024];
894
	char *index(), *rindex();
895
 
896
	beg = index(li_ne, ':');
897
	if (beg == NULL)
898
		return;
899
	if (&beg[-3] < li_ne)
900
		return;
901
	if (!(  ( (beg[-3] == ' ' || beg[-3] == '\t')
902
	        && beg[-2] == 'e'
903
		&& beg[-1] == 'x')
904
	     || ( (beg[-3] == ' ' || beg[-3] == '\t')
905
	        && beg[-2] == 'v'
906
		&& beg[-1] == 'i'))) return;
907
	strncpy(cmdbuf, beg+1, sizeof cmdbuf);
908
	end = rindex(cmdbuf, ':');
909
	if (end == NULL)
910
		return;
911
	*end = 0;
912
	globp = cmdbuf;
913
	commands(1, 1);
914
}