diff options
Diffstat (limited to 'system/pdksh')
35 files changed, 3914 insertions, 0 deletions
diff --git a/system/pdksh/README b/system/pdksh/README new file mode 100644 index 0000000000000..8e74dd787f2b9 --- /dev/null +++ b/system/pdksh/README @@ -0,0 +1,9 @@ +PD-ksh is a mostly complete AT&T ksh look-alike (see NOTES file for a list +of things not supported). Work is mostly finished to make it fully +compatible with both POSIX and AT&T ksh (when the two don't conflict). + +Since pdksh is free and compiles and runs on most common unix systems, it +is very useful in creating a consistent user interface across multiple +machines. For example, in the CS dept. of MUN, pdksh is installed on a +variety of machines including Suns, HPs, DecStations, pcs running Linux, +etc., and is the login shell of ~5200 users. diff --git a/system/pdksh/doinst.sh b/system/pdksh/doinst.sh new file mode 100644 index 0000000000000..1c7b18bd1833f --- /dev/null +++ b/system/pdksh/doinst.sh @@ -0,0 +1,5 @@ + +if ! grep -q '/bin/pdksh' etc/shells ; then + printf "/bin/pdksh\n" >> etc/shells ; +fi + diff --git a/system/pdksh/patches/000_add_destdir.patch b/system/pdksh/patches/000_add_destdir.patch new file mode 100644 index 0000000000000..fba38ea1b3126 --- /dev/null +++ b/system/pdksh/patches/000_add_destdir.patch @@ -0,0 +1,23 @@ +diff -Nur pdksh-5.2.14.orig/Makefile.in pdksh-5.2.14/Makefile.in +--- pdksh-5.2.14.orig/Makefile.in 1999-07-13 12:06:53.000000000 -0500 ++++ pdksh-5.2.14/Makefile.in 2009-09-26 19:09:46.183509569 -0500 +@@ -80,8 +80,8 @@ + $(CC) -c $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) $(CFLAGS) $< + + install: installdirs all +- $(INSTALL_PROGRAM) $(SHELL_PROG)$(exe_suffix) $(bindir)/`echo $(SHELL_PROG)|sed '$(transform)'`$(exe_suffix) +- -$(INSTALL_DATA) $(SHELL_PROG).1 $(mandir)/`echo $(SHELL_PROG)|sed '$(transform)'`.$(manext) ++ $(INSTALL_PROGRAM) $(SHELL_PROG)$(exe_suffix) $(DESTDIR)/$(bindir)/`echo $(SHELL_PROG)|sed '$(transform)'`$(exe_suffix) ++ -$(INSTALL_DATA) $(SHELL_PROG).1 $(DESTDIR)/$(mandir)/`echo $(SHELL_PROG)|sed '$(transform)'`.$(manext) + -@prog=$(bindir)/`echo $(SHELL_PROG)|sed '$(transform)'`$(exe_suffix);\ + test -f /etc/shells \ + && (grep "^$$prog\$$" /etc/shells > /dev/null \ +@@ -90,7 +90,7 @@ + you should add it if you want to set your shell to $(SHELL_PROG)") + + installdirs: +- $(srcdir)/mkinstalldirs $(bindir) $(mandir) ++ $(srcdir)/mkinstalldirs $(DESTDIR)/$(bindir) $(DESTDIR)/$(mandir) + + uninstall: + rm -f $(bindir)/`echo $(SHELL_PROG)|sed '$(transform)'`$(exe_suffix) diff --git a/system/pdksh/patches/001_upstream-readonly-vars.patch b/system/pdksh/patches/001_upstream-readonly-vars.patch new file mode 100644 index 0000000000000..616a5102d97a1 --- /dev/null +++ b/system/pdksh/patches/001_upstream-readonly-vars.patch @@ -0,0 +1,172 @@ + * Applied patch from upstream ftp site to fix problem with readonly + variables (closes: #57727). +Index: pdksh-5.2.14/jobs.c +=================================================================== +--- pdksh-5.2.14.orig/jobs.c 2008-04-15 20:47:52.000000000 +0200 ++++ pdksh-5.2.14/jobs.c 2008-04-15 20:48:46.000000000 +0200 +@@ -219,8 +219,7 @@ + static void check_job ARGS((Job *j)); + static void put_job ARGS((Job *j, int where)); + static void remove_job ARGS((Job *j, const char *where)); +-static void kill_job ARGS((Job *j)); +-static void fill_command ARGS((char *c, int len, struct op *t)); ++static int kill_job ARGS((Job *j, int sig)); + + /* initialize job control */ + void +@@ -294,10 +293,17 @@ + && procpid == kshpid))))) + { + killed = 1; +- killpg(j->pgrp, SIGHUP); ++ if (j->pgrp == 0) ++ kill_job(j, SIGHUP); ++ else ++ killpg(j->pgrp, SIGHUP); + #ifdef JOBS +- if (j->state == PSTOPPED) +- killpg(j->pgrp, SIGCONT); ++ if (j->state == PSTOPPED) { ++ if (j->pgrp == 0) ++ kill_job(j, SIGCONT); ++ else ++ killpg(j->pgrp, SIGCONT); ++ } + #endif /* JOBS */ + } + } +@@ -497,7 +503,7 @@ + put_job(j, PJ_PAST_STOPPED); + } + +- fill_command(p->command, sizeof(p->command), t); ++ snptreef(p->command, sizeof(p->command), "%T", t); + + /* create child process */ + forksleep = 1; +@@ -508,7 +514,7 @@ + forksleep <<= 1; + } + if (i < 0) { +- kill_job(j); ++ kill_job(j, SIGKILL); + remove_job(j, "fork failed"); + #ifdef NEED_PGRP_SYNC + if (j_sync_open) { +@@ -823,11 +829,10 @@ + } + + if (j->pgrp == 0) { /* started when !Flag(FMONITOR) */ +- for (p=j->proc_list; p != (Proc *) 0; p = p->next) +- if (kill(p->pid, sig) < 0) { +- bi_errorf("%s: %s", cp, strerror(errno)); +- rv = 1; +- } ++ if (kill_job(j, sig) < 0) { ++ bi_errorf("%s: %s", cp, strerror(errno)); ++ rv = 1; ++ } + } else { + #ifdef JOBS + if (j->state == PSTOPPED && (sig == SIGTERM || sig == SIGHUP)) +@@ -1825,50 +1830,17 @@ + * + * If jobs are compiled in then this routine expects sigchld to be blocked. + */ +-static void +-kill_job(j) ++static int ++kill_job(j, sig) + Job *j; ++ int sig; + { + Proc *p; ++ int rval = 0; + + for (p = j->proc_list; p != (Proc *) 0; p = p->next) + if (p->pid != 0) +- (void) kill(p->pid, SIGKILL); +-} +- +-/* put a more useful name on a process than snptreef does (in certain cases) */ +-static void +-fill_command(c, len, t) +- char *c; +- int len; +- struct op *t; +-{ +- int alen; +- char **ap; +- +- if (t->type == TEXEC || t->type == TCOM) { +- /* Causes problems when set -u is in effect, can also +- cause problems when array indices evaluated (may have +- side effects, eg, assignment, incr, etc.) +- if (t->type == TCOM) +- ap = eval(t->args, DOBLANK|DONTRUNCOMMAND); +- else +- */ +- ap = t->args; +- --len; /* save room for the null */ +- while (len > 0 && *ap != (char *) 0) { +- alen = strlen(*ap); +- if (alen > len) +- alen = len; +- memcpy(c, *ap, alen); +- c += alen; +- len -= alen; +- if (len > 0) { +- *c++ = ' '; len--; +- } +- ap++; +- } +- *c = '\0'; +- } else +- snptreef(c, len, "%T", t); ++ if (kill(p->pid, sig) < 0) ++ rval = -1; ++ return rval; + } +Index: pdksh-5.2.14/shf.c +=================================================================== +--- pdksh-5.2.14.orig/shf.c 2008-04-15 20:47:52.000000000 +0200 ++++ pdksh-5.2.14/shf.c 2008-04-15 20:48:46.000000000 +0200 +@@ -355,7 +355,6 @@ + shf->rp = nbuf + (shf->rp - shf->buf); + shf->wp = nbuf + (shf->wp - shf->buf); + shf->rbsize += shf->wbsize; +- shf->wbsize += shf->wbsize; + shf->wnleft += shf->wbsize; + shf->wbsize *= 2; + shf->buf = nbuf; +Index: pdksh-5.2.14/var.c +=================================================================== +--- pdksh-5.2.14.orig/var.c 2008-04-15 20:47:52.000000000 +0200 ++++ pdksh-5.2.14/var.c 2008-04-15 20:48:46.000000000 +0200 +@@ -353,7 +353,9 @@ + const char *s; + int error_ok; + { +- if (vq->flag & RDONLY) { ++ int no_ro_check = error_ok & 0x4; ++ error_ok &= ~0x4; ++ if ((vq->flag & RDONLY) && !no_ro_check) { + warningf(TRUE, "%s: is read only", vq->name); + if (!error_ok) + errorf(null); +@@ -715,13 +717,13 @@ + if (val != NULL) { + if (vp->flag&INTEGER) { + /* do not zero base before assignment */ +- setstr(vp, val, KSH_UNWIND_ERROR); ++ setstr(vp, val, KSH_UNWIND_ERROR | 0x4); + /* Done after assignment to override default */ + if (base > 0) + vp->type = base; + } else + /* setstr can't fail (readonly check already done) */ +- setstr(vp, val, KSH_RETURN_ERROR); ++ setstr(vp, val, KSH_RETURN_ERROR | 0x4); + } + + /* only x[0] is ever exported, so use vpbase */ diff --git a/system/pdksh/patches/010_OpenBSD-patches.patch b/system/pdksh/patches/010_OpenBSD-patches.patch new file mode 100644 index 0000000000000..ebb3c9e64c0d0 --- /dev/null +++ b/system/pdksh/patches/010_OpenBSD-patches.patch @@ -0,0 +1,1112 @@ + * Applied some patches from OpenBSD: + + Use mkstemp to create temporary files + + Kill -s now works + + Escapes special characters in tab completitions + + Introduce FSH flag, which is set when the shell is called as `sh'. + + tree.c: Fix three off-by-one errors. + + c_sh.c: don't set close-on-exec flag on file descriptors in FSH mode + (closes: #154540). Documented the change in ksh(1). + + history.c: Compare the return from mmap with MAP_FAILED, do not cast it + to int and compare with -1. + + main.c: set edit mode to emacs by default, may be overridden by the + environment or the user. Also, we want tab completion in vi by default. + + misc.c: use strtol() in getn(). + + emacs.c: + - bind TAB (^I) to complete-list by default + - complete-list first completes; if that does not work, it lists + - fix a memleak in do_complete() + + edit.c: + - completion now works after '=' (dd), and ':' (ssh) and ` (backtick) + - add '#' to the list of escaped characters during vi/emacs filename + completion + + + exec.c: Found and fixed yet another problem with `set -e' scripts + (see a changelog entry for 5.2.14-3), which caused `dpkg-buildpackage -B' + to fail on systems where /bin/sh is ksh. + + + c_sh.c: Make `set' command return 0 always, not only in the POSIX mode. + According to Jeff Sheinberg <jeffsh@localnet.com>, this new behaviour + is more compatible with SUSv2 standard and other shells (esp. ksh93) + (closes: #118476). Documented the change in ksh(1) man page. + + + c_test.c: The special case code for "test -x" over NFS was + incorrect. The right thing to do is to try access(2) first + (since that occurs on the NFS server side) and only check for the + absence of an execute bit when access(2) succeeds. + + edit.c: in word location, fix forward scanning so it correctly + account for any escaped char and not only spaces. for "foo + (bar.a)" and "foo (bar a)", cd foo\ \(bar.<tab> will correctly + expand to foo\ \(bar.a\). + + + vi.c: Buffers are not strings so use memcpy(), not strlcpy() to copy + them. Also add some further bounds checks in the name of paranoia. + + exec.c: Unbreak parameter assignment when calling bourne style + functions. + + exec.c: For the >& and <& operators, add a check for "dup from" == + "dup to" and just return success if they are the same. Fixes the + "ls 2>&2" problem. + + eval.c, exec.c, io.c, jobs.c: If "from fd" == "to fd" don't call + dup2() or close "from fd". + +Index: pdksh-5.2.14/c_ksh.c +=================================================================== +--- pdksh-5.2.14.orig/c_ksh.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/c_ksh.c 2009-09-17 00:32:08.000000000 +0200 +@@ -1208,6 +1208,7 @@ + builtin_opt.optarg); + return 1; + } ++ break; + case '?': + return 1; + } +Index: pdksh-5.2.14/edit.c +=================================================================== +--- pdksh-5.2.14.orig/edit.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/edit.c 2009-09-17 00:32:08.000000000 +0200 +@@ -15,6 +15,9 @@ + # include <sys/stream.h> /* needed for <sys/ptem.h> */ + # include <sys/ptem.h> /* needed for struct winsize */ + #endif /* OS_SCO */ ++#ifdef DEBIAN ++#include <sys/ioctl.h> ++#endif /* DEBIAN */ + #include <ctype.h> + #include "ksh_stat.h" + +@@ -552,7 +555,11 @@ + { + char *toglob; + char **words; ++#ifndef DEBIAN + int nwords; ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ int nwords, i, idx, escaping; ++#endif /* DEBIAN */ + XPtrV w; + struct source *s, *sold; + +@@ -561,6 +568,22 @@ + + toglob = add_glob(str, slen); + ++#ifdef DEBIAN /* patch from OpenBSD */ ++ /* remove all escaping backward slashes */ ++ escaping = 0; ++ for(i = 0, idx = 0; toglob[i]; i++) { ++ if (toglob[i] == '\\' && !escaping) { ++ escaping = 1; ++ continue; ++ } ++ ++ toglob[idx] = toglob[i]; ++ idx++; ++ if (escaping) escaping = 0; ++ } ++ toglob[idx] = '\0'; ++ ++#endif /* DEBIAN */ + /* + * Convert "foo*" (toglob) to an array of strings (words) + */ +@@ -722,7 +745,12 @@ + return nwords; + } + ++#ifndef DEBIAN + #define IS_WORDC(c) !(ctype(c, C_LEX1) || (c) == '\'' || (c) == '"') ++#else /* patch from OpenBSD */ ++#define IS_WORDC(c) !( ctype(c, C_LEX1) || (c) == '\'' || (c) == '"' \ ++ || (c) == '`' || (c) == '=' || (c) == ':' ) ++#endif + + static int + x_locate_word(buf, buflen, pos, startp, is_commandp) +@@ -747,11 +775,23 @@ + /* Keep going backwards to start of word (has effect of allowing + * one blank after the end of a word) + */ ++#ifndef DEBIAN + for (; start > 0 && IS_WORDC(buf[start - 1]); start--) ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ for (; (start > 0 && IS_WORDC(buf[start - 1])) ++ || (start > 1 && buf[start-2] == '\\'); start--) ++#endif /* DEBIAN */ + ; + /* Go forwards to end of word */ ++#ifndef DEBIAN + for (end = start; end < buflen && IS_WORDC(buf[end]); end++) + ; ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ for (end = start; end < buflen && IS_WORDC(buf[end]); end++) { ++ if (buf[end] == '\\' && (end+1) < buflen) ++ end++; ++ } ++#endif /* DEBIAN */ + + if (is_commandp) { + int iscmd; +@@ -759,7 +799,11 @@ + /* Figure out if this is a command */ + for (p = start - 1; p >= 0 && isspace(buf[p]); p--) + ; ++#ifndef DEBIAN + iscmd = p < 0 || strchr(";|&()", buf[p]); ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ iscmd = p < 0 || strchr(";|&()`", buf[p]); ++#endif + if (iscmd) { + /* If command has a /, path, etc. is not searched; + * only current directory is searched, which is just +@@ -961,6 +1005,9 @@ + { + const char *sp, *p; + char *xp; ++#ifdef DEBIAN /* patch from OpenBSD */ ++ int staterr; ++#endif /* DEBIAN */ + int pathlen; + int patlen; + int oldsize, newsize, i, j; +@@ -995,13 +1042,23 @@ + memcpy(xp, pat, patlen); + + oldsize = XPsize(*wp); ++#ifndef DEBIAN + glob_str(Xstring(xs, xp), wp, 0); ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ glob_str(Xstring(xs, xp), wp, 1); /* mark dirs */ ++#endif + newsize = XPsize(*wp); + + /* Check that each match is executable... */ + words = (char **) XPptrv(*wp); + for (i = j = oldsize; i < newsize; i++) { ++#ifndef DEBIAN + if (search_access(words[i], X_OK, (int *) 0) >= 0) { ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ staterr = 0; ++ if ((search_access(words[i], X_OK, &staterr) >= 0) ++ || (staterr == EISDIR)) { ++#endif + words[j] = words[i]; + if (!(flags & XCF_FULLPATH)) + memmove(words[j], words[j] + pathlen, +@@ -1018,4 +1075,42 @@ + Xfree(xs, xp); + } + ++#ifdef DEBIAN /* patch from OpenBSD */ ++/* ++ * if argument string contains any special characters, they will ++ * be escaped and the result will be put into edit buffer by ++ * keybinding-specific function ++ */ ++int ++x_escape(s, len, putbuf_func) ++ const char *s; ++ size_t len; ++ int putbuf_func ARGS((const char *s, size_t len)); ++{ ++ size_t add, wlen; ++ const char *ifs = str_val(local("IFS", 0)); ++ int rval=0; ++ ++ for (add = 0, wlen = len; wlen - add > 0; add++) { ++ if (strchr("\\$(){}*&;#|<>\"'`", s[add]) || strchr(ifs, s[add])) { ++ if (putbuf_func(s, add) != 0) { ++ rval = -1; ++ break; ++ } ++ ++ putbuf_func("\\", 1); ++ putbuf_func(&s[add], 1); ++ ++ add++; ++ wlen -= add; ++ s += add; ++ add = -1; /* after the increment it will go to 0 */ ++ } ++ } ++ if (wlen > 0 && rval == 0) ++ rval = putbuf_func(s, wlen); ++ ++ return (rval); ++} ++#endif /* DEBIAN */ + #endif /* EDIT */ +Index: pdksh-5.2.14/edit.h +=================================================================== +--- pdksh-5.2.14.orig/edit.h 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/edit.h 2009-09-17 00:32:08.000000000 +0200 +@@ -55,6 +55,9 @@ + int x_longest_prefix ARGS((int nwords, char *const *words)); + int x_basename ARGS((const char *s, const char *se)); + void x_free_words ARGS((int nwords, char **words)); ++#ifdef DEBIAN /* patch from OpenBSD */ ++int x_escape ARGS((const char *, size_t, int (*)(const char *s, size_t len))); ++#endif /* DEBIAN */ + /* emacs.c */ + int x_emacs ARGS((char *buf, size_t len)); + void x_init_emacs ARGS((void)); +Index: pdksh-5.2.14/emacs.c +=================================================================== +--- pdksh-5.2.14.orig/emacs.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/emacs.c 2009-09-17 00:32:08.000000000 +0200 +@@ -138,6 +138,10 @@ + static int x_e_getc ARGS((void)); + static void x_e_putc ARGS((int c)); + static void x_e_puts ARGS((const char *s)); ++#ifdef DEBIAN /* patch from OpenBSD */ ++static int x_comment ARGS((int c)); ++static int x_emacs_putbuf ARGS((const char *s, size_t len)); ++#endif /* DEBIAN */ + static int x_fold_case ARGS((int c)); + static char *x_lastcp ARGS((void)); + static void do_complete ARGS((int flags, Comp_type type)); +@@ -269,6 +273,9 @@ + { XFUNC_transpose, 0, CTRL('T') }, + #endif + { XFUNC_complete, 1, CTRL('[') }, ++#ifdef DEBIAN /* patch from OpenBSD */ ++ { XFUNC_comp_list, 0, CTRL('I') }, ++#endif /* DEBIAN */ + { XFUNC_comp_list, 1, '=' }, + { XFUNC_enumerate, 1, '?' }, + { XFUNC_expand, 1, '*' }, +@@ -313,6 +320,9 @@ + * entries. + */ + { XFUNC_meta2, 1, '[' }, ++#ifdef DEBIAN /* patch from OpenBSD */ ++ { XFUNC_meta2, 1, 'O' }, ++#endif /* DEBIAN */ + { XFUNC_prev_com, 2, 'A' }, + { XFUNC_next_com, 2, 'B' }, + { XFUNC_mv_forw, 2, 'C' }, +@@ -468,6 +478,23 @@ + return 0; + } + ++#ifdef DEBIAN /* patch from OpenBSD */ ++/* ++ * this is used for x_escape() in do_complete() ++ */ ++static int ++x_emacs_putbuf(s, len) ++ const char *s; ++ size_t len; ++{ ++ int rval; ++ ++ if ((rval = x_do_ins(s, len)) != 0) ++ return (rval); ++ return (rval); ++} ++ ++#endif /* DEBIAN */ + static int + x_del_back(c) + int c; +@@ -1485,7 +1512,11 @@ + for (j = 0; j < X_TABSZ; j++) + x_tab[i][j] = XFUNC_error; + for (i = 0; i < NELEM(x_defbindings); i++) ++#ifndef DEBIAN + x_tab[x_defbindings[i].xdb_tab][x_defbindings[i].xdb_char] ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ x_tab[(unsigned char)x_defbindings[i].xdb_tab][x_defbindings[i].xdb_char] ++#endif /* DEBIAN */ + = x_defbindings[i].xdb_func; + + x_atab = (char *(*)[X_TABSZ]) alloc(sizeofN(*x_atab, X_NTABS), AEDIT); +@@ -1754,6 +1785,7 @@ + int flags; /* XCF_{COMMAND,FILE,COMMAND_FILE} */ + Comp_type type; + { ++#ifndef DEBIAN + char **words; + int nwords = 0; + int start, end; +@@ -1828,8 +1860,13 @@ + if (nlen > 0) { + x_goto(xbuf + start); + x_delete(end - start, FALSE); ++#ifndef DEBIAN + words[0][nlen] = '\0'; + x_ins(words[0]); ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ x_escape(words[0], nlen, x_emacs_putbuf); ++ x_adjust(); ++#endif /* DEBIAN */ + /* If single match is not a directory, add a + * space to the end... + */ +@@ -1841,6 +1878,54 @@ + } + break; + } ++#else /* patch from OpenBSD */ ++ char **words; ++ int nwords; ++ int start, end, nlen, olen; ++ int is_command; ++ int completed = 0; ++ ++ nwords = x_cf_glob(flags, xbuf, xep - xbuf, xcp - xbuf, ++ &start, &end, &words, &is_command); ++ /* no match */ ++ if (nwords == 0) { ++ x_e_putc(BEL); ++ return; ++ } ++ ++ if (type == CT_LIST) { ++ x_print_expansions(nwords, words, is_command); ++ x_redraw(0); ++ x_free_words(nwords, words); ++ return; ++ } ++ ++ olen = end - start; ++ nlen = x_longest_prefix(nwords, words); ++ /* complete */ ++ if (nlen > olen) { ++ x_goto(xbuf + start); ++ x_delete(olen, FALSE); ++ x_escape(words[0], nlen, x_emacs_putbuf); ++ x_adjust(); ++ completed = 1; ++ } ++ /* add space if single non-dir match */ ++ if ((nwords == 1) && (!ISDIRSEP(words[0][nlen - 1]))) { ++ x_ins(space); ++ completed = 1; ++ } ++ ++ if (type == CT_COMPLIST && !completed) { ++ x_print_expansions(nwords, words, is_command); ++ completed = 1; ++ } ++ ++ if (completed) ++ x_redraw(0); ++ ++ x_free_words(nwords, words); ++#endif /* DEBIAN */ + } + + /* NAME: +Index: pdksh-5.2.14/io.c +=================================================================== +--- pdksh-5.2.14.orig/io.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/io.c 2009-09-17 00:32:08.000000000 +0200 +@@ -318,7 +318,7 @@ + shf_flush(&shf_iob[fd]); + if (ofd < 0) /* original fd closed */ + close(fd); +- else { ++ else if (fd != ofd) { + ksh_dup2(ofd, fd, TRUE); /* XXX: what to do if this fails? */ + close(ofd); + } +@@ -502,7 +502,9 @@ + Temp_type type; + struct temp **tlist; + { ++#ifndef DEBIAN + static unsigned int inc; ++#endif + struct temp *tp; + int len; + int fd; +@@ -516,6 +518,14 @@ + tp->name = path = (char *) &tp[1]; + tp->shf = (struct shf *) 0; + tp->type = type; ++#ifdef DEBIAN /* based on patch from OpenBSD */ ++ shf_snprintf(path, len, "%s/kshXXXXXX", dir); ++ fd = mkstemp(path); ++ if (fd >= 0) ++ tp->shf = shf_fdopen(fd, SHF_WR, (struct shf *) 0); ++ if (fd >= 0) ++ fchmod(fd, 0600); ++#else /* DEBIAN */ + while (1) { + /* Note that temp files need to fit 8.3 DOS limits */ + shf_snprintf(path, len, "%s/sh%05u.%03x", +@@ -542,6 +552,7 @@ + break; + } + tp->next = NULL; ++#endif /* DEBIAN */ + tp->pid = procpid; + + tp->next = *tlist; +Index: pdksh-5.2.14/vi.c +=================================================================== +--- pdksh-5.2.14.orig/vi.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/vi.c 2009-09-17 00:32:08.000000000 +0200 +@@ -63,6 +63,9 @@ + static void vi_pprompt ARGS((int full)); + static void vi_error ARGS((void)); + static void vi_macro_reset ARGS((void)); ++#ifdef DEBIAN /* patch from OpenBSD */ ++static int x_vi_putbuf ARGS((const char *s, size_t len)); ++#endif /* DEBIAN */ + + #define C_ 0x1 /* a valid command that isn't a M_, E_, U_ */ + #define M_ 0x2 /* movement command (h, l, etc.) */ +@@ -235,7 +238,7 @@ + + x_putc('\r'); x_putc('\n'); x_flush(); + +- if (c == -1) ++ if (c == -1 || len <= es->linelen) + return -1; + + if (es->cbuf != buf) +@@ -459,15 +462,22 @@ + else { + locpat[srchlen++] = ch; + if ((ch & 0x80) && Flag(FVISHOW8)) { ++ if (es->linelen + 2 > es->cbufsize) ++ vi_error(); + es->cbuf[es->linelen++] = 'M'; + es->cbuf[es->linelen++] = '-'; + ch &= 0x7f; + } + if (ch < ' ' || ch == 0x7f) { ++ if (es->linelen + 2 > es->cbufsize) ++ vi_error(); + es->cbuf[es->linelen++] = '^'; + es->cbuf[es->linelen++] = ch ^ '@'; +- } else ++ } else { ++ if (es->linelen >= es->cbufsize) ++ vi_error(); + es->cbuf[es->linelen++] = ch; ++ } + es->cursor = es->linelen; + refresh(0); + } +@@ -690,7 +700,7 @@ + /* End nonstandard vi commands } */ + + default: +- if (es->linelen == es->cbufsize - 1) ++ if (es->linelen >= es->cbufsize - 1) + return -1; + ibuf[inslen++] = ch; + if (insert == INSERT) { +@@ -1403,7 +1413,7 @@ + new = (struct edstate *)alloc(sizeof(struct edstate), APERM); + new->cbuf = alloc(old->cbufsize, APERM); + new->cbufsize = old->cbufsize; +- strcpy(new->cbuf, old->cbuf); ++ memcpy(new->cbuf, old->cbuf, old->linelen); + new->linelen = old->linelen; + new->cursor = old->cursor; + new->winleft = old->winleft; +@@ -1414,7 +1424,7 @@ + restore_edstate(new, old) + struct edstate *old, *new; + { +- strncpy(new->cbuf, old->cbuf, old->linelen); ++ memcpy(new->cbuf, old->cbuf, old->linelen); + new->linelen = old->linelen; + new->cursor = old->cursor; + new->winleft = old->winleft; +@@ -1470,6 +1480,19 @@ + holdlen = 0; + } + ++#ifdef DEBIAN /* patch from OpenBSD */ ++/* ++ * this is used for calling x_escape() in complete_word() ++ */ ++static int ++x_vi_putbuf(s, len) ++ const char *s; ++ size_t len; ++{ ++ return putbuf(s, len, 0); ++} ++ ++#endif /* DEBIAN */ + static int + putbuf(buf, len, repl) + const char *buf; +@@ -1965,7 +1988,11 @@ + del_range(start, end); + es->cursor = start; + for (i = 0; i < nwords; ) { ++#ifndef DEBIAN + if (putbuf(words[i], (int) strlen(words[i]), 0) != 0) { ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ if (x_escape(words[i], strlen(words[i]), x_vi_putbuf) != 0) { ++#endif /* DEBIAN */ + rval = -1; + break; + } +@@ -2068,9 +2095,18 @@ + buf = save_edstate(es); + del_range(start, end); + es->cursor = start; ++#ifndef DEBIAN + if (putbuf(match, match_len, 0) != 0) + rval = -1; + else if (is_unique) { ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ ++ /* escape all shell-sensitive characters and put the result into ++ * command buffer */ ++ rval = x_escape(match, match_len, x_vi_putbuf); ++ ++ if (rval == 0 && is_unique) { ++#endif /* DEBIAN */ + /* If exact match, don't undo. Allows directory completions + * to be used (ie, complete the next portion of the path). + */ +Index: pdksh-5.2.14/c_sh.c +=================================================================== +--- pdksh-5.2.14.orig/c_sh.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/c_sh.c 2009-09-17 00:32:08.000000000 +0200 +@@ -643,6 +643,7 @@ + for (wp = l->argv; (*wp++ = *owp++) != NULL; ) + ; + } ++#ifndef DEBIAN + /* POSIX says set exit status is 0, but old scripts that use + * getopt(1), use the construct: set -- `getopt ab:c "$@"` + * which assumes the exit value set will be that of the `` +@@ -650,6 +651,12 @@ + * if there are no command substitutions). + */ + return Flag(FPOSIX) ? 0 : subst_exstat; ++#else ++ /* On Debian we always want set to return 0 like ksh93 does. ++ * See: Bug#118476. ++ */ ++ return 0; ++#endif /* DEBIAN */ + } + + int +@@ -844,7 +851,7 @@ + * keeps them open). + */ + #ifdef KSH +- if (i > 2 && e->savefd[i]) ++ if (!Flag(FSH) &&i > 2 && e->savefd[i]) + fd_clexec(i); + #endif /* KSH */ + } +Index: pdksh-5.2.14/exec.c +=================================================================== +--- pdksh-5.2.14.orig/exec.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/exec.c 2009-09-17 00:32:31.000000000 +0200 +@@ -228,8 +228,10 @@ + e->savefd[1] = savefd(1, 0); + + openpipe(pv); +- ksh_dup2(pv[0], 0, FALSE); +- close(pv[0]); ++ if (pv[0] != 0) { ++ ksh_dup2(pv[0], 0, FALSE); ++ close(pv[0]); ++ } + coproc.write = pv[1]; + coproc.job = (void *) 0; + +@@ -448,18 +450,19 @@ + int volatile flags; + { + int i; +- int rv = 0; ++ volatile int rv = 0; + register char *cp; + register char **lastp; + static struct op texec; /* Must be static (XXX but why?) */ + int type_flags; + int keepasn_ok; + int fcflags = FC_BI|FC_FUNC|FC_PATH; ++ int bourne_function_call = 0; + + #ifdef KSH + /* snag the last argument for $_ XXX not the same as at&t ksh, + * which only seems to set $_ after a newline (but not in +- * functions/dot scripts, but in interactive and scipt) - ++ * functions/dot scripts, but in interactive and script) - + * perhaps save last arg here and set it in shell()?. + */ + if (Flag(FTALKING) && *(lastp = ap)) { +@@ -544,9 +547,10 @@ + newblock(); + /* ksh functions don't keep assignments, POSIX functions do. */ + if (keepasn_ok && tp && tp->type == CFUNC +- && !(tp->flag & FKSH)) +- type_flags = 0; +- else ++ && !(tp->flag & FKSH)) { ++ bourne_function_call = 1; ++ type_flags = 0; ++ } else + type_flags = LOCAL|LOCAL_COPY|EXPORT; + } + if (Flag(FEXPORT)) +@@ -563,6 +567,8 @@ + shf_flush(shl_out); + } + typeset(cp, type_flags, 0, 0, 0); ++ if (bourne_function_call && !(type_flags & EXPORT)) ++ typeset(cp, LOCAL|LOCAL_COPY|EXPORT, 0, 0, 0); + } + + if ((cp = *ap) == NULL) { +@@ -710,10 +716,12 @@ + } + + #ifdef KSH +- /* set $_ to program's full path */ +- /* setstr() can't fail here */ +- setstr(typeset("_", LOCAL|EXPORT, 0, INTEGER, 0), tp->val.s, +- KSH_RETURN_ERROR); ++ if (!Flag(FSH)) { ++ /* set $_ to program's full path */ ++ /* setstr() can't fail here */ ++ setstr(typeset("_", LOCAL|EXPORT, 0, INTEGER, 0), tp->val.s, ++ KSH_RETURN_ERROR); ++ } + #endif /* KSH */ + + if (flags&XEXEC) { +@@ -1351,6 +1359,8 @@ + snptreef((char *) 0, 32, "%R", &iotmp), emsg); + return -1; + } ++ if (u == iop->unit) ++ return 0; /* "dup from" == "dup to" */ + break; + } + } +@@ -1375,13 +1385,20 @@ + return -1; + } + /* Do not save if it has already been redirected (i.e. "cat >x >y"). */ +- if (e->savefd[iop->unit] == 0) +- /* c_exec() assumes e->savefd[fd] set for any redirections. +- * Ask savefd() not to close iop->unit - allows error messages +- * to be seen if iop->unit is 2; also means we can't lose +- * the fd (eg, both dup2 below and dup2 in restfd() failing). +- */ +- e->savefd[iop->unit] = savefd(iop->unit, 1); ++ if (e->savefd[iop->unit] == 0) { ++#ifdef DEBIAN /* patch from OpenBSD */ ++ /* If these are the same, it means unit was previously closed */ ++ if (u == iop->unit) ++ e->savefd[iop->unit] = -1; ++ else ++#endif ++ /* c_exec() assumes e->savefd[fd] set for any redirections. ++ * Ask savefd() not to close iop->unit - allows error messages ++ * to be seen if iop->unit is 2; also means we can't lose ++ * the fd (eg, both dup2 below and dup2 in restfd() failing). ++ */ ++ e->savefd[iop->unit] = savefd(iop->unit, 1); ++ } + + if (do_close) + close(iop->unit); +Index: pdksh-5.2.14/history.c +=================================================================== +--- pdksh-5.2.14.orig/history.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/history.c 2009-09-17 00:32:08.000000000 +0200 +@@ -858,8 +858,8 @@ + /* + * check on its validity + */ +- if ((int)base == -1 || *base != HMAGIC1 || base[1] != HMAGIC2) { +- if ((int)base != -1) ++ if (base == MAP_FAILED || *base != HMAGIC1 || base[1] != HMAGIC2) { ++ if (base != MAP_FAILED) + munmap((caddr_t)base, hsize); + hist_finish(); + unlink(hname); +@@ -893,7 +893,7 @@ + static int + hist_count_lines(base, bytes) + register unsigned char *base; +- register int bytes; ++ int bytes; + { + State state = shdr; + register lines = 0; +@@ -1015,8 +1015,8 @@ + register int bytes; + { + State state; +- int lno; +- unsigned char *line; ++ int lno = -1; ++ unsigned char *line = NULL; + + for (state = shdr; bytes-- > 0; base++) { + switch (state) { +@@ -1105,7 +1105,7 @@ + /* someone has added some lines */ + bytes = sizenow - hsize; + base = (unsigned char *)mmap(0, sizenow, PROT_READ, MAP_FLAGS, histfd, 0); +- if ((int)base == -1) ++ if (base == MAP_FAILED) + goto bad; + new = base + hsize; + if (*new != COMMAND) { +Index: pdksh-5.2.14/jobs.c +=================================================================== +--- pdksh-5.2.14.orig/jobs.c 2009-09-17 00:32:06.000000000 +0200 ++++ pdksh-5.2.14/jobs.c 2009-09-17 00:32:08.000000000 +0200 +@@ -627,8 +627,10 @@ + SS_RESTORE_IGN|SS_FORCE); + if (!(flags & (XPIPEI | XCOPROC))) { + int fd = open("/dev/null", 0); +- (void) ksh_dup2(fd, 0, TRUE); +- close(fd); ++ if (fd != 0) { ++ (void) ksh_dup2(fd, 0, TRUE); ++ close(fd); ++ } + } + } + remove_job(j, "child"); /* in case of `jobs` command */ +@@ -811,7 +813,7 @@ + int sig; + { + Job *j; +- Proc *p; ++/* Proc *p; */ /* unused */ + int rv = 0; + int ecode; + #ifdef JOB_SIGS +Index: pdksh-5.2.14/lex.c +=================================================================== +--- pdksh-5.2.14.orig/lex.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/lex.c 2009-09-17 00:32:08.000000000 +0200 +@@ -699,11 +699,13 @@ + + case '(': /*)*/ + #ifdef KSH +- if ((c2 = getsc()) == '(') /*)*/ +- /* XXX need to handle ((...); (...)) */ +- c = MDPAREN; +- else +- ungetsc(c2); ++ if (!Flag(FSH)) { ++ if ((c2 = getsc()) == '(') /*)*/ ++ /* XXX need to handle ((...); (...)) */ ++ c = MDPAREN; ++ else ++ ungetsc(c2); ++ } + #endif /* KSH */ + return c; + /*(*/ +@@ -1119,7 +1121,7 @@ + */ + { + struct shf *shf; +- char *ps1; ++ char * volatile ps1; + Area *saved_atemp; + + ps1 = str_val(global("PS1")); +Index: pdksh-5.2.14/main.c +=================================================================== +--- pdksh-5.2.14.orig/main.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/main.c 2009-09-17 00:32:08.000000000 +0200 +@@ -201,7 +201,24 @@ + change_flag(FPOSIX, OF_SPECIAL, 1); + #endif /* POSIXLY_CORRECT */ + +- /* import enviroment */ ++#ifdef DEBIAN /* patch from OpenBSD */ ++ /* Check to see if we're /bin/sh. */ ++ if (!strcmp(&kshname[strlen(kshname) - 3], "/sh") ++ || !strcmp(kshname, "sh") || !strcmp(kshname, "-sh")) ++ Flag(FSH) = 1; ++ ++ /* Set edit mode to emacs by default, may be overridden ++ * by the environment or the user. Also, we want tab completion ++ * on in vi by default. */ ++#if defined(EDIT) && defined(EMACS) ++ change_flag(FEMACS, OF_SPECIAL, 1); ++#endif /* EDIT && EMACS */ ++ #if defined(EDIT) && defined(VI) ++ Flag(FVITABCOMPLETE) = 1; ++#endif /* EDIT && VI */ ++#endif /* DEBIAN */ ++ ++ /* import environment */ + if (environ != NULL) + for (wp = environ; *wp != NULL; wp++) + typeset(*wp, IMPORT|EXPORT, 0, 0, 0); +Index: pdksh-5.2.14/misc.c +=================================================================== +--- pdksh-5.2.14.orig/misc.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/misc.c 2009-09-17 00:32:08.000000000 +0200 +@@ -159,6 +159,7 @@ + { "posix", 0, OF_ANY }, /* non-standard */ + { "privileged", 'p', OF_ANY }, + { "restricted", 'r', OF_CMDLINE }, ++ { "sh", 0, OF_ANY }, /* non-standard */ /* from OpenBSD */ + { "stdin", 's', OF_CMDLINE }, /* pseudo non-standard */ + { "trackall", 'h', OF_ANY }, + { "verbose", 'v', OF_ANY }, +@@ -309,8 +310,15 @@ + #ifdef OS2 + ; + #else /* OS2 */ ++#ifndef DEBIAN + setuid(ksheuid = getuid()); + setgid(getgid()); ++#else /* patch from OpenBSD */ ++ seteuid(ksheuid = getuid()); ++ setuid(ksheuid); ++ setegid(getgid()); ++ setgid(getgid()); ++#endif /* DEBIAN */ + #endif /* OS2 */ + } else if (f == FPOSIX && newval) { + #ifdef BRACE_EXPAND +@@ -471,6 +479,7 @@ + const char *as; + int *ai; + { ++#ifndef DEBIAN + const char *s; + register int n; + int sawdigit = 0; +@@ -484,6 +493,19 @@ + if (*s || !sawdigit) + return 0; + return 1; ++#else /* patch from OpenBSD */ ++ char *p; ++ long n; ++ ++ n = strtol(as, &p, 10); ++ ++ if (!*as || *p || INT_MIN >= n || n >= INT_MAX) ++ return 0; ++ ++ *ai = (int)n; ++ return 1; ++#endif ++ + } + + /* getn() that prints error */ +Index: pdksh-5.2.14/sh.h +=================================================================== +--- pdksh-5.2.14.orig/sh.h 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/sh.h 2009-09-17 00:32:08.000000000 +0200 +@@ -382,7 +382,11 @@ + */ + + typedef struct Area { ++#ifndef DEBIAN + struct Block *freelist; /* free list */ ++#else /* patch from OpenBSD */ ++ struct link *freelist; /* free list */ ++#endif + } Area; + + EXTERN Area aperm; /* permanent object space */ +@@ -501,6 +505,7 @@ + FPOSIX, /* -o posix: be posixly correct */ + FPRIVILEGED, /* -p: use suid_profile */ + FRESTRICTED, /* -r: restricted shell */ ++ FSH, /* -o sh: favor sh behavour */ + FSTDIN, /* -s: (invocation) parse stdin */ + FTRACKALL, /* -h: create tracked aliases for all commands */ + FVERBOSE, /* -v: echo input */ +Index: pdksh-5.2.14/tests/th +=================================================================== +--- pdksh-5.2.14.orig/tests/th 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/tests/th 2009-09-17 00:32:08.000000000 +0200 +@@ -1,4 +1,4 @@ +-#!/usr/local/bin/perl ++#!/usr/bin/perl + + # + # Test harness for pdksh tests. +@@ -131,7 +131,7 @@ + $os = defined $^O ? $^O : 'unknown'; + + require 'signal.ph' unless $os eq 'os2'; +-require 'errno.ph' unless $os eq 'os2'; ++# require 'errno.ph' unless $os eq 'os2'; + require 'getopts.pl'; + + ($prog = $0) =~ s#.*/##; +Index: pdksh-5.2.14/trap.c +=================================================================== +--- pdksh-5.2.14.orig/trap.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/trap.c 2009-09-17 00:32:08.000000000 +0200 +@@ -68,6 +68,8 @@ + alarm_catcher(sig) + int sig; + { ++ int errno_ = errno; ++ + if (ksh_tmout_state == TMOUT_READING) { + int left = alarm(0); + +@@ -77,6 +79,7 @@ + } else + alarm(left); + } ++ errno = errno_; + return RETSIGVAL; + } + #endif /* KSH */ +@@ -111,6 +114,7 @@ + int i; + { + Trap *p = &sigtraps[i]; ++ int errno_ = errno; + + trap = p->set = 1; + if (p->flags & TF_DFL_INTR) +@@ -125,6 +129,7 @@ + if (sigtraps[i].cursig == trapsig) /* this for SIGCHLD,SIGALRM */ + sigaction(i, &Sigact_trap, (struct sigaction *) 0); + #endif /* V7_SIGNALS */ ++ errno = errno_; + return RETSIGVAL; + } + +Index: pdksh-5.2.14/tree.c +=================================================================== +--- pdksh-5.2.14.orig/tree.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/tree.c 2009-09-17 00:32:08.000000000 +0200 +@@ -506,7 +506,7 @@ + for (tw = t->vars; *tw++ != NULL; ) + ; + rw = r->vars = (char **) +- alloc((int)(tw - t->vars) * sizeof(*tw), ap); ++ alloc((tw - t->vars + 1) * sizeof(*tw), ap); + for (tw = t->vars; *tw != NULL; ) + *rw++ = wdcopy(*tw++, ap); + *rw = NULL; +@@ -518,7 +518,7 @@ + for (tw = t->args; *tw++ != NULL; ) + ; + rw = r->args = (char **) +- alloc((int)(tw - t->args) * sizeof(*tw), ap); ++ alloc((tw - t->args + 1) * sizeof(*tw), ap); + for (tw = t->args; *tw != NULL; ) + *rw++ = wdcopy(*tw++, ap); + *rw = NULL; +@@ -679,7 +679,7 @@ + + for (ior = iow; *ior++ != NULL; ) + ; +- ior = (struct ioword **) alloc((int)(ior - iow) * sizeof(*ior), ap); ++ ior = (struct ioword **) alloc((ior - iow + 1) * sizeof(*ior), ap); + + for (i = 0; iow[i] != NULL; i++) { + register struct ioword *p, *q; +Index: pdksh-5.2.14/c_test.c +=================================================================== +--- pdksh-5.2.14.orig/c_test.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/c_test.c 2009-09-17 00:32:08.000000000 +0200 +@@ -124,10 +124,10 @@ + te.pos.wp = wp + 1; + te.wp_end = wp + argc; + +- /* ++ /* + * Handle the special cases from POSIX.2, section 4.62.4. +- * Implementation of all the rules isn't necessary since +- * our parser does the right thing for the ommited steps. ++ * Implementation of all the rules isn't necessary since ++ * our parser does the right thing for the omitted steps. + */ + if (argc <= 5) { + char **owp = wp; +@@ -238,7 +238,7 @@ + if (not) + res = !res; + } +- return res; ++ return res; + case TO_FILRD: /* -r */ + return test_eaccess(opnd1, R_OK) == 0; + case TO_FILWR: /* -w */ +@@ -456,10 +456,12 @@ + } + #endif /* !HAVE_DEV_FD */ + +- /* On most (all?) unixes, access() says everything is executable for ++ res = eaccess(path, mode); ++ /* ++ * On most (all?) unixes, access() says everything is executable for + * root - avoid this on files by using stat(). + */ +- if ((mode & X_OK) && ksheuid == 0) { ++ if (res == 0 && ksheuid == 0 && (mode & X_OK)) { + struct stat statb; + + if (stat(path, &statb) < 0) +@@ -469,13 +471,7 @@ + else + res = (statb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) + ? 0 : -1; +- /* Need to check other permissions? If so, use access() as +- * this will deal with root on NFS. +- */ +- if (res == 0 && (mode & (R_OK|W_OK))) +- res = eaccess(path, mode); +- } else +- res = eaccess(path, mode); ++ } + + return res; + } +Index: pdksh-5.2.14/eval.c +=================================================================== +--- pdksh-5.2.14.orig/eval.c 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/eval.c 2009-09-17 00:32:08.000000000 +0200 +@@ -870,8 +870,11 @@ + openpipe(pv); + shf = shf_fdopen(pv[0], SHF_RD, (struct shf *) 0); + ofd1 = savefd(1, 0); /* fd 1 may be closed... */ +- ksh_dup2(pv[1], 1, FALSE); +- close(pv[1]); ++ if (pv[1] != 1) { ++ ksh_dup2(pv[1], 1, FALSE); ++ close(pv[1]); ++ } ++ + execute(t, XFORK|XXCOM|XPIPEO); + restfd(1, ofd1); + startlast(); +Index: pdksh-5.2.14/tests/regress.t +=================================================================== +--- pdksh-5.2.14.orig/tests/regress.t 2009-09-17 00:31:58.000000000 +0200 ++++ pdksh-5.2.14/tests/regress.t 2009-09-17 00:32:08.000000000 +0200 +@@ -156,11 +156,12 @@ + echo $? + shoud not print 0. (according to /bin/sh, at&t ksh88, and the + getopt(1) man page - not according to POSIX) ++ For Debian - it should print 0, cf. bug#118476. + stdin: + set -- `false` + echo $? + expected-stdout: +- 1 ++ 0 + --- + + diff --git a/system/pdksh/patches/011_OpenBSD-alloc.patch b/system/pdksh/patches/011_OpenBSD-alloc.patch new file mode 100644 index 0000000000000..ec272897e2bb1 --- /dev/null +++ b/system/pdksh/patches/011_OpenBSD-alloc.patch @@ -0,0 +1,199 @@ + + alloc.c: Kill hand-made memory allocation code, that is definitely + buggy. Replace with simple wrapper around malloc, at least this works, + and it's easier to debug anyways. + + alloc.c: Don't allow alloc() and aresize() to fail. Their return + value was only checked in two place (both in conjunction with + str_save). Upon malloc/realloc failure we call internal_errorf() + which pops throws and error and pops back to the last good state. +Index: pdksh-5.2.14/alloc.c +=================================================================== +--- pdksh-5.2.14.orig/alloc.c 2008-04-15 20:46:56.000000000 +0200 ++++ pdksh-5.2.14/alloc.c 2008-04-15 20:50:18.000000000 +0200 +@@ -1,3 +1,5 @@ ++#ifndef DEBIAN ++ + /* + * area-based allocation built on malloc/free + */ +@@ -110,6 +112,13 @@ + Block *block; + struct {int _;} junk; /* alignment */ + double djunk; /* alignment */ ++#ifdef DEBIAN /* patch from RedHat */ ++#ifdef __ia64__ ++ /* IA64 requires 16 byte alignment for some objects, so make ++ * this the minimum allocation size */ ++ char ajunk[16]; ++#endif ++#endif + }; + + struct Block { +@@ -282,7 +291,9 @@ + * working (as it assumes size < ICELLS means it is not + * a `large object'). + */ +- if (oldcells > ICELLS && cells > ICELLS) { ++ if (oldcells > ICELLS && cells > ICELLS ++ && ((dp-2)->block->last == dp+oldcells) /* don't destroy blocks which have grown! */ ++ ) { + Block *bp = (dp-2)->block; + Block *nbp; + /* Saved in case realloc fails.. */ +@@ -332,7 +343,7 @@ + * (need to check that cells < ICELLS so we don't make an + * object a `large' - that would mess everything up). + */ +- if (dp && cells > oldcells && cells <= ICELLS) { ++ if (dp && cells > oldcells) { + Cell *fp, *fpp; + Block *bp = (dp-2)->block; + int need = cells - oldcells - NOBJECT_FIELDS; +@@ -363,7 +374,7 @@ + * it to malloc...) + * Note: this also handles cells == oldcells (a no-op). + */ +- if (dp && cells <= oldcells && oldcells <= ICELLS) { ++ if (dp && cells <= oldcells) { + int split; + + split = oldcells - cells; +@@ -411,7 +422,9 @@ + + /* If this is a large object, just free it up... */ + /* Release object... */ +- if ((dp-1)->size > ICELLS) { ++ if ((dp-1)->size > ICELLS ++ && (bp->last == dp + (dp-1)->size) /* don't free non-free blocks which have grown! */ ++ ) { + ablockfree(bp, ap); + ACHECK(ap); + return; +@@ -774,3 +787,127 @@ + # endif /* TEST_ALLOC */ + + #endif /* MEM_DEBUG */ ++ ++#else /* DEBIAN */ /* patch from OpenBSD */ ++ ++/* $OpenBSD: alloc.c,v 1.6 2003/08/05 20:52:27 millert Exp $ */ ++/* ++ * Copyright (c) 2002 Marc Espie. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS ++ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD ++ * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/* ++ * area-based allocation built on malloc/free ++ */ ++ ++#include "sh.h" ++ ++struct link { ++ struct link *prev; ++ struct link *next; ++}; ++ ++Area * ++ainit(Area *ap) ++{ ++ ap->freelist = NULL; ++ return ap; ++} ++ ++void ++afreeall(Area *ap) ++{ ++ struct link *l, *l2; ++ ++ for (l = ap->freelist; l != NULL; l = l2) { ++ l2 = l->next; ++ free(l); ++ } ++ ap->freelist = NULL; ++} ++ ++#define L2P(l) ( (void *)(((char *)(l)) + sizeof(struct link)) ) ++#define P2L(p) ( (struct link *)(((char *)(p)) - sizeof(struct link)) ) ++ ++void * ++alloc(size_t size, Area *ap) ++{ ++ struct link *l; ++ ++ l = malloc(size + sizeof(struct link)); ++ if (l == NULL) ++ internal_errorf(1, "unable to allocate memory"); ++ l->next = ap->freelist; ++ l->prev = NULL; ++ if (ap->freelist) ++ ap->freelist->prev = l; ++ ap->freelist = l; ++ ++ return L2P(l); ++} ++ ++void * ++aresize(void *ptr, size_t size, Area *ap) ++{ ++ struct link *l, *l2, *lprev, *lnext; ++ ++ if (ptr == NULL) ++ return alloc(size, ap); ++ ++ l = P2L(ptr); ++ lprev = l->prev; ++ lnext = l->next; ++ ++ l2 = realloc(l, size+sizeof(struct link)); ++ if (l2 == NULL) ++ internal_errorf(1, "unable to allocate memory"); ++ if (lprev) ++ lprev->next = l2; ++ else ++ ap->freelist = l2; ++ if (lnext) ++ lnext->prev = l2; ++ ++ return L2P(l2); ++} ++ ++void ++afree(void *ptr, Area *ap) ++{ ++ struct link *l; ++ ++ if (!ptr) ++ return; ++ ++ l = P2L(ptr); ++ ++ if (l->prev) ++ l->prev->next = l->next; ++ else ++ ap->freelist = l->next; ++ if (l->next) ++ l->next->prev = l->prev; ++ ++ free(l); ++} ++#endif /* DEBIAN */ diff --git a/system/pdksh/patches/020_PLD-patches.patch b/system/pdksh/patches/020_PLD-patches.patch new file mode 100644 index 0000000000000..81c189f243d38 --- /dev/null +++ b/system/pdksh/patches/020_PLD-patches.patch @@ -0,0 +1,84 @@ + * Apply patches from PLD distribution (pdksh-5.2.14-23.src.rpm) + + pdksh-eval-segv.patch, fixes one more segfault bug + + pdksh-rlimit_locks.patch, adds flocks support to ulimit. + * c_ulimit.c: enclose all uses of RLIMIT_LOCKS with appropriate #ifdefs + (closes: #307323). +Index: pdksh-5.2.14/c_sh.c +=================================================================== +--- pdksh-5.2.14.orig/c_sh.c 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/c_sh.c 2008-04-15 20:50:48.000000000 +0200 +@@ -422,7 +422,8 @@ + c_eval(wp) + char **wp; + { +- register struct source *s; ++ register struct source *s,*olds=source; ++ int retval; + + if (ksh_getopt(wp, &builtin_opt, null) == '?') + return 1; +@@ -456,7 +457,9 @@ + exstat = subst_exstat; + } + +- return shell(s, FALSE); ++ retval=shell(s, FALSE); ++ source=olds; ++ return retval; + } + + int +Index: pdksh-5.2.14/c_ulimit.c +=================================================================== +--- pdksh-5.2.14.orig/c_ulimit.c 2008-04-15 20:46:56.000000000 +0200 ++++ pdksh-5.2.14/c_ulimit.c 2008-04-15 20:50:48.000000000 +0200 +@@ -111,6 +111,9 @@ + #ifdef RLIMIT_SWAP + { "swap(kbytes)", RLIMIT_SWAP, RLIMIT_SWAP, 1024, 'w' }, + #endif ++#ifdef RLIMIT_LOCKS ++ { "flocks", RLIMIT, RLIMIT_LOCKS, RLIMIT_LOCKS, -1, 'L' }, ++#endif + { (char *) 0 } + }; + static char options[3 + NELEM(limits)]; +@@ -189,7 +192,18 @@ + for (l = limits; l->name; l++) { + #ifdef HAVE_SETRLIMIT + if (l->which == RLIMIT) { +- getrlimit(l->gcmd, &limit); ++ int getreturn; ++ ++ getreturn=getrlimit(l->gcmd, &limit); ++#ifdef RLIMIT_LOCKS ++ if ( getreturn < 0 ) { ++ if ( ( errno == EINVAL ) && ++ ( l->gcmd == RLIMIT_LOCKS ) ) { ++ limit.rlim_cur = RLIM_INFINITY; ++ limit.rlim_max = RLIM_INFINITY; ++ } ++ } ++#endif + if (how & SOFT) + val = limit.rlim_cur; + else if (how & HARD) +@@ -225,11 +239,17 @@ + if (how & HARD) + limit.rlim_max = val; + if (setrlimit(l->scmd, &limit) < 0) { +- if (errno == EPERM) ++ if (errno == EPERM) { + bi_errorf("exceeds allowable limit"); +- else ++#ifdef RLIMIT_LOCKS ++ } else if ( ( errno == EINVAL ) && ++ ( l->scmd == RLIMIT_LOCKS ) ) { ++ bi_errorf("unable to set it on the current kernel"); ++#endif ++ } else { + bi_errorf("bad limit: %s", + strerror(errno)); ++ } + return 1; + } + } else { diff --git a/system/pdksh/patches/030_posh-eval.patch b/system/pdksh/patches/030_posh-eval.patch new file mode 100644 index 0000000000000..e9f668493c618 --- /dev/null +++ b/system/pdksh/patches/030_posh-eval.patch @@ -0,0 +1,29 @@ +pdksh (5.2.14-13) unstable; urgency=low + + * c_sh.c: Apply patch from the posh package to make `eval false || true' + not exit with -e (closes: #269067). +Index: pdksh-5.2.14/c_sh.c +=================================================================== +--- pdksh-5.2.14.orig/c_sh.c 2008-04-15 20:50:48.000000000 +0200 ++++ pdksh-5.2.14/c_sh.c 2008-04-15 20:51:18.000000000 +0200 +@@ -423,7 +423,7 @@ + char **wp; + { + register struct source *s,*olds=source; +- int retval; ++ int retval, errexitflagtmp; + + if (ksh_getopt(wp, &builtin_opt, null) == '?') + return 1; +@@ -456,8 +456,10 @@ + */ + exstat = subst_exstat; + } +- ++ errexitflagtmp = Flag(FERREXIT); ++ Flag(FERREXIT) = 0; + retval=shell(s, FALSE); ++ Flag(FERREXIT) = errexitflagtmp; + source=olds; + return retval; + } diff --git a/system/pdksh/patches/040_Debian-gcc-warnings.patch b/system/pdksh/patches/040_Debian-gcc-warnings.patch new file mode 100644 index 0000000000000..6970b4b4ea2de --- /dev/null +++ b/system/pdksh/patches/040_Debian-gcc-warnings.patch @@ -0,0 +1,147 @@ + * Compiled with -Wall, fixed some gcc warnings. +Index: pdksh-5.2.14/c_ksh.c +=================================================================== +--- pdksh-5.2.14.orig/c_ksh.c 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/c_ksh.c 2008-04-15 20:51:49.000000000 +0200 +@@ -1110,13 +1110,14 @@ + return 1; + } + wp += builtin_opt.optind; +- if (!*wp) ++ if (!*wp) { + if (j_jobs((char *) 0, flag, nflag)) + rv = 1; +- else ++ } else { + for (; *wp; wp++) + if (j_jobs(*wp, flag, nflag)) + rv = 1; ++ } + return rv; + } + +Index: pdksh-5.2.14/io.c +=================================================================== +--- pdksh-5.2.14.orig/io.c 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/io.c 2008-04-15 20:51:49.000000000 +0200 +@@ -297,11 +297,12 @@ + + if (fd < FDBASE) { + nfd = ksh_dupbase(fd, FDBASE); +- if (nfd < 0) ++ if (nfd < 0) { + if (errno == EBADF) + return -1; + else + errorf("too many files open in shell"); ++ } + if (!noclose) + close(fd); + } else +Index: pdksh-5.2.14/jobs.c +=================================================================== +--- pdksh-5.2.14.orig/jobs.c 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/jobs.c 2008-04-15 20:51:49.000000000 +0200 +@@ -1566,11 +1566,12 @@ + break; + } + +- if (how != JP_SHORT) ++ if (how != JP_SHORT) { + if (p == j->proc_list) + shf_fprintf(shf, "[%d] %c ", j->job, jobchar); + else + shf_fprintf(shf, "%s", filler); ++ } + + if (how == JP_LONG) + shf_fprintf(shf, "%5d ", p->pid); +Index: pdksh-5.2.14/lex.c +=================================================================== +--- pdksh-5.2.14.orig/lex.c 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/lex.c 2008-04-15 20:51:49.000000000 +0200 +@@ -645,11 +645,12 @@ + if (c == c2 || (c == '<' && c2 == '>')) { + iop->flag = c == c2 ? + (c == '>' ? IOCAT : IOHERE) : IORDWR; +- if (iop->flag == IOHERE) ++ if (iop->flag == IOHERE) { + if ((c2 = getsc()) == '-') + iop->flag |= IOSKIP; + else + ungetsc(c2); ++ } + } else if (c2 == '&') + iop->flag = IODUP | (c == '<' ? IORDUP : 0); + else { +Index: pdksh-5.2.14/main.c +=================================================================== +--- pdksh-5.2.14.orig/main.c 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/main.c 2008-04-15 20:51:49.000000000 +0200 +@@ -593,11 +593,12 @@ + if (trap) + runtraps(0); + +- if (s->next == NULL) ++ if (s->next == NULL) { + if (Flag(FVERBOSE)) + s->flags |= SF_ECHO; + else + s->flags &= ~SF_ECHO; ++ } + + if (interactive) { + j_notify(); +Index: pdksh-5.2.14/table.c +=================================================================== +--- pdksh-5.2.14.orig/table.c 2008-04-15 20:46:56.000000000 +0200 ++++ pdksh-5.2.14/table.c 2008-04-15 20:51:49.000000000 +0200 +@@ -53,7 +53,7 @@ + if (otblp == NULL) + return; + for (i = 0; i < osize; i++) +- if ((tblp = otblp[i]) != NULL) ++ if ((tblp = otblp[i]) != NULL) { + if ((tblp->flag&DEFINED)) { + for (p = &ntblp[hash(tblp->name) + & (tp->size-1)]; +@@ -65,6 +65,7 @@ + } else if (!(tblp->flag & FINUSE)) { + afree((void*)tblp, tp->areap); + } ++ } + afree((void*)otblp, tp->areap); + } + +Index: pdksh-5.2.14/var.c +=================================================================== +--- pdksh-5.2.14.orig/var.c 2008-04-15 20:48:46.000000000 +0200 ++++ pdksh-5.2.14/var.c 2008-04-15 20:51:49.000000000 +0200 +@@ -63,11 +63,12 @@ + + e->loc = l->next; /* pop block */ + for (i = l->vars.size; --i >= 0; ) +- if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL)) ++ if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL)) { + if ((vq = global(vp->name))->flag & ISSET) + setspec(vq); + else + unsetspec(vq); ++ } + if (l->flags & BF_DOGETOPTS) + user_opt = l->getopts_state; + afreeall(&l->area); +@@ -217,11 +218,12 @@ + } + for (l = e->loc; ; l = l->next) { + vp = tsearch(&l->vars, n, h); +- if (vp != NULL) ++ if (vp != NULL) { + if (array) + return arraysearch(vp, val); + else + return vp; ++ } + if (l->next == NULL) + break; + } diff --git a/system/pdksh/patches/041_Debian-tilde-expansion.patch b/system/pdksh/patches/041_Debian-tilde-expansion.patch new file mode 100644 index 0000000000000..30741eb470e95 --- /dev/null +++ b/system/pdksh/patches/041_Debian-tilde-expansion.patch @@ -0,0 +1,15 @@ + * Don't do tilde expansion after `=' sign in non-assignments. + Patch stolen from the posh package (closes: #187839). +Index: pdksh-5.2.14/eval.c +=================================================================== +--- pdksh-5.2.14.orig/eval.c 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/eval.c 2008-04-15 20:52:19.000000000 +0200 +@@ -627,7 +627,7 @@ + #endif /* BRACE_EXPAND */ + case '=': + /* Note first unquoted = for ~ */ +- if (!(f & DOTEMP_) && !saw_eq) { ++ if (!(f & DOTEMP_) && !saw_eq && (f & DOASNTILDE)) { + saw_eq = 1; + tilde_ok = 1; + } diff --git a/system/pdksh/patches/042_Debian-eaccess.patch b/system/pdksh/patches/042_Debian-eaccess.patch new file mode 100644 index 0000000000000..c859dd459ab6f --- /dev/null +++ b/system/pdksh/patches/042_Debian-eaccess.patch @@ -0,0 +1,140 @@ + * Wrote function eaccess (used to be a macro defined as `access'), + which swaps real uid and gid with the effective ones, calls access, + and reverts the uid/gid. This fixes the test builtin command not + working properly when shell is privileged (closes: #245213). +Index: pdksh-5.2.14/c_test.c +=================================================================== +--- pdksh-5.2.14.orig/c_test.c 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/c_test.c 2008-04-15 20:52:50.000000000 +0200 +@@ -338,7 +338,7 @@ + case TO_FILUID: /* -O */ + return test_stat(opnd1, &b1) == 0 && b1.st_uid == ksheuid; + case TO_FILGID: /* -G */ +- return test_stat(opnd1, &b1) == 0 && b1.st_gid == getegid(); ++ return test_stat(opnd1, &b1) == 0 && b1.st_gid == kshegid; + /* + * Binary Operators + */ +@@ -656,3 +656,36 @@ + else + bi_errorf("%s", msg); + } ++ ++ ++#ifdef DEBIAN ++int eaccess(const char *pathname, int mode) { ++ int need_setreuid, need_setregid; ++ int result; ++ int _errno; ++ ++ ++ ++ if (( need_setregid = ( kshgid != kshegid ) )) { ++ setregid( kshegid, kshgid ); ++ } ++ ++ if (( need_setreuid = ( kshuid != ksheuid ) )) { ++ setreuid( ksheuid, kshuid ); ++ } ++ ++ result = access( pathname, mode ); ++ _errno = errno; ++ ++ if ( need_setregid ) { ++ setregid( kshgid, kshegid ); ++ } ++ ++ if ( need_setreuid ) { ++ setreuid( kshuid, ksheuid ); ++ } ++ ++ errno = _errno; ++ return result; ++} ++#endif +Index: pdksh-5.2.14/main.c +=================================================================== +--- pdksh-5.2.14.orig/main.c 2008-04-15 20:51:49.000000000 +0200 ++++ pdksh-5.2.14/main.c 2008-04-15 20:52:50.000000000 +0200 +@@ -269,6 +269,9 @@ + + + ksheuid = geteuid(); ++ kshuid = getuid(); ++ kshgid = getgid(); ++ kshegid = getegid(); + safe_prompt = ksheuid ? "$ " : "# "; + { + struct tbl *vp = global("PS1"); +@@ -283,7 +286,7 @@ + } + + /* Set this before parsing arguments */ +- Flag(FPRIVILEGED) = getuid() != ksheuid || getgid() != getegid(); ++ Flag(FPRIVILEGED) = kshuid != ksheuid || kshgid != kshegid; + + /* this to note if monitor is set on command line (see below) */ + Flag(FMONITOR) = 127; +Index: pdksh-5.2.14/misc.c +=================================================================== +--- pdksh-5.2.14.orig/misc.c 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/misc.c 2008-04-15 20:52:50.000000000 +0200 +@@ -19,6 +19,7 @@ + int isfile)); + static const unsigned char *cclass ARGS((const unsigned char *p, int sub)); + ++ + /* + * Fast character classes + */ +@@ -311,13 +312,13 @@ + ; + #else /* OS2 */ + #ifndef DEBIAN +- setuid(ksheuid = getuid()); +- setgid(getgid()); ++ setuid(ksheuid = kshuid = getuid()); ++ setgid(kshegid = kshgid = getgid()); + #else /* patch from OpenBSD */ +- seteuid(ksheuid = getuid()); ++ seteuid(ksheuid = kshuid = getuid()); + setuid(ksheuid); +- setegid(getgid()); +- setgid(getgid()); ++ setegid(kshegid = kshgid = getgid()); ++ setgid(kshegid); + #endif /* DEBIAN */ + #endif /* OS2 */ + } else if (f == FPOSIX && newval) { +@@ -1365,3 +1366,4 @@ + return b; + #endif /* HAVE_GETCWD */ + } ++ +Index: pdksh-5.2.14/sh.h +=================================================================== +--- pdksh-5.2.14.orig/sh.h 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/sh.h 2008-04-15 20:52:50.000000000 +0200 +@@ -353,8 +353,12 @@ + #define NUFILE 10 /* Number of user-accessible files */ + #define FDBASE 10 /* First file usable by Shell */ + ++#ifndef DEBIAN + /* you're not going to run setuid shell scripts, are you? */ + #define eaccess(path, mode) access(path, mode) ++#else ++EXTERN int eaccess( const char * pathname, int mode ); ++#endif + + /* Make MAGIC a char that might be printed to make bugs more obvious, but + * not a char that is used often. Also, can't use the high bit as it causes +@@ -372,6 +376,9 @@ + EXTERN pid_t kshpid; /* $$, shell pid */ + EXTERN pid_t procpid; /* pid of executing process */ + EXTERN int ksheuid; /* effective uid of shell */ ++EXTERN int kshegid; /* effective gid of shell */ ++EXTERN int kshuid; /* real uid of shell */ ++EXTERN int kshgid; /* real gid of shell */ + EXTERN int exstat; /* exit status */ + EXTERN int subst_exstat; /* exit status of last $(..)/`..` */ + EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */ diff --git a/system/pdksh/patches/043_Debian-siglist.patch b/system/pdksh/patches/043_Debian-siglist.patch new file mode 100644 index 0000000000000..bd7a9af805f71 --- /dev/null +++ b/system/pdksh/patches/043_Debian-siglist.patch @@ -0,0 +1,23 @@ + * siglist.sh: fix sed command line + * siglist.sh: pass `-' to trap call, fixes FTBFS on sparc. +Index: pdksh-5.2.14/siglist.sh +=================================================================== +--- pdksh-5.2.14.orig/siglist.sh 2008-04-15 20:46:55.000000000 +0200 ++++ pdksh-5.2.14/siglist.sh 2008-04-15 20:53:20.000000000 +0200 +@@ -16,14 +16,14 @@ + CPP="${1-cc -E}" + + # The trap here to make up for a bug in bash (1.14.3(1)) that calls the trap +-(trap $trapsigs; ++(trap - $trapsigs; + echo '#include "sh.h"'; + echo ' { QwErTy SIGNALS , "DUMMY" , "hook for number of signals" },'; + sed -e '/^[ ]*#/d' -e 's/^[ ]*\([^ ][^ ]*\)[ ][ ]*\(.*[^ ]\)[ ]*$/#ifdef SIG\1\ + { QwErTy SIG\1 , "\1", "\2" },\ + #endif/') > $in + $CPP $in > $out +-sed -n 's/{ QwErTy/{/p' < $out | awk '{print NR, $0}' | sort +2n +0n | ++sed -n 's/{ QwErTy/{/p' < $out | awk '{print NR, $0}' | sort -k 3n -k 1n | + sed 's/^[0-9]* //' | + awk 'BEGIN { last=0; nsigs=0; } + { diff --git a/system/pdksh/patches/044_Debian-emacs-crash.patch b/system/pdksh/patches/044_Debian-emacs-crash.patch new file mode 100644 index 0000000000000..047302811bf96 --- /dev/null +++ b/system/pdksh/patches/044_Debian-emacs-crash.patch @@ -0,0 +1,18 @@ + * emacs.c: Fix segmentation fault bug when ksh used bash history file + (closes: #284358). +Index: pdksh-5.2.14/emacs.c +=================================================================== +--- pdksh-5.2.14.orig/emacs.c 2008-04-15 20:49:47.000000000 +0200 ++++ pdksh-5.2.14/emacs.c 2008-04-15 20:53:50.000000000 +0200 +@@ -883,9 +883,9 @@ + } + x_histp = hp; + oldsize = x_size_str(xbuf); +- (void)strcpy(xbuf, *hp); ++ (void)strncpy(xbuf, *hp, xend - xbuf - 1); + xbp = xbuf; +- xep = xcp = xbuf + strlen(*hp); ++ xep = xcp = xbuf + strlen(xbuf); + xlp_valid = FALSE; + if (xep > x_lastcp()) + x_goto(xep); diff --git a/system/pdksh/patches/045_Debian-job-control.patch b/system/pdksh/patches/045_Debian-job-control.patch new file mode 100644 index 0000000000000..4e1696265a7df --- /dev/null +++ b/system/pdksh/patches/045_Debian-job-control.patch @@ -0,0 +1,130 @@ + * Fix job control bug in non-interactive scripts (closes: #296446) + Many thanks to Paul Stroud <pstroud@gmail.com> for the patch. + * lex.c: Don't expand aliases if there's an opening bracket just after + the token. Fixes unreported problem with pdksh reporting syntax error + on the init scripts that define function named `stop' (clashing + with an built-in alias.) +Index: pdksh-5.2.14/jobs.c +=================================================================== +--- pdksh-5.2.14.orig/jobs.c 2009-07-18 15:20:19.000000000 +0200 ++++ pdksh-5.2.14/jobs.c 2009-07-18 15:20:27.000000000 +0200 +@@ -340,12 +340,17 @@ + int i; + + if (Flag(FMONITOR)) { +- /* Don't call get_tty() 'til we own the tty process group */ +- tty_init(FALSE); ++ int use_tty; ++ if (Flag(FTALKING)) { ++ /* Don't call get_tty() 'til we own the tty process group */ ++ use_tty = 1; ++ tty_init(FALSE); ++ } else ++ use_tty = 0; + + # ifdef TTY_PGRP + /* no controlling tty, no SIGT* */ +- ttypgrp_ok = tty_fd >= 0 && tty_devtty; ++ ttypgrp_ok = use_tty && tty_fd >= 0 && tty_devtty; + + if (ttypgrp_ok && (our_pgrp = getpgID()) < 0) { + warningf(FALSE, "j_init: getpgrp() failed: %s", +@@ -401,8 +406,10 @@ + strerror(errno)); + } + # endif /* NTTYDISC && TIOCSETD */ +- if (!ttypgrp_ok) +- warningf(FALSE, "warning: won't have full job control"); ++ if (Flag(FTALKING)) { ++ if (!ttypgrp_ok) ++ warningf(FALSE, "warning: won't have full job control"); ++ } + # endif /* TTY_PGRP */ + if (tty_fd >= 0) + get_tty(tty_fd, &tty_state); +Index: pdksh-5.2.14/lex.c +=================================================================== +--- pdksh-5.2.14.orig/lex.c 2009-07-18 15:20:19.000000000 +0200 ++++ pdksh-5.2.14/lex.c 2009-07-18 15:20:27.000000000 +0200 +@@ -723,7 +723,15 @@ + #endif /* KSH */ + ) /* ONEWORD? */ + return LWORD; +- ungetsc(c); /* unget terminator */ ++ ++ /* unget terminator */ ++ ungetsc(c); ++ ++ /* ++ * note: the alias-vs-function code below depends on several ++ * interna: starting from here, source->str is not modified; ++ * the way getsc() and ungetsc() operate; etc. ++ */ + + /* copy word to unprefixed string ident */ + for (sp = yylval.cp, dp = ident; dp < ident+IDENT && (c = *sp++) == CHAR; ) +@@ -747,6 +755,33 @@ + if ((cf & ALIAS) && (p = tsearch(&aliases, ident, h)) + && (p->flag & ISSET)) + { ++ /* ++ * this still points to the same character as the ++ * ungetsc'd terminator from above ++ */ ++ const char *cp = source->str; ++ ++ /* prefer POSIX but not Korn functions over aliases */ ++ while (*cp == ' ' || *cp == '\t') ++ /* ++ * this is like getsc() without skipping ++ * over Source boundaries (including not ++ * parsing ungetsc'd characters that got ++ * pushed into an SREREAD) which is what ++ * we want here anyway: find out whether ++ * the alias name is followed by a POSIX ++ * function definition (only the opening ++ * parenthesis is checked though) ++ */ ++ ++cp; ++ /* prefer functions over aliases */ ++ if (*cp == '(' /*)*/) { ++ /* ++ * delete alias upon encountering function ++ * definition ++ */ ++ tdelete(p); ++ } else { + register Source *s; + + for (s = source; s->type == SALIAS; s = s->next) +@@ -760,6 +795,7 @@ + source = s; + afree(yylval.cp, ATEMP); + goto Again; ++ } + } + } + +Index: pdksh-5.2.14/ksh.Man +=================================================================== +--- pdksh-5.2.14.orig/ksh.Man 2009-07-18 15:20:07.000000000 +0200 ++++ pdksh-5.2.14/ksh.Man 2009-07-18 15:21:11.000000000 +0200 +@@ -390,6 +390,7 @@ + .IP "\fIname\fP \fB()\fP \fIcommand\fP" + Mostly the same as \fBfunction\fP. + See Functions below. ++Whitespace (space or tab) after \fIname\fP will be ignored most of the time. + .\"}}} + .\"{{{ time [-p] [ pipeline ] + .IP "\fBtime\fP [ \fB-p\fP ] [ \fIpipeline\fP ]" +@@ -1457,6 +1458,10 @@ + so \fBgetopts\fP can be used properly both inside and outside the function + (Bourne-style functions leave \fBOPTIND\fP untouched, so using \fBgetopts\fP + inside a function interferes with using \fBgetopts\fP outside the function). ++.br ++Bourne-style function definitions take precedence over alias dereferences ++and remove alias definitions upon encounter, while aliases take precedence ++over Korn-style functions. + .nr PD \n(P2 + In the future, the following differences will also be added: + .nr P2 \n(PD diff --git a/system/pdksh/patches/050_various-man-fixes.patch b/system/pdksh/patches/050_various-man-fixes.patch new file mode 100644 index 0000000000000..8504f3eca79a7 --- /dev/null +++ b/system/pdksh/patches/050_various-man-fixes.patch @@ -0,0 +1,260 @@ +Various fixes (typos, references, etc.) to ksh(1) man page. +Index: pdksh-5.2.14/ksh.Man +=================================================================== +--- pdksh-5.2.14.orig/ksh.Man 2009-09-16 23:23:42.000000000 +0200 ++++ pdksh-5.2.14/ksh.Man 2009-09-16 23:23:46.000000000 +0200 +@@ -18,7 +18,7 @@ + .\"}}} + .\"{{{ Title + .ksh( +-.TH KSH 1 "August 19, 1996" "" "User commands" ++.TH PDKSH 1 "August 19, 1996" "" "User commands" + .ksh) + .sh( + .TH SH 1 "August 19, 1996" "" "User commands" +@@ -27,7 +27,7 @@ + .\"{{{ Name + .SH NAME + .ksh( +-ksh \- Public domain Korn shell ++pdksh \- Public domain Korn shell + .ksh) + .sh( + sh \- Public domain Bourne shell +@@ -37,12 +37,12 @@ + .SH SYNOPSIS + .ad l + .ksh( +-\fBksh\fP ++\fBpdksh\fP + .ksh) + .sh( + \fBsh\fP + .sh) +-[\fB\(+-abCefhikmnprsuvxX\fP] [\fB\(+-o\fP \fIoption\fP] [ [ \fB\-c\fP \fIcommand-string\fP [\fIcommand-name\fP] | \fB\-s\fP | \fIfile\fP ] [\fIargument\fP ...] ] ++[\fB+\-abCefhikmnprsuvxX\fP] [\fB+\-o\fP \fIoption\fP] [ [ \fB\-c\fP \fIcommand-string\fP [\fIcommand-name\fP] | \fB\-s\fP | \fIfile\fP ] [\fIargument\fP ...] ] + .ad b + .\"}}} + .\"{{{ Description +@@ -602,7 +602,7 @@ + The later form can be treated as arrays by appending an array + index of the form: \fB[\fP\fIexpr\fP\fB]\fP where \fIexpr\fP is + an arithmetic expression. +-Array indicies are currently limited to the range 0 through 1023, inclusive. ++Array indices are currently limited to the range 0 through 1023, inclusive. + Parameter substitutions take the form \fB$\fP\fIname\fP, + \fB${\fP\fIname\fP\fB}\fP or + \fB${\fP\fIname\fP\fB[\fP\fIexpr\fP\fB]}\fP, where \fIname\fP is a +@@ -640,7 +640,7 @@ + .\"{{{ environment + Parameters with the export attribute (set using the \fBexport\fP or + \fBtypeset \-x\fP commands, or by parameter assignments followed by simple +-commands) are put in the environment (see \fIenviron\fP(5)) of commands ++commands) are put in the environment (see \fIenviron\fP(7)) of commands + run by the shell as \fIname\fP\fB=\fP\fIvalue\fP pairs. + The order in which parameters appear in the environment of a command + is unspecified. +@@ -1119,12 +1119,12 @@ + like \fB[\fP..\fB]\fP, except it matches any character not inside the brackets. + .ksh( + .IP "\fB*(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP" +-matches any string of characters that matches zero or more occurances ++matches any string of characters that matches zero or more occurrences + of the specified patterns. + Example: the pattern \fB*(foo|bar)\fP matches the strings + `', `foo', `bar', `foobarfoo', \fIetc.\fP. + .IP "\fB+(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP" +-matches any string of characters that matches one or more occurances ++matches any string of characters that matches one or more occurrences + of the specified patterns. + Example: the pattern \fB+(foo|bar)\fP matches the strings + `foo', `bar', `foobarfoo', \fIetc.\fP. +@@ -1306,8 +1306,8 @@ + When used as a prefix operator, the result is the incremented value of + the parameter, when used as a postfix operator, the result is the + original value of the parameter. +-.IP "\fB++\fP" +-similar to \fB++\fP, except the paramter is decremented by 1. ++.IP "\fB--\fP" ++similar to \fB++\fP, except the parameter is decremented by 1. + .IP "\fB,\fP" + separates two arithmetic expressions; the left hand side is evaluated first, + then the right. The result is value of the expression on the right hand side. +@@ -1383,7 +1383,7 @@ + This can be avoided by redirecting the output to a numbered + file descriptor (as this also causes the shell to close its copy). + Note that this behaviour is slightly different from the original Korn shell +-which closes its copy of the write portion of the co-processs output when the ++which closes its copy of the write portion of the co-process's output when the + most recently started co-process (instead of when all sharing co-processes) + exits. + .IP \ \ \(bu +@@ -1450,7 +1450,7 @@ + the \fB$0\fP parameter is set to the name of the function + (Bourne-style functions leave \fB$0\fP untouched). + .IP \ \ \(bu +-parameter assignments preceeding function calls are not kept in ++parameter assignments preceding function calls are not kept in + the shell environment + (executing Bourne-style functions will keep assignments). + .IP \ \ \(bu +@@ -1540,6 +1540,10 @@ + For example, `\fBset \-\- `false`; echo $?\fP' prints 0 in posix mode, + 1 in non-posix mode. This construct is used in most shell scripts that + use the old \fIgetopt\fP(1) command. ++.br ++(\fBDEBIAN NOTE\fP: This is no longer true on Debian systems. For compatibility ++with ksh93, \fBset\fP command always returns exit status set to 0, regardless ++of posix or non-posix mode.) + .IP \ \ \(bu + argument expansion of \fBalias\fP, \fBexport\fP, \fBreadonly\fP, and + \fBtypeset\fP commands: in posix mode, normal argument expansion done; +@@ -1585,7 +1589,7 @@ + Just to confuse things, if the posix option is turned off (see \fBset\fP + command below) some special commands are very special in that + no field splitting, file globing, brace expansion nor tilde expansion +-is preformed on arguments that look like assignments. ++is performed on arguments that look like assignments. + Regular built-in commands are different only in that the \fBPATH\fP + parameter is not used to find them. + .PP +@@ -1644,7 +1648,7 @@ + Exit status is set to zero. + .\"}}} + .\"{{{ alias [ -d | +-t [ -r ] ] [+-px] [+-] [name1[=value1] ...] +-.IP "\fBalias\fP [ \fB\-d\fP | \fB\(+-t\fP [\fB\-r\fP] ] [\fB\(+-px\fP] [\fB\(+-\fP] [\fIname1\fP[\fB=\fP\fIvalue1\fP] ...]" ++.IP "\fBalias\fP [ \fB\-d\fP | \fB+\-t\fP [\fB\-r\fP] ] [\fB+\-px\fP] [\fB+\-\fP] [\fIname1\fP[\fB=\fP\fIvalue1\fP] ...]" + Without arguments, \fBalias\fP lists all aliases. + For any name without a value, the existing alias is listed. + Any name with a value defines an alias (see Aliases above). +@@ -1694,7 +1698,7 @@ + .IP "\fBcd\fP [\fB\-LP\fP] [\fIdir\fP]" + Set the working directory to \fIdir\fP. If the parameter \fBCDPATH\fP + is set, it lists directories to search in for \fIdir\fP. +-\fIdir\fP. An empty entry in the \fBCDPATH\fP entry means the current ++An empty entry in the \fBCDPATH\fP entry means the current + directory. + If a non-empty directory from \fBCDPATH\fP is used, the resulting full + path is printed to standard output. +@@ -1788,6 +1792,9 @@ + commands that are not built-in to the shell). + Note that the Bourne shell differs here: it does pass these + file descriptors on. ++.br ++(\fBDEBIAN NOTE\fP: when the shell is called as \fI/bin/sh\fP, it does pass ++these file descriptors on, like the Bourne shell.) + .ksh) + .sh( + Any file descriptors which are opened or \fIdup\fP(2)-ed +@@ -2008,12 +2015,12 @@ + while the original Korn shell only treats profiles as \fB.\fP scripts. + .\"}}} + .\"{{{ set [+-abCefhkmnpsuvxX] [+-o [option]] [+-A name] [--] [arg ...] +-.IP "\fBset\fP [\fB\(+-abCefhkmnpsuvxX\fP] [\fB\(+-o\fP [\fIoption\fP]] [\fB\(+-A\fP \fIname\fP] [\fB\-\-\fP] [\fIarg\fP ...]" ++.IP "\fBset\fP [\fB+\-abCefhkmnpsuvxX\fP] [\fB+\-o\fP [\fIoption\fP]] [\fB+\-A\fP \fIname\fP] [\fB\-\-\fP] [\fIarg\fP ...]" + The set command can be used to set (\fB\-\fP) or clear (\fB+\fP) shell options, + set the positional parameters, or set an array parameter. +-Options can be changed using the \fB\(+-o\fP \fIoption\fP syntax, ++Options can be changed using the \fB+\-o\fP \fIoption\fP syntax, + where \fIoption\fP is the long name of an option, or using +-the \fB\(+-\fP\fIletter\fP syntax, where \fIletter\fP is the ++the \fB+\-\fP\fIletter\fP syntax, where \fIletter\fP is the + option's single letter name (not all options have a single letter name). + The following table lists both option letters (if they exist) and long names + along with a description of what the option does. +@@ -2144,7 +2151,7 @@ + Causes the \fBcd\fP and \fBpwd\fP commands to use `physical' + (\fIi.e.\fP, the filesystem's) \fB..\fP directories instead of `logical' + directories (\fIi.e.\fP, the shell handles \fB..\fP, which allows the user +-to be obliveous of symlink links to directories). ++to be oblivious of symlink links to directories). + Clear by default. Note that setting + this option does not effect the current value of the \fBPWD\fP parameter; + only the \fBcd\fP command changes \fBPWD\fP. +@@ -2153,6 +2160,10 @@ + posix T{ + Enable posix mode. See POSIX Mode above. + T} ++ sh T{ ++This option is set only when ksh was called as a standard \fI/bin/sh\fP shell. ++(Note: This option is a Debian and OpenBSD addition). ++T} + vi T{ + Enable vi-like command line editing (interactive shells only). + T} +@@ -2419,7 +2430,7 @@ + are received. + \fBHandler\fP is either a null string, indicating the signals are to + be ignored, a minus (\fB\-\fP), indicating that the default action is to +-be taken for the signals (see signal(2 or 3)), or a string containing shell ++be taken for the signals (see signal(2)), or a string containing shell + commands to be evaluated and executed at the first opportunity (\fIi.e.\fP, + when the current command completes, or before printing the next \fBPS1\fP + prompt) after receipt of one of the signals. +@@ -2450,7 +2461,7 @@ + A command that exits with a zero value. + .\"}}} + .\"{{{ typeset [[+-Ulprtux] [-L[n]] [-R[n]] [-Z[n]] [-i[n]] | -f [-tux]] [name[=value] ...] +-.IP "\fBtypeset\fP [[\(+-Ulprtux] [\fB\-L\fP[\fIn\fP]] [\fB\-R\fP[\fIn\fP]] [\fB\-Z\fP[\fIn\fP]] [\fB\-i\fP[\fIn\fP]] | \fB\-f\fP [\fB\-tux\fP]] [\fIname\fP[\fB=\fP\fIvalue\fP] ...]" ++.IP "\fBtypeset\fP [[+\-Ulprtux] [\fB\-L\fP[\fIn\fP]] [\fB\-R\fP[\fIn\fP]] [\fB\-Z\fP[\fIn\fP]] [\fB\-i\fP[\fIn\fP]] | \fB\-f\fP [\fB\-tux\fP]] [\fIname\fP[\fB=\fP\fIvalue\fP] ...]" + Display or set parameter attributes. + With no \fIname\fP arguments, parameter attributes are displayed: if no options + arg used, the current attributes of all parameters are printed as typeset +@@ -2517,7 +2528,7 @@ + \-p T{ + Print complete typeset commands that can be used to re-create the + attributes (but not the values) of parameters. +-This is the default action (option exists for ksh93 compatability). ++This is the default action (option exists for ksh93 compatibility). + T} + \-r T{ + Readonly attribute: parameters with the this attribute may not be assigned to +@@ -2546,8 +2557,8 @@ + T} + .TE + .\"}}} +-.\"{{{ ulimit [-acdfHlmnpsStvw] [value] +-.IP "\fBulimit\fP [\fB\-acdfHlmnpsStvw\fP] [\fIvalue\fP]" ++.\"{{{ ulimit [-acdfHlmnpsStvwL] [value] ++.IP "\fBulimit\fP [\fB\-acdfHlmnpsStvwL\fP] [\fIvalue\fP]" + Display or set process limits. + If no options are used, the file size limit (\fB\-f\fP) is assumed. + \fBvalue\fP, if specified, may be either be an arithmetic expression or the +@@ -2592,6 +2603,8 @@ + not kbytes). + .IP \fB\-w\fP + Impose a limit of \fIn\fP kbytes on the amount of swap space used. ++.IP \fB\-L\fP ++Impose a limit of \fIn\fP locks that can be held on files. + .PP + As far as \fBulimit\fP is concerned, a block is 512 bytes. + .RE +@@ -3091,12 +3104,12 @@ + .\"}}} + .\"{{{ search-character-backward n ^[^] + .IP "\fBsearch-character-backward\fP \fIn\fP \fB^[^]\fP" +-Search backward in the current line for the \fIn\fPth occurance of the ++Search backward in the current line for the \fIn\fPth occurrence of the + next character typed. + .\"}}} + .\"{{{ search-character-forward n ^] + .IP "\fBsearch-character-forward\fP \fIn\fP \fB^]\fP" +-Search forward in the current line for the \fIn\fPth occurance of the ++Search forward in the current line for the \fIn\fPth occurrence of the + next character typed. + .\"}}} + .\"{{{ search-history ^R +@@ -3523,7 +3536,7 @@ + csh(1), ed(1), getconf(1), getopt(1), sed(1), stty(1), vi(1), + dup(2), execve(2), getgid(2), getuid(2), open(2), pipe(2), wait(2), + getopt(3), rand(3), signal(3), system(3), +-environ(5) ++environ(7) + .PP + .IR "The KornShell Command and Programming Language" , + Morris Bolsky and David Korn, 1989, ISBN 0-13-516972-0. +@@ -3535,3 +3548,4 @@ + .IR "IEEE Standard for information Technology \- Portable Operating System Interface (POSIX) \- Part 2: Shell and Utilities" , + IEEE Inc, 1993, ISBN 1-55937-255-9. + .\"}}} ++.\" vim:ft=nroff diff --git a/system/pdksh/patches/101_PLD-pdksh-EDITMODE.patch b/system/pdksh/patches/101_PLD-pdksh-EDITMODE.patch new file mode 100644 index 0000000000000..f40d572804f94 --- /dev/null +++ b/system/pdksh/patches/101_PLD-pdksh-EDITMODE.patch @@ -0,0 +1,92 @@ +add EDITMODE variable +(from PLD) + +Index: pdksh-5.2.14/ksh.Man +=================================================================== +--- pdksh-5.2.14.orig/ksh.Man 2009-09-16 23:24:45.000000000 +0200 ++++ pdksh-5.2.14/ksh.Man 2009-09-16 23:24:49.000000000 +0200 +@@ -791,13 +791,21 @@ + \fBselect\fP, \fBset \-o\fP and \fBkill \-l\fP commands + to format information in columns. + .\"}}} ++.\"{{{ EDITMODE ++.ksh( ++.IP \fBEDITMODE\fP ++If set, this parameter controls the command line editing mode for ++interactive shells. If the last component of the path specified in this ++parameter contains the string \fBvi\fP, \fBemacs\fP or \fBgmacs\fP, the ++vi, emacs or gmacs (Gosling emacs) editing mode is enabled, respectively. ++.\"}}} ++.ksh) + .\"{{{ EDITOR + .ksh( + .IP \fBEDITOR\fP + If the \fBVISUAL\fP parameter is not set, this parameter controls the + command line editing mode for interactive shells. +-See \fBVISUAL\fP parameter below for how this works. +-.ksh) ++See \fBEDITMODE\fP parameter above for how this works. + .\"}}} + .\"{{{ ENV + .IP \fBENV\fP +@@ -1044,7 +1052,7 @@ + .\"{{{ VISUAL + .ksh( + .IP \fBVISUAL\fP +-If set, this parameter controls the command line editing mode for ++If set, and \fBEDITMODE\fP is unset, this parameter controls the command line editing mode for + interactive shells. If the last component of the path specified in this + parameter contains the string \fBvi\fP, \fBemacs\fP or \fBgmacs\fP, the + vi, emacs or gmacs (Gosling emacs) editing mode is enabled, respectively. +Index: pdksh-5.2.14/table.h +=================================================================== +--- pdksh-5.2.14.orig/table.h 2009-09-16 23:24:45.000000000 +0200 ++++ pdksh-5.2.14/table.h 2009-09-16 23:24:49.000000000 +0200 +@@ -168,6 +168,7 @@ + #define V_TMOUT 15 + #define V_TMPDIR 16 + #define V_LINENO 17 ++#define V_EDITMODE 18 + + /* values for set_prompt() */ + #define PS1 0 /* command */ +Index: pdksh-5.2.14/var.c +=================================================================== +--- pdksh-5.2.14.orig/var.c 2009-09-16 23:24:45.000000000 +0200 ++++ pdksh-5.2.14/var.c 2009-09-16 23:24:49.000000000 +0200 +@@ -95,6 +95,7 @@ + #endif /* HISTORY */ + #ifdef EDIT + { "EDITOR", V_EDITOR }, ++ { "EDITMODE", V_EDITMODE }, + { "VISUAL", V_VISUAL }, + #endif /* EDIT */ + #ifdef KSH +@@ -111,7 +112,7 @@ + int i; + struct tbl *tp; + +- tinit(&specials, APERM, 32); /* must be 2^n (currently 17 specials) */ ++ tinit(&specials, APERM, 32); /* must be 2^n (currently 18 specials) */ + for (i = 0; names[i].name; i++) { + tp = tenter(&specials, names[i].name, hash(names[i].name)); + tp->flag = DEFINED|ISSET; +@@ -1017,11 +1018,15 @@ + #endif /* HISTORY */ + #ifdef EDIT + case V_VISUAL: +- set_editmode(str_val(vp)); ++ if (!(global("EDITMODE")->flag & ISSET)) ++ set_editmode(str_val(vp)); + break; + case V_EDITOR: +- if (!(global("VISUAL")->flag & ISSET)) +- set_editmode(str_val(vp)); ++ if (!(global("EDITMODE")->flag & ISSET)) ++ if(!(global("VISUAL")->flag & ISSET)) ++ set_editmode(str_val(vp)); ++ case V_EDITMODE: ++ set_editmode(str_val(vp)); + break; + case V_COLUMNS: + if ((x_cols = intval(vp)) <= MIN_COLS) diff --git a/system/pdksh/patches/102_PLD-pdksh-ulimit-vmem.patch b/system/pdksh/patches/102_PLD-pdksh-ulimit-vmem.patch new file mode 100644 index 0000000000000..483226c7a3d6e --- /dev/null +++ b/system/pdksh/patches/102_PLD-pdksh-ulimit-vmem.patch @@ -0,0 +1,18 @@ +support for `ulimit -v' +(from PLD) + +Index: pdksh-5.2.14/c_ulimit.c +=================================================================== +--- pdksh-5.2.14.orig/c_ulimit.c 2008-04-15 20:50:48.000000000 +0200 ++++ pdksh-5.2.14/c_ulimit.c 2008-04-15 20:55:52.000000000 +0200 +@@ -38,6 +38,10 @@ + # define KSH_RLIM_INFINITY ((rlim_t) 1 << (sizeof(rlim_t) * 8 - 1) - 1) + #endif /* RLIM_INFINITY */ + ++#if !defined(RLIMIT_VMEM) && defined(RLIMIT_AS) ++# define RLIMIT_VMEM RLIMIT_AS ++#endif ++ + int + c_ulimit(wp) + char **wp; diff --git a/system/pdksh/patches/103_PLD-pdksh-unset.patch b/system/pdksh/patches/103_PLD-pdksh-unset.patch new file mode 100644 index 0000000000000..9f17b9409b6da --- /dev/null +++ b/system/pdksh/patches/103_PLD-pdksh-unset.patch @@ -0,0 +1,26 @@ +unset on unknown variable is not an error, +see http://www.opengroup.org/onlinepubs/009695399/utilities/unset.html +(from PLD) + +Index: pdksh-5.2.14/c_sh.c +=================================================================== +--- pdksh-5.2.14.orig/c_sh.c 2008-04-15 20:51:18.000000000 +0200 ++++ pdksh-5.2.14/c_sh.c 2008-04-15 20:56:22.000000000 +0200 +@@ -688,16 +688,13 @@ + if (unset_var) { /* unset variable */ + struct tbl *vp = global(id); + +- if (!(vp->flag & ISSET)) +- ret = 1; + if ((vp->flag&RDONLY)) { + bi_errorf("%s is read only", vp->name); + return 1; + } + unset(vp, strchr(id, '[') ? 1 : 0); + } else { /* unset function */ +- if (define(id, (struct op *) NULL)) +- ret = 1; ++ define(id, (struct op *) NULL); + } + return ret; + } diff --git a/system/pdksh/patches/104_Debian-#415167-lack-of-dot-arguments.patch b/system/pdksh/patches/104_Debian-#415167-lack-of-dot-arguments.patch new file mode 100644 index 0000000000000..ee3eca2ff0081 --- /dev/null +++ b/system/pdksh/patches/104_Debian-#415167-lack-of-dot-arguments.patch @@ -0,0 +1,22 @@ +unset on unknown variable is not an error, +see http://www.opengroup.org/onlinepubs/009695399/utilities/unset.html +(from PLD) + +@DPATCH@ +Index: pdksh-5.2.14/c_sh.c +=================================================================== +--- pdksh-5.2.14.orig/c_sh.c 2008-04-15 20:56:22.000000000 +0200 ++++ pdksh-5.2.14/c_sh.c 2008-04-15 20:56:53.000000000 +0200 +@@ -183,8 +183,10 @@ + if (ksh_getopt(wp, &builtin_opt, null) == '?') + return 1; + +- if ((cp = wp[builtin_opt.optind]) == NULL) +- return 0; ++ if ((cp = wp[builtin_opt.optind]) == NULL) { ++ bi_errorf("missing argument"); ++ return 1; ++ } + file = search(cp, path, R_OK, &err); + if (file == NULL) { + bi_errorf("%s: %s", cp, err ? strerror(err) : "not found"); diff --git a/system/pdksh/patches/105_OpenBSD-heredoc-quote.patch b/system/pdksh/patches/105_OpenBSD-heredoc-quote.patch new file mode 100644 index 0000000000000..1cb8577437eec --- /dev/null +++ b/system/pdksh/patches/105_OpenBSD-heredoc-quote.patch @@ -0,0 +1,53 @@ +Fix for `Bug#219343 backslash is swallowed in HERE document' from OpenBSD: + * exec.c (1.42), lex.c (1.37), lex.h (1.10): Fix " handling in here + documents. POSIX says they are not special, so cat << EOF \" EOF + should print \" Fixes PR 4472; testing jmc@ and Adam Montague. ok +(from OpenBSD) + +Index: pdksh-5.2.14/exec.c +=================================================================== +--- pdksh-5.2.14.orig/exec.c 2009-09-17 00:32:31.000000000 +0200 ++++ pdksh-5.2.14/exec.c 2009-09-17 00:32:59.000000000 +0200 +@@ -1480,7 +1480,7 @@ + s = pushs(SSTRING, ATEMP); + s->start = s->str = content; + source = s; +- if (yylex(ONEWORD) != LWORD) ++ if (yylex(ONEWORD|HEREDOC) != LWORD) + internal_errorf(1, "herein: yylex"); + source = osource; + shf_puts(evalstr(yylval.cp, 0), shf); +Index: pdksh-5.2.14/lex.c +=================================================================== +--- pdksh-5.2.14.orig/lex.c 2009-09-17 00:32:52.000000000 +0200 ++++ pdksh-5.2.14/lex.c 2009-09-17 00:32:59.000000000 +0200 +@@ -240,10 +240,16 @@ + case '\\': + c = getsc(); + switch (c) { +- case '"': case '\\': ++ case '\\': + case '$': case '`': + *wp++ = QCHAR, *wp++ = c; + break; ++ case '"': ++ if ((cf & HEREDOC) == 0) { ++ *wp++ = QCHAR, *wp++ = c; ++ break; ++ } ++ /* FALLTROUGH */ + default: + Xcheck(ws, wp); + if (c) { /* trailing \ is lost */ +Index: pdksh-5.2.14/lex.h +=================================================================== +--- pdksh-5.2.14.orig/lex.h 2009-09-17 00:31:55.000000000 +0200 ++++ pdksh-5.2.14/lex.h 2009-09-17 00:32:59.000000000 +0200 +@@ -113,6 +113,7 @@ + #define ESACONLY BIT(7) /* only accept esac keyword */ + #define CMDWORD BIT(8) /* parsing simple command (alias related) */ + #define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */ ++#define HEREDOC BIT(10) /* parsing heredoc */ + + #define HERES 10 /* max << in line */ + diff --git a/system/pdksh/patches/106_Debian-man-hyphens.patch b/system/pdksh/patches/106_Debian-man-hyphens.patch new file mode 100644 index 0000000000000..f541719fc9608 --- /dev/null +++ b/system/pdksh/patches/106_Debian-man-hyphens.patch @@ -0,0 +1,59 @@ +Quote '-' chars in man page to make lintian happy. +Index: pdksh-5.2.14/ksh.Man +=================================================================== +--- pdksh-5.2.14.orig/ksh.Man 2009-07-18 15:18:29.000000000 +0200 ++++ pdksh-5.2.14/ksh.Man 2009-07-18 15:18:30.000000000 +0200 +@@ -445,7 +445,7 @@ + the \fB&&\fP and \fB||\fP operators. + This means that in the statement + .ce +-\fB[[ -r foo && $(< foo) = b*r ]]\fP ++\fB[[ \-r foo && $(< foo) = b*r ]]\fP + the \fB$(< foo)\fP is evaluated if and only if the file \fBfoo\fP exists + and is readable. + .nr PD \n(P2 +@@ -2092,7 +2092,7 @@ + See Shell Startup above for a description of what this + means. + T} +--r restricted T{ ++\-r restricted T{ + Enable restricted mode \(em this option can only be used when the shell is + invoked. See Shell Startup above for a description of what this + means. +@@ -2198,7 +2198,7 @@ + These options can also be used upon invocation of the shell. The current + set of options (with single letter names) can be found in the + parameter \fB\-\fP. +-\fBset -o\fP with no option name will list all the options and whether each ++\fBset \-o\fP with no option name will list all the options and whether each + is on or off; \fBset +o\fP will print the long names of all options that + are currently on. + .sp +@@ -2303,7 +2303,7 @@ + As a non-standard extension, if the option starts with a \fB!\fP, the test + is negated; the test always fails if option doesn't exist (thus + .RS +-\fB[ -o \fP\fIfoo\fP \fB-o -o !\fP\fIfoo\fP \fB]\fP ++\fB[ \-o \fP\fIfoo\fP \fB\-o \-o !\fP\fIfoo\fP \fB]\fP + .RE + returns true if and only if option \fIfoo\fP exists). + T} +@@ -2380,7 +2380,7 @@ + (where \fIn\fP is a file descriptor number), + the \fBtest\fP command will attempt to fake it for all tests that + operate on files (except the \fB-e\fP test). +-I.e., \fB[ -w /dev/fd/2 ]\fP tests if file descriptor 2 is writable. ++I.e., \fB[ \-w /dev/fd/2 ]\fP tests if file descriptor 2 is writable. + .sp + Note that some special rules are applied (courtesy of POSIX) if the + number of arguments to \fBtest\fP or \fB[\fP \&... \fB]\fP is less than +@@ -2410,7 +2410,7 @@ + .nf + 0.00s real 0.00s user 0.00s system + .fi +-unless the -p option is given (only possible if \fIpipeline\fP is a simple ++unless the \-p option is given (only possible if \fIpipeline\fP is a simple + command), in which case the output is slightly longer: + .nf + real 0.00 diff --git a/system/pdksh/patches/107_Debian-gcc-warnings2.patch b/system/pdksh/patches/107_Debian-gcc-warnings2.patch new file mode 100644 index 0000000000000..ea46ecb162e6b --- /dev/null +++ b/system/pdksh/patches/107_Debian-gcc-warnings2.patch @@ -0,0 +1,23 @@ +Fix gcc warnings. +Index: pdksh-5.2.14/eval.c +=================================================================== +--- pdksh-5.2.14.orig/eval.c 2008-04-15 21:11:04.000000000 +0200 ++++ pdksh-5.2.14/eval.c 2008-04-15 21:15:24.000000000 +0200 +@@ -201,6 +201,8 @@ + word = (f&DOBLANK) ? IFS_WS : IFS_WORD; + st_head.next = (SubType *) 0; + st = &st_head; ++ x.split = 0; ++ x.str = NULL; + + while (1) { + Xcheck(ds, dp); +@@ -280,7 +282,7 @@ + { + char *varname = ++sp; /* skip the { or x (}) */ + int stype; +- int slen; ++ int slen = 0; + + sp = strchr(sp, '\0') + 1; /* skip variable */ + type = varsub(&x, varname, sp, &stype, &slen); diff --git a/system/pdksh/patches/108_Debian-sysconf_retval_check.patch b/system/pdksh/patches/108_Debian-sysconf_retval_check.patch new file mode 100644 index 0000000000000..c0a710a90a9ce --- /dev/null +++ b/system/pdksh/patches/108_Debian-sysconf_retval_check.patch @@ -0,0 +1,41 @@ +Fix `internal error: j_async: bad nzombie (0)' that occured with `sudo pdksh -c "sleep 10&"' + +Sudo sets RLIMIT_NPROC to unlimited, and sysconf returns that value as -1. +Index: pdksh-5.2.14/jobs.c +=================================================================== +--- pdksh-5.2.14.orig/jobs.c 2008-05-26 21:46:41.000000000 +0200 ++++ pdksh-5.2.14/jobs.c 2008-05-26 21:56:12.000000000 +0200 +@@ -174,9 +174,9 @@ + static Job *async_job; + static pid_t async_pid; + +-static int nzombie; /* # of zombies owned by this process */ ++static long nzombie; /* # of zombies owned by this process */ + static INT32 njobs; /* # of jobs started */ +-static int child_max; /* CHILD_MAX */ ++static long child_max; /* CHILD_MAX */ + + + #ifdef JOB_SIGS +@@ -227,6 +227,12 @@ + int mflagset; + { + child_max = CHILD_MAX; /* so syscon() isn't always being called */ ++#if defined(HAVE_SYSCONF) && defined(_SC_CHILD_MAX) ++ if (child_max < 0) { ++ child_max = LONG_MAX; ++ } ++#endif ++ + + #ifdef JOB_SIGS + sigemptyset(&sm_default); +@@ -1131,7 +1137,7 @@ + if (!oldest) { + /* XXX debugging */ + if (!(async_job->flags & JF_ZOMBIE) || nzombie != 1) { +- internal_errorf(0, "j_async: bad nzombie (%d)", nzombie); ++ internal_errorf(0, "j_async: bad nzombie (%ld)", nzombie); + nzombie = 0; + } + break; diff --git a/system/pdksh/patches/109_mksh-delete_key.patch b/system/pdksh/patches/109_mksh-delete_key.patch new file mode 100644 index 0000000000000..b0617581149c4 --- /dev/null +++ b/system/pdksh/patches/109_mksh-delete_key.patch @@ -0,0 +1,115 @@ +Patch from mksh to make delete key work (closes: #190566) +Index: pdksh-5.2.14/emacs.c +=================================================================== +--- pdksh-5.2.14.orig/emacs.c 2009-09-15 20:59:29.000000000 +0200 ++++ pdksh-5.2.14/emacs.c 2009-09-15 21:06:50.000000000 +0200 +@@ -327,6 +327,26 @@ + { XFUNC_next_com, 2, 'B' }, + { XFUNC_mv_forw, 2, 'C' }, + { XFUNC_mv_back, 2, 'D' }, ++ /* These for ansi arrow keys: arguablely shouldn't be here by ++ * default, but its simpler/faster/smaller than using termcap ++ * entries. ++ */ ++ { XFUNC_meta2, 1, '[' }, ++ { XFUNC_meta2, 1, 'O' }, ++ { XFUNC_prev_com, 2, 'A' }, ++ { XFUNC_next_com, 2, 'B' }, ++ { XFUNC_mv_forw, 2, 'C' }, ++ { XFUNC_mv_back, 2, 'D' }, ++ { XFUNC_mv_begin | 0x80, 2, '1' }, ++ { XFUNC_mv_begin | 0x80, 2, '7' }, ++ { XFUNC_mv_begin, 2, 'H' }, ++ { XFUNC_mv_end | 0x80, 2, '4' }, ++ { XFUNC_mv_end | 0x80, 2, '8' }, ++ { XFUNC_mv_end, 2, 'F' }, ++ { XFUNC_del_char | 0x80, 2, '3' }, ++ { XFUNC_prev_com | 0x80, 2, '5' }, ++ { XFUNC_next_com | 0x80, 2, '6' }, ++ + }; + + int +@@ -371,7 +391,14 @@ + return 0; + + f = x_curprefix == -1 ? XFUNC_insert +- : x_tab[x_curprefix][c&CHARMASK]; ++ : x_tab[x_curprefix][c&CHARMASK] ; ++ ++ if (f & 0x80) { ++ f &= 0x7F; ++ if ((i = x_e_getc()) != '~') ++ x_e_ungetc(i); ++ } ++ + + if (!(x_ftab[f].xf_flags & XF_PREFIX) + && x_last_command != XFUNC_set_arg) +@@ -1385,6 +1412,7 @@ + x_print(prefix, key) + int prefix, key; + { ++ int f = x_tab[prefix][key]; + if (prefix == 1) + shprintf("%s", x_mapout(x_prefix1)); + if (prefix == 2) +@@ -1393,9 +1421,9 @@ + if (prefix == 3) + shprintf("%s", x_mapout(x_prefix3)); + #endif /* OS2 */ +- shprintf("%s = ", x_mapout(key)); +- if (x_tab[prefix][key] != XFUNC_ins_string) +- shprintf("%s\n", x_ftab[x_tab[prefix][key]].xf_name); ++ shprintf("%s%s = ", x_mapout(key), (f & 0x80) ? "~" : ""); ++ if ((f & 0x7F) != XFUNC_ins_string) ++ shprintf("%s\n", x_ftab[f & 0x7F].xf_name); + else + shprintf("'%s'\n", x_atab[prefix][key]); + } +@@ -1410,6 +1438,7 @@ + int prefix, key; + char *sp = NULL; + char *m1, *m2; ++ char hastilde; + + if (x_tab == NULL) { + bi_errorf("cannot bind, not a tty"); +@@ -1437,7 +1466,7 @@ + return 0; + } + +- m1 = x_mapin(a1); ++ m2 = m1 = x_mapin(a1); + prefix = key = 0; + for (;; m1++) { + key = *m1 & CHARMASK; +@@ -1453,6 +1482,19 @@ + break; + } + ++ if (*++m1 && ((*m1 != '~') || *(m1+1))) { ++ char msg[256] = "key sequence '"; ++ const char *c = a1; ++ m1 = msg + strlen(msg); ++ while (*c && m1 < (msg + sizeof(msg) - 3)) ++ strcat(msg, x_mapout(*c++)); ++ bi_errorf("%s' too long", msg); ++ return (1); ++ } ++ ++ hastilde = *m1; ++ afree(m2, ATEMP); ++ + if (a2 == NULL) { + x_print(prefix, key); + return 0; +@@ -1483,7 +1525,7 @@ + + if (x_tab[prefix][key] == XFUNC_ins_string && x_atab[prefix][key]) + afree((void *)x_atab[prefix][key], AEDIT); +- x_tab[prefix][key] = f; ++ x_tab[prefix][key] = f | (hastilde ? 0x80 : 0); + x_atab[prefix][key] = sp; + + /* Track what the user has bound so x_emacs_keys() won't toast things */ diff --git a/system/pdksh/patches/110_Debian-exit-negative-number.patch b/system/pdksh/patches/110_Debian-exit-negative-number.patch new file mode 100644 index 0000000000000..d7af113275f30 --- /dev/null +++ b/system/pdksh/patches/110_Debian-exit-negative-number.patch @@ -0,0 +1,46 @@ +Fix problem with `exit -1' giving `ksh: exit: -1: unknown option' (see bug#502934) + +Index: pdksh-5.2.14/c_sh.c +=================================================================== +--- pdksh-5.2.14.orig/c_sh.c 2009-09-19 11:38:39.000000000 +0200 ++++ pdksh-5.2.14/c_sh.c 2009-09-19 11:39:33.000000000 +0200 +@@ -534,9 +534,14 @@ + int n; + char *arg; + +- if (ksh_getopt(wp, &builtin_opt, null) == '?') +- return 1; +- arg = wp[builtin_opt.optind]; ++ if (!Flag(FPOSIX) // not posix ++ && *wp && *(wp + 1) && !*(wp + 2)) // only one argument passed ++ arg=*(wp + 1); // code regardless of starting with '-' or not ++ else { ++ if (ksh_getopt(wp, &builtin_opt, null) == '?') ++ return 1; ++ arg = wp[builtin_opt.optind]; ++ } + + if (arg) { + if (!getn(arg, &n)) { +Index: pdksh-5.2.14/tests/debian-110.t +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ pdksh-5.2.14/tests/debian-110.t 2009-09-19 11:41:59.000000000 +0200 +@@ -0,0 +1,17 @@ ++name: debian-110-1 ++description: ++ Check if exit -1 is allowed for ! posix ++stdin: ++ (set +o posix; exit -1); echo A $? ++expected-stdout: ++ A 255 ++--- ++name: debian-110-2 ++description: ++ Check if exit -1 is not allowed for posix ++stdin: ++ (set -o posix; exit -1); echo A $? ++expected-stdout: ++ A 1 ++expected-fail: yes ++--- diff --git a/system/pdksh/patches/111_mksh-set-e.patch b/system/pdksh/patches/111_mksh-set-e.patch new file mode 100644 index 0000000000000..ca6f42b18f25e --- /dev/null +++ b/system/pdksh/patches/111_mksh-set-e.patch @@ -0,0 +1,422 @@ +Fix `set -e' handling from mksh (see bugs #71256, #546332, closes: #387755). +Index: pdksh-5.2.14/exec.c +=================================================================== +--- pdksh-5.2.14.orig/exec.c 2009-09-19 11:54:58.000000000 +0200 ++++ pdksh-5.2.14/exec.c 2009-09-19 11:55:01.000000000 +0200 +@@ -15,7 +15,7 @@ + #endif /* KSH */ + + static int comexec ARGS((struct op *t, struct tbl *volatile tp, char **ap, +- int volatile flags)); ++ int volatile flags, volatile int * volatile xerrok)); + static void scriptexec ARGS((struct op *tp, char **ap)); + static int call_builtin ARGS((struct tbl *tp, char **wp)); + static int iosetup ARGS((struct ioword *iop, struct tbl *tp)); +@@ -70,12 +70,13 @@ + * execute command tree + */ + int +-execute(t, flags) ++execute(t, flags, xerrok) + struct op * volatile t; + volatile int flags; /* if XEXEC don't fork */ ++ volatile int * volatile xerrok; + { + int i; +- volatile int rv = 0; ++ volatile int rv = 0, dummy = 0; + int pv[2]; + char ** volatile ap; + char *s, *cp; +@@ -85,6 +86,10 @@ + if (t == NULL) + return 0; + ++ /* Caller doesn't care if XERROK should propagate. */ ++ if (xerrok == NULL) ++ xerrok = &dummy; ++ + /* Is this the end of a pipeline? If so, we want to evaluate the + * command arguments + bool_t eval_done = FALSE; +@@ -94,7 +99,7 @@ + } + */ + if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE) +- return exchild(t, flags & ~XTIME, -1); /* run in sub-process */ ++ return exchild(t, flags & ~XTIME, xerrok, -1); /* run in sub-process */ + + newenv(E_EXEC); + if (trap) +@@ -152,11 +157,11 @@ + + switch(t->type) { + case TCOM: +- rv = comexec(t, tp, ap, flags); ++ rv = comexec(t, tp, ap, flags, xerrok); + break; + + case TPAREN: +- rv = execute(t->left, flags|XFORK); ++ rv = execute(t->left, flags|XFORK, xerrok); + break; + + case TPIPE: +@@ -173,7 +178,7 @@ + * (: ; cat /etc/termcap) | sleep 1 + * will hang forever). + */ +- exchild(t->left, flags|XPIPEO|XCCLOSE, pv[0]); ++ exchild(t->left, flags|XPIPEO|XCCLOSE, NULL, pv[0]); + (void) ksh_dup2(pv[0], 0, FALSE); /* stdin of next */ + closepipe(pv); + flags |= XPIPEI; +@@ -182,17 +187,17 @@ + restfd(1, e->savefd[1]); /* stdout of last */ + e->savefd[1] = 0; /* no need to re-restore this */ + /* Let exchild() close 0 in parent, after fork, before wait */ +- i = exchild(t, flags|XPCLOSE, 0); ++ i = exchild(t, flags|XPCLOSE, xerrok, 0); + if (!(flags&XBGND) && !(flags&XXCOM)) + rv = i; + break; + + case TLIST: + while (t->type == TLIST) { +- execute(t->left, flags & XERROK); ++ execute(t->left, flags & XERROK, NULL); + t = t->right; + } +- rv = execute(t, flags & XERROK); ++ rv = execute(t, flags & XERROK, xerrok); + break; + + #ifdef KSH +@@ -257,7 +262,7 @@ + */ + flags &= ~XEXEC; + exchild(t->left, flags|XBGND|XFORK|XCOPROC|XCCLOSE, +- coproc.readw); ++ NULL, coproc.readw); + break; + } + #endif /* KSH */ +@@ -267,20 +272,24 @@ + * forks again for async... parent should optimize + * this to "foo &"... + */ +- rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK); ++ rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK, xerrok); + break; + + case TOR: + case TAND: +- rv = execute(t->left, XERROK); +- if (t->right != NULL && (rv == 0) == (t->type == TAND)) +- rv = execute(t->right, flags & XERROK); +- else +- flags |= XERROK; ++ rv = execute(t->left, XERROK, xerrok); ++ if ((rv == 0) == (t->type == TAND)) ++ rv = execute(t->right, XERROK, xerrok); ++ flags |= XERROK; ++ if (xerrok) ++ *xerrok = 1; + break; + + case TBANG: +- rv = !execute(t->right, XERROK); ++ rv = !execute(t->right, XERROK, xerrok); ++ flags |= XERROK; ++ if (xerrok) ++ *xerrok = 1; + break; + + #ifdef KSH +@@ -328,7 +337,7 @@ + if (t->type == TFOR) { + while (*ap != NULL) { + setstr(global(t->str), *ap++, KSH_UNWIND_ERROR); +- rv = execute(t->left, flags & XERROK); ++ rv = execute(t->left, flags & XERROK, xerrok); + } + } + #ifdef KSH +@@ -340,7 +349,7 @@ + } + is_first = FALSE; + setstr(global(t->str), cp, KSH_UNWIND_ERROR); +- rv = execute(t->left, flags & XERROK); ++ rv = execute(t->left, flags & XERROK, xerrok); + } + } + } +@@ -365,17 +374,17 @@ + } + } + rv = 0; /* in case of a continue */ +- while ((execute(t->left, XERROK) == 0) == (t->type == TWHILE)) +- rv = execute(t->right, flags & XERROK); ++ while ((execute(t->left, XERROK, NULL) == 0) == (t->type == TWHILE)) ++ rv = execute(t->right, flags & XERROK, xerrok); + break; + + case TIF: + case TELIF: + if (t->right == NULL) + break; /* should be error */ +- rv = execute(t->left, XERROK) == 0 ? +- execute(t->right->left, flags & XERROK) : +- execute(t->right->right, flags & XERROK); ++ rv = execute(t->left, XERROK, NULL) == 0 ? ++ execute(t->right->left, flags & XERROK, xerrok) : ++ execute(t->right->right, flags & XERROK, xerrok); + break; + + case TCASE: +@@ -387,11 +396,11 @@ + goto Found; + break; + Found: +- rv = execute(t->left, flags & XERROK); ++ rv = execute(t->left, flags & XERROK, xerrok); + break; + + case TBRACE: +- rv = execute(t->left, flags & XERROK); ++ rv = execute(t->left, flags & XERROK, xerrok); + break; + + case TFUNCT: +@@ -402,7 +411,7 @@ + /* Clear XEXEC so nested execute() call doesn't exit + * (allows "ls -l | time grep foo"). + */ +- rv = timex(t, flags & ~XEXEC); ++ rv = timex(t, flags & ~XEXEC, xerrok); + break; + + case TEXEC: /* an eval'd TCOM */ +@@ -430,7 +439,8 @@ + quitenv(); /* restores IO */ + if ((flags&XEXEC)) + unwind(LEXIT); /* exit child */ +- if (rv != 0 && !(flags & XERROK)) { ++ if (rv != 0 && !(flags & XERROK) ++ && (xerrok == NULL || !*xerrok)) { + if (Flag(FERREXIT)) + unwind(LERROR); + trapsig(SIGERR_); +@@ -443,11 +453,12 @@ + */ + + static int +-comexec(t, tp, ap, flags) ++comexec(t, tp, ap, flags, xerrok) + struct op *t; + struct tbl *volatile tp; + register char **ap; + int volatile flags; ++ volatile int * volatile xerrok; + { + int i; + volatile int rv = 0; +@@ -660,7 +671,7 @@ + i = ksh_sigsetjmp(e->jbuf, 0); + if (i == 0) { + /* seems odd to pass XERROK here, but at&t ksh does */ +- exstat = execute(tp->val.t, flags & XERROK); ++ exstat = execute(tp->val.t, flags & XERROK, xerrok); + i = LRETURN; + } + kshname = old_kshname; +@@ -737,7 +748,7 @@ + texec.left = t; /* for tprint */ + texec.str = tp->val.s; + texec.args = ap; +- rv = exchild(&texec, flags, -1); ++ rv = exchild(&texec, flags, xerrok, -1); + break; + } + Leave: +Index: pdksh-5.2.14/c_sh.c +=================================================================== +--- pdksh-5.2.14.orig/c_sh.c 2009-09-19 11:54:58.000000000 +0200 ++++ pdksh-5.2.14/c_sh.c 2009-09-19 11:55:01.000000000 +0200 +@@ -725,9 +725,10 @@ + * time pipeline (really a statement, not a built-in command) + */ + int +-timex(t, f) ++timex(t, f, xerrok) + struct op *t; + int f; ++ volatile int * xerrok; + { + #define TF_NOARGS BIT(0) + #define TF_NOREAL BIT(1) /* don't report real time */ +@@ -753,7 +754,7 @@ + if (t->left->type == TCOM) + t->left->str = opts; + opts[0] = 0; +- rv = execute(t->left, f | XTIME); ++ rv = execute(t->left, f | XTIME, xerrok); + tf |= opts[0]; + t1t = ksh_times(&t1); + } else +Index: pdksh-5.2.14/eval.c +=================================================================== +--- pdksh-5.2.14.orig/eval.c 2009-09-19 11:54:58.000000000 +0200 ++++ pdksh-5.2.14/eval.c 2009-09-19 11:55:01.000000000 +0200 +@@ -877,7 +877,7 @@ + close(pv[1]); + } + +- execute(t, XFORK|XXCOM|XPIPEO); ++ execute(t, XFORK|XXCOM|XPIPEO, NULL); + restfd(1, ofd1); + startlast(); + xp->split = 1; /* waitlast() */ +Index: pdksh-5.2.14/jobs.c +=================================================================== +--- pdksh-5.2.14.orig/jobs.c 2009-09-19 11:54:58.000000000 +0200 ++++ pdksh-5.2.14/jobs.c 2009-09-19 11:55:01.000000000 +0200 +@@ -443,9 +443,10 @@ + + /* execute tree in child subprocess */ + int +-exchild(t, flags, close_fd) ++exchild(t, flags, xerrok, close_fd) + struct op *t; + int flags; ++ volatile int *xerrok; + int close_fd; /* used if XPCLOSE or XCCLOSE */ + { + static Proc *last_proc; /* for pipelines */ +@@ -464,7 +465,7 @@ + /* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND + * (also done in another execute() below) + */ +- return execute(t, flags & (XEXEC | XERROK)); ++ return execute(t, flags & (XEXEC | XERROK), xerrok); + + #ifdef JOB_SIGS + /* no SIGCHLD's while messing with job and process lists */ +@@ -659,7 +660,7 @@ + #endif /* OS2 */ + tty_close(); + cleartraps(); +- execute(t, (flags & XERROK) | XEXEC); /* no return */ ++ execute(t, (flags & XERROK) | XEXEC, xerrok); /* no return */ + internal_errorf(0, "exchild: execute() returned"); + unwind(LLEAVE); + /* NOTREACHED */ +Index: pdksh-5.2.14/main.c +=================================================================== +--- pdksh-5.2.14.orig/main.c 2009-09-19 11:54:58.000000000 +0200 ++++ pdksh-5.2.14/main.c 2009-09-19 11:55:01.000000000 +0200 +@@ -634,7 +634,7 @@ + } + + if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY))) +- exstat = execute(t, 0); ++ exstat = execute(t, 0, NULL); + + if (t != NULL && t->type != TEOF && interactive && really_exit) + really_exit = 0; +Index: pdksh-5.2.14/proto.h +=================================================================== +--- pdksh-5.2.14.orig/proto.h 2009-09-19 11:54:58.000000000 +0200 ++++ pdksh-5.2.14/proto.h 2009-09-19 11:55:01.000000000 +0200 +@@ -42,7 +42,7 @@ + int c_unset ARGS((char **wp)); + int c_ulimit ARGS((char **wp)); + int c_times ARGS((char **wp)); +-int timex ARGS((struct op *t, int f)); ++int timex ARGS((struct op *t, int f, volatile int *xerrok)); + void timex_hook ARGS((struct op *t, char ** volatile *app)); + int c_exec ARGS((char **wp)); + int c_builtin ARGS((char **wp)); +@@ -65,7 +65,7 @@ + int glob_str ARGS((char *cp, XPtrV *wp, int markdirs)); + /* exec.c */ + int fd_clexec ARGS((int fd)); +-int execute ARGS((struct op * volatile t, volatile int flags)); ++int execute ARGS((struct op * volatile t, volatile int flags, volatile int * volatile xerrok)); + int shcomexec ARGS((char **wp)); + struct tbl * findfunc ARGS((const char *name, unsigned int h, int create)); + int define ARGS((const char *name, struct op *t)); +@@ -138,7 +138,7 @@ + void j_init ARGS((int mflagset)); + void j_exit ARGS((void)); + void j_change ARGS((void)); +-int exchild ARGS((struct op *t, int flags, int close_fd)); ++int exchild ARGS((struct op *t, int flags, volatile int * xerrok, int close_fd)); + void startlast ARGS((void)); + int waitlast ARGS((void)); + int waitfor ARGS((const char *cp, int *sigp)); +Index: pdksh-5.2.14/tests/debian-111.t +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ pdksh-5.2.14/tests/debian-111.t 2009-09-19 12:02:51.000000000 +0200 +@@ -0,0 +1,60 @@ ++name: debian-111-1 ++description: ++ Check set -e regression ++stdin: ++ set -e; true; false && true; echo OK ++expected-stdout: ++ OK ++--- ++name: debian-111-2 ++description: ++ Regression for #387755 ++stdin: ++ set -e ++ ! true ++ ! false ++ echo OK ++expected-stdout: ++ OK ++--- ++name: debian-111-3 ++description: ++ Regression for #387755 ++stdin: ++ set -e; (false); echo here ++expected-stdout: ++expected-fail: yes ++--- ++name: debian-111-4 ++description: ++ Regression for #387755 ++stdin: ++ set +e; (false); echo here ++expected-stdout: ++ here ++--- ++name: debian-111-5 ++description: ++ Regression for #71256 ++stdin: ++ set -e ++ if true; then ++ false && echo something ++ fi ++ echo OK ++expected-stdout: ++ OK ++--- ++name: debian-111-6 ++description: ++ Regression for #71256 ++stdin: ++ set +e ++ if true; then ++ false && echo something ++ fi ++ echo OK ++expected-stdout: ++ OK ++--- ++ diff --git a/system/pdksh/patches/112_OpenBSD-test.patch b/system/pdksh/patches/112_OpenBSD-test.patch new file mode 100644 index 0000000000000..7058a2dac8416 --- /dev/null +++ b/system/pdksh/patches/112_OpenBSD-test.patch @@ -0,0 +1,58 @@ +From OpenBSD: + +2009-03-01 21:11 otto + + * c_test.c (1.18): Fix PR #723: test(1) operator precedence + inconsistent with POSIX Make sure ksh builtin test and test(1) do + not differ. From Christiano Farina Haesbaert. ok miod@ + + +Index: pdksh-5.2.14/c_test.c +=================================================================== +--- pdksh-5.2.14.orig/c_test.c 2009-09-19 11:22:39.000000000 +0200 ++++ pdksh-5.2.14/c_test.c 2009-09-19 12:03:25.000000000 +0200 +@@ -551,15 +551,23 @@ + } + return res; + } +- if ((op = (Test_op) (*te->isa)(te, TM_UNOP))) { +- /* unary expression */ +- opnd1 = (*te->getopnd)(te, op, do_eval); +- if (!opnd1) { +- (*te->error)(te, -1, "missing argument"); +- return 0; +- } ++ /* ++ * Binary should have precedence over unary in this case ++ * so that something like test \( -f = -f \) is accepted ++ */ ++ if ((te->flags & TEF_DBRACKET) || (&te->pos.wp[1] < te->wp_end && ++ !test_isop(te, TM_BINOP, te->pos.wp[1]))) { ++ if ((op = (Test_op) (*te->isa)(te, TM_UNOP))) { ++ /* unary expression */ ++ opnd1 = (*te->getopnd)(te, op, do_eval); ++ if (!opnd1) { ++ (*te->error)(te, -1, "missing argument"); ++ return 0; ++ } + +- return (*te->eval)(te, op, opnd1, (const char *) 0, do_eval); ++ return (*te->eval)(te, op, opnd1, (const char *) 0, ++ do_eval); ++ } + } + opnd1 = (*te->getopnd)(te, TO_NONOP, do_eval); + if (!opnd1) { +Index: pdksh-5.2.14/tests/debian-112.t +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ pdksh-5.2.14/tests/debian-112.t 2009-09-19 12:06:33.000000000 +0200 +@@ -0,0 +1,8 @@ ++name: debian-112-1 ++description: ++ Check test operator precedence ++stdin: ++ test \( -f = -f \) && echo OK ++expected-stdout: ++ OK ++--- diff --git a/system/pdksh/patches/113_OpenBSD-memory.patch b/system/pdksh/patches/113_OpenBSD-memory.patch new file mode 100644 index 0000000000000..79e7b59833ad1 --- /dev/null +++ b/system/pdksh/patches/113_OpenBSD-memory.patch @@ -0,0 +1,148 @@ +From OpenBSD: + +2009-04-19 22:34 sthen + + * misc.c (1.37): don't print extraneous padding characters when + tab-completion file/command lists encounter a name too long for + the width of the terminal. + + from Matthew Haub, no objections krw@. + +2008-08-11 23:50 jaredy + + * tree.c (1.19): plug a memleak when freeing io redirection in + commands. the leaked memory is actually reclaimed when the + command finishes but may grow until that happens, e.g. during + command execution. + + ok phessler@. testing sobrado@ jmc@ oga@. + +2008-07-23 18:34 jaredy + + * c_sh.c (1.38), syn.c (1.28): fix stack abuse in the `time' + commmand, using alloc()'d memory instead. + + reported by Thorsten Glaser, thanks. + + ok millert@, earlier version miod@ + +2008-07-21 19:30 millert + + * alloc.c (1.8): Extra sanity checking for afree(); OK deraadt@ + and pvalchev@ + +2008-07-12 14:33 miod + + * misc.c (1.34): Fix a strlcpy() bound. + + + +Index: pdksh-5.2.14/tree.c +=================================================================== +--- pdksh-5.2.14.orig/tree.c 2009-09-19 11:22:37.000000000 +0200 ++++ pdksh-5.2.14/tree.c 2009-09-19 12:06:43.000000000 +0200 +@@ -755,4 +755,5 @@ + afree((void*)p->heredoc, ap); + afree((void*)p, ap); + } ++ afree(iow, ap); + } +Index: pdksh-5.2.14/syn.c +=================================================================== +--- pdksh-5.2.14.orig/syn.c 2009-09-19 11:22:37.000000000 +0200 ++++ pdksh-5.2.14/syn.c 2009-09-19 12:06:43.000000000 +0200 +@@ -375,6 +375,11 @@ + case TIME: + syniocf &= ~(KEYWORD|ALIAS); + t = pipeline(0); ++ if (t) { ++ t->str = alloc(2, ATEMP); ++ t->str[0] = '\0'; /* TF_* flags */ ++ t->str[1] = '\0'; ++ } + t = block(TTIME, t, NOBLOCK, NOWORDS); + break; + +Index: pdksh-5.2.14/alloc.c +=================================================================== +--- pdksh-5.2.14.orig/alloc.c 2009-09-19 11:22:37.000000000 +0200 ++++ pdksh-5.2.14/alloc.c 2009-09-19 12:06:43.000000000 +0200 +@@ -894,13 +894,20 @@ + void + afree(void *ptr, Area *ap) + { +- struct link *l; ++ struct link *l, *l2; + + if (!ptr) + return; + + l = P2L(ptr); + ++ for (l2 = ap->freelist; l2 != NULL; l2 = l2->next) { ++ if (l == l2) ++ break; ++ } ++ if (l2 == NULL) ++ internal_errorf(1, "afree: %p not present in area %p", ptr, ap); ++ + if (l->prev) + l->prev->next = l->next; + else +Index: pdksh-5.2.14/c_sh.c +=================================================================== +--- pdksh-5.2.14.orig/c_sh.c 2009-09-19 11:55:01.000000000 +0200 ++++ pdksh-5.2.14/c_sh.c 2009-09-19 12:06:43.000000000 +0200 +@@ -738,7 +738,6 @@ + clock_t t0t, t1t = 0; + int tf = 0; + extern clock_t j_usrtime, j_systime; /* computed by j_wait */ +- char opts[1]; + + t0t = ksh_times(&t0); + if (t->left) { +@@ -751,11 +750,9 @@ + * really work as it only counts the last job). + */ + j_usrtime = j_systime = 0; +- if (t->left->type == TCOM) +- t->left->str = opts; +- opts[0] = 0; + rv = execute(t->left, f | XTIME, xerrok); +- tf |= opts[0]; ++ if (t->left->type == TCOM) ++ tf |= t->left->str[0]; + t1t = ksh_times(&t1); + } else + tf = TF_NOARGS; +Index: pdksh-5.2.14/misc.c +=================================================================== +--- pdksh-5.2.14.orig/misc.c 2009-09-19 11:22:37.000000000 +0200 ++++ pdksh-5.2.14/misc.c 2009-09-19 12:06:43.000000000 +0200 +@@ -1123,6 +1123,7 @@ + int r, c; + int rows, cols; + int nspace; ++ int col_width; + + /* max_width + 1 for the space. Note that no space + * is printed after the last column to avoid problems +@@ -1141,6 +1142,9 @@ + rows = n; + } + ++ col_width = max_width; ++ if (cols == 1) ++ col_width = 0; /* Don't pad entries in single column output. */ + nspace = (x_cols - max_width * cols) / cols; + if (nspace <= 0) + nspace = 1; +@@ -1149,7 +1153,7 @@ + i = c * rows + r; + if (i < n) { + shf_fprintf(shf, "%-*s", +- max_width, ++ col_width, + (*func)(arg, i, str, max_width + 1)); + if (c + 1 < cols) + shf_fprintf(shf, "%*s", nspace, null); diff --git a/system/pdksh/patches/114_OpenBSD-let-crash.patch b/system/pdksh/patches/114_OpenBSD-let-crash.patch new file mode 100644 index 0000000000000..b859a55f50391 --- /dev/null +++ b/system/pdksh/patches/114_OpenBSD-let-crash.patch @@ -0,0 +1,37 @@ +From OpenBSD: + +2009-06-01 20:20 deraadt + + * expr.c (1.20): "let --" was crashing ksh; found by + phy0@rambler.ru. Various other expressions involving ++ and -- + also ran into this. Insufficient checks for end of parse in the + tokenizer made it assume that an lvalue had been found ok millert + otto + +Index: pdksh-5.2.14/expr.c +=================================================================== +--- pdksh-5.2.14.orig/expr.c 2009-09-19 11:22:35.000000000 +0200 ++++ pdksh-5.2.14/expr.c 2009-09-19 12:07:08.000000000 +0200 +@@ -558,7 +558,8 @@ + enum token op; + struct tbl *vasn; + { +- if (vasn->name[0] == '\0' && !(vasn->flag & EXPRLVALUE)) ++ if (es->tok == END || ++ (vasn->name[0] == '\0' && !(vasn->flag & EXPRLVALUE))) + evalerr(es, ET_LVALUE, opinfo[(int) op].name); + else if (vasn->flag & RDONLY) + evalerr(es, ET_RDONLY, opinfo[(int) op].name); +Index: pdksh-5.2.14/tests/debian-114.t +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ pdksh-5.2.14/tests/debian-114.t 2009-09-19 12:11:08.000000000 +0200 +@@ -0,0 +1,8 @@ ++name: debian-114-1 ++description: ++ Check if let crashes ++stdin: ++ let -- ++ exit 0 ++expected-stderr-pattern: /\-\- requires lvalue/ ++--- diff --git a/system/pdksh/patches/115_OpenBSD-echo-posix.patch b/system/pdksh/patches/115_OpenBSD-echo-posix.patch new file mode 100644 index 0000000000000..47a9f37826f46 --- /dev/null +++ b/system/pdksh/patches/115_OpenBSD-echo-posix.patch @@ -0,0 +1,140 @@ +From OpenBSD: + +2009-02-07 15:03 kili + + * c_ksh.c (1.33): + Ensure that *wp isn't NULL. + + ok otto@ + +2009-02-07 08:24 guenther + + * c_ksh.c (1.32), ksh.1 (1.124), sh.1 (1.78): Make built-in echo + behave according to POSIX when set -o posix is in effect: the + only option is -n, and only one of those is parsed. + + diff from Ingo Schwarze ok otto@ kili@; manpage changes ok jmc@ + + +Index: pdksh-5.2.14/c_ksh.c +=================================================================== +--- pdksh-5.2.14.orig/c_ksh.c 2009-09-19 11:22:34.000000000 +0200 ++++ pdksh-5.2.14/c_ksh.c 2009-09-19 12:13:54.000000000 +0200 +@@ -247,23 +247,30 @@ + * by default. + */ + wp += 1; +- while ((s = *wp) && *s == '-' && s[1]) { +- while (*++s) +- if (*s == 'n') +- nflags &= ~PO_NL; +- else if (*s == 'e') +- nflags |= PO_EXPAND; +- else if (*s == 'E') +- nflags &= ~PO_EXPAND; +- else +- /* bad option: don't use nflags, print +- * argument +- */ ++ if (Flag(FPOSIX)) { ++ if (*wp && strcmp(*wp, "-n") == 0) { ++ flags &= ~PO_NL; ++ wp++; ++ } ++ } else { ++ while ((s = *wp) && *s == '-' && s[1]) { ++ while (*++s) ++ if (*s == 'n') ++ nflags &= ~PO_NL; ++ else if (*s == 'e') ++ nflags |= PO_EXPAND; ++ else if (*s == 'E') ++ nflags &= ~PO_EXPAND; ++ else ++ /* bad option: don't use ++ * nflags, print argument ++ */ ++ break; ++ if (*s) + break; +- if (*s) +- break; +- wp++; +- flags = nflags; ++ wp++; ++ flags = nflags; ++ } + } + } else { + int optc; +Index: pdksh-5.2.14/ksh.Man +=================================================================== +--- pdksh-5.2.14.orig/ksh.Man 2009-09-19 11:22:34.000000000 +0200 ++++ pdksh-5.2.14/ksh.Man 2009-09-19 12:13:54.000000000 +0200 +@@ -1521,6 +1521,13 @@ + In future, a new option (\fB\-v\fP perhaps) will be added to distinguish + the two behaviours. + .IP \ \ \(bu ++\fBecho\fP ++options. ++In POSIX mode, \fB\-e\fP and \fB\-E\fP ++are not treated as options, but printed like other arguments; ++in non-POSIX mode, these options control the interpretation ++of backslash sequences. ++.IP \ \ \(bu + \fBfg\fP exit status: in posix mode, the exit status is 0 if no errors occur; + in non-posix mode, the exit status is that of the last foregrounded job. + .IP \ \ \(bu +@@ -1780,6 +1787,9 @@ + \fB\-n\fP suppresses the trailing newline, \fB\-e\fP enables backslash + interpretation (a no-op, since this is normally done), and \fB\-E\fP which + suppresses backslash interpretation. ++If the \fIposix\fP ++option is set, only the first argument is treated as an option, and only ++if it is exactly \fB-n\fP. + .\"}}} + .\"{{{ eval command ... + .IP "\fBeval\fP \fIcommand ...\fP" +Index: pdksh-5.2.14/tests/debian-115.t +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ pdksh-5.2.14/tests/debian-115.t 2009-09-19 12:18:11.000000000 +0200 +@@ -0,0 +1,38 @@ ++name: debian-115-1 ++description: ++ Check if echo does not accept -e in posix mode ++stdin: ++ set -o posix ++ echo -e test ++expected-stdout: ++ -e test ++--- ++name: debian-115-2 ++description: ++ Check if echo accepts -e in non-posix mode ++stdin: ++ set +o posix ++ echo -e test ++expected-stdout: ++ test ++--- ++name: debian-115-3 ++description: ++ Check if echo accepts -n in posix mode ++stdin: ++ set -o posix ++ echo -n test ++ echo " OK" ++expected-stdout: ++ test OK ++--- ++name: debian-115-4 ++description: ++ Check if echo accepts -n in non-posix mode ++stdin: ++ set +o posix ++ echo -n test ++ echo " OK" ++expected-stdout: ++ test OK ++--- diff --git a/system/pdksh/patches/116_OpenBSD-history.patch b/system/pdksh/patches/116_OpenBSD-history.patch new file mode 100644 index 0000000000000..9be184b29871a --- /dev/null +++ b/system/pdksh/patches/116_OpenBSD-history.patch @@ -0,0 +1,47 @@ +From OpenBSD: + +2008-07-03 19:52 otto + + * lex.c (1.44): fix inifinite loop with set -o csh-history and + !<space> as input. report and testing by david@; ok millert@ + jaredy@ + +2008-05-20 02:30 fgsch + + * history.c (1.36): cast pointer arithmetic to unsigned so we can + behave correctly on underflows. fixes fc -l 1 in my box where + line is 1667511151. krw@ ok. + +Index: pdksh-5.2.14/history.c +=================================================================== +--- pdksh-5.2.14.orig/history.c 2009-09-17 22:18:37.000000000 +0200 ++++ pdksh-5.2.14/history.c 2009-09-17 23:46:06.000000000 +0200 +@@ -385,7 +385,7 @@ + + if (getn(str, &n)) { + hp = histptr + (n < 0 ? n : (n - hist_source->line)); +- if (hp < history) { ++ if ((long)hp < (long)history) { + if (approx) + hp = hist_get_oldest(); + else { +@@ -862,7 +862,8 @@ + if (base != MAP_FAILED) + munmap((caddr_t)base, hsize); + hist_finish(); +- unlink(hname); ++ if (unlink(hname) != 0) ++ return; + goto retry; + } + if (hsize > 2) { +@@ -870,7 +871,8 @@ + if (lines > histsize) { + /* we need to make the file smaller */ + if (hist_shrink(base, hsize)) +- unlink(hname); ++ if (unlink(hname) != 0) ++ return; + munmap((caddr_t)base, hsize); + hist_finish(); + goto retry; diff --git a/system/pdksh/patches/117_Debian-test.patch b/system/pdksh/patches/117_Debian-test.patch new file mode 100644 index 0000000000000..5756df78d9519 --- /dev/null +++ b/system/pdksh/patches/117_Debian-test.patch @@ -0,0 +1,78 @@ +Fix 4-argument test - bug#465250 +Index: pdksh-5.2.14/c_test.c +=================================================================== +--- pdksh-5.2.14.orig/c_test.c 2009-09-19 12:03:25.000000000 +0200 ++++ pdksh-5.2.14/c_test.c 2009-09-19 12:18:27.000000000 +0200 +@@ -131,10 +131,27 @@ + */ + if (argc <= 5) { + char **owp = wp; ++ char **owpend = te.wp_end; + int invert = 0; + Test_op op; + const char *opnd1, *opnd2; + ++ if (argc >= 2 && ((*te.isa)(&te, TM_OPAREN))) ++ { ++ te.pos.wp = te.wp_end - 1; ++ if ((*te.isa)(&te, TM_CPAREN)) ++ { ++ argc -= 2; ++ te.wp_end--; ++ te.pos.wp = owp + 2; ++ } ++ else ++ { ++ te.pos.wp = owp + 1; ++ te.wp_end = owpend; ++ } ++ } ++ + while (--argc >= 0) { + if ((*te.isa)(&te, TM_END)) + return !0; +@@ -173,6 +190,7 @@ + break; + } + te.pos.wp = owp + 1; ++ te.wp_end = owpend; + } + + return test_parse(&te); +Index: pdksh-5.2.14/tests/debian-117.t +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ pdksh-5.2.14/tests/debian-117.t 2009-09-19 12:22:53.000000000 +0200 +@@ -0,0 +1,32 @@ ++name: debian-117-1 ++description: ++ Check test - bug#465250 ++stdin: ++ test \( ! -e \) ; echo $? ++expected-stdout: ++ 1 ++--- ++name: debian-117-2 ++description: ++ Check test - bug#465250 ++stdin: ++ test \( -e \) ; echo $? ++expected-stdout: ++ 0 ++--- ++name: debian-117-3 ++description: ++ Check test - bug#465250 ++stdin: ++ test ! -e ; echo $? ++expected-stdout: ++ 1 ++--- ++name: debian-117-4 ++description: ++ Check test - bug#465250 ++stdin: ++ test -e ; echo $? ++expected-stdout: ++ 0 ++--- diff --git a/system/pdksh/pdksh.SlackBuild b/system/pdksh/pdksh.SlackBuild new file mode 100644 index 0000000000000..b0483f01f7028 --- /dev/null +++ b/system/pdksh/pdksh.SlackBuild @@ -0,0 +1,100 @@ +#!/bin/sh -e + +# Copyright (c) 2009, Daniel LEVAI +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the <organization> nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Build script for PD-ksh + +PRGNAM=pdksh +VERSION=5.2.14 +ARCH=${ARCH:-i486} +BUILD=${BUILD:-3} +TAG=${TAG:-_SBo} + +CWD=$(pwd) +TMP=${TMP:-/tmp/SBo} +PKG=$TMP/package-$PRGNAM +OUTPUT=${OUTPUT:-/tmp} + +if [ "${ARCH}" == "i486" ];then + SLKCFLAGS='-O2 -march=i486 -mtune=i686' + LIBDIRSUFFIX="" +elif [ "$ARCH" == "i686" ]; then + SLKCFLAGS="-O2 -march=i686 -mtune=i686" + LIBDIRSUFFIX="" +elif [ "${ARCH}" == "x86_64" ];then + SLKCFLAGS='-O2 -fPIC' + LIBDIRSUFFIX="64" +fi + +set -e + +rm -rf $PKG +mkdir -p $TMP $PKG $OUTPUT +cd $TMP +rm -rf $PRGNAM-$VERSION +tar zxvf $CWD/$PRGNAM-$VERSION.tar.gz +cd $PRGNAM-$VERSION +chown -R root:root . +find . \ + \( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \ + -exec chmod 755 {} \; -o \ + \( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \ + -exec chmod 644 {} \; + +for patch in "${CWD}"/patches/*;do + patch -p1 < "${patch}" +done + + +# we are lying here with defining DEBIAN, but so many patches are depending on this, we must use it... +CFLAGS="$SLKCFLAGS -DDEBIAN" \ +./configure \ + --prefix=/usr \ + --exec-prefix=/ \ + --libdir=/lib${LIBDIRSUFFIX} \ + --sysconfdir=/etc \ + --mandir=/usr/man \ + --program-prefix='pd' \ + --build=${ARCH}-slackware-linux + +make +make install DESTDIR=$PKG + +strip --strip-unneeded $PKG/bin/pdksh +gzip -9 $PKG/usr/man/man1/pdksh.1 + +mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION +cp -a \ + BUG-REPORTS ChangeLog CONTRIBUTORS IAFA-PACKAGE \ + INSTALL LEGAL NEWS NOTES PROJECTS README \ + $PKG/usr/doc/$PRGNAM-$VERSION + +mkdir -p $PKG/install +cat $CWD/slack-desc > $PKG/install/slack-desc +cat $CWD/doinst.sh > $PKG/install/doinst.sh + +cd $PKG +/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.${PKGTYPE:-tgz} diff --git a/system/pdksh/pdksh.info b/system/pdksh/pdksh.info new file mode 100644 index 0000000000000..8f37ae98ce33c --- /dev/null +++ b/system/pdksh/pdksh.info @@ -0,0 +1,10 @@ +PRGNAM="pdksh" +VERSION="5.2.14" +HOMEPAGE="http://www.cs.mun.ca/~michael/pdksh/" +DOWNLOAD="http://www.cs.mun.ca/~michael/pdksh/files/pdksh-5.2.14.tar.gz" +MD5SUM="871106b3bd937e1afba9f2ef7c43aef3" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +MAINTAINER="Daniel LEVAI" +EMAIL="leva@ecentrum.hu" +APPROVED="michiel" diff --git a/system/pdksh/slack-desc b/system/pdksh/slack-desc new file mode 100644 index 0000000000000..1cefc797a3ed4 --- /dev/null +++ b/system/pdksh/slack-desc @@ -0,0 +1,13 @@ + |-----handy-ruler------------------------------------------------------| +pdksh: PD-ksh is a clone of the AT&T Korn shell. +pdksh: +pdksh: PD-ksh has most of the ksh88 features, not much of the ksh93 features, +pdksh: and a number of its own features. +pdksh: Strong points are: +pdksh: It is free and quite portable - you should be able to compile it easily +pdksh: on pretty much any unix box. +pdksh: The vi editing mode is better (IMHO) than that of ksh88 or ksh93 +pdksh: (command/file completion using tab (optional), less buggy). +pdksh: Its weak points are that there are still a few differences from ksh88. +pdksh: +pdksh: Homepage: http://www.cs.mun.ca/~michael/pdksh/ |