Hi!

----

Attached is a small patch
("ksh93_dynamic_HISTFILE_HISTSIZE_001.diff.txt") which makes the
"HISTFILE" and "HISTSIZE" variables setable at runtime (the feature has
been requested seveal times to allow per-session history files and/or a
way to set the history size to a larger value in ~/.profile even for the
current login shell itself).

Notes:
- The discipline function for HISTFILE/HISTSIZE (|put_history()|)
doesn't check whether the value of the variable really changes or stays
the same. In theory we could check whether the variable's value really
changes but usually the name of the history is usually only changed once
in /etc/profile, ~/.profile, /etc/ksh.kshrc or ~/.kshrc file and the
history is (usually) not open when files like ~/.kshrc are sourced and
therefore any tracking of value changes would be a NO-OP - therefore
it's IMO not worth the additional amount of code to do any value
tracking (but I can add the matching code on demand).
- The patch tries to get rid of direct accesses to |sh| and replaces
them with local |Shell_t *shp| variables.

There is one nit: Would it be usefull to completely seperate the
|hist_*()|-functions from the |Shell_t| object, e.g. make the history
code completely self-contained (e.g.
1. split |sh_histinit()| into a |hist_open()| part which creates a
|History_t| and wrap it in a new |sh_histinit()| which calls
|hist_open()| and then sets the |Shell_t|-specific bits
2. create a |sh_histclose()| which calls |hist_close()| and then
(un-)sets the matching variables in |Shell_t|
3. create a |sh_histfind()| which calls |hist_find()| with a callback to
check whether the search should be aborted.
4. |hist_copy()| and |hist_word()| should take a |History_t *|-handle as
argument (and it may be nice to do the same for |hist_check()| and
|hist_clean()| to make the API "clean" for any future changes/updates)
) ?

----

Bye,
Roland

-- 
  __ .  . __
 (o.\ \/ /.o) roland.mainz at nrubsig.org
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 7950090
 (;O/ \/ \O;)
-------------- next part --------------
Index: src/lib/libshell/common/include/history.h
===================================================================
--- src/lib/libshell/common/include/history.h   (revision 694)
+++ src/lib/libshell/common/include/history.h   (working copy)
@@ -37,6 +37,7 @@
        char            *histname;      /* name of history file */
        int32_t         histind;        /* current command number index */
        int             histsize;       /* number of accessible history lines */
+       void            *histshell;     /* shell parent */
 #ifdef _HIST_PRIVATE
        _HIST_PRIVATE
 #endif /* _HIST_PRIVATE */
@@ -56,7 +57,7 @@
 #define        hist_min(hp)    
((_Hist=((int)((hp)->histind-(hp)->histsize)))>=0?_Hist:0)
 #define        hist_max(hp)    ((int)((hp)->histind))
 /* these are the history interface routines */
-extern int             sh_histinit(void);
+extern int             sh_histinit(void*);
 extern void            hist_cancel(History_t*);
 extern void            hist_close(History_t*);
 extern int             hist_copy(char*, int, int, int);
Index: src/lib/libshell/common/edit/history.c
===================================================================
--- src/lib/libshell/common/edit/history.c      (revision 694)
+++ src/lib/libshell/common/edit/history.c      (working copy)
@@ -179,8 +179,9 @@
  * cleaned up.
  * hist_open() returns 1, if history file is open
  */
