1 /* $NetBSD: hist.c,v 1.22 2019/01/05 16:54:00 christos Exp $ */
2 
3 /*-
4  * Copyright (c) 1980, 1991, 1993
5  *        The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)hist.c      8.1 (Berkeley) 5/31/93";
36 #else
37 __RCSID("$NetBSD: hist.c,v 1.22 2019/01/05 16:54:00 christos Exp $");
38 #endif
39 #endif /* not lint */
40 
41 #include <sys/types.h>
42 
43 #include <stdarg.h>
44 #include <stdlib.h>
45 
46 #include "csh.h"
47 #include "extern.h"
48 
49 static void hfree(struct Hist *);
50 static void dohist1(struct Hist *, int *, int, int);
51 static void phist(struct Hist *, int);
52 
53 void
savehist(struct wordent * sp)54 savehist(struct wordent *sp)
55 {
56     struct Hist *hp, *np;
57     Char *cp;
58     int histlen;
59 
60     histlen = 0;
61 
62     /* throw away null lines */
63     if (sp->next->word[0] == '\n')
64           return;
65     cp = value(STRhistory);
66     if (*cp) {
67           Char *p = cp;
68 
69           while (*p) {
70               if (!Isdigit(*p)) {
71                     histlen = 0;
72                     break;
73               }
74               histlen = histlen * 10 + *p++ - '0';
75           }
76     }
77     for (hp = &Histlist; (np = hp->Hnext) != NULL;)
78           if (eventno - np->Href >= histlen || histlen == 0)
79               hp->Hnext = np->Hnext, hfree(np);
80           else
81               hp = np;
82     (void) enthist(++eventno, sp, 1);
83 }
84 
85 #ifdef EDIT
86 void
loadhist(struct Hist * hp)87 loadhist(struct Hist *hp) {
88     char *h = NULL;
89 
90     if (hi == NULL || hp == NULL)
91           return;
92     loadhist(hp->Hnext);
93     if (sprlex(&h, &hp->Hlex) != -1) {
94           HistEvent ev;
95           history(hi, &ev, H_ENTER, h);
96     }
97 }
98 #endif
99 
100 struct Hist *
enthist(int event,struct wordent * lp,int docopy)101 enthist(int event, struct wordent *lp, int docopy)
102 {
103     struct Hist *np;
104 
105 #ifdef EDIT
106     if (hi) {
107           char *h = NULL;
108           if (sprlex(&h, lp) != -1) {
109               HistEvent ev;
110               history(hi, &ev, H_ENTER, h);
111           }
112     }
113 #endif
114     np = xmalloc(sizeof(*np));
115     np->Hnum = np->Href = event;
116     if (docopy) {
117           copylex(&np->Hlex, lp);
118     }
119     else {
120           np->Hlex.next = lp->next;
121           lp->next->prev = &np->Hlex;
122           np->Hlex.prev = lp->prev;
123           lp->prev->next = &np->Hlex;
124     }
125     np->Hnext = Histlist.Hnext;
126     Histlist.Hnext = np;
127     return (np);
128 }
129 
130 static void
hfree(struct Hist * hp)131 hfree(struct Hist *hp)
132 {
133     freelex(&hp->Hlex);
134     free(hp);
135 }
136 
137 void
138 /*ARGSUSED*/
dohist(Char ** v,struct command * t)139 dohist(Char **v, struct command *t)
140 {
141     sigset_t nsigset;
142     int hflg, n, rflg;
143 
144     hflg = 0;
145     rflg = 0;
146 
147     if (getn(value(STRhistory)) == 0)
148           return;
149     if (setintr) {
150           sigemptyset(&nsigset);
151           (void)sigaddset(&nsigset, SIGINT);
152           (void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL);
153     }
154     while (*++v && **v == '-') {
155           Char *vp = *v;
156 
157           while (*++vp)
158               switch (*vp) {
159               case 'h':
160                     hflg++;
161                     break;
162               case 'r':
163                     rflg++;
164                     break;
165               case '-':                 /* ignore multiple '-'s */
166                     break;
167               default:
168                     stderror(ERR_HISTUS);
169                     /* NOTREACHED */
170               }
171     }
172     if (*v)
173           n = getn(*v);
174     else {
175           n = getn(value(STRhistory));
176     }
177     dohist1(Histlist.Hnext, &n, rflg, hflg);
178 }
179 
180 static void
dohist1(struct Hist * hp,int * np,int rflg,int hflg)181 dohist1(struct Hist *hp, int *np, int rflg, int hflg)
182 {
183     int print;
184 
185     print = (*np) > 0;
186 
187     for (; hp != 0; hp = hp->Hnext) {
188           (*np)--;
189           hp->Href++;
190           if (rflg == 0) {
191               dohist1(hp->Hnext, np, rflg, hflg);
192               if (print)
193                     phist(hp, hflg);
194               return;
195           }
196           if (*np >= 0)
197               phist(hp, hflg);
198     }
199 }
200 
201 static void
phist(struct Hist * hp,int hflg)202 phist(struct Hist *hp, int hflg)
203 {
204     if (hflg == 0)
205           (void)fprintf(cshout, "%6d\t", hp->Hnum);
206     prlex(cshout, &hp->Hlex);
207 }
208