Toshaan Bharvani
6 months ago
5 changed files with 900 additions and 17 deletions
@ -0,0 +1,541 @@ |
|||||||
|
diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile |
||||||
|
index f6e6ac8..9d72d87 100644 |
||||||
|
--- a/src/cmd/ksh93/Mamfile |
||||||
|
+++ b/src/cmd/ksh93/Mamfile |
||||||
|
@@ -220,30 +220,18 @@ make install |
||||||
|
done pmain.o generated |
||||||
|
make libshell.a archive |
||||||
|
prev shell.req |
||||||
|
- make cd_pwd.o |
||||||
|
- make bltins/cd_pwd.c |
||||||
|
- make include/test.h implicit |
||||||
|
- prev include/shtable.h implicit |
||||||
|
- make include/defs.h implicit |
||||||
|
- prev include/regress.h implicit dontcare |
||||||
|
- prev include/shtable.h |
||||||
|
- prev include/shell.h |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/endian.h |
||||||
|
- prev include/name.h |
||||||
|
- prev include/argnod.h implicit |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/cdt.h |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/error.h |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/sfio.h |
||||||
|
+ make alarm.o |
||||||
|
+ make bltins/alarm.c |
||||||
|
+ make FEATURE/time implicit |
||||||
|
+ prev features/time |
||||||
|
+ exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time |
||||||
|
+ make ${PACKAGE_ast_INCLUDE}/times.h implicit |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/ast_time.h implicit |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/ast.h |
||||||
|
- done include/defs.h |
||||||
|
- done include/test.h |
||||||
|
- make ${PACKAGE_ast_INCLUDE}/ls.h implicit |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit dontcare |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/ast_fs.h |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/ast_std.h |
||||||
|
- done ${PACKAGE_ast_INCLUDE}/ls.h |
||||||
|
+ done ${PACKAGE_ast_INCLUDE}/times.h |
||||||
|
+ done FEATURE/time generated |
||||||
|
make include/builtins.h implicit |
||||||
|
- prev include/shtable.h |
||||||
|
+ prev include/shtable.h implicit |
||||||
|
make FEATURE/dynamic implicit |
||||||
|
prev features/dynamic |
||||||
|
exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/dynamic |
||||||
|
@@ -251,6 +239,36 @@ make install |
||||||
|
done FEATURE/dynamic generated |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/option.h |
||||||
|
done include/builtins.h |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/error.h |
||||||
|
+ make include/defs.h implicit |
||||||
|
+ prev include/regress.h implicit |
||||||
|
+ prev include/shtable.h |
||||||
|
+ prev include/shell.h |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/endian.h |
||||||
|
+ prev include/name.h |
||||||
|
+ prev include/argnod.h implicit |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/cdt.h |
||||||
|
+ prev FEATURE/externs |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/error.h |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/sfio.h |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/ast.h |
||||||
|
+ done include/defs.h |
||||||
|
+ prev shopt.h |
||||||
|
+ done bltins/alarm.c |
||||||
|
+ exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -c bltins/alarm.c |
||||||
|
+ done alarm.o generated |
||||||
|
+ make cd_pwd.o |
||||||
|
+ make bltins/cd_pwd.c |
||||||
|
+ make include/test.h implicit |
||||||
|
+ prev include/shtable.h |
||||||
|
+ prev include/defs.h |
||||||
|
+ done include/test.h |
||||||
|
+ make ${PACKAGE_ast_INCLUDE}/ls.h implicit |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/ast_fs.h |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/ast_std.h |
||||||
|
+ done ${PACKAGE_ast_INCLUDE}/ls.h |
||||||
|
+ prev include/builtins.h |
||||||
|
prev include/name.h |
||||||
|
make include/path.h implicit |
||||||
|
make FEATURE/acct implicit |
||||||
|
@@ -341,14 +359,7 @@ make install |
||||||
|
make misc.o |
||||||
|
make bltins/misc.c |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/times.h |
||||||
|
- make FEATURE/time implicit |
||||||
|
- prev features/time |
||||||
|
- exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time |
||||||
|
- make ${PACKAGE_ast_INCLUDE}/times.h implicit |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/ast_time.h implicit dontcare |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/ast.h |
||||||
|
- done ${PACKAGE_ast_INCLUDE}/times.h dontcare |
||||||
|
- done FEATURE/time generated |
||||||
|
+ prev FEATURE/time |
||||||
|
prev FEATURE/locale |
||||||
|
make include/jobs.h implicit |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/vmalloc.h |
||||||
|
@@ -1175,7 +1186,7 @@ make install |
||||||
|
done edit/hexpand.c |
||||||
|
exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -c edit/hexpand.c |
||||||
|
done hexpand.o generated |
||||||
|
- exec - ${AR} rc libshell.a cd_pwd.o cflow.o enum.o getopts.o hist.o misc.o mkservice.o print.o read.o sleep.o trap.o test.o typeset.o ulimit.o umask.o whence.o main.o nvdisc.o nvtype.o arith.o args.o array.o completion.o defs.o edit.o expand.o regress.o fault.o fcin.o |
||||||
|
+ exec - ${AR} rc libshell.a alarm.o cd_pwd.o cflow.o enum.o getopts.o hist.o misc.o mkservice.o print.o read.o sleep.o trap.o test.o typeset.o ulimit.o umask.o whence.o main.o nvdisc.o nvtype.o arith.o args.o array.o completion.o defs.o edit.o expand.o regress.o fault.o fcin.o |
||||||
|
exec - ${AR} rc libshell.a history.o init.o io.o jobs.o lex.o macro.o name.o nvtree.o parse.o path.o string.o streval.o subshell.o tdump.o timers.o trestore.o waitevent.o xec.o limits.o msg.o strdata.o testops.o keywords.o options.o signals.o aliases.o builtins.o variables.o lexstates.o emacs.o vi.o hexpand.o |
||||||
|
exec - (ranlib libshell.a) >/dev/null 2>&1 || true |
||||||
|
done libshell.a generated |
||||||
|
diff --git a/src/cmd/ksh93/bltins/alarm.c b/src/cmd/ksh93/bltins/alarm.c |
||||||
|
new file mode 100644 |
||||||
|
index 0000000..f31bed7 |
||||||
|
--- /dev/null |
||||||
|
+++ b/src/cmd/ksh93/bltins/alarm.c |
||||||
|
@@ -0,0 +1,277 @@ |
||||||
|
+/*********************************************************************** |
||||||
|
+* * |
||||||
|
+* This software is part of the ast package * |
||||||
|
+* Copyright (c) 1982-2012 AT&T Intellectual Property * |
||||||
|
+* Copyright (c) 2020-2023 Contributors to ksh 93u+m * |
||||||
|
+* and is licensed under the * |
||||||
|
+* Eclipse Public License, Version 2.0 * |
||||||
|
+* * |
||||||
|
+* A copy of the License is available at * |
||||||
|
+* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html * |
||||||
|
+* (with md5 checksum 84283fa8859daf213bdda5a9f8d1be1d) * |
||||||
|
+* * |
||||||
|
+* David Korn <dgk@research.att.com> * |
||||||
|
+* Martijn Dekker <martijn@inlv.org> * |
||||||
|
+* Johnothan King <johnothanking@protonmail.com> * |
||||||
|
+* * |
||||||
|
+***********************************************************************/ |
||||||
|
+/* |
||||||
|
+ * alarm [-r] [varname [+]when] |
||||||
|
+ * |
||||||
|
+ * David Korn |
||||||
|
+ * AT&T Labs |
||||||
|
+ * |
||||||
|
+ */ |
||||||
|
+ |
||||||
|
+/* |
||||||
|
+ * TODO: 2014 email from David Korn cited at <https://bugzilla.redhat.com/1176670>: |
||||||
|
+ * |
||||||
|
+ * > I never documented the alarm builtin because it is problematic. The |
||||||
|
+ * > problem is that traps can't safely be handled asynchronously. What should |
||||||
|
+ * > happen is that the trap is marked for execution (sh.trapnote) and run after |
||||||
|
+ * > the current command completes. The time trap should wake up the shell if |
||||||
|
+ * > it is blocked and it should return and then handle the trap. |
||||||
|
+ */ |
||||||
|
+ |
||||||
|
+#include "shopt.h" |
||||||
|
+#include "defs.h" |
||||||
|
+#include <error.h> |
||||||
|
+#include "builtins.h" |
||||||
|
+#include "FEATURE/time" |
||||||
|
+ |
||||||
|
+#define R_FLAG 1 |
||||||
|
+#define L_FLAG 2 |
||||||
|
+ |
||||||
|
+struct tevent |
||||||
|
+{ |
||||||
|
+ Namfun_t fun; |
||||||
|
+ Namval_t *node; |
||||||
|
+ Namval_t *action; |
||||||
|
+ struct tevent *next; |
||||||
|
+ long milli; |
||||||
|
+ int flags; |
||||||
|
+ void *timeout; |
||||||
|
+}; |
||||||
|
+ |
||||||
|
+static const char ALARM[] = "alarm"; |
||||||
|
+ |
||||||
|
+static void trap_timeout(void*); |
||||||
|
+ |
||||||
|
+/* |
||||||
|
+ * insert timeout item on current given list in sorted order |
||||||
|
+ */ |
||||||
|
+static void *time_add(struct tevent *item, void *list) |
||||||
|
+{ |
||||||
|
+ struct tevent *tp = (struct tevent*)list; |
||||||
|
+ if(!tp || item->milli < tp->milli) |
||||||
|
+ { |
||||||
|
+ item->next = tp; |
||||||
|
+ list = item; |
||||||
|
+ } |
||||||
|
+ else |
||||||
|
+ { |
||||||
|
+ while(tp->next && item->milli > tp->next->milli) |
||||||
|
+ tp = tp->next; |
||||||
|
+ item->next = tp->next; |
||||||
|
+ tp->next = item; |
||||||
|
+ } |
||||||
|
+ tp = item; |
||||||
|
+ tp->timeout = sh_timeradd(tp->milli,tp->flags&R_FLAG,trap_timeout,tp); |
||||||
|
+ return list; |
||||||
|
+} |
||||||
|
+ |
||||||
|
+/* |
||||||
|
+ * delete timeout item from current given list, delete timer |
||||||
|
+ */ |
||||||
|
+static void *time_delete(struct tevent *item, void *list) |
||||||
|
+{ |
||||||
|
+ struct tevent *tp = (struct tevent*)list; |
||||||
|
+ if(item==tp) |
||||||
|
+ list = tp->next; |
||||||
|
+ else |
||||||
|
+ { |
||||||
|
+ while(tp && tp->next != item) |
||||||
|
+ tp = tp->next; |
||||||
|
+ if(tp) |
||||||
|
+ tp->next = item->next; |
||||||
|
+ } |
||||||
|
+ if(item->timeout) |
||||||
|
+ sh_timerdel(item->timeout); |
||||||
|
+ return list; |
||||||
|
+} |
||||||
|
+ |
||||||
|
+static void print_alarms(void *list) |
||||||
|
+{ |
||||||
|
+ struct tevent *tp = (struct tevent*)list; |
||||||
|
+ while(tp) |
||||||
|
+ { |
||||||
|
+ if(tp->timeout) |
||||||
|
+ { |
||||||
|
+ char *name = nv_name(tp->node); |
||||||
|
+ if(tp->flags&R_FLAG) |
||||||
|
+ { |
||||||
|
+ double d = tp->milli; |
||||||
|
+ sfprintf(sfstdout,e_alrm1,name,d/1000.); |
||||||
|
+ } |
||||||
|
+ else |
||||||
|
+ sfprintf(sfstdout,e_alrm2,name,nv_getnum(tp->node)); |
||||||
|
+ } |
||||||
|
+ tp = tp->next; |
||||||
|
+ } |
||||||
|
+} |
||||||
|
+ |
||||||
|
+static void trap_timeout(void* handle) |
||||||
|
+{ |
||||||
|
+ struct tevent *tp = (struct tevent*)handle; |
||||||
|
+ sh.trapnote |= SH_SIGALRM; |
||||||
|
+ if(!(tp->flags&R_FLAG)) |
||||||
|
+ tp->timeout = 0; |
||||||
|
+ tp->flags |= L_FLAG; |
||||||
|
+ sh.sigflag[SIGALRM] |= SH_SIGALRM; |
||||||
|
+ if(sh_isstate(SH_TTYWAIT)) |
||||||
|
+ sh_timetraps(); |
||||||
|
+} |
||||||
|
+ |
||||||
|
+void sh_timetraps(void) |
||||||
|
+{ |
||||||
|
+ struct tevent *tp, *tpnext; |
||||||
|
+ struct tevent *tptop; |
||||||
|
+ while(1) |
||||||
|
+ { |
||||||
|
+ sh.sigflag[SIGALRM] &= ~SH_SIGALRM; |
||||||
|
+ tptop= (struct tevent*)sh.st.timetrap; |
||||||
|
+ for(tp=tptop;tp;tp=tpnext) |
||||||
|
+ { |
||||||
|
+ tpnext = tp->next; |
||||||
|
+ if(tp->flags&L_FLAG) |
||||||
|
+ { |
||||||
|
+ tp->flags &= ~L_FLAG; |
||||||
|
+ if(tp->action) |
||||||
|
+ sh_fun(tp->action,tp->node,NULL); |
||||||
|
+ tp->flags &= ~L_FLAG; |
||||||
|
+ if(!tp->flags) |
||||||
|
+ nv_unset(tp->node); |
||||||
|
+ } |
||||||
|
+ } |
||||||
|
+ if(!(sh.sigflag[SIGALRM]&SH_SIGALRM)) |
||||||
|
+ break; |
||||||
|
+ } |
||||||
|
+} |
||||||
|
+ |
||||||
|
+ |
||||||
|
+/* |
||||||
|
+ * This trap function catches "alarm" actions only |
||||||
|
+ */ |
||||||
|
+static char *setdisc(Namval_t *np, const char *event, Namval_t* action, Namfun_t *fp) |
||||||
|
+{ |
||||||
|
+ struct tevent *tp = (struct tevent*)fp; |
||||||
|
+ if(!event) |
||||||
|
+ return action ? Empty : (char*)ALARM; |
||||||
|
+ if(strcmp(event,ALARM)!=0) |
||||||
|
+ { |
||||||
|
+ /* try the next level */ |
||||||
|
+ return nv_setdisc(np, event, action, fp); |
||||||
|
+ } |
||||||
|
+ if(action==np) |
||||||
|
+ action = tp->action; |
||||||
|
+ else |
||||||
|
+ tp->action = action; |
||||||
|
+ return action ? (char*)action : Empty; |
||||||
|
+} |
||||||
|
+ |
||||||
|
+/* |
||||||
|
+ * catch assignments and set alarm traps |
||||||
|
+ */ |
||||||
|
+static void putval(Namval_t* np, const char* val, int flag, Namfun_t* fp) |
||||||
|
+{ |
||||||
|
+ struct tevent *tp = (struct tevent*)fp; |
||||||
|
+ double d; |
||||||
|
+ if(val) |
||||||
|
+ { |
||||||
|
+ double now; |
||||||
|
+#ifdef timeofday |
||||||
|
+ struct timeval tmp; |
||||||
|
+ timeofday(&tmp); |
||||||
|
+ now = tmp.tv_sec + 1.e-6*tmp.tv_usec; |
||||||
|
+#else |
||||||
|
+ now = (double)time(NULL); |
||||||
|
+#endif /* timeofday */ |
||||||
|
+ nv_putv(np,val,flag,fp); |
||||||
|
+ d = nv_getnum(np); |
||||||
|
+ if(*val=='+') |
||||||
|
+ { |
||||||
|
+ double x = d + now; |
||||||
|
+ nv_putv(np,(char*)&x,NV_INTEGER|NV_DOUBLE,fp); |
||||||
|
+ } |
||||||
|
+ else |
||||||
|
+ d -= now; |
||||||
|
+ tp->milli = 1000*(d+.0005); |
||||||
|
+ if(tp->timeout) |
||||||
|
+ sh.st.timetrap = time_delete(tp,sh.st.timetrap); |
||||||
|
+ if(tp->milli > 0) |
||||||
|
+ sh.st.timetrap = time_add(tp,sh.st.timetrap); |
||||||
|
+ } |
||||||
|
+ else |
||||||
|
+ { |
||||||
|
+ tp = (struct tevent*)nv_stack(np, NULL); |
||||||
|
+ sh.st.timetrap = time_delete(tp,sh.st.timetrap); |
||||||
|
+ nv_unset(np); |
||||||
|
+ free(fp); |
||||||
|
+ } |
||||||
|
+} |
||||||
|
+ |
||||||
|
+static const Namdisc_t alarmdisc = |
||||||
|
+{ |
||||||
|
+ sizeof(struct tevent), |
||||||
|
+ putval, |
||||||
|
+ 0, |
||||||
|
+ 0, |
||||||
|
+ setdisc, |
||||||
|
+}; |
||||||
|
+ |
||||||
|
+int b_alarm(int argc,char *argv[],Shbltin_t *context) |
||||||
|
+{ |
||||||
|
+ int n,rflag=0; |
||||||
|
+ Namval_t *np; |
||||||
|
+ struct tevent *tp; |
||||||
|
+ while (n = optget(argv, sh_optalarm)) switch (n) |
||||||
|
+ { |
||||||
|
+ case 'r': |
||||||
|
+ rflag = R_FLAG; |
||||||
|
+ break; |
||||||
|
+ case ':': |
||||||
|
+ errormsg(SH_DICT,2, "%s", opt_info.arg); |
||||||
|
+ break; |
||||||
|
+ case '?': |
||||||
|
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); |
||||||
|
+ UNREACHABLE(); |
||||||
|
+ } |
||||||
|
+ argc -= opt_info.index; |
||||||
|
+ argv += opt_info.index; |
||||||
|
+ if(error_info.errors) |
||||||
|
+ { |
||||||
|
+ errormsg(SH_DICT,ERROR_usage(2),optusage(NULL)); |
||||||
|
+ UNREACHABLE(); |
||||||
|
+ } |
||||||
|
+ if(argc==0) |
||||||
|
+ { |
||||||
|
+ print_alarms(sh.st.timetrap); |
||||||
|
+ return 0; |
||||||
|
+ } |
||||||
|
+ if(argc!=2) |
||||||
|
+ { |
||||||
|
+ errormsg(SH_DICT,ERROR_usage(2),optusage(NULL)); |
||||||
|
+ UNREACHABLE(); |
||||||
|
+ } |
||||||
|
+ np = nv_open(argv[0],sh.var_tree,NV_NOARRAY|NV_VARNAME); |
||||||
|
+ if(!nv_isnull(np)) |
||||||
|
+ nv_unset(np); |
||||||
|
+ nv_setattr(np, NV_DOUBLE); |
||||||
|
+ tp = sh_newof(NULL,struct tevent,1,0); |
||||||
|
+ tp->fun.disc = &alarmdisc; |
||||||
|
+ tp->flags = rflag; |
||||||
|
+ tp->node = np; |
||||||
|
+ nv_stack(np,(Namfun_t*)tp); |
||||||
|
+ nv_putval(np, argv[1], 0); |
||||||
|
+ return 0; |
||||||
|
+} |
||||||
|
diff --git a/src/cmd/ksh93/bltins/sleep.c b/src/cmd/ksh93/bltins/sleep.c |
||||||
|
index b34e62d..3bb55b1 100644 |
||||||
|
--- a/src/cmd/ksh93/bltins/sleep.c |
||||||
|
+++ b/src/cmd/ksh93/bltins/sleep.c |
||||||
|
@@ -127,6 +127,8 @@ skip: |
||||||
|
if(tloc < (now=time(NULL))) |
||||||
|
break; |
||||||
|
d = (double)(tloc-now); |
||||||
|
+ if(sh.sigflag[SIGALRM]&SH_SIGTRAP) |
||||||
|
+ sh_timetraps(); |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
diff --git a/src/cmd/ksh93/data/builtins.c b/src/cmd/ksh93/data/builtins.c |
||||||
|
index 760b7ce..22ea156 100644 |
||||||
|
--- a/src/cmd/ksh93/data/builtins.c |
||||||
|
+++ b/src/cmd/ksh93/data/builtins.c |
||||||
|
@@ -116,6 +116,7 @@ const struct shtable3 shtab_builtins[] = |
||||||
|
"pwd", NV_BLTIN|BLT_ENV, bltin(pwd), |
||||||
|
"read", NV_BLTIN|BLT_ENV, bltin(read), |
||||||
|
"sleep", NV_BLTIN, bltin(sleep), |
||||||
|
+ "alarm", NV_BLTIN|BLT_ENV, bltin(alarm), |
||||||
|
"times", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(times), |
||||||
|
"ulimit", NV_BLTIN|BLT_ENV, bltin(ulimit), |
||||||
|
"umask", NV_BLTIN|BLT_ENV, bltin(umask), |
||||||
|
@@ -2170,6 +2171,8 @@ const char sh_optwhence[] = |
||||||
|
; |
||||||
|
|
||||||
|
|
||||||
|
+const char e_alrm1[] = "alarm -r %s +%.3g\n"; |
||||||
|
+const char e_alrm2[] = "alarm %s %.3f\n"; |
||||||
|
const char e_baddisc[] = "%s: invalid discipline function"; |
||||||
|
const char e_nofork[] = "cannot fork"; |
||||||
|
const char e_nosignal[] = "%s: unknown signal name"; |
||||||
|
diff --git a/src/cmd/ksh93/include/builtins.h b/src/cmd/ksh93/include/builtins.h |
||||||
|
index 34c697c..f6b3f59 100644 |
||||||
|
--- a/src/cmd/ksh93/include/builtins.h |
||||||
|
+++ b/src/cmd/ksh93/include/builtins.h |
||||||
|
@@ -115,6 +115,8 @@ extern int b_times(int, char*[],Shbltin_t*); |
||||||
|
|
||||||
|
extern short b_enum_nelem(Namfun_t*); |
||||||
|
|
||||||
|
+extern const char e_alrm1[]; |
||||||
|
+extern const char e_alrm2[]; |
||||||
|
extern const char e_badfun[]; |
||||||
|
extern const char e_baddisc[]; |
||||||
|
extern const char e_nofork[]; |
||||||
|
diff --git a/src/cmd/ksh93/include/defs.h b/src/cmd/ksh93/include/defs.h |
||||||
|
index 306ea7e..b5bfb67 100644 |
||||||
|
--- a/src/cmd/ksh93/include/defs.h |
||||||
|
+++ b/src/cmd/ksh93/include/defs.h |
||||||
|
@@ -143,6 +143,7 @@ extern void sh_subjobcheck(pid_t); |
||||||
|
extern int sh_subsavefd(int); |
||||||
|
extern void sh_subtmpfile(void); |
||||||
|
extern char *sh_substitute(const char*,const char*,char*); |
||||||
|
+extern void sh_timetraps(void); |
||||||
|
extern const char *_sh_translate(const char*); |
||||||
|
extern int sh_trace(char*[],int); |
||||||
|
extern void sh_trim(char*); |
||||||
|
diff --git a/src/cmd/ksh93/include/fault.h b/src/cmd/ksh93/include/fault.h |
||||||
|
index b57a0ab..7750f80 100644 |
||||||
|
--- a/src/cmd/ksh93/include/fault.h |
||||||
|
+++ b/src/cmd/ksh93/include/fault.h |
||||||
|
@@ -58,6 +58,7 @@ typedef void (*SH_SIGTYPE)(int,void(*)(int)); |
||||||
|
#define SH_SIGIGNORE 040 /* default is ignore signal */ |
||||||
|
#define SH_SIGINTERACTIVE 0100 /* handle interactive specially */ |
||||||
|
#define SH_SIGTSTP 0200 /* tstp signal received */ |
||||||
|
+#define SH_SIGALRM 0200 /* timer alarm received */ |
||||||
|
#define SH_SIGTERM SH_SIGOFF /* term signal received */ |
||||||
|
#define SH_SIGRUNTIME 0400 /* runtime value */ |
||||||
|
|
||||||
|
diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h |
||||||
|
index 57c402d..9794995 100644 |
||||||
|
--- a/src/cmd/ksh93/include/shell.h |
||||||
|
+++ b/src/cmd/ksh93/include/shell.h |
||||||
|
@@ -211,6 +211,7 @@ struct sh_scoped |
||||||
|
char **otrap; /* save parent pseudosignals for v=$(trap) */ |
||||||
|
char **trapcom; /* EXIT and signals */ |
||||||
|
char **otrapcom; /* save parent EXIT and signals for v=$(trap) */ |
||||||
|
+ void *timetrap; |
||||||
|
struct Ufunction *real_fun; /* current 'function name' function */ |
||||||
|
int repl_index; |
||||||
|
char *repl_arg; |
||||||
|
diff --git a/src/cmd/ksh93/sh/fault.c b/src/cmd/ksh93/sh/fault.c |
||||||
|
index 3409a6c..510bf56 100644 |
||||||
|
--- a/src/cmd/ksh93/sh/fault.c |
||||||
|
+++ b/src/cmd/ksh93/sh/fault.c |
||||||
|
@@ -447,6 +447,8 @@ void sh_chktrap(void) |
||||||
|
sh_exit(sh.exitval); |
||||||
|
} |
||||||
|
} |
||||||
|
+ if(sh.sigflag[SIGALRM]&SH_SIGALRM) |
||||||
|
+ sh_timetraps(); |
||||||
|
#if SHOPT_BGX |
||||||
|
if((sh.sigflag[SIGCHLD]&SH_SIGTRAP) && sh.st.trapcom[SIGCHLD]) |
||||||
|
job_chldtrap(1); |
||||||
|
diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c |
||||||
|
index 116ae3b..be333b2 100644 |
||||||
|
--- a/src/cmd/ksh93/sh/jobs.c |
||||||
|
+++ b/src/cmd/ksh93/sh/jobs.c |
||||||
|
@@ -1466,6 +1466,8 @@ int job_wait(pid_t pid) |
||||||
|
continue; |
||||||
|
if(nochild) |
||||||
|
break; |
||||||
|
+ if(sh.sigflag[SIGALRM]&SH_SIGTRAP) |
||||||
|
+ sh_timetraps(); |
||||||
|
if((intr && sh.trapnote) || (pid==1 && !intr)) |
||||||
|
break; |
||||||
|
} |
||||||
|
diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh |
||||||
|
index 83b4086..92d2708 100755 |
||||||
|
--- a/src/cmd/ksh93/tests/builtins.sh |
||||||
|
+++ b/src/cmd/ksh93/tests/builtins.sh |
||||||
|
@@ -1222,6 +1222,28 @@ function test_usage |
||||||
|
done 3< <(builtin) |
||||||
|
}; test_usage |
||||||
|
|
||||||
|
+# ====== |
||||||
|
+# The 'alarm' builtin could make 'read' crash due to IFS table corruption caused by unsafe asynchronous execution. |
||||||
|
+# https://bugzilla.redhat.com/1176670 |
||||||
|
+if (builtin alarm) 2>/dev/null |
||||||
|
+then got=$( { "$SHELL" -c ' |
||||||
|
+ builtin alarm |
||||||
|
+ alarm -r alarm_handler +.005 |
||||||
|
+ i=0 |
||||||
|
+ function alarm_handler.alarm |
||||||
|
+ { |
||||||
|
+ let "(++i) > 20" && exit |
||||||
|
+ } |
||||||
|
+ while :; do |
||||||
|
+ echo cargo,odds and ends,jetsam,junk,wreckage,castoffs,sea-drift |
||||||
|
+ done | while IFS="," read arg1 arg2 arg3 arg4 junk; do |
||||||
|
+ : |
||||||
|
+ done |
||||||
|
+ '; } 2>&1) |
||||||
|
+ ((!(e = $?))) || err_exit 'crash with alarm and IFS' \ |
||||||
|
+ "(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))" |
||||||
|
+fi |
||||||
|
+ |
||||||
|
# ====== |
||||||
|
# Verify that the POSIX 'test' builtin exits with status 2 when given an invalid binary operator. |
||||||
|
for operator in '===' ']]' |
||||||
|
@@ -1581,7 +1603,7 @@ let Errors+=$? |
||||||
|
# Most built-ins should handle --version |
||||||
|
while IFS= read -r bltin <&3 |
||||||
|
do case $bltin in |
||||||
|
- echo | test | true | false | \[ | : | catclose | catgets | catopen | Dt* | _Dt* | X* | login | newgrp ) |
||||||
|
+ alarm | echo | test | true | false | \[ | : | catclose | catgets | catopen | Dt* | _Dt* | X* | login | newgrp ) |
||||||
|
continue ;; |
||||||
|
fc | hist ) |
||||||
|
((SHOPT_SCRIPTONLY)) && continue ;; |
@ -0,0 +1,162 @@ |
|||||||
|
diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile |
||||||
|
index abc9ee1a5..d266f2178 100644 |
||||||
|
--- a/src/cmd/ksh93/Mamfile |
||||||
|
+++ b/src/cmd/ksh93/Mamfile |
||||||
|
@@ -222,6 +222,10 @@ make install |
||||||
|
prev shell.req |
||||||
|
make alarm.o |
||||||
|
make bltins/alarm.c |
||||||
|
+ make include/io.h implicit |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/sfio.h |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/ast.h |
||||||
|
+ done include/io.h |
||||||
|
make FEATURE/time implicit |
||||||
|
prev features/time |
||||||
|
exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time |
||||||
|
@@ -239,6 +243,22 @@ make install |
||||||
|
done FEATURE/dynamic generated |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/option.h |
||||||
|
done include/builtins.h |
||||||
|
+ make include/shlex.h implicit |
||||||
|
+ make include/lexstates.h implicit |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/wctype.h |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/wchar.h |
||||||
|
+ make FEATURE/locale implicit |
||||||
|
+ prev features/locale |
||||||
|
+ exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/locale |
||||||
|
+ done FEATURE/locale generated |
||||||
|
+ done include/lexstates.h |
||||||
|
+ prev include/shtable.h |
||||||
|
+ make include/shnodes.h implicit |
||||||
|
+ prev include/argnod.h implicit |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/ast.h |
||||||
|
+ done include/shnodes.h |
||||||
|
+ prev ${PACKAGE_ast_INCLUDE}/cdt.h |
||||||
|
+ done include/shlex.h |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/error.h |
||||||
|
make include/defs.h implicit |
||||||
|
prev include/regress.h implicit |
||||||
|
@@ -246,7 +266,7 @@ make install |
||||||
|
prev include/shell.h |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/endian.h |
||||||
|
prev include/name.h |
||||||
|
- prev include/argnod.h implicit |
||||||
|
+ prev include/argnod.h |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/cdt.h |
||||||
|
prev FEATURE/externs |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/error.h |
||||||
|
@@ -292,10 +312,7 @@ make install |
||||||
|
make cflow.o |
||||||
|
make bltins/cflow.c |
||||||
|
prev include/builtins.h |
||||||
|
- make include/shnodes.h implicit |
||||||
|
- prev include/argnod.h |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/ast.h |
||||||
|
- done include/shnodes.h |
||||||
|
+ prev include/shnodes.h |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/error.h |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/ast.h |
||||||
|
prev include/defs.h |
||||||
|
@@ -341,10 +358,7 @@ make install |
||||||
|
done FEATURE/ttys generated |
||||||
|
done include/terminal.h |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/sig.h |
||||||
|
- make FEATURE/locale implicit |
||||||
|
- prev features/locale |
||||||
|
- exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/locale |
||||||
|
- done FEATURE/locale generated |
||||||
|
+ prev FEATURE/locale |
||||||
|
make FEATURE/cmds implicit |
||||||
|
prev features/cmds |
||||||
|
exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/cmds |
||||||
|
@@ -353,6 +367,7 @@ make install |
||||||
|
prev include/builtins.h |
||||||
|
prev include/history.h |
||||||
|
prev include/name.h |
||||||
|
+ prev include/io.h |
||||||
|
make include/io.h implicit |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/sfio.h |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/ast.h |
||||||
|
@@ -443,11 +458,7 @@ make install |
||||||
|
prev include/builtins.h |
||||||
|
prev include/name.h |
||||||
|
prev include/io.h |
||||||
|
- make include/lexstates.h implicit |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/wctype.h |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/wchar.h |
||||||
|
- prev FEATURE/locale |
||||||
|
- done include/lexstates.h |
||||||
|
+ prev include/lexstates.h |
||||||
|
prev include/variables.h |
||||||
|
prev include/defs.h |
||||||
|
prev ${PACKAGE_ast_INCLUDE}/error.h |
||||||
|
@@ -545,12 +556,7 @@ make install |
||||||
|
make whence.o |
||||||
|
make bltins/whence.c |
||||||
|
prev include/builtins.h |
||||||
|
- make include/shlex.h implicit |
||||||
|
- prev include/lexstates.h |
||||||
|
- prev include/shtable.h |
||||||
|
- prev include/shnodes.h |
||||||
|
- prev ${PACKAGE_ast_INCLUDE}/cdt.h |
||||||
|
- done include/shlex.h |
||||||
|
+ prev include/shlex.h |
||||||
|
prev include/path.h |
||||||
|
prev include/name.h |
||||||
|
prev include/shtable.h |
||||||
|
diff --git a/src/cmd/ksh93/bltins/alarm.c b/src/cmd/ksh93/bltins/alarm.c |
||||||
|
index f31bed711..63d4d6cbf 100644 |
||||||
|
--- a/src/cmd/ksh93/bltins/alarm.c |
||||||
|
+++ b/src/cmd/ksh93/bltins/alarm.c |
||||||
|
@@ -23,21 +23,13 @@ |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
-/* |
||||||
|
- * TODO: 2014 email from David Korn cited at <https://bugzilla.redhat.com/1176670>: |
||||||
|
- * |
||||||
|
- * > I never documented the alarm builtin because it is problematic. The |
||||||
|
- * > problem is that traps can't safely be handled asynchronously. What should |
||||||
|
- * > happen is that the trap is marked for execution (sh.trapnote) and run after |
||||||
|
- * > the current command completes. The time trap should wake up the shell if |
||||||
|
- * > it is blocked and it should return and then handle the trap. |
||||||
|
- */ |
||||||
|
- |
||||||
|
#include "shopt.h" |
||||||
|
#include "defs.h" |
||||||
|
#include <error.h> |
||||||
|
+#include <shlex.h> |
||||||
|
#include "builtins.h" |
||||||
|
#include "FEATURE/time" |
||||||
|
+#include "io.h" |
||||||
|
|
||||||
|
#define R_FLAG 1 |
||||||
|
#define L_FLAG 2 |
||||||
|
@@ -147,7 +139,26 @@ void sh_timetraps(void) |
||||||
|
{ |
||||||
|
tp->flags &= ~L_FLAG; |
||||||
|
if(tp->action) |
||||||
|
- sh_fun(tp->action,tp->node,NULL); |
||||||
|
+ { |
||||||
|
+ /* Call the alarm discipline function. This may occur at any time including parse time, |
||||||
|
+ * so save the lexer state and push/pop context to make sure we can restore it. */ |
||||||
|
+ struct checkpt checkpoint; |
||||||
|
+ int jmpval; |
||||||
|
+ int savexit = sh.savexit; |
||||||
|
+ Lex_t *lexp = (Lex_t*)sh.lex_context, savelex = *lexp; |
||||||
|
+ sh_lexopen(lexp, 0); /* needs full init (0), not what it calls reinit (1) */ |
||||||
|
+ sh_pushcontext(&checkpoint, 1); |
||||||
|
+ jmpval = sigsetjmp(checkpoint.buff,0); |
||||||
|
+ if(!jmpval) |
||||||
|
+ sh_fun(tp->action,tp->node,NULL); |
||||||
|
+ sh_popcontext(&checkpoint); |
||||||
|
+ if(sh.topfd != checkpoint.topfd) |
||||||
|
+ sh_iorestore(checkpoint.topfd,jmpval); |
||||||
|
+ *lexp = savelex; |
||||||
|
+ sh.savexit = savexit; /* avoid influencing $? */ |
||||||
|
+ if(jmpval) |
||||||
|
+ siglongjmp(*sh.jmplist,jmpval); |
||||||
|
+ } |
||||||
|
tp->flags &= ~L_FLAG; |
||||||
|
if(!tp->flags) |
||||||
|
nv_unset(tp->node); |
@ -0,0 +1,99 @@ |
|||||||
|
From 2075b2b96208ac8b989ca316dcdd674c3f488e2b Mon Sep 17 00:00:00 2001 |
||||||
|
From: Martijn Dekker <martijn@inlv.org> |
||||||
|
Date: Thu, 28 Dec 2023 04:02:28 +0000 |
||||||
|
Subject: [PATCH] Fix crash on failure to trim ~/.sh_history |
||||||
|
|
||||||
|
@vmihalko writes: |
||||||
|
> We were able to reproduce an old issue mentioned in |
||||||
|
> https://bugzilla.redhat.com/show_bug.cgi?id=1885399 using the |
||||||
|
> latest version of ksh. The corresponding code has not changed |
||||||
|
> much in the past few years. |
||||||
|
> |
||||||
|
> To provide further explanation, the problem arises when a user's |
||||||
|
> .sh_history file grows to a size that triggers the hist_trim |
||||||
|
> function, but the user lacks (after the creation of .sh_history) |
||||||
|
> the necessary write permissions to their $HOME directory. As a |
||||||
|
> result, ksh becomes stuck in a recursive loop between the |
||||||
|
> sh_histinit(src/cmd/ksh93/edit/history.c#L203) function and the |
||||||
|
> hist_trim(src/cmd/ksh93/edit/history.c#L417) function. |
||||||
|
> |
||||||
|
> Conditions for reproduction: |
||||||
|
> |
||||||
|
> 1. The size of the .sh_history file is larger than the HIST_MAX |
||||||
|
> limit. (src/cmd/ksh93/edit/history.c, line 325) |
||||||
|
> 2. .sh_history file has not been changed in the HIST_RECENT |
||||||
|
> seconds (src/cmd/ksh93/edit/history.c, line 406) |
||||||
|
> 3. The user does not have permission to write to the $HOME |
||||||
|
> directory. |
||||||
|
|
||||||
|
src/cmd/ksh93/edit/history.c: hist_trim(): |
||||||
|
- Print a warning and return if unlink(2) fails. The warning tells |
||||||
|
the user to check the history file's parent directory is |
||||||
|
writable. This is the best I realistically do for now, because |
||||||
|
this function's basic method assumes a writable parent directory. |
||||||
|
- The temp file fallback is deleted because it's fundamentally |
||||||
|
flawed: it assumes the temp file is made on the same volume as |
||||||
|
the history file and can simply be rename(2)'d in place. Even |
||||||
|
on systems where this is the case, it doesn't appear to be |
||||||
|
working correctly, but this is not worth looking into. |
||||||
|
|
||||||
|
Resolves: https://github.com/ksh93/ksh/issues/695 |
||||||
|
--- |
||||||
|
src/cmd/ksh93/edit/history.c | 34 ++++------------------------------ |
||||||
|
1 files changed, 4 insertions(+), 30 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c |
||||||
|
index c49c23244d00..f3672bf6e220 100644 |
||||||
|
--- a/src/cmd/ksh93/edit/history.c |
||||||
|
+++ b/src/cmd/ksh93/edit/history.c |
||||||
|
@@ -419,34 +419,13 @@ static History_t* hist_trim(History_t *hp, int n) |
||||||
|
char *cp; |
||||||
|
int incmd=1, c=0; |
||||||
|
History_t *hist_new, *hist_old = hp; |
||||||
|
- char *buff, *endbuff, *tmpname=0; |
||||||
|
+ char *buff, *endbuff; |
||||||
|
off_t oldp,newp; |
||||||
|
struct stat statb; |
||||||
|
- unlink(hist_old->histname); |
||||||
|
- if(access(hist_old->histname,F_OK) >= 0) |
||||||
|
+ if(unlink(hist_old->histname) < 0) |
||||||
|
{ |
||||||
|
- /* The unlink can fail on Windows 95 */ |
||||||
|
- int fd; |
||||||
|
- char *last, *name=hist_old->histname; |
||||||
|
- sh_close(sffileno(hist_old->histfp)); |
||||||
|
- tmpname = (char*)sh_malloc(strlen(name)+14); |
||||||
|
- if(last = strrchr(name,'/')) |
||||||
|
- { |
||||||
|
- *last = 0; |
||||||
|
- pathtmp(tmpname,name,"hist",NULL); |
||||||
|
- *last = '/'; |
||||||
|
- } |
||||||
|
- else |
||||||
|
- pathtmp(tmpname,e_dot,"hist",NULL); |
||||||
|
- if(rename(name,tmpname) < 0) |
||||||
|
- { |
||||||
|
- free(tmpname); |
||||||
|
- tmpname = name; |
||||||
|
- } |
||||||
|
- fd = open(tmpname,O_RDONLY|O_cloexec); |
||||||
|
- sfsetfd(hist_old->histfp,fd); |
||||||
|
- if(tmpname==name) |
||||||
|
- tmpname = 0; |
||||||
|
+ errormsg(SH_DICT,ERROR_warn(0),"cannot trim history file %s; make sure parent directory is writable",hist_old->histname); |
||||||
|
+ return hist_ptr = hist_old; |
||||||
|
} |
||||||
|
hist_ptr = 0; |
||||||
|
if(fstat(sffileno(hist_old->histfp),&statb)>=0) |
||||||
|
@@ -501,11 +480,6 @@ static History_t* hist_trim(History_t *hp, int n) |
||||||
|
} |
||||||
|
hist_cancel(hist_new); |
||||||
|
sfclose(hist_old->histfp); |
||||||
|
- if(tmpname) |
||||||
|
- { |
||||||
|
- unlink(tmpname); |
||||||
|
- free(tmpname); |
||||||
|
- } |
||||||
|
free((char*)hist_old); |
||||||
|
return hist_ptr = hist_new; |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
From 9eb8532ccacf1cfdb7ba18f51eba68776852ef7c Mon Sep 17 00:00:00 2001 |
||||||
|
From: Vincent Mihalkovic <vmihalko@redhat.com> |
||||||
|
Date: Thu, 8 Feb 2024 22:10:58 +0100 |
||||||
|
Subject: [PATCH] Re-fix use of strdup on a NULL pointer (re: 9a9da2c2) (#718) |
||||||
|
|
||||||
|
Thank you @lzaoral for debugging this issue and creating this |
||||||
|
reproducer: |
||||||
|
|
||||||
|
$ tty # check that the shell is connected to a pseudoterminal |
||||||
|
/dev/pts/4 |
||||||
|
$ mkdir /var/tmp/chroottest |
||||||
|
$ dnf --releasever=39 --installroot=/var/tmp/chroottest install ksh |
||||||
|
$ echo "/dev/udp/127.0.0.1/514;0;104" | |
||||||
|
sudo tee /var/tmp/chroottest/etc/ksh_audit |
||||||
|
$ sudo chroot /var/tmp/chroottest /bin/ksh -lic 'exit 0' |
||||||
|
(ksh segfaults) |
||||||
|
|
||||||
|
Analysis: On Linux, ttyname(3)[*] may fail if: |
||||||
|
|
||||||
|
* EBADF Bad file descriptor. |
||||||
|
* ENODEV fd refers to a slave pseudoterminal device but the |
||||||
|
corresponding pathname could not be found [...]. |
||||||
|
* ENOTTY fd does not refer to a terminal device. |
||||||
|
|
||||||
|
Calling isatty(3) before ttyname(3) only prevents the first and |
||||||
|
third cases. |
||||||
|
|
||||||
|
src/cmd/ksh93/edit/history.c: sh_histinit(): |
||||||
|
- To catch the second case, let's call ttyname(2) directly, check |
||||||
|
for NULL and remove the redundant isatty() call. |
||||||
|
|
||||||
|
[*] https://man7.org/linux/man-pages/man3/ttyname.3.html |
||||||
|
--- |
||||||
|
src/cmd/ksh93/edit/history.c | 4 +++- |
||||||
|
1 files changed, 3 insertions(+), 1 deletions(-) |
||||||
|
|
||||||
|
diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c |
||||||
|
index a7b084e5c16f..25832a59265b 100644 |
||||||
|
--- a/src/cmd/ksh93/edit/history.c |
||||||
|
+++ b/src/cmd/ksh93/edit/history.c |
||||||
|
@@ -15,6 +15,7 @@ |
||||||
|
* Johnothan King <johnothanking@protonmail.com> * |
||||||
|
* hyenias <58673227+hyenias@users.noreply.github.com> * |
||||||
|
* Govind Kamat <govind_kamat@yahoo.com> * |
||||||
|
+* Vincent Mihalkovic <vmihalko@redhat.com> * |
||||||
|
* * |
||||||
|
***********************************************************************/ |
||||||
|
/* |
||||||
|
@@ -353,7 +354,8 @@ int sh_histinit(void) |
||||||
|
if(fd>=0) |
||||||
|
{ |
||||||
|
fcntl(fd,F_SETFD,FD_CLOEXEC); |
||||||
|
- hp->tty = sh_strdup(isatty(2)?ttyname(2):"notty"); |
||||||
|
+ const char* tty = ttyname(2); |
||||||
|
+ hp->tty = sh_strdup(tty?tty:"notty"); |
||||||
|
hp->auditfp = sfnew(NULL,NULL,-1,fd,SF_WRITE); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue