* Fix job control bug in non-interactive scripts (closes: #296446) Many thanks to Paul Stroud 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