868 lines
16 KiB
C
868 lines
16 KiB
C
/*
|
|
** docmd2.c
|
|
**
|
|
** routines to actually execute commands
|
|
**
|
|
** This file is part of mse, under GPLv3.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
|
|
#include "se.h"
|
|
#include "changetty.h"
|
|
#include "docmd1.h"
|
|
#include "docmd2.h"
|
|
#include "edit.h"
|
|
#include "extern.h"
|
|
#include "main.h"
|
|
#include "misc.h"
|
|
#include "pat.h"
|
|
#include "scratch.h"
|
|
#include "screen.h"
|
|
#include "term.h"
|
|
|
|
/* append --- append lines after "line" */
|
|
|
|
int append (int line, char str[])
|
|
{
|
|
char lin[MAXLINE];
|
|
char term;
|
|
int ret;
|
|
int len, i, dpos, dotseen;
|
|
|
|
Curln = line;
|
|
|
|
if (str[0] == ':') /* text to be added is in the command line */
|
|
ret = inject (&str[1]);
|
|
else
|
|
{
|
|
Cmdrow = Toprow + (Curln - Topln) + 1; /* 1 below Curln */
|
|
lin[0] = EOS;
|
|
if (Indent > 0 || line <= 0)
|
|
len = max (0, Indent - 1);
|
|
else /* do auto indent */
|
|
{
|
|
LINEDESC *k;
|
|
k = se_gettxt (line);
|
|
for (len = 0; Txt[len] == ' '; len++)
|
|
;
|
|
}
|
|
dpos = len; /* position for terminating '.' */
|
|
|
|
for (ret = NOSTATUS; ret == NOSTATUS; )
|
|
{
|
|
if (! hwinsdel()) /* do it the old, slow way */
|
|
{
|
|
if (Cmdrow > Botrow)
|
|
{
|
|
Cmdrow = Toprow + 1;
|
|
cprow (Botrow, Toprow);
|
|
adjust_window (Curln, Curln);
|
|
if (First_affected > Topln)
|
|
First_affected = Topln;
|
|
}
|
|
clrrow (Cmdrow);
|
|
if (Cmdrow < Botrow)
|
|
clrrow (Cmdrow + 1);
|
|
}
|
|
else /* try to be smart about it */
|
|
{
|
|
if (Cmdrow > Botrow)
|
|
{
|
|
Cmdrow--;
|
|
dellines (Toprow, 1);
|
|
inslines (Cmdrow, 1);
|
|
Topln++;
|
|
}
|
|
else
|
|
{
|
|
dellines (Botrow, 1);
|
|
inslines (Cmdrow, 1);
|
|
}
|
|
}
|
|
prompt ("apd>");
|
|
do
|
|
getcmd (lin, Firstcol, &len, &term);
|
|
while (term == CURSOR_UP || term == CURSOR_DOWN
|
|
|| term == CURSOR_SAME);
|
|
|
|
dotseen = 0;
|
|
if (lin[0] == '.' && lin[1] == '\n' && lin[2] == EOS)
|
|
dotseen = 1;
|
|
for (i = 0; i < dpos && lin[i] == ' '; i++)
|
|
;
|
|
if (i == dpos && lin[dpos] == '.' && lin[dpos + 1] == '\n'
|
|
&& lin[dpos+2] == EOS)
|
|
dotseen = 1;
|
|
|
|
if (dotseen)
|
|
{
|
|
if (hwinsdel())
|
|
{
|
|
dellines (Cmdrow, 1);
|
|
inslines (Botrow, 1);
|
|
}
|
|
ret = OK;
|
|
}
|
|
else if (inject (lin) == ERR)
|
|
ret = ERR;
|
|
else /* inject occured */
|
|
prompt (""); /* erase prompt */
|
|
Cmdrow++;
|
|
if (term != FUNNY)
|
|
{
|
|
if (Indent > 0)
|
|
len = Indent - 1;
|
|
else /* do auto indent */
|
|
for (len = 0; lin[len] == ' '; len++)
|
|
;
|
|
dpos = len;
|
|
lin[0] = EOS;
|
|
}
|
|
}
|
|
Cmdrow = Botrow + 1;
|
|
if (hwinsdel()) /* since we take control */
|
|
{ /* of the screen, we're sure */
|
|
Sctop = Topln; /* it's still OK */
|
|
|
|
for (i = 0; i < Sclen; i++)
|
|
Scline[i] = Sctop + i <= Lastln ? i : -1;
|
|
}
|
|
}
|
|
if (Curln == 0 && Lastln > 0) /* for 0a or 1i followed by "." */
|
|
Curln = 1;
|
|
if (First_affected > line)
|
|
First_affected = line;
|
|
|
|
tflush ();
|
|
return (ret);
|
|
}
|
|
|
|
/* copy --- copy line1 through line2 after line3 */
|
|
|
|
int copy (int line3)
|
|
{
|
|
int i;
|
|
int ret;
|
|
LINEDESC *ptr3, *after3, *k;
|
|
|
|
ret = ERR;
|
|
|
|
if (Line1 <= 0)
|
|
Errcode = EORANGE;
|
|
else
|
|
{
|
|
ret = OK;
|
|
Curln = line3;
|
|
k = getind (Line1);
|
|
for (i = Line1; i <= Line2; i++)
|
|
{
|
|
gtxt (k);
|
|
if (inject (Txt) == ERR || intrpt ())
|
|
{
|
|
ret = ERR;
|
|
break;
|
|
}
|
|
if (Line1 < line3)
|
|
k++;
|
|
else
|
|
k += 2;
|
|
/*
|
|
* inject calls blkmove, which will shift the
|
|
* lines down one in the array, so we add two
|
|
* instead of one to get to the next line.
|
|
*/
|
|
}
|
|
First_affected = min (First_affected, line3 + 1);
|
|
}
|
|
return (ret);
|
|
}
|
|
|
|
|
|
/* delete --- delete lines from through to */
|
|
|
|
int se_delete (int from, int to, int *status)
|
|
{
|
|
LINEDESC *k1, *k2, *j1, *j2, *l1;
|
|
|
|
if (from <= 0) /* can't delete line 0 */
|
|
{
|
|
*status = ERR;
|
|
Errcode = EORANGE;
|
|
}
|
|
else
|
|
{
|
|
if (First_affected > from)
|
|
First_affected = from;
|
|
blkmove (from, to, MAXBUF - 1); /* stick at end of buffer */
|
|
|
|
Lastln -= to - from + 1; /* adjust number of last line */
|
|
Curln = prevln (from);
|
|
|
|
Lost_lines += Limcnt;
|
|
Limcnt = to - from + 1; /* number of lines "deleted" */
|
|
|
|
/* point at first deleted */
|
|
Limbo = &Buf[MAXBUF - (to - from + 1)];
|
|
|
|
*status = OK;
|
|
svdel (from, to - from + 1);
|
|
Buffer_changed = YES;
|
|
}
|
|
|
|
return (*status);
|
|
}
|
|
|
|
|
|
/* join --- join a group of lines into a single line */
|
|
|
|
int join (char sub[])
|
|
{
|
|
char new[MAXLINE];
|
|
int l, line, sublen;
|
|
int ret;
|
|
LINEDESC *k;
|
|
|
|
ret = OK;
|
|
if (Line1 <= 0)
|
|
{
|
|
Errcode = EORANGE;
|
|
return (ERR);
|
|
}
|
|
|
|
sublen = strlen (sub) + 1; /* length of separator & EOS */
|
|
line = Line1;
|
|
k = getind (line);
|
|
gtxt (k);
|
|
move_ (Txt, new, (int) k -> Lineleng); /* move in first chunk */
|
|
l = k -> Lineleng;
|
|
|
|
for (line++; line <= Line2; line++)
|
|
{
|
|
if (intrpt ())
|
|
return (ERR);
|
|
if (new[l - 2] == '\n') /* zap the NEWLINE */
|
|
l--;
|
|
k = NEXTLINE(k); /* get the next line */
|
|
gtxt (k);
|
|
if (l + sublen - 1 + k -> Lineleng - 1 > MAXLINE) /* won't fit */
|
|
{
|
|
Errcode = E2LONG;
|
|
return (ERR);
|
|
}
|
|
move_ (sub, &new[l - 1], sublen); /* insert separator string */
|
|
l += sublen - 1;
|
|
move_ (Txt, &new[l - 1], (int) k -> Lineleng); /* move next line */
|
|
l += k -> Lineleng - 1;
|
|
}
|
|
Curln = Line2; /* all this will replace line1 through line2 */
|
|
ret = inject (new); /* inject the new line */
|
|
if (ret == OK)
|
|
ret = se_delete (Line1, Line2, &ret); /* delete old lines */
|
|
Curln++;
|
|
|
|
if (First_affected > Curln)
|
|
First_affected = Curln;
|
|
|
|
return (ret);
|
|
}
|
|
|
|
|
|
/* move --- move line1 through line2 after line3 */
|
|
|
|
int move (int line3)
|
|
{
|
|
LINEDESC *k0, *k1, *k2, *k3, *k4, *k5;
|
|
|
|
if (Line1 <= 0)
|
|
{
|
|
Errcode = EORANGE;
|
|
return (ERR);
|
|
}
|
|
|
|
if (Line1 <= line3 && line3 <= Line2)
|
|
{
|
|
Errcode = EINSIDEOUT;
|
|
return (ERR);
|
|
}
|
|
|
|
blkmove (Line1, Line2, line3);
|
|
|
|
if (line3 > Line1)
|
|
{
|
|
Curln = line3;
|
|
}
|
|
else
|
|
Curln = line3 + (Line2 - Line1 + 1);
|
|
|
|
Buffer_changed = YES;
|
|
First_affected = min (First_affected, min (Line1, line3));
|
|
|
|
return (OK);
|
|
}
|
|
|
|
/* overlay --- let user edit lines directly */
|
|
|
|
void overlay (int *status)
|
|
{
|
|
char savtxt[MAXLINE], term, kname;
|
|
static char empty[] = "\n";
|
|
int lng, vcol, lcurln, scurln;
|
|
LINEDESC *indx;
|
|
|
|
*status = OK;
|
|
if (Line1 == 0)
|
|
{
|
|
Curln = 0;
|
|
*status = inject (empty);
|
|
if (*status == ERR)
|
|
return;
|
|
First_affected = 1;
|
|
Line1 = 1;
|
|
Line2++;
|
|
}
|
|
|
|
for (lcurln = Line1; lcurln <= Line2; lcurln++)
|
|
{
|
|
Curln = lcurln;
|
|
vcol = Overlay_col - 1;
|
|
do {
|
|
adjust_window (Curln, Curln);
|
|
updscreen ();
|
|
Cmdrow = Curln - Topln + Toprow;
|
|
indx = se_gettxt (Curln);
|
|
lng = indx -> Lineleng;
|
|
if (Txt[lng - 2] == '\n') /* clobber newline */
|
|
lng--;
|
|
if (vcol < 0)
|
|
vcol = lng - 1;
|
|
while (lng - 1 < vcol)
|
|
{
|
|
Txt[lng - 1] = ' ';
|
|
lng++;
|
|
}
|
|
Txt[lng - 1] = '\n';
|
|
Txt[lng] = EOS;
|
|
move_ (Txt, savtxt, lng + 1); /* make a copy of the line */
|
|
getcmd (Txt, Firstcol, &vcol, &term);
|
|
if (term == FUNNY)
|
|
{
|
|
if (First_affected > Curln)
|
|
First_affected = Curln;
|
|
Cmdrow = Botrow + 1;
|
|
return;
|
|
}
|
|
if (strcmp (Txt, savtxt) != 0) /* was line changed? */
|
|
{
|
|
kname = indx -> Markname;
|
|
se_delete (Curln, Curln, status);
|
|
scurln = Curln;
|
|
if (*status == OK)
|
|
*status = inject (Txt);
|
|
if (*status == ERR)
|
|
{
|
|
Cmdrow = Botrow + 1;
|
|
return;
|
|
}
|
|
indx = getind (nextln (scurln));
|
|
indx -> Markname = kname;
|
|
}
|
|
else
|
|
{ /* in case end-of-line is moved */
|
|
if (First_affected > Curln)
|
|
First_affected = Curln;
|
|
}
|
|
switch (term) {
|
|
case CURSOR_UP:
|
|
if (Curln > 1)
|
|
Curln--;
|
|
else
|
|
Curln = Lastln;
|
|
break;
|
|
case CURSOR_DOWN:
|
|
if (Curln < Lastln)
|
|
Curln++;
|
|
else
|
|
Curln = min (1, Lastln);
|
|
break;
|
|
case CURSOR_SAME:
|
|
vcol = 0;
|
|
break;
|
|
}
|
|
} while (term == CURSOR_UP ||
|
|
term == CURSOR_DOWN ||
|
|
term == CURSOR_SAME);
|
|
}
|
|
Cmdrow = Botrow + 1;
|
|
return;
|
|
}
|
|
|
|
|
|
/* subst --- substitute "sub" for occurrences of pattern */
|
|
|
|
int subst (char sub[], int gflag, int glob)
|
|
{
|
|
char new[MAXLINE], kname;
|
|
int line, m, k, lastm;
|
|
int j, junk, status, subbed, ret;
|
|
int tagbeg[10], tagend[10];
|
|
LINEDESC *inx;
|
|
|
|
if (Globals && glob)
|
|
ret = OK;
|
|
else
|
|
ret = ERR;
|
|
|
|
if (Line1 <= 0)
|
|
{
|
|
Errcode = EORANGE;
|
|
return (ERR);
|
|
}
|
|
|
|
/* the following code has been removed for your protection
|
|
se_index() occasionally grabs newlines out of the character class
|
|
counter in a pattern. for example [0-9] doesn't work due to this
|
|
|
|
if (se_index (Pat, '\n') != -1) # never delete NEWLINE
|
|
{
|
|
Errcode = EBADPAT;
|
|
return (ERR);
|
|
}
|
|
*/
|
|
|
|
for (line = Line1; line <= Line2; line++)
|
|
{
|
|
if (intrpt ())
|
|
break;
|
|
j = 0;
|
|
subbed = NO;
|
|
inx = se_gettxt (line);
|
|
lastm = -1;
|
|
for (k = 0; Txt[k] != EOS; )
|
|
{
|
|
for (m = 1; m <= 9; m++)
|
|
{
|
|
tagbeg[m] = -1;
|
|
tagend[m] = -1;
|
|
}
|
|
if (gflag == YES || subbed == NO)
|
|
m = amatch (Txt, k, Pat, &tagbeg[1], &tagend[1]);
|
|
else
|
|
m = -1;
|
|
if (m > -1 && lastm != m) /* replace matched text */
|
|
{
|
|
subbed = YES;
|
|
tagbeg[0] = k;
|
|
tagend[0] = m;
|
|
catsub (Txt, tagbeg, tagend, sub, new, &j, MAXLINE);
|
|
lastm = m;
|
|
}
|
|
if (m == -1 || m == k) /* no match or null match */
|
|
{
|
|
junk = addset (Txt[k], new, &j, MAXLINE);
|
|
k++;
|
|
}
|
|
else
|
|
k = m; /* skip matched text */
|
|
}
|
|
if (subbed == YES)
|
|
{
|
|
if (addset (EOS, new, &j, MAXLINE) == NO)
|
|
{
|
|
ret = ERR;
|
|
Errcode = E2LONG;
|
|
break;
|
|
}
|
|
kname = inx -> Markname;
|
|
se_delete (line, line, &status); /* remembers dot */
|
|
ret = inject (new);
|
|
if (First_affected > Curln)
|
|
First_affected = Curln;
|
|
if (ret == ERR)
|
|
break;
|
|
inx = getind (Curln);
|
|
inx -> Markname = kname;
|
|
ret = OK;
|
|
Buffer_changed = YES;
|
|
}
|
|
else /* subbed == NO */
|
|
Errcode = ENOMATCH;
|
|
}
|
|
|
|
return (ret);
|
|
}
|
|
|
|
|
|
/* uniquely_name --- mark-name line; make sure no other line has same name */
|
|
|
|
void uniquely_name (char kname, int *status)
|
|
{
|
|
int line;
|
|
LINEDESC *k;
|
|
|
|
defalt (Curln, Curln);
|
|
|
|
if (Line1 <= 0)
|
|
{
|
|
*status = ERR;
|
|
Errcode = EORANGE;
|
|
return;
|
|
}
|
|
|
|
*status = OK;
|
|
line = 0;
|
|
k = Line0;
|
|
|
|
do {
|
|
line++;
|
|
k = NEXTLINE(k);
|
|
if (line == Line2)
|
|
k -> Markname = kname;
|
|
else if (k -> Markname == kname)
|
|
k -> Markname = DEFAULTNAME;
|
|
} while (line < Lastln);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/* draw_box --- draw or erase a box at coordinates in command line */
|
|
|
|
int draw_box (char lin[], int *i)
|
|
{
|
|
int left, right, col, len;
|
|
int junk;
|
|
LINEDESC *k;
|
|
char text[MAXLINE];
|
|
char kname, ch;
|
|
|
|
left = ctoi (lin, i);
|
|
if (left <= 0 || left > MAXLINE)
|
|
{
|
|
Errcode = EBADCOL;
|
|
return (ERR);
|
|
}
|
|
|
|
if (lin[*i] == ',')
|
|
{
|
|
(*i)++;
|
|
SKIPBL (lin, *i);
|
|
right = ctoi (lin, i);
|
|
if (right <= 0 || right >= MAXLINE || left > right)
|
|
{
|
|
Errcode = EBADCOL;
|
|
return (ERR);
|
|
}
|
|
}
|
|
else
|
|
right = left;
|
|
|
|
SKIPBL (lin, *i);
|
|
if (lin[*i] == '\n')
|
|
ch = ' ';
|
|
else
|
|
ch = lin[(*i)++];
|
|
|
|
if (lin[*i] != '\n')
|
|
{
|
|
Errcode = EEGARB;
|
|
return (ERR);
|
|
}
|
|
|
|
if (Line1 <= 0)
|
|
{
|
|
Errcode = EORANGE;
|
|
return (ERR);
|
|
}
|
|
|
|
for (Curln = Line1; Curln <= Line2; Curln++)
|
|
{
|
|
k = se_gettxt (Curln);
|
|
len = k -> Lineleng;
|
|
move_ (Txt, text, len);
|
|
|
|
if (text[len - 2] == '\n')
|
|
col = len - 1;
|
|
else
|
|
col = len;
|
|
while (col <= right)
|
|
{
|
|
text[col - 1] = ' ';
|
|
col++;
|
|
}
|
|
text[col - 1] = '\n';
|
|
text[col] = EOS;
|
|
|
|
if (Curln == Line1 || Curln == Line2)
|
|
for (col = left; col <= right; col++)
|
|
text[col - 1] = ch;
|
|
else
|
|
{
|
|
text[left - 1] = ch;
|
|
text[right - 1] = ch;
|
|
}
|
|
|
|
if (strcmp (text, Txt) != 0)
|
|
{
|
|
kname = k -> Markname;
|
|
if (se_delete (Curln, Curln, &junk) == ERR
|
|
|| inject (text) == ERR)
|
|
return (ERR);
|
|
k = getind (Curln);
|
|
k -> Markname = kname;
|
|
Buffer_changed = YES;
|
|
}
|
|
}
|
|
|
|
Curln = Line1; /* move to top of box */
|
|
if (First_affected > Curln)
|
|
First_affected = Curln;
|
|
adjust_window (Curln, Curln);
|
|
updscreen ();
|
|
|
|
return (OK);
|
|
}
|
|
|
|
|
|
/* dfltsopt --- set the 's' option to the extension on the file name */
|
|
|
|
void dfltsopt (char name[])
|
|
{
|
|
int i;
|
|
|
|
for (i = strlen (name) - 1; i >= 0; i--)
|
|
if (name[i] == '.')
|
|
{
|
|
dosopt (&name[i + 1]);
|
|
break;
|
|
}
|
|
if (i < 0)
|
|
dosopt ("");
|
|
}
|
|
|
|
|
|
|
|
/* doshell --- escape to the Shell to run one or more Unix commands */
|
|
|
|
/*
|
|
** emulate vi: if running just a shell, redraw the screen as
|
|
** soon as the shell exits. if running a program, let the user
|
|
** redraw the screen when he/she is ready.
|
|
**
|
|
** also emulate USG Unix 5.0 ed: a ! as the first character is
|
|
** replaced by the previous shell command; an unescaped % is replaced
|
|
** by the saved file name. The expanded command is echoed.
|
|
*/
|
|
|
|
#define DEFAULT_PATH SHELL
|
|
#define DEF_SHELL (rindex(DEFAULT_PATH, '/') ? rindex(DEFAULT_PATH, '/') + 1 : NULL)
|
|
|
|
int doshell (char lin[], int *pi)
|
|
{
|
|
int rc;
|
|
int forkstatus, childstatus;
|
|
void (*save_quit)(int);
|
|
void (*save_int)(int);
|
|
int i, auto_redraw;
|
|
char *path, *name, *p;
|
|
char new_command[MAXLINE];
|
|
int j, k;
|
|
static char sav_com[MAXLINE] = "";
|
|
int expanded = NO;
|
|
|
|
if (Nlines == 0) /* use normal 'ed' behavior */
|
|
{
|
|
tflush (); /* flush out the terminal output */
|
|
position_cursor (Nrows - 1, 0); /* bottom left corner */
|
|
|
|
if ((p = getenv ("SHELL")) == NULL || strcmp (p, DEFAULT_PATH) == 0)
|
|
{
|
|
path = DEFAULT_PATH;
|
|
name = DEF_SHELL; /* default */
|
|
}
|
|
/* on Berkeley systems, check the other shell */
|
|
else if (strcmp (p, "/bin/sh") == 0)
|
|
{
|
|
path = "/bin/sh";
|
|
name = "sh";
|
|
}
|
|
else
|
|
{
|
|
if (p[0] == '/') /* full pathname there */
|
|
{
|
|
/* work backwards to find just name */
|
|
path = p;
|
|
i = strlen (p);
|
|
while (p[i] != '/')
|
|
i--;
|
|
i++; /* skip '/' */
|
|
name = &p[i];
|
|
}
|
|
else
|
|
{
|
|
char buf[MAXLINE];
|
|
memset(buf, '\0', MAXLINE);
|
|
snprintf (buf, MAXLINE-1,
|
|
"unknown shell, using %s",
|
|
DEF_SHELL);
|
|
remark (buf);
|
|
path = DEFAULT_PATH;
|
|
name = DEF_SHELL;
|
|
}
|
|
}
|
|
|
|
auto_redraw = (lin[*pi] == '\n') ? YES : NO;
|
|
|
|
/* build command, checking for leading !, and % anywhere */
|
|
if (lin[*pi] == '!')
|
|
{
|
|
if (sav_com[0] != EOS)
|
|
{
|
|
for (j = 0; sav_com[j] != EOS; j++)
|
|
new_command[j] = sav_com[j];
|
|
if (new_command[j-1] == '\n')
|
|
j--;
|
|
(*pi)++;
|
|
expanded = YES;
|
|
}
|
|
else
|
|
{
|
|
Errcode = ENOCMD;
|
|
return (ERR);
|
|
}
|
|
}
|
|
else
|
|
j = 0;
|
|
|
|
for (i = *pi; lin[i] != EOS; i++)
|
|
{
|
|
if (lin[i] == ESCAPE)
|
|
{
|
|
if (lin[i+1] != '%')
|
|
{
|
|
new_command[j++] = ESCAPE;
|
|
new_command[j++] = lin[++i];
|
|
}
|
|
else
|
|
new_command[j++] = lin[++i];
|
|
}
|
|
else if (lin[i] == '%')
|
|
{
|
|
for (k = 0; Savfil[k] != EOS; k++)
|
|
new_command[j++] = Savfil[k];
|
|
expanded = YES;
|
|
}
|
|
else
|
|
new_command[j++] = lin[i];
|
|
}
|
|
|
|
if (new_command[j-1] == '\n')
|
|
j--;
|
|
new_command[j] = EOS;
|
|
|
|
memset (sav_com, EOS, MAXLINE);
|
|
strncpy (sav_com, new_command, MAXLINE-1); /* save it */
|
|
|
|
ttynormal ();
|
|
t_exit ();
|
|
rc = write (1, "\n\n", 2); /* clear out a line */
|
|
if (rc == -1)
|
|
{
|
|
Errcode = ESTUPID;
|
|
return ERR;
|
|
}
|
|
|
|
forkstatus = fork();
|
|
if (forkstatus == -1) /* the fork failed */
|
|
{
|
|
ttyedit ();
|
|
t_init ();
|
|
Errcode = ECANTFORK;
|
|
return ERR;
|
|
}
|
|
|
|
if (forkstatus == 0) /* we're in the child process */
|
|
{
|
|
signal (SIGINT, SIG_DFL);
|
|
signal (SIGQUIT, SIG_DFL);
|
|
|
|
if (strcmp (name, "sh") != 0) /* not /bin/sh */
|
|
{
|
|
signal (SIGTSTP, SIG_DFL);
|
|
}
|
|
else
|
|
{
|
|
signal (SIGTSTP, SIG_IGN);
|
|
}
|
|
|
|
if (auto_redraw) /* no params; run a shell */
|
|
{
|
|
execl (path, name, NULL);
|
|
_exit (RETERR); /* exec failed, notify parent */
|
|
}
|
|
else
|
|
{
|
|
if (expanded) /* echo it */
|
|
{
|
|
printf ("%s\n", new_command);
|
|
}
|
|
execl (path, name, "-c", new_command, NULL);
|
|
_exit (RETERR);
|
|
}
|
|
}
|
|
|
|
/* we're in the parent process here */
|
|
save_int = signal (SIGINT, SIG_IGN); /* ignore interrupts */
|
|
save_quit = signal (SIGQUIT, SIG_IGN);
|
|
while (wait (&childstatus) != forkstatus)
|
|
;
|
|
save_int = signal (SIGINT, save_int); /* catch interupts */
|
|
save_quit = signal (SIGQUIT, save_quit);
|
|
|
|
rc = write (1, "\n\n", 2); /* clear out some message space */
|
|
if (rc == -1)
|
|
{
|
|
Errcode = ESTUPID;
|
|
return ERR;
|
|
}
|
|
|
|
Currow = Nrows - 1;
|
|
Curcol = 0;
|
|
if ((childstatus >> 8) != 0)
|
|
{
|
|
ttyedit ();
|
|
t_init ();
|
|
Errcode = ENOSHELL;
|
|
return ERR;
|
|
}
|
|
|
|
/* a la vi: */
|
|
if (! auto_redraw)
|
|
{
|
|
int c;
|
|
|
|
printf ("type return to continue: ");
|
|
while ((c = getchar()) != '\n' && c != EOF)
|
|
;
|
|
}
|
|
|
|
ttyedit ();
|
|
t_init ();
|
|
restore_screen ();
|
|
|
|
return OK;
|
|
}
|
|
else
|
|
{
|
|
remark ("Not implemented yet");
|
|
}
|
|
|
|
return OK;
|
|
}
|