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