After the channel TX power bug fixing in rt2560_read_config(), it is impossble
[dragonfly.git] / contrib / tcsh / sh.hist.c
blob96d37ba46cba6bc57a31aeee0b963a5c3a91d038
1 /* $Header: /src/pub/tcsh/sh.hist.c,v 3.29 2002/06/25 19:02:11 christos Exp $ */
2 /*
3 * sh.hist.c: Shell history expansions and substitutions
4 */
5 /*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 #include "sh.h"
35 RCSID("$Id: sh.hist.c,v 3.29 2002/06/25 19:02:11 christos Exp $")
37 #include "tc.h"
39 extern bool histvalid;
40 extern Char histline[];
41 Char HistLit = 0;
43 static bool heq __P((struct wordent *, struct wordent *));
44 static void hfree __P((struct Hist *));
45 static void dohist1 __P((struct Hist *, int *, int));
46 static void phist __P((struct Hist *, int));
48 #define HIST_ONLY 0x01
49 #define HIST_SAVE 0x02
50 #define HIST_LOAD 0x04
51 #define HIST_REV 0x08
52 #define HIST_CLEAR 0x10
53 #define HIST_MERGE 0x20
54 #define HIST_TIME 0x40
57 * C shell
60 void
61 savehist(sp, mflg)
62 struct wordent *sp;
63 bool mflg;
65 register struct Hist *hp, *np;
66 register int histlen = 0;
67 Char *cp;
69 /* throw away null lines */
70 if (sp && sp->next->word[0] == '\n')
71 return;
72 cp = varval(STRhistory);
73 if (*cp) {
74 register Char *p = cp;
76 while (*p) {
77 if (!Isdigit(*p)) {
78 histlen = 0;
79 break;
81 histlen = histlen * 10 + *p++ - '0';
84 if (sp)
85 (void) enthist(++eventno, sp, 1, mflg);
86 for (hp = &Histlist; (np = hp->Hnext) != NULL;)
87 if (eventno - np->Href >= histlen || histlen == 0)
88 hp->Hnext = np->Hnext, hfree(np);
89 else
90 hp = np;
93 static bool
94 heq(a0, b0)
95 struct wordent *a0, *b0;
97 struct wordent *a = a0->next, *b = b0->next;
99 for (;;) {
100 if (Strcmp(a->word, b->word) != 0)
101 return 0;
102 a = a->next;
103 b = b->next;
104 if (a == a0)
105 return (b == b0) ? 1 : 0;
106 if (b == b0)
107 return 0;
112 struct Hist *
113 enthist(event, lp, docopy, mflg)
114 int event;
115 register struct wordent *lp;
116 bool docopy;
117 bool mflg;
119 extern time_t Htime;
120 struct Hist *p = NULL, *pp = &Histlist;
121 int n, r;
122 register struct Hist *np;
123 Char *dp;
125 if ((dp = varval(STRhistdup)) != STRNULL) {
126 if (eq(dp, STRerase)) {
127 /* masaoki@akebono.tky.hp.com (Kobayashi Masaoki) */
128 struct Hist *px;
129 for (p = pp; (px = p, p = p->Hnext) != NULL;)
130 if (heq(lp, &(p->Hlex))){
131 px->Hnext = p->Hnext;
132 if (Htime != 0 && p->Htime > Htime)
133 Htime = p->Htime;
134 n = p->Href;
135 hfree(p);
136 for (p = px->Hnext; p != NULL; p = p->Hnext)
137 p->Href = n--;
138 break;
141 else if (eq(dp, STRall)) {
142 for (p = pp; (p = p->Hnext) != NULL;)
143 if (heq(lp, &(p->Hlex))) {
144 eventno--;
145 break;
148 else if (eq(dp, STRprev)) {
149 if (pp->Hnext && heq(lp, &(pp->Hnext->Hlex))) {
150 p = pp->Hnext;
151 eventno--;
156 np = p ? p : (struct Hist *) xmalloc((size_t) sizeof(*np));
158 /* Pick up timestamp set by lex() in Htime if reading saved history */
159 if (Htime != (time_t) 0) {
160 np->Htime = Htime;
161 Htime = 0;
163 else
164 (void) time(&(np->Htime));
166 if (p == np)
167 return np;
169 np->Hnum = np->Href = event;
170 if (docopy) {
171 copylex(&np->Hlex, lp);
172 if (histvalid)
173 np->histline = Strsave(histline);
174 else
175 np->histline = NULL;
177 else {
178 np->Hlex.next = lp->next;
179 lp->next->prev = &np->Hlex;
180 np->Hlex.prev = lp->prev;
181 lp->prev->next = &np->Hlex;
182 np->histline = NULL;
184 if (mflg)
186 while ((p = pp->Hnext) && (p->Htime > np->Htime))
187 pp = p;
188 while (p && p->Htime == np->Htime)
190 if (heq(&p->Hlex, &np->Hlex))
192 eventno--;
193 hfree(np);
194 return (p);
196 pp = p;
197 p = p->Hnext;
199 for (p = Histlist.Hnext; p != pp->Hnext; p = p->Hnext)
201 n = p->Hnum; r = p->Href;
202 p->Hnum = np->Hnum; p->Href = np->Href;
203 np->Hnum = n; np->Href = r;
206 np->Hnext = pp->Hnext;
207 pp->Hnext = np;
208 return (np);
211 static void
212 hfree(hp)
213 register struct Hist *hp;
216 freelex(&hp->Hlex);
217 if (hp->histline)
218 xfree((ptr_t) hp->histline);
219 xfree((ptr_t) hp);
223 /*ARGSUSED*/
224 void
225 dohist(vp, c)
226 Char **vp;
227 struct command *c;
229 int n, hflg = 0;
231 USE(c);
232 if (getn(varval(STRhistory)) == 0)
233 return;
234 if (setintr)
235 #ifdef BSDSIGS
236 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
237 #else
238 (void) sigrelse(SIGINT);
239 #endif
240 while (*++vp && **vp == '-') {
241 Char *vp2 = *vp;
243 while (*++vp2)
244 switch (*vp2) {
245 case 'c':
246 hflg |= HIST_CLEAR;
247 break;
248 case 'h':
249 hflg |= HIST_ONLY;
250 break;
251 case 'r':
252 hflg |= HIST_REV;
253 break;
254 case 'S':
255 hflg |= HIST_SAVE;
256 break;
257 case 'L':
258 hflg |= HIST_LOAD;
259 break;
260 case 'M':
261 hflg |= HIST_MERGE;
262 break;
263 case 'T':
264 hflg |= HIST_TIME;
265 break;
266 default:
267 stderror(ERR_HISTUS, "chrSLMT");
268 break;
272 if (hflg & HIST_CLEAR) {
273 struct Hist *np, *hp;
274 for (hp = &Histlist; (np = hp->Hnext) != NULL;)
275 hp->Hnext = np->Hnext, hfree(np);
278 if (hflg & (HIST_LOAD | HIST_MERGE)) {
279 loadhist(*vp, (hflg & HIST_MERGE) ? 1 : 0);
280 return;
282 else if (hflg & HIST_SAVE) {
283 rechist(*vp, 1);
284 return;
286 if (*vp)
287 n = getn(*vp);
288 else {
289 n = getn(varval(STRhistory));
291 dohist1(Histlist.Hnext, &n, hflg);
294 static void
295 dohist1(hp, np, hflg)
296 struct Hist *hp;
297 int *np, hflg;
299 bool print = (*np) > 0;
301 for (; hp != 0; hp = hp->Hnext) {
302 (*np)--;
303 if ((hflg & HIST_REV) == 0) {
304 dohist1(hp->Hnext, np, hflg);
305 if (print)
306 phist(hp, hflg);
307 return;
309 if (*np >= 0)
310 phist(hp, hflg);
314 static void
315 phist(hp, hflg)
316 register struct Hist *hp;
317 int hflg;
319 extern bool output_raw;
320 if (hflg & HIST_ONLY) {
322 * Control characters have to be written as is (output_raw).
323 * This way one can preserve special characters (like tab) in
324 * the history file.
325 * From: mveksler@vnet.ibm.com (Veksler Michael)
327 output_raw= 1;
328 if (hflg & HIST_TIME)
330 * Make file entry with history time in format:
331 * "+NNNNNNNNNN" (10 digits, left padded with ascii '0')
334 xprintf("#+%010lu\n", hp->Htime);
336 if (HistLit && hp->histline)
337 xprintf("%S\n", hp->histline);
338 else
339 prlex(&hp->Hlex);
340 output_raw= 0;
342 else {
343 Char *cp = str2short("%h\t%T\t%R\n");
344 Char buf[INBUFSIZE];
345 struct varent *vp = adrof(STRhistory);
347 if (vp && vp->vec != NULL && vp->vec[0] && vp->vec[1])
348 cp = vp->vec[1];
350 tprintf(FMT_HISTORY, buf, cp, INBUFSIZE, NULL, hp->Htime, (ptr_t) hp);
351 for (cp = buf; *cp;)
352 xputchar(*cp++);
357 void
358 fmthist(fmt, ptr, buf, bufsiz)
359 int fmt;
360 ptr_t ptr;
361 char *buf;
362 size_t bufsiz;
364 struct Hist *hp = (struct Hist *) ptr;
365 switch (fmt) {
366 case 'h':
367 (void) xsnprintf(buf, bufsiz, "%6d", hp->Hnum);
368 break;
369 case 'R':
370 if (HistLit && hp->histline)
371 (void) xsnprintf(buf, bufsiz, "%S", hp->histline);
372 else {
373 Char ibuf[INBUFSIZE], *ip;
374 char *p;
375 (void) sprlex(ibuf, sizeof(ibuf) / sizeof(Char), &hp->Hlex);
376 for (p = buf, ip = ibuf; (*p++ = (CHAR & *ip++)) != '\0'; )
377 continue;
379 break;
380 default:
381 buf[0] = '\0';
382 break;
387 void
388 rechist(fname, ref)
389 Char *fname;
390 int ref;
392 Char *snum;
393 int fp, ftmp, oldidfds;
394 struct varent *shist;
395 static Char *dumphist[] = {STRhistory, STRmhT, 0, 0};
397 if (fname == NULL && !ref)
398 return;
400 * If $savehist is just set, we use the value of $history
401 * else we use the value in $savehist
403 if (((snum = varval(STRsavehist)) == STRNULL) &&
404 ((snum = varval(STRhistory)) == STRNULL))
405 snum = STRmaxint;
408 if (fname == NULL) {
409 if ((fname = varval(STRhistfile)) == STRNULL)
410 fname = Strspl(varval(STRhome), &STRtildothist[1]);
411 else
412 fname = Strsave(fname);
414 else
415 fname = globone(fname, G_ERROR);
418 * The 'savehist merge' feature is intended for an environment
419 * with numerous shells beeing in simultaneous use. Imagine
420 * any kind of window system. All these shells 'share' the same
421 * ~/.history file for recording their command line history.
422 * Currently the automatic merge can only succeed when the shells
423 * nicely quit one after another.
425 * Users that like to nuke their environment require here an atomic
426 * loadhist-creat-dohist(dumphist)-close
427 * sequence.
429 * jw.
432 * We need the didfds stuff before loadhist otherwise
433 * exec in a script will fail to print if merge is set.
434 * From: mveksler@iil.intel.com (Veksler Michael)
436 oldidfds = didfds;
437 didfds = 0;
438 if ((shist = adrof(STRsavehist)) != NULL && shist->vec != NULL)
439 if (shist->vec[1] && eq(shist->vec[1], STRmerge))
440 loadhist(fname, 1);
441 fp = creat(short2str(fname), 0600);
442 if (fp == -1) {
443 didfds = oldidfds;
444 return;
446 ftmp = SHOUT;
447 SHOUT = fp;
448 dumphist[2] = snum;
449 dohist(dumphist, NULL);
450 (void) close(fp);
451 SHOUT = ftmp;
452 didfds = oldidfds;
453 xfree((ptr_t) fname);
457 void
458 loadhist(fname, mflg)
459 Char *fname;
460 bool mflg;
462 static Char *loadhist_cmd[] = {STRsource, NULL, NULL, NULL};
463 loadhist_cmd[1] = mflg ? STRmm : STRmh;
465 if (fname != NULL)
466 loadhist_cmd[2] = fname;
467 else if ((fname = varval(STRhistfile)) != STRNULL)
468 loadhist_cmd[2] = fname;
469 else
470 loadhist_cmd[2] = STRtildothist;
472 dosource(loadhist_cmd, NULL);