4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 /* Copyright (c) 1981 Regents of the University of California */
41 #define nochng() lchng = chng
45 * Main loop for command mode command decoding.
46 * A few commands are executed here, but main function
47 * is to strip command addresses, do a little address oriented
48 * processing and call command routines to do the real work.
50 extern unsigned char *Version
;
52 commands(noprompt
, exitoneof
)
53 bool noprompt
, exitoneof
;
66 unsigned char *vgetpass();
74 * If dot at last command
75 * ended up at zero, advance to one if there is a such.
85 * If autoprint or trailing print flags,
86 * print the line at the specified offset
87 * before the next command.
89 if ((pflag
|| lchng
!= chng
&& value(vi_AUTOPRINT
) &&
90 !inglobal
&& !inopen
&& endline
) || poffset
!= 0) {
94 addr1
= addr2
= dot
+ poffset
;
96 if (addr1
< one
|| addr1
> dol
)
97 error(value(vi_TERSE
) ?
98 gettext("Offset out-of-bounds") :
99 gettext("Offset after command "
110 * Print prompt if appropriate.
111 * If not in global flush output first to prevent
112 * going into pfast mode unreasonably.
116 if (!hush
&& value(vi_PROMPT
) && !globp
&&
117 !noprompt
&& endline
) {
125 * Gobble up the address.
126 * Degenerate addresses yield ".".
129 given
= seensemi
= 0;
135 if (c
== ',' || c
== ';')
137 else if (addr1
!= 0) {
163 * eat multiple colons
168 * Set command name for special character commands.
173 * If called via : escape from open or visual, limit
174 * the set of available commands here to save work below.
177 if (c
== '\n' || c
== '\r' ||
178 c
== CTRL('d') || c
== EOF
) {
187 tailprim(Command
, 1, 1);
193 switch (peekchar()) {
221 (void) append(gettty
, addr2
);
227 switch (peekchar()) {
244 (void) crypt_close(perm
);
246 if ((kflag
= run_setkey(perm
,
248 gettext("Enter key:"))))) == -1) {
252 smerror(gettext("Encryption facility "
267 if (peekchar() == 'd') {
271 if (savedfile
[0] == '/' ||
277 p
= (unsigned char *)
287 if (chdir((char *)p
) < 0)
289 if (savedfile
[0] != '/')
294 tailprim((unsigned char *)"change",
310 #else /* XPG6 and Solaris */
312 #endif /* XPG4ONLY */
317 if (append(gettty
, addr1
- 1) == 0) {
320 * P2003.2/D9:5.10.7.2.4, p. 646,
321 * assertion 214(A). If nothing changed,
322 * set dot to the line preceding the lines
339 * Caution: dp and dl have special meaning already.
346 #else /* XPG6 and Solaris */
348 #endif /* XPG4ONLY */
359 if (crflag
== 2 || crflag
== -2)
361 tail(peekchar() == 'x' ? "ex" : "edit");
363 if (!exclam() && chng
)
367 if (inopen
&& !value(vi_AUTOWRITE
)) {
371 ungetchar(lastchar());
374 if (chng
&& dol
> zero
) {
376 error(value(vi_TERSE
) ?
377 gettext("No write") :
378 gettext("No write since "
429 (void) append(gettty
, addr2
- 1);
431 if (dot
== zero
&& dol
> zero
)
446 * if no count was specified, addr1 == addr2. if only
447 * 1 range arg was specified, inc addr2 to allow
448 * joining of the next line.
450 if (given
< 2 && (addr1
== addr2
) && (addr2
!= dol
))
453 #else /* XPG6 and Solaris */
454 if (given
< 2 && addr2
!= dol
)
456 #endif /* XPG4ONLY */
467 (unsigned char *)gettext("Mark what?") :
469 gettext("%s requires following "
473 error((vi_TERSE
) ? gettext("Bad mark") :
474 gettext("Mark must specify a letter"));
477 names
[c
- 'a'] = *addr2
&~ 01;
487 #else /* XPG6 and Solaris */
489 #endif /* XPG4ONLY */
495 if (peekchar() == 'a') {
497 if (peekchar() == 'p') {
515 if (peekchar() == 'u') {
524 if (chng
&& dol
> zero
) {
526 error(value(vi_TERSE
) ?
527 gettext("No write") :
528 gettext("No write since last "
529 "change (:%s! overrides)"),
551 switch (peekchar()) {
579 if (peekchar() == 'e') {
585 "Preserve failed!"));
589 * error() incs errcnt. this is
590 * misleading here; and a
591 * violation of POSIX. so call
593 * this is for assertion ex:222.
596 gettext("File preserved."));
600 gettext("File preserved."));
616 if (clear_screen
&& span() > lines
) {
621 * poffset is nonzero if trailing + or - flags
622 * were given, and in that case we need to
623 * adjust dot before printing a line.
626 plines(addr1
, addr2
, 1);
656 if (peekchar() == 'e') {
658 switch (peekchar()) {
666 if (chng
&& dol
> zero
)
669 gettext("No write") :
680 ungetchar(lastchar());
689 if (!exclam() && chng
)
693 ungetchar(lastchar());
714 if (crflag
== 2 || crflag
== -2)
715 /* restore crflag for new input text */
717 if (savedfile
[0] == 0 && dol
== zero
)
721 if (peekchar() == '!') {
731 if (inopen
&& endline
&& addr1
> zero
&& addr1
< dol
)
736 switch (peekchar()) {
738 * Caution: 2nd char cannot be c, g, or r
739 * because these have meaning to substitute.
754 putpad((unsigned char *)exit_ca_mode
);
757 unixwt(1, unixex("-i", (char *)0, 0, 0));
781 * for POSIX, "su" with no other distinguishing
782 * characteristics, maps to "s". Re. P1003.D11,
785 * so, unless the "su" is followed by a "s" or
786 * a "!", we assume that the user means "s".
788 switch (d
= peekchar()) {
813 Command
= (unsigned char *)"substitute";
823 if (peekchar() == 'a') {
824 tagflg
= 1; /* :tag command */
840 if (peekchar() == 'n') {
842 switch (peekchar()) {
851 tail2of("unabbreviate");
869 switch (peekchar()) {
875 viprintf("%s", Version
);
900 tail(c
== 'q' ? "wq" : "write");
902 if (skipwh() && peekchar() == '!') {
922 crflag
= -1; /* determine if file is encrypted */
926 crflag
= 1; /* assume files read in are encrypted */
943 #else /* XPG6 and Solaris */
945 #endif /* XPG4ONLY */
965 if (c
== '\n' || c
== '\r')
967 if (any(c
, "@*\n\r"))
972 error(gettext("Bad register"));
989 if (cursor_up
!= NOSTR
&& c
== '\n' &&
998 gettext("At end-of-file"));
999 addr1
= addr2
= dot
+ 1;
1007 if (c
== CTRL('k')) {
1013 plines(addr1
, addr2
, 1);
1035 viprintf("%d", lineno(addr2
));
1045 (void) vi_filter(2);
1049 putpad((unsigned char *)exit_ca_mode
);
1053 unixwt(1, unixex("-c", uxb
, 0, 0));
1055 error(gettext("Invalid tags file:"
1056 " contains shell escape"));
1058 vclrech(1); /* vcontin(0); */
1067 for (cnt
= 1; peekchar() == c
; cnt
++)
1086 * Chtty sys call at UCB may cause a
1087 * input which was a tty to suddenly be
1088 * turned into /dev/null.
1106 if (!isalpha(c
) || !isascii(c
))
1109 tailprim((unsigned char *)"", 0, 0);
1114 char multic
[MULTI_BYTE_MAX
];
1116 length
= _mbftowc(multic
, &wchar
, getchar
, &peekc
);
1119 multic
[length
] = '\0';
1120 error((vi_TERSE
) ? gettext("What?") :
1121 gettext("Unknown command character '%s'"),