/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* Copyright (c) 1979 Regents of the University of California */
#pragma ident "%Z%%M% %I% %E% SMI"
#include "ex.h"
#include "ex_temp.h"
#include "ex_tty.h"
#include "ex_vis.h"
extern int getchar();
/*
* Unix escapes, filtering
*/
/*
* First part of a shell escape,
* parse the line, expanding # and % and ! and printing if implied.
*/
void
{
short c;
int len;
int contread = 0;
printub = 0;
c = peekchar();
if (c == '\n' || c == EOF) {
(void) getchar();
gettext("Incomplete shell escape command") :
gettext("Incomplete shell escape command - use 'shell' to get a shell"));
}
for (;;) {
if (!isascii(c)) {
if (c == EOF)
break;
uxb[0] = 0;
}
goto loop_check;
}
}
(void) getchar();
switch (c) {
case '\\':
c = getchar();
/*
* If we encountered a backslash-escaped
* newline, and we're processing a continuation
* command, then continue processing until
* non-backslash-escaped newline is reached.
*/
if (contcmd && (c == '\n')) {
contread = 1;
}
}
default:
uxb[0] = 0;
}
/*
* If this is a tag command (-t or :tag),
* then don't save any command that follows
* '!' in the invalid tags file, ie:
* '!!' should not repeat the invalid command
* later on when tagflg has been cleared.
*/
if (!tagflg)
*up++ = c;
break;
case '!':
if (*fp == 0) {
uxb[0] = 0;
gettext("No previous command") :
gettext("No previous command to substitute for !"));
}
printub++;
while (*fp) {
goto tunix;
}
/* If up = uxb it means we are on the first
* character inside the shell command.
* (i.e., after the ":!")
*
* The user has just entered ":!!" which
* means that though there is only technically
* one '!' we know he really meant ":!!!". So
* substitute the last command for him.
*/
if (*fp == 0) {
uxb[0] = 0;
gettext("No previous command") :
gettext("No previous command to substitute for !"));
}
printub++;
while (*fp) {
goto tunix;
}
} else {
/*
* Treat a lone "!" as just a regular character
* so commands like "mail machine!login" will
* work as usual (i.e., the user doesn't need
* to dereference the "!" with "\!").
*/
uxb[0] = 0;
}
*up++ = c;
}
break;
case '#':
if (*fp == 0) {
uxb[0] = 0;
gettext("No alternate filename") :
gettext("No alternate filename to substitute for #"));
}
goto uexp;
case '%':
if (*fp == 0) {
uxb[0] = 0;
gettext("No filename") :
gettext("No filename to substitute for %%"));
}
uexp:
printub++;
while (*fp) {
goto tunix;
}
break;
}
c = peekchar();
/*
* If contread was set, then the newline just
* processed was preceeded by a backslash, and
* not considered the end of the command. Reset
* it here in case another backslash-escaped
* newline is processed.
*/
contread = 0;
continue;
} else {
(void) getchar();
break;
}
}
if (c == EOF)
ungetchar(c);
*up = 0;
if (!inopen)
resetflav();
if (warn)
ckaw();
vnfl();
gettext("[No write since last change]")));
noonl();
flush();
} else
warn = 0;
if (printub) {
if (uxb[0] == 0)
gettext("No previous command to repeat"));
if (inopen) {
splitw++;
vclean();
}
if (warn)
vnfl();
if (hush == 0)
vclreol();
} else
putnl();
flush();
}
}
/*
* Do the real work for execution of a shell escape.
* Mode is like the number passed to open system calls
* and indicates filtering. If input is implied, newstdin
* must have been setup already.
*/
{
ttymode f;
#ifdef SIGTSTP
if (dosusp)
#endif
if (inopen)
/* Newstdin should be io so it will be closed */
if (inopen)
setty(f);
}
#ifndef VFORK
#else
#endif
if (pid < 0) {
if (mode & 1) {
}
setrupt();
if (inopen)
setty(f);
}
if (pid == 0) {
if (mode & 2) {
close(0);
}
if (mode & 1) {
close(1);
if (inopen) {
close(2);
dup(1);
}
}
if (io)
if (tfile)
if (ruptible)
flush();
}
if (mode & 1) {
}
if (newstdin)
return (f);
}
/*
* Wait for the command to complete.
* C flags suppression of printing.
*/
void
unixwt(c, f)
bool c;
ttymode f;
{
waitfor();
#ifdef SIGTSTP
if (dosusp)
#endif
if (inopen)
setty(f);
setrupt();
viprintf("!\n");
flush();
termreset();
gettmode();
}
}
/*
* Setup a pipeline for the filtration implied by mode
* which is like a open number. If input is required to
* the filter, then a child editor is created to write it.
* If output is catch it from io which is created by unixex.
*/
int
{
ttymode f; /* was register */
int status2;
mode++;
if (mode & 2) {
if (pid < 0) {
setrupt();
}
if (pid2 == 0) {
extern unsigned char tfname[];
setrupt();
/* To prevent seeking in this process and the
parent, we must reopen tfile here */
putfile(1);
}
setrupt();
}
if (mode == 3) {
(void) delete(0);
}
if (mode == 1)
deletenone();
if (mode & 1) {
if(FIXUNDO)
#ifdef UNDOTRACE
if (trace)
#endif
}
io = -1;
if (pid2) {
do
}
return (0);
}
/*
* Set up to do a recover, getting io to be a pipe from
* the recover process.
*/
void
recover(void)
{
if (pid < 0) {
}
if (pid == 0) {
close(2);
dup(1);
close(1);
if(xflag) {
} else
close(1);
dup(2);
}
}
/*
* Wait for the process (pid an external) to complete.
*/
void
waitfor(void)
{
do
if ((status & 0377) == 0)
else {
/*
* TRANSLATION_NOTE
* Reference order of arguments must not
* be changed using '%digit$', since vi's
* viprintf() does not support it.
*/
status & 0177);
if (status & 0200)
putchar('\n');
}
}
/*
* The end of a recover operation. If the process
* exits non-zero, force not edited; otherwise force
* a write.
*/
void
revocer(void)
{
waitfor();
edited = 0;
else
change();
}