-int  sh_histinit(void)
+int  sh_histinit(void *sh_context)
 {
+       Shell_t *shp = (Shell_t *)sh_context;
        register int fd;
        register History_t *hp;
        register char *histname;
@@ -189,7 +190,7 @@
        register char *cp;
        register off_t hsize = 0;
 
-       if(sh.hist_ptr=hist_ptr)
+       if(shp->hist_ptr=hist_ptr)
                return(1);
        if(!(histname = nv_getval(HISTFILE)))
        {
@@ -206,7 +207,7 @@
        {
                /* reuse history file if same name */
                wasopen = 0;
-               sh.hist_ptr = hist_ptr = hp;
+               shp->hist_ptr = hist_ptr = hp;
                if(strcmp(histname,hp->histname)==0)
                        return(1);
                else
@@ -243,7 +244,7 @@
        {
 #if KSHELL
                /* don't allow root a history_file in /tmp */
-               if(sh.userid)
+               if(shp->userid)
 #endif /* KSHELL */
                {
                        if(!(fname = pathtmp(NIL(char*),0,0,NIL(int*))))
@@ -265,7 +266,8 @@
                close(fd);
                return(0);
        }
-       sh.hist_ptr = hist_ptr = hp;
+       shp->hist_ptr = hist_ptr = hp;
+       hp->histshell = shp;
        hp->histsize = maxlines;
        hp->histmask = histmask;
        hp->histfp= 
sfnew(NIL(Sfio_t*),hp->histbuff,HIST_BSIZE,fd,SF_READ|SF_WRITE|SF_APPENDWR|SF_SHARE);
@@ -338,10 +340,12 @@
 
 void hist_close(register History_t *hp)
 {
+       Shell_t *shp = hp->histshell;
+
        sfclose(hp->histfp);
        free((char*)hp);
        hist_ptr = 0;
-       sh.hist_ptr = 0;
+       shp->hist_ptr = NULL;
 #if SHOPT_ACCTFILE
        if(acctfd)
        {
@@ -378,6 +382,7 @@
 
 static void hist_trim(History_t *hp, int n)
 {
+       Shell_t *shp = hp->histshell;
        register char *cp;
        register int incmd=1, c=0;
        register History_t *hist_new, *hist_old = hp;
@@ -413,7 +418,7 @@
                histinit = 1;
                histmode =  statb.st_mode;
        }
-       if(!sh_histinit())
+       if(!sh_histinit(shp))
        {
                /* use the old history file */
                hist_ptr = hist_old;
@@ -655,9 +660,12 @@
 
 void hist_flush(register History_t *hp)
 {
+       Shell_t *shp;
        register char *buff;
        if(hp)
        {
+               shp = hp->histshell;
+
                if(buff=(char*)sfreserve(hp->histfp,0,SF_LOCKR))
                {
                        hp->histflush = sfvalue(hp->histfp)+1;
@@ -668,7 +676,7 @@
                if(sfsync(hp->histfp)<0)
                {
                        hist_close(hp);
-                       if(!sh_histinit())
+                       if(!sh_histinit(shp))
                                sh_offoption(SH_HISTORY);
                }
                hp->histflush = 0;
@@ -835,11 +843,14 @@
        off_t offset;
        int *coffset=0;
        Histloc_t location;
+       Shell_t *shp;
+
        location.hist_command = -1;
        location.hist_char = 0;
        location.hist_line = 0;
        if(!hp)
                return(location);
+       shp = hp->histshell;
        /* leading ^ means beginning of line unless escaped */
        if(flag)
        {
@@ -876,7 +887,7 @@
                }
 #if KSHELL
                /* allow a search to be aborted */
-               if(sh.trapnote&SH_SIGSET)
+               if(shp->trapnote&SH_SIGSET)
                        break;
 #endif /* KSHELL */
        }
Index: src/lib/libshell/common/bltins/hist.c
===================================================================
--- src/lib/libshell/common/bltins/hist.c       (revision 694)
+++ src/lib/libshell/common/bltins/hist.c       (working copy)
@@ -57,7 +57,7 @@
 #endif
        Histloc_t location;
        NOT_USED(argc);
-       if(!sh_histinit())
+       if(!sh_histinit(shp))
                errormsg(SH_DICT,ERROR_system(1),e_histopen);
        hp = shp->hist_ptr;
        while((flag = optget(argv,sh_opthist))) switch(flag)
Index: src/lib/libshell/common/bltins/read.c
===================================================================
--- src/lib/libshell/common/bltins/read.c       (revision 694)
+++ src/lib/libshell/common/bltins/read.c       (working copy)
@@ -313,7 +313,7 @@
                timerdel(timeslot);
        if((flags&S_FLAG) && !shp->hist_ptr)
        {
-               sh_histinit();
+               sh_histinit(shp);
                if(!shp->hist_ptr)
                        flags &= ~S_FLAG;
        }
Index: src/lib/libshell/common/bltins/print.c
===================================================================
--- src/lib/libshell/common/bltins/print.c      (revision 694)
+++ src/lib/libshell/common/bltins/print.c      (working copy)
@@ -196,7 +196,7 @@
                        break;
                case 's':
                        /* print to history file */
-                       if(!sh_histinit())
+                       if(!sh_histinit(shp))
                                errormsg(SH_DICT,ERROR_system(1),e_history);
                        fd = sffileno(shp->hist_ptr->histfp);
                        sh_onstate(SH_HISTORY);
Index: src/lib/libshell/common/sh/init.c
===================================================================
--- src/lib/libshell/common/sh/init.c   (revision 694)
+++ src/lib/libshell/common/sh/init.c   (working copy)
@@ -121,6 +121,8 @@
        struct shell    ENV_init;
        struct shell    VISUAL_init;
        struct shell    EDITOR_init;
+       struct shell    HISTFILE_init;
+       struct shell    HISTSIZE_init;
        struct shell    OPTINDEX_init;
        struct seconds  SECONDS_init;
        struct rand     RAND_init;
@@ -192,6 +194,31 @@
        nv_putv(np, val, flags, fp);
 }
 
+/* Trap for HISTFILE and HISTSIZE variables */
+static void put_history(register Namval_t* np,const char *val,int 
flags,Namfun_t *fp)
+{
+       Shell_t *shp = ((struct shell*)fp)->sh;
+       int     history_open = shp->hist_ptr?TRUE:FALSE;
+       
+       if (history_open)
+       {
+               hist_close(shp->hist_ptr);
+               (HISTCUR)->nvalue.lp = 0;
+       }
+       
+       /* In theory we could check whether the variable's value really 
+        * changes but usually the name of the history is usually only
+        * changed once in the profile or kshrc file and therefore it's
+        * not worth the additional amount of code. */
+
+       nv_putv(np, val, flags, fp);
+
+       if (history_open)
+       {
+               sh_histinit(shp);
+       }
+}
+
 /* Trap for OPTINDEX */
 static void put_optindex(Namval_t* np,const char *val,int flags,Namfun_t *fp)
 {
@@ -714,6 +741,7 @@
 static const Namdisc_t CDPATH_disc     = {  sizeof(struct shell), put_cdpath 
}; 
 #endif
 static const Namdisc_t EDITOR_disc     = {  sizeof(struct shell), put_ed };
+static const Namdisc_t HISTFILE_disc   = {  sizeof(struct shell), put_history 
};
 static const Namdisc_t OPTINDEX_disc   = {  sizeof(struct shell), 
put_optindex, 0, nget_optindex };
 static const Namdisc_t SECONDS_disc    = {  sizeof(struct seconds), 
put_seconds, get_seconds, nget_seconds };
 static const Namdisc_t RAND_disc       = {  sizeof(struct rand), put_rand, 
get_rand, nget_rand };
@@ -1207,6 +1235,14 @@
        ip->EDITOR_init.hdr.disc = &EDITOR_disc;
        ip->EDITOR_init.hdr.nofree = 1;
        ip->EDITOR_init.sh = shp;
+
+       ip->HISTFILE_init.hdr.disc = &HISTFILE_disc;
+       ip->HISTFILE_init.hdr.nofree = 1;
+       ip->HISTFILE_init.sh = shp;
+       ip->HISTSIZE_init.hdr.disc = &HISTFILE_disc;
+       ip->HISTSIZE_init.hdr.nofree = 1;
+       ip->HISTSIZE_init.sh = shp;
+
        ip->OPTINDEX_init.hdr.disc = &OPTINDEX_disc;
        ip->OPTINDEX_init.hdr.nofree = 1;
        ip->OPTINDEX_init.sh = shp;
@@ -1251,6 +1287,8 @@
        nv_stack(ENVNOD, &ip->ENV_init.hdr);
        nv_stack(VISINOD, &ip->VISUAL_init.hdr);
        nv_stack(EDITNOD, &ip->EDITOR_init.hdr);
+       nv_stack(HISTFILE, &ip->HISTFILE_init.hdr);
+       nv_stack(HISTSIZE, &ip->HISTSIZE_init.hdr);
        nv_stack(OPTINDNOD, &ip->OPTINDEX_init.hdr);
        nv_stack(SECONDS, &ip->SECONDS_init.hdr);
        nv_stack(L_ARGNOD, &ip->L_ARG_init.hdr);
Index: src/lib/libshell/common/sh/io.c
===================================================================
--- src/lib/libshell/common/sh/io.c     (revision 694)
+++ src/lib/libshell/common/sh/io.c     (working copy)
@@ -2142,7 +2142,7 @@
        switch(fd)
        {
            case SH_IOHISTFILE:
-               if(!sh_histinit())
+               if(!sh_histinit(&sh))
                        return(iop);
                fd = sffileno(sh.hist_ptr->histfp);
                break;
Index: src/lib/libshell/common/sh/main.c
===================================================================
--- src/lib/libshell/common/sh/main.c   (revision 694)
+++ src/lib/libshell/common/sh/main.c   (working copy)
@@ -402,7 +402,7 @@
                if(nv_isnull(PS1NOD))
                        
nv_putval(PS1NOD,(shp->euserid?e_stdprompt:e_supprompt),NV_RDONLY);
                sh_sigdone();
-               if(sh_histinit())
+               if(sh_histinit(shp))
                        sh_onoption(SH_HISTORY);
        }
        else

Reply via email to