diff --git a/bin/ksh/c_ksh.c b/bin/ksh/c_ksh.c index 731ec5867825..b50c4b255a6d 100644 --- a/bin/ksh/c_ksh.c +++ b/bin/ksh/c_ksh.c @@ -766,6 +766,12 @@ c_typeset(wp) for (l = e->loc; l; l = l->next) { for (p = tsort(&l->vars); (vp = *p++); ) for (; vp; vp = vp->u.array) { + /* Report an unset param only if the user has + * explicitly given it some attribute (like export); + * otherwise, after "echo $FOO", we would report FOO... + */ + if (!(vp->flag & ISSET) && !(vp->flag & USERATTRIB)) + continue; if (flag && (vp->flag & flag) == 0) continue; /* no arguments */ diff --git a/bin/ksh/exec.c b/bin/ksh/exec.c index 0d3152890674..09c16cc56c72 100644 --- a/bin/ksh/exec.c +++ b/bin/ksh/exec.c @@ -32,7 +32,7 @@ static int dbteste_eval ARGS((Test_env *te, Test_op op, const char *opnd1, static void dbteste_error ARGS((Test_env *te, int offset, const char *msg)); #endif /* KSH */ #ifdef OS2 -static int search_access1 ARGS((const char *path, int mode)); +static int search_access1 ARGS((const char *path, int mode, int *errnop)); #endif /* OS2 */ @@ -415,6 +415,7 @@ execute(t, flags) } #endif restoresigs(); + cleanup_proc_env(); ksh_execve(t->str, t->args, ap); if (errno == ENOEXEC) scriptexec(t, ap); diff --git a/bin/ksh/jobs.c b/bin/ksh/jobs.c index 6215d3b3a140..e5dab1d65e40 100644 --- a/bin/ksh/jobs.c +++ b/bin/ksh/jobs.c @@ -462,9 +462,9 @@ exchild(t, flags, close_fd) last_proc = p; } else { #ifdef NEED_PGRP_SYNC - if (j_sync_open) { - closepipe(j_sync_pipe); + if (j_sync_open) { /* should never happen */ j_sync_open = 0; + closepipe(j_sync_pipe); } /* don't do the sync pipe business if there is no pipeline */ if (flags & XPIPEO) { @@ -527,19 +527,31 @@ exchild(t, flags, close_fd) if (Flag(FMONITOR) && !(flags&XXCOM)) { int dotty = 0; # ifdef NEED_PGRP_SYNC - int dosync = 0; + int first_child_sync = 0; # endif /* NEED_PGRP_SYNC */ +# ifdef NEED_PGRP_SYNC + if (j_sync_open) { + /* + * The Parent closes 0, keeps 1 open 'til the whole + * pipeline is started. The First child closes 1, + * keeps 0 open (reads from it). The remaining + * children just have to close 1 (parent has already + * closeed 0). + */ + if (j->pgrp == 0) { /* First process */ + close(j_sync_pipe[ischild]); + j_sync_pipe[ischild] = -1; + first_child_sync = ischild; + } else if (ischild) { + j_sync_open = 0; + closepipe(j_sync_pipe); + } + } +# endif /* NEED_PGRP_SYNC */ if (j->pgrp == 0) { /* First process */ j->pgrp = p->pid; dotty = 1; -# ifdef NEED_PGRP_SYNC - if (j_sync_open) { - close(j_sync_pipe[ischild]); - j_sync_pipe[ischild] = -1; - dosync = ischild; - } -# endif /* NEED_PGRP_SYNC */ } /* set pgrp in both parent and child to deal with race @@ -556,13 +568,11 @@ exchild(t, flags, close_fd) tcsetpgrp(tty_fd, j->pgrp); # endif /* TTY_PGRP */ # ifdef NEED_PGRP_SYNC - if (ischild && j_sync_open) { - if (dosync) { - char c; - while (read(j_sync_pipe[0], &c, 1) == -1 - && errno == EINTR) - ; - } + if (first_child_sync) { + char c; + while (read(j_sync_pipe[0], &c, 1) == -1 + && errno == EINTR) + ; close(j_sync_pipe[0]); j_sync_open = 0; } @@ -1119,14 +1129,14 @@ j_startjob(j) #ifdef NEED_PGRP_SYNC if (j_sync_open) { - closepipe(j_sync_pipe); j_sync_open = 0; + closepipe(j_sync_pipe); } #endif /* NEED_PGRP_SYNC */ #ifdef JOB_SIGS if (held_sigchld) { held_sigchld = 0; - /* Don't call j_sigchild() as it may remove job... */ + /* Don't call j_sigchld() as it may remove job... */ kill(procpid, SIGCHLD); } #endif /* JOB_SIGS */ @@ -1342,7 +1352,7 @@ found: /* * Called only when a process in j has exited/stopped (ie, called only - * from j_sigchild()). If no processes are running, the job status + * from j_sigchld()). If no processes are running, the job status * and state are updated, asynchronous job notification is done and, * if unneeded, the job is removed. * diff --git a/bin/ksh/ksh.1 b/bin/ksh/ksh.1 index 9851e07b7072..50542833420d 100644 --- a/bin/ksh/ksh.1 +++ b/bin/ksh/ksh.1 @@ -1822,9 +1822,10 @@ If the input line ends in a backslash and the \fB\-r\fP option was not used, the backslash and newline are stripped and more input is read. If no input is read, \fBread\fP exits with a non-zero status. .sp -A prompt, which is printed to standard error before any input is read, may be -specified by appending and question mark and the prompt to the -first parameter (\fIe.g.\fP, \fBread nfoo?'number of foos: '\fP). +The first parameter may have a question mark and a string appended to it, in +which case the string is used as a prompt (printed to standard error before +any input is read) if the input is a tty +(\fIe.g.\fP, \fBread nfoo?'number of foos: '\fP). .sp The \fB\-u\fP\fIn\fP and \fB\-p\fP options cause input to be read from file descriptor \fIn\fP or the current co-process (see Co-Processes above diff --git a/bin/ksh/lex.c b/bin/ksh/lex.c index 0f7df422e560..2eee052b2c27 100644 --- a/bin/ksh/lex.c +++ b/bin/ksh/lex.c @@ -869,6 +869,7 @@ getsc__() s = source; /* avoid reading eof twice */ s->str = NULL; + break; } } continue; diff --git a/bin/ksh/main.c b/bin/ksh/main.c index ca87f4a10a21..3a49da7406c4 100644 --- a/bin/ksh/main.c +++ b/bin/ksh/main.c @@ -14,17 +14,17 @@ extern char **environ; * global data */ -static void reclaim ARGS((void)); -static void remove_temps ARGS((struct temp *tp)); -static int is_restricted ARGS((char *name)); +static void reclaim ARGS((void)); +static void remove_temps ARGS((struct temp *tp)); +static int is_restricted ARGS((char *name)); /* * shell initialization */ -static const char initifs [] = "IFS= \t\n"; /* must be R/W */ +static const char initifs [] = "IFS= \t\n"; /* must be R/W */ -static const char initsubs [] = +static const char initsubs [] = "${PS2=> } ${PS3=#? } ${PS4=+ }"; static const char version_param[] = @@ -35,7 +35,7 @@ static const char version_param[] = #endif /* KSH */ ; -static const char *const initcoms [] = { +static const char *const initcoms [] = { "typeset", "-x", "SHELL", "PATH", "HOME", NULL, "typeset", "-r", version_param, NULL, "typeset", "-ri", "PPID", NULL, @@ -118,11 +118,9 @@ main(argc, argv) ainit(&aperm); /* initialize permanent Area */ /* set up base enviroment */ + memset(&env, 0, sizeof(env)); env.type = E_NONE; ainit(&env.area); - env.savefd = NULL; - env.oenv = NULL; - env.loc = (struct block *) 0; e = &env; newblock(); /* set up global l->vars and l->funs */ @@ -727,6 +725,17 @@ cleanup_parents_env() e->oenv = (struct env *) 0; } +/* Called just before an execve cleanup stuff temporary files */ +void +cleanup_proc_env() +{ + struct env *ep; + + for (ep = e; ep; ep = ep->oenv) + remove_temps(ep->temps); + remove_temps(func_heredocs); +} + /* remove temp files and free ATEMP Area */ static void reclaim() @@ -741,25 +750,43 @@ remove_temps(tp) struct temp *tp; { #ifdef OS2 - static char tmpfile[30]; - int status; + static struct temp *delayed_remove; + struct temp *t, **tprev; - if (strlen (tmpfile) > 0 ) { - unlink(tmpfile); - *tmpfile=0; - } + if (delayed_remove) { + for (tprev = &delayed_remove, t = delayed_remove; t; t = *tprev) + /* No need to check t->pid here... */ + if (unlink(t->name) >= 0 || errno == ENOENT) { + *tprev = t->next; + afree(t, APERM); + } else + tprev = &t->next; + } #endif /* OS2 */ for (; tp != NULL; tp = tp->next) - if (tp->pid == procpid) + if (tp->pid == procpid) { #ifdef OS2 - { status=unlink(tp->name); - if (status < 0) - strcpy(tmpfile, tp->name); - } + /* OS/2 (and dos) do not allow files that are currently + * open to be removed, so we cache it away for future + * removal. + * XXX should only do this if errno + * is Efile-still-open-can't-remove + * (but I don't know what that is...) + */ + if (unlink(tp->name) < 0 && errno != ENOENT) { + t = (struct temp *) alloc( + sizeof(struct temp) + strlen(tp->name) + 1, + APERM); + memset(t, 0, sizeof(struct temp)); + strcpy(t->name, tp->name); + t->next = delayed_remove; + delayed_remove = t; + } #else /* OS2 */ unlink(tp->name); #endif /* OS2 */ + } } /* Returns true if name refers to a restricted shell */ diff --git a/bin/ksh/proto.h b/bin/ksh/proto.h index 64951e269fee..722712cf6d3f 100644 --- a/bin/ksh/proto.h +++ b/bin/ksh/proto.h @@ -1,7 +1,7 @@ /* * prototypes for PD-KSH * originally generated using "cproto.c 3.5 92/04/11 19:28:01 cthuang " - * $Id: proto.h,v 1.1.1.1 1996/09/21 23:35:15 jtc Exp $ + * $Id: proto.h,v 1.1.1.2 1996/12/18 04:50:31 jtc Exp $ */ /* alloc.c */ @@ -163,6 +163,7 @@ void unwind ARGS((int i)) GCC_FUNC_ATTR(noreturn); void newenv ARGS((int type)); void quitenv ARGS((void)); void cleanup_parents_env ARGS((void)); +void cleanup_proc_env ARGS((void)); void aerror ARGS((Area *ap, const char *msg)) GCC_FUNC_ATTR(noreturn); /* misc.c */ diff --git a/bin/ksh/syn.c b/bin/ksh/syn.c index 4ee7c41209b3..f27707d1c3d9 100644 --- a/bin/ksh/syn.c +++ b/bin/ksh/syn.c @@ -121,6 +121,9 @@ c_list() t = andor(); if (t != NULL) { + /* Token has always been read/rejected at this point, so + * we don't worray about what flags to pass token() + */ while ((c = token(0)) == ';' || c == '&' || c == COPROC || (c == '\n' && (multiline.on || inalias(source)))) { @@ -206,7 +209,10 @@ get_command(cf) XPinit(args, 16); XPinit(vars, 16); - if (multiline.on) + /* Don't want to pass CONTIN if reading interactively as just hitting + * return would print PS2 instead of PS1. + */ + if (multiline.on || inalias(source)) cf = CONTIN; syniocf = KEYWORD|ALIAS; switch (c = token(cf|KEYWORD|ALIAS|VARASN)) { diff --git a/bin/ksh/table.h b/bin/ksh/table.h index f4861ec77955..d95de4cec8b4 100644 --- a/bin/ksh/table.h +++ b/bin/ksh/table.h @@ -1,4 +1,4 @@ -/* $Id: table.h,v 1.1.1.1 1996/09/21 23:35:17 jtc Exp $ */ +/* $Id: table.h,v 1.1.1.2 1996/12/18 04:50:42 jtc Exp $ */ /* * generic hashed associative table for commands and variables. @@ -64,6 +64,11 @@ struct tbl { /* table item */ #define FKSH BIT(11) /* function defined with function x (vs x()) */ #define SPEC_BI BIT(12) /* a POSIX special builtin */ #define REG_BI BIT(13) /* a POSIX regular builtin */ +/* Attributes that can be set by the user (used to decide if an unset param + * should be repoted by set/typeset). Does not include ARRAY or LOCAL. + */ +#define USERATTRIB (EXPORT|INTEGER|RDONLY|LJUST|RJUST|ZEROFIL\ + |LCASEV|UCASEV_AL|INT_U|INT_L) /* command types */ #define CNONE 0 /* undefined */ diff --git a/bin/ksh/tty.h b/bin/ksh/tty.h index 1220aa7cf921..33e83ebb2c08 100644 --- a/bin/ksh/tty.h +++ b/bin/ksh/tty.h @@ -8,7 +8,7 @@ last edit: 30-Jul-1987 D A Gwyn */ -/* $Id: tty.h,v 1.1.1.1 1996/09/21 23:35:17 jtc Exp $ */ +/* $Id: tty.h,v 1.1.1.2 1996/12/18 04:50:47 jtc Exp $ */ /* some useful #defines */ #ifdef EXTERN @@ -19,12 +19,34 @@ # define EXTERN_DEFINED #endif +/* Don't know of a system on which including sys/ioctl.h with termios.h + * causes problems. If there is one, these lines need to be deleted and + * aclocal.m4 needs to have stuff un-commented. + */ +#ifdef SYS_IOCTL_WITH_TERMIOS +# define SYS_IOCTL_WITH_TERMIOS +#endif /* SYS_IOCTL_WITH_TERMIOS */ +#ifdef SYS_IOCTL_WITH_TERMIO +# define SYS_IOCTL_WITH_TERMIO +#endif /* SYS_IOCTL_WITH_TERMIO */ + #ifdef HAVE_TERMIOS_H # include +# ifdef SYS_IOCTL_WITH_TERMIOS +# if !(defined(sun) && !defined(__svr4__)) /* too many warnings on sunos */ + /* Need to include sys/ioctl.h on some systems to get the TIOCGWINSZ + * stuff (eg, digital unix). + */ +# include +# endif /* !(sun && !__svr4__) */ +# endif /* SYS_IOCTL_WITH_TERMIOS */ typedef struct termios TTY_state; #else # ifdef HAVE_TERMIO_H # include +# ifdef SYS_IOCTL_WITH_TERMIO +# include /* see comment above in termios stuff */ +# endif /* SYS_IOCTL_WITH_TERMIO */ # if _BSD_SYSV /* BRL UNIX System V emulation */ # ifndef NTTYDISC # define TIOCGETD _IOR( 't', 0, int ) diff --git a/bin/ksh/version.c b/bin/ksh/version.c index 1f8b11dd937d..61064092deff 100644 --- a/bin/ksh/version.c +++ b/bin/ksh/version.c @@ -5,4 +5,4 @@ #include "sh.h" const char ksh_version [] = - "@(#)PD KSH v5.2.11 96/10/08"; + "@(#)PD KSH v5.2.12 96/10/29"; diff --git a/bin/ksh/vi.c b/bin/ksh/vi.c index 53bff9d0a801..15d4df484780 100644 --- a/bin/ksh/vi.c +++ b/bin/ksh/vi.c @@ -1135,7 +1135,8 @@ vi_cmd(argcnt, cmd) case Ctrl('i'): /* Nonstandard vi/ksh */ if (!Flag(FVITABCOMPLETE)) return -1; - /* FALLTHROUGH */ + complete_word(1, argcnt); + break; case Ctrl('['): /* some annoying at&t ksh's */ if (!Flag(FVIESCCOMPLETE)) @@ -1841,11 +1842,11 @@ display(wb1, wb2, leftside) if (ch < ' ' || ch == 0x7f) { *twb1++ = '^'; if (++col < winwidth) { - *twb1++ = es->cbuf[cur] ^ '@'; + *twb1++ = ch ^ '@'; col++; } } else { - *twb1++ = es->cbuf[cur]; + *twb1++ = ch; col++; } }