#include "ex.h"
#include "ex_temp.h"
#include "ex_tty.h"
#include "ex_vis.h"
extern int getchar();
void
unix0(bool warn, int contcmd)
{
unsigned char *up, *fp;
short c;
char multic[MB_LEN_MAX + 1];
int len;
int contread = 0;
wchar_t wc;
unsigned char printub, puxb[UXBSIZE + sizeof (int)];
const char *specialchars = (contcmd ? "%#!\n" : "%#!");
printub = 0;
CP(puxb, uxb);
c = peekchar();
if (c == '\n' || c == EOF) {
(void) getchar();
error(value(vi_TERSE) ?
gettext("Incomplete shell escape command") :
gettext("Incomplete shell escape command - use 'shell' to get a shell"));
}
up = (unsigned char *)uxb;
for (;;) {
if (!isascii(c)) {
if (c == EOF)
break;
if ((len = _mbftowc(multic, &wc, getchar, &peekc)) > 0) {
if ((up + len) >= (unsigned char *)&uxb[UXBSIZE]) {
uxb[0] = 0;
error(gettext("Command too long"));
}
strncpy(up, multic, len);
up += len;
goto loop_check;
}
}
(void) getchar();
switch (c) {
case '\\':
if (any(peekchar(), specialchars)) {
c = getchar();
if (contcmd && (c == '\n')) {
contread = 1;
}
}
default:
if (up >= (unsigned char *)&uxb[UXBSIZE]) {
tunix:
uxb[0] = 0;
error(gettext("Command too long"));
}
if (!tagflg)
*up++ = c;
break;
case '!':
if (up != (unsigned char *)uxb && *puxb != 0) {
fp = puxb;
if (*fp == 0) {
uxb[0] = 0;
error(value(vi_TERSE) ?
gettext("No previous command") :
gettext("No previous command to substitute for !"));
}
printub++;
while (*fp) {
if (up >= (unsigned char *)&uxb[UXBSIZE])
goto tunix;
*up++ = *fp++;
}
} else if (up == (unsigned char *)uxb) {
fp = puxb;
if (*fp == 0) {
uxb[0] = 0;
error(value(vi_TERSE) ?
gettext("No previous command") :
gettext("No previous command to substitute for !"));
}
printub++;
while (*fp) {
if (up >= (unsigned char *)&uxb[UXBSIZE])
goto tunix;
*up++ = *fp++;
}
} else {
if (up >= (unsigned char *)&uxb[UXBSIZE]) {
uxb[0] = 0;
error(gettext("Command too long"));
}
*up++ = c;
}
break;
case '#':
fp = (unsigned char *)altfile;
if (*fp == 0) {
uxb[0] = 0;
error(value(vi_TERSE) ?
gettext("No alternate filename") :
gettext("No alternate filename to substitute for #"));
}
goto uexp;
case '%':
fp = savedfile;
if (*fp == 0) {
uxb[0] = 0;
error(value(vi_TERSE) ?
gettext("No filename") :
gettext("No filename to substitute for %%"));
}
uexp:
printub++;
while (*fp) {
if (up >= (unsigned char *)&uxb[UXBSIZE])
goto tunix;
*up++ = *fp++;
}
break;
}
loop_check:
c = peekchar();
if (c == '"' || c == '|' || (contread > 0) || !endcmd(c)) {
contread = 0;
continue;
} else {
(void) getchar();
break;
}
}
if (c == EOF)
ungetchar(c);
*up = 0;
if (!inopen)
resetflav();
if (warn)
ckaw();
if (warn && hush == 0 && chng && xchng != chng && value(vi_WARN) && dol > zero) {
xchng = chng;
vnfl();
viprintf(mesg(value(vi_TERSE) ? gettext("[No write]") :
gettext("[No write since last change]")));
noonl();
flush();
} else
warn = 0;
if (printub) {
if (uxb[0] == 0)
error(value(vi_TERSE) ? gettext("No previous command") :
gettext("No previous command to repeat"));
if (inopen) {
splitw++;
vclean();
vgoto(WECHO, 0);
}
if (warn)
vnfl();
if (hush == 0)
lprintf("!%s", uxb);
if (inopen && Outchar != termchar) {
vclreol();
vgoto(WECHO, 0);
} else
putnl();
flush();
}
}
ttymode
unixex(opt, up, newstdin, mode)
unsigned char *opt, *up;
int newstdin, mode;
{
int pvec[2];
ttymode f;
signal(SIGINT, SIG_IGN);
#ifdef SIGTSTP
if (dosusp)
signal(SIGTSTP, SIG_DFL);
#endif
if (inopen)
f = setty(normf);
if ((mode & 1) && pipe(pvec) < 0) {
if (inopen)
setty(f);
error(gettext("Can't make pipe for filter"));
}
#ifndef VFORK
pid = fork();
#else
pid = vfork();
#endif
if (pid < 0) {
if (mode & 1) {
close(pvec[0]);
close(pvec[1]);
}
setrupt();
if (inopen)
setty(f);
error(gettext("No more processes"));
}
if (pid == 0) {
if (mode & 2) {
close(0);
dup(newstdin);
close(newstdin);
}
if (mode & 1) {
close(pvec[0]);
close(1);
dup(pvec[1]);
if (inopen) {
close(2);
dup(1);
}
close(pvec[1]);
}
if (io)
close(io);
if (tfile)
close(tfile);
signal(SIGHUP, oldhup);
signal(SIGQUIT, oldquit);
if (ruptible)
signal(SIGINT, SIG_DFL);
execlp((char *)svalue(vi_SHELL), (char *)svalue(vi_SHELL),
opt, up, (char *)0);
viprintf(gettext("Invalid SHELL value: %s\n"),
svalue(vi_SHELL));
flush();
error(NOSTR);
}
if (mode & 1) {
io = pvec[0];
close(pvec[1]);
}
if (newstdin)
close(newstdin);
return (f);
}
void
unixwt(c, f)
bool c;
ttymode f;
{
waitfor();
#ifdef SIGTSTP
if (dosusp)
signal(SIGTSTP, onsusp);
#endif
if (inopen)
setty(f);
setrupt();
if (!inopen && c && hush == 0) {
viprintf("!\n");
flush();
termreset();
gettmode();
}
}
int
vi_filter(int mode)
{
static int pvec[2];
ttymode f;
int nlines = lineDOL();
int status2;
pid_t pid2 = 0;
mode++;
if (mode & 2) {
signal(SIGINT, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
if (pipe(pvec) < 0)
error(gettext("Can't make pipe"));
pid2 = fork();
io = pvec[0];
if (pid < 0) {
setrupt();
close(pvec[1]);
error(gettext("No more processes"));
}
if (pid2 == 0) {
extern unsigned char tfname[];
setrupt();
io = pvec[1];
close(pvec[0]);
close(tfile);
tfile = open(tfname, 2);
putfile(1);
exit(errcnt);
}
close(pvec[1]);
io = pvec[0];
setrupt();
}
f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode);
if (mode == 3) {
(void) delete(0);
addr2 = addr1 - 1;
}
if (mode == 1)
deletenone();
if (mode & 1) {
if(FIXUNDO)
undap1 = undap2 = addr2+1;
(void)append(getfile, addr2);
#ifdef UNDOTRACE
if (trace)
vudump(gettext("after append in filter"));
#endif
}
close(io);
io = -1;
unixwt(!inopen, f);
if (pid2) {
(void)kill(pid2, 9);
do
rpid = waitpid(pid2, &status2, 0);
while (rpid == (pid_t)-1 && errno == EINTR);
}
netchHAD(nlines);
return (0);
}
void
recover(void)
{
static int pvec[2];
if (pipe(pvec) < 0)
error(gettext(" Can't make pipe for recovery"));
pid = fork();
io = pvec[0];
if (pid < 0) {
close(pvec[1]);
error(gettext(" Can't fork to execute recovery"));
}
if (pid == 0) {
unsigned char cryptkey[19];
close(2);
dup(1);
close(1);
dup(pvec[1]);
close(pvec[1]);
if(xflag) {
strcpy(cryptkey, "CrYpTkEy=XXXXXXXXX");
strcpy(cryptkey + 9, key);
if(putenv((char *)cryptkey) != 0)
smerror(gettext(" Cannot copy key to environment"));
execlp(EXRECOVER, "exrecover", "-x", svalue(vi_DIRECTORY), file, (char *) 0);
} else
execlp(EXRECOVER, "exrecover", svalue(vi_DIRECTORY), file, (char *) 0);
close(1);
dup(2);
error(gettext(" No recovery routine"));
}
close(pvec[1]);
}
void
waitfor(void)
{
do
rpid = waitpid(pid, &status, 0);
while (rpid == (pid_t)-1 && errno != ECHILD);
if ((status & 0377) == 0)
status = (status >> 8) & 0377;
else {
viprintf(gettext("%d: terminated with signal %d"), pid,
status & 0177);
if (status & 0200)
viprintf(gettext(" -- core dumped"));
putchar('\n');
}
}
void
revocer(void)
{
waitfor();
if (pid == rpid && status != 0)
edited = 0;
else
change();
}