summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Zle/zle_main.c2
-rw-r--r--Src/builtin.c4
-rw-r--r--Src/exec.c11
-rw-r--r--Src/hist.c68
-rw-r--r--Src/init.c2
-rw-r--r--Src/utils.c24
6 files changed, 71 insertions, 40 deletions
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 7fb6878da..f564b84ee 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -736,7 +736,7 @@ raw_getbyte(long do_keytmout, char *cptr)
 # endif
 
 
-			callhookfunc(lwatch_funcs[i], funcargs, 0);
+			callhookfunc(lwatch_funcs[i], funcargs, 0, NULL);
 			if (errflag) {
 			    /* No sensible way of handling errors here */
 			    errflag = 0;
diff --git a/Src/builtin.c b/Src/builtin.c
index af2c24fd6..c7ed283a9 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -1139,7 +1139,7 @@ cd_new_pwd(int func, LinkNode dir, int quiet)
     fflush(stdout);
     fflush(stderr);
     if (!quiet)
-	callhookfunc("chpwd", NULL, 1);
+	callhookfunc("chpwd", NULL, 1, NULL);
 
     dirstacksize = getiparam("DIRSTACKSIZE");
     /* handle directory stack sizes out of range */
@@ -4578,7 +4578,7 @@ zexit(int val, int from_where)
     lastval = val;
     if (sigtrapped[SIGEXIT])
 	dotrap(SIGEXIT);
-    callhookfunc("zshexit", NULL, 1);
+    callhookfunc("zshexit", NULL, 1, NULL);
     runhookdef(EXITHOOK, NULL);
     if (opts[MONITOR] && interact && (SHTTY != -1)) {
        release_pgrp();
diff --git a/Src/exec.c b/Src/exec.c
index 7ce657032..437a45c37 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -4093,6 +4093,16 @@ loadautofn(Shfunc shf, int fksh, int autol)
 /*
  * execute a shell function
  *
+ * name is the name of the function
+ *
+ * prog is the code to execute
+ *
+ * doshargs, if set, are parameters to pass to the function,
+ * in which the first element is the function name (even if
+ * FUNCTIONARGZERO is set as this is handled inside this function).
+ *
+ * flags are a set of the PM_ flags associated with the function.
+ *
  * If noreturnval is nonzero, then reset the current return
  * value (lastval) to its value before the shell function
  * was executed.  However, in any case return the status value
@@ -4160,6 +4170,7 @@ doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int noreturnval)
 	    oargv0 = argzero;
 	    argzero = ztrdup(getdata(node));
 	}
+	/* first node contains name regardless of option */
 	node = node->next;
 	for (; node; node = node->next, x++)
 	    *x = ztrdup(getdata(node));
diff --git a/Src/hist.c b/Src/hist.c
index a1bc73636..f856eedff 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -130,8 +130,7 @@ mod_export int hist_skip_flags;
 
 /* Bits of histactive variable */
 #define HA_ACTIVE	(1<<0)	/* History mechanism is active */
-#define HA_NOSTORE	(1<<1)	/* Don't store the line when finished */
-#define HA_NOINC	(1<<2)	/* Don't store, curhist not incremented */
+#define HA_NOINC	(1<<1)	/* Don't store, curhist not incremented */
 
 /* Array of word beginnings and endings in current history line. */
 
@@ -180,6 +179,30 @@ int hlinesz;
  
 static zlong defev;
 
+/* Remember the last line in the history file so we can find it again. */
+static struct histfile_stats {
+    char *text;
+    time_t stim, mtim;
+    off_t fpos, fsiz;
+    zlong next_write_ev;
+} lasthist;
+
+static struct histsave {
+    struct histfile_stats lasthist;
+    char *histfile;
+    HashTable histtab;
+    Histent hist_ring;
+    zlong curhist;
+    zlong histlinect;
+    zlong histsiz;
+    zlong savehistsiz;
+    int locallevel;
+} *histsave_stack;
+static int histsave_stack_size = 0;
+static int histsave_stack_pos = 0;
+
+static zlong histfile_linect;
+
 /* add a character to the current history word */
 
 static void
@@ -1082,7 +1105,8 @@ should_ignore_line(Eprog prog)
 mod_export int
 hend(Eprog prog)
 {
-    int flag, save = 1;
+    LinkList hookargs = newlinklist();
+    int flag, save = 1, hookret, stack_pos = histsave_stack_pos;
     char *hf;
 
     DPUTS(stophist != 2 && !(inbufflags & INP_ALIAS) && !chline,
@@ -1092,7 +1116,7 @@ hend(Eprog prog)
 	settyinfo(&shttyinfo);
     if (!(histactive & HA_NOINC))
 	unlinkcurline();
-    if (histactive & (HA_NOSTORE|HA_NOINC)) {
+    if (histactive & HA_NOINC) {
 	zfree(chline, hlinesz);
 	zfree(chwords, chwordlen*sizeof(short));
 	chline = NULL;
@@ -1103,6 +1127,10 @@ hend(Eprog prog)
     if (hist_ignore_all_dups != isset(HISTIGNOREALLDUPS)
      && (hist_ignore_all_dups = isset(HISTIGNOREALLDUPS)) != 0)
 	histremovedups();
+    
+    addlinknode(hookargs, "zshaddhistory");
+    addlinknode(hookargs, chline);
+    callhookfunc("zshaddhistory", hookargs, 1, &hookret);
     /* For history sharing, lock history file once for both read and write */
     hf = getsparam("HISTFILE");
     if (isset(SHAREHISTORY) && lockhistfile(hf, 0)) {
@@ -1123,7 +1151,7 @@ hend(Eprog prog)
 	}
 	if (chwordpos <= 2)
 	    save = 0;
-	else if (should_ignore_line(prog))
+	else if (hookret || should_ignore_line(prog))
 	    save = -1;
     }
     if (flag & (HISTFLAG_DONE | HISTFLAG_RECALL)) {
@@ -1203,6 +1231,12 @@ hend(Eprog prog)
     if (isset(SHAREHISTORY)? histfileIsLocked() : isset(INCAPPENDHISTORY))
 	savehistfile(hf, 0, HFILE_USE_OPTIONS | HFILE_FAST);
     unlockhistfile(hf); /* It's OK to call this even if we aren't locked */
+    /*
+     * No good reason for the user to push the history more than once, but
+     * it's easy to be tidy...
+     */
+    while (histsave_stack_pos > stack_pos)
+	pophiststack();
     unqueue_signals();
     return !(flag & HISTFLAG_NOEXEC || errflag);
 }
@@ -1942,30 +1976,6 @@ resizehistents(void)
     }
 }
 
-/* Remember the last line in the history file so we can find it again. */
-static struct histfile_stats {
-    char *text;
-    time_t stim, mtim;
-    off_t fpos, fsiz;
-    zlong next_write_ev;
-} lasthist;
-
-static struct histsave {
-    struct histfile_stats lasthist;
-    char *histfile;
-    HashTable histtab;
-    Histent hist_ring;
-    zlong curhist;
-    zlong histlinect;
-    zlong histsiz;
-    zlong savehistsiz;
-    int locallevel;
-} *histsave_stack;
-static int histsave_stack_size = 0;
-static int histsave_stack_pos = 0;
-
-static zlong histfile_linect;
-
 static int
 readhistline(int start, char **bufp, int *bufsiz, FILE *in)
 {
diff --git a/Src/init.c b/Src/init.c
index e3c89008a..7a64df17e 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -175,7 +175,7 @@ loop(int toplevel, int justonce)
 		addlinknode(args, dupstring(getjobtext(prog, NULL)));
 		addlinknode(args, cmdstr = getpermtext(prog, NULL));
 
-		callhookfunc("preexec", args, 1);
+		callhookfunc("preexec", args, 1, NULL);
 
 		/* The only permanent storage is from getpermtext() */
 		zsfree(cmdstr);
diff --git a/Src/utils.c b/Src/utils.c
index 154ca8627..ae0d43876 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1117,25 +1117,31 @@ time_t lastwatch;
 
 /*
  * Call a function given by "name" with optional arguments
- * "lnklist".  If "arrayp" is not zero, we also look through
+ * "lnklist".  If these are present the first argument is the function name.
+ *
+ * If "arrayp" is not zero, we also look through
  * the array "name"_functions and execute functions found there.
+ *
+ * If "retval" is not NULL, the return value of the first hook function to
+ * return non-zero is stored in *"retval".  The return value is not otherwise
+ * available as the calling context is restored.
  */
 
 /**/
 mod_export int
-callhookfunc(char *name, LinkList lnklst, int arrayp)
+callhookfunc(char *name, LinkList lnklst, int arrayp, int *retval)
 {
     Eprog prog;
 	/*
 	 * Save stopmsg, since user doesn't get a chance to respond
 	 * to a list of jobs generated in a hook.
 	 */
-    int osc = sfcontext, osm = stopmsg, stat = 1;
+    int osc = sfcontext, osm = stopmsg, stat = 1, ret = 0;
 
     sfcontext = SFC_HOOK;
 
     if ((prog = getshfunc(name)) != &dummy_eprog) {
-	doshfunc(name, prog, lnklst, 0, 1);
+	ret = doshfunc(name, prog, lnklst, 0, 1);
 	stat = 0;
     }
 
@@ -1151,7 +1157,9 @@ callhookfunc(char *name, LinkList lnklst, int arrayp)
 	if ((arrptr = getaparam(arrnam))) {
 	    for (; *arrptr; arrptr++) {
 		if ((prog = getshfunc(*arrptr)) != &dummy_eprog) {
-		    doshfunc(arrnam, prog, lnklst, 0, 1);
+		    int newret = doshfunc(arrnam, prog, lnklst, 0, 1);
+		    if (!ret)
+			ret = newret;
 		    stat = 0;
 		}
 	    }
@@ -1161,6 +1169,8 @@ callhookfunc(char *name, LinkList lnklst, int arrayp)
     sfcontext = osc;
     stopmsg = osm;
 
+    if (retval)
+	*retval = ret;
     return stat;
 }
 
@@ -1200,7 +1210,7 @@ preprompt(void)
 
     /* If a shell function named "precmd" exists, *
      * then execute it.                           */
-    callhookfunc("precmd", NULL, 1);
+    callhookfunc("precmd", NULL, 1, NULL);
     if (errflag)
 	return;
 
@@ -1208,7 +1218,7 @@ preprompt(void)
      * "periodic" exists, 3) it's been greater than PERIOD since we *
      * executed any such hook, then execute it now.                 */
     if (period && (time(NULL) > lastperiodic + period) &&
-	!callhookfunc("periodic", NULL, 1))
+	!callhookfunc("periodic", NULL, 1, NULL))
 	lastperiodic = time(NULL);
     if (errflag)
 	return;