~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/3rdparty/qtcsh/sh.hist.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Header$ */
 
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.
 
8
 *
 
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. All advertising materials mentioning features or use of this software
 
18
 *    must display the following acknowledgement:
 
19
 *      This product includes software developed by the University of
 
20
 *      California, Berkeley and its contributors.
 
21
 * 4. Neither the name of the University nor the names of its contributors
 
22
 *    may be used to endorse or promote products derived from this software
 
23
 *    without specific prior written permission.
 
24
 *
 
25
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
26
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
27
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
28
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
29
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
30
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
31
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
32
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
33
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
34
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
35
 * SUCH DAMAGE.
 
36
 */
 
37
#include "sh.h"
 
38
 
 
39
RCSID("$Id$")
 
40
 
 
41
#include "tc.h"
 
42
 
 
43
extern bool histvalid;
 
44
extern Char histline[];
 
45
Char HistLit = 0;
 
46
 
 
47
static  bool    heq     __P((struct wordent *, struct wordent *));
 
48
static  void    hfree   __P((struct Hist *));
 
49
static  void    dohist1 __P((struct Hist *, int *, int));
 
50
static  void    phist   __P((struct Hist *, int));
 
51
 
 
52
#define HIST_ONLY       0x01
 
53
#define HIST_SAVE       0x02
 
54
#define HIST_LOAD       0x04
 
55
#define HIST_REV        0x08
 
56
#define HIST_CLEAR      0x10
 
57
#define HIST_MERGE      0x20
 
58
#define HIST_TIME       0x40
 
59
 
 
60
/*
 
61
 * C shell
 
62
 */
 
63
 
 
64
void
 
65
savehist(sp, mflg)
 
66
    struct wordent *sp;
 
67
    bool mflg;
 
68
{
 
69
    register struct Hist *hp, *np;
 
70
    register int histlen = 0;
 
71
    Char   *cp;
 
72
 
 
73
    /* throw away null lines */
 
74
    if (sp && sp->next->word[0] == '\n')
 
75
        return;
 
76
    cp = varval(STRhistory);
 
77
    if (*cp) {
 
78
        register Char *p = cp;
 
79
 
 
80
        while (*p) {
 
81
            if (!Isdigit(*p)) {
 
82
                histlen = 0;
 
83
                break;
 
84
            }
 
85
            histlen = histlen * 10 + *p++ - '0';
 
86
        }
 
87
    }
 
88
    if (sp)
 
89
        (void) enthist(++eventno, sp, 1, mflg);
 
90
    for (hp = &Histlist; (np = hp->Hnext) != NULL;)
 
91
        if (eventno - np->Href >= histlen || histlen == 0)
 
92
            hp->Hnext = np->Hnext, hfree(np);
 
93
        else
 
94
            hp = np;
 
95
}
 
96
 
 
97
static bool
 
98
heq(a0, b0)
 
99
    struct wordent *a0, *b0;
 
100
{
 
101
    struct wordent *a = a0->next, *b = b0->next;
 
102
 
 
103
    for (;;) {
 
104
        if (Strcmp(a->word, b->word) != 0)
 
105
            return 0;
 
106
        a = a->next;
 
107
        b = b->next;
 
108
        if (a == a0)
 
109
            return (b == b0) ? 1 : 0;
 
110
        if (b == b0)
 
111
            return 0;
 
112
    } 
 
113
}
 
114
 
 
115
 
 
116
struct Hist *
 
117
enthist(event, lp, docopy, mflg)
 
118
    int     event;
 
119
    register struct wordent *lp;
 
120
    bool    docopy;
 
121
    bool    mflg;
 
122
{
 
123
    extern time_t Htime;
 
124
    struct Hist *p = NULL, *pp = &Histlist;
 
125
    int n, r;
 
126
    register struct Hist *np;
 
127
    Char *dp;
 
128
    
 
129
    if ((dp = varval(STRhistdup)) != STRNULL) {
 
130
        if (eq(dp, STRerase)) {
 
131
            /* masaoki@akebono.tky.hp.com (Kobayashi Masaoki) */
 
132
            struct Hist *px;
 
133
            for (p = pp; (px = p, p = p->Hnext) != NULL;)
 
134
                if (heq(lp, &(p->Hlex))){
 
135
                    px->Hnext = p->Hnext;
 
136
                    if (Htime != 0 && p->Htime > Htime)
 
137
                        Htime = p->Htime;
 
138
                    n = p->Href;
 
139
                    hfree(p);
 
140
                    for (p = px->Hnext; p != NULL; p = p->Hnext)
 
141
                        p->Href = n--;
 
142
                    break;
 
143
                }
 
144
        }
 
145
        else if (eq(dp, STRall)) {
 
146
            for (p = pp; (p = p->Hnext) != NULL;)
 
147
                if (heq(lp, &(p->Hlex))) {
 
148
                    eventno--;
 
149
                    break;
 
150
                }
 
151
        }
 
152
        else if (eq(dp, STRprev)) {
 
153
            if (pp->Hnext && heq(lp, &(pp->Hnext->Hlex))) {
 
154
                p = pp->Hnext;
 
155
                eventno--;
 
156
            }
 
157
        }
 
158
    }
 
159
 
 
160
    np = p ? p : (struct Hist *) xmalloc((size_t) sizeof(*np));
 
161
 
 
162
    /* Pick up timestamp set by lex() in Htime if reading saved history */
 
163
    if (Htime != (time_t) 0) {
 
164
        np->Htime = Htime;
 
165
        Htime = 0;
 
166
    }
 
167
    else
 
168
        (void) time(&(np->Htime));
 
169
 
 
170
    if (p == np)
 
171
        return np;
 
172
 
 
173
    np->Hnum = np->Href = event;
 
174
    if (docopy) {
 
175
        copylex(&np->Hlex, lp);
 
176
        if (histvalid)
 
177
            np->histline = Strsave(histline);
 
178
        else
 
179
            np->histline = NULL;
 
180
    }
 
181
    else {
 
182
        np->Hlex.next = lp->next;
 
183
        lp->next->prev = &np->Hlex;
 
184
        np->Hlex.prev = lp->prev;
 
185
        lp->prev->next = &np->Hlex;
 
186
        np->histline = NULL;
 
187
    }
 
188
    if (mflg)
 
189
      {
 
190
        while ((p = pp->Hnext) && (p->Htime > np->Htime))
 
191
          pp = p;
 
192
        while (p && p->Htime == np->Htime)
 
193
          {
 
194
            if (heq(&p->Hlex, &np->Hlex))
 
195
              {
 
196
                eventno--;
 
197
                hfree(np);
 
198
                return (p);
 
199
              }
 
200
            pp = p;
 
201
            p = p->Hnext;
 
202
          }
 
203
        for (p = Histlist.Hnext; p != pp->Hnext; p = p->Hnext)
 
204
          {
 
205
            n = p->Hnum; r = p->Href;
 
206
            p->Hnum = np->Hnum; p->Href = np->Href;
 
207
            np->Hnum = n; np->Href = r;
 
208
          }
 
209
      }
 
210
    np->Hnext = pp->Hnext;
 
211
    pp->Hnext = np;
 
212
    return (np);
 
213
}
 
214
 
 
215
static void
 
216
hfree(hp)
 
217
    register struct Hist *hp;
 
218
{
 
219
 
 
220
    freelex(&hp->Hlex);
 
221
    if (hp->histline)
 
222
        xfree((ptr_t) hp->histline);
 
223
    xfree((ptr_t) hp);
 
224
}
 
225
 
 
226
 
 
227
/*ARGSUSED*/
 
228
void
 
229
dohist(vp, c)
 
230
    Char  **vp;
 
231
    struct command *c;
 
232
{
 
233
    int     n, hflg = 0;
 
234
 
 
235
    USE(c);
 
236
    if (getn(varval(STRhistory)) == 0)
 
237
        return;
 
238
    if (setintr)
 
239
#ifdef BSDSIGS
 
240
        (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
 
241
#else
 
242
        (void) sigrelse(SIGINT);
 
243
#endif
 
244
    while (*++vp && **vp == '-') {
 
245
        Char   *vp2 = *vp;
 
246
 
 
247
        while (*++vp2)
 
248
            switch (*vp2) {
 
249
            case 'c':
 
250
                hflg |= HIST_CLEAR;
 
251
                break;
 
252
            case 'h':
 
253
                hflg |= HIST_ONLY;
 
254
                break;
 
255
            case 'r':
 
256
                hflg |= HIST_REV;
 
257
                break;
 
258
            case 'S':
 
259
                hflg |= HIST_SAVE;
 
260
                break;
 
261
            case 'L':
 
262
                hflg |= HIST_LOAD;
 
263
                break;
 
264
            case 'M':
 
265
                hflg |= HIST_MERGE;
 
266
                break;
 
267
            case 'T':
 
268
                hflg |= HIST_TIME;
 
269
                break;
 
270
            default:
 
271
                stderror(ERR_HISTUS, "chrSLMT");
 
272
                break;
 
273
            }
 
274
    }
 
275
 
 
276
    if (hflg & HIST_CLEAR) {
 
277
        struct Hist *np, *hp;
 
278
        for (hp = &Histlist; (np = hp->Hnext) != NULL;)
 
279
            hp->Hnext = np->Hnext, hfree(np);
 
280
    }
 
281
 
 
282
    if (hflg & (HIST_LOAD | HIST_MERGE)) {
 
283
        loadhist(*vp, (hflg & HIST_MERGE) ? 1 : 0);
 
284
        return;
 
285
    }
 
286
    else if (hflg & HIST_SAVE) {
 
287
        rechist(*vp, 1);
 
288
        return;
 
289
    }
 
290
    if (*vp)
 
291
        n = getn(*vp);
 
292
    else {
 
293
        n = getn(varval(STRhistory));
 
294
    }
 
295
    dohist1(Histlist.Hnext, &n, hflg);
 
296
}
 
297
 
 
298
static void
 
299
dohist1(hp, np, hflg)
 
300
    struct Hist *hp;
 
301
    int    *np, hflg;
 
302
{
 
303
    bool    print = (*np) > 0;
 
304
 
 
305
    for (; hp != 0; hp = hp->Hnext) {
 
306
        (*np)--;
 
307
        if ((hflg & HIST_REV) == 0) {
 
308
            dohist1(hp->Hnext, np, hflg);
 
309
            if (print)
 
310
                phist(hp, hflg);
 
311
            return;
 
312
        }
 
313
        if (*np >= 0)
 
314
            phist(hp, hflg);
 
315
    }
 
316
}
 
317
 
 
318
static void
 
319
phist(hp, hflg)
 
320
    register struct Hist *hp;
 
321
    int     hflg;
 
322
{
 
323
    extern bool output_raw;
 
324
    if (hflg & HIST_ONLY) {
 
325
       /*
 
326
        * Control characters have to be written as is (output_raw).
 
327
        * This way one can preserve special characters (like tab) in
 
328
        * the history file.
 
329
        * From: mveksler@vnet.ibm.com (Veksler Michael)
 
330
        */
 
331
        output_raw= 1;
 
332
        if (hflg & HIST_TIME)
 
333
            /* 
 
334
             * Make file entry with history time in format:
 
335
             * "+NNNNNNNNNN" (10 digits, left padded with ascii '0') 
 
336
             */
 
337
 
 
338
            xprintf("#+%010lu\n", hp->Htime);
 
339
 
 
340
        if (HistLit && hp->histline)
 
341
            xprintf("%S\n", hp->histline);
 
342
        else
 
343
            prlex(&hp->Hlex);
 
344
        output_raw= 0;
 
345
    }
 
346
    else {
 
347
        Char   *cp = str2short("%h\t%T\t%R\n");
 
348
        Char buf[INBUFSIZE];
 
349
        struct varent *vp = adrof(STRhistory);
 
350
 
 
351
        if (vp && vp->vec[0] && vp->vec[1])
 
352
            cp = vp->vec[1];
 
353
 
 
354
        tprintf(FMT_HISTORY, buf, cp, INBUFSIZE, NULL, hp->Htime, (ptr_t) hp);
 
355
        for (cp = buf; *cp;)
 
356
            xputchar(*cp++);
 
357
    }
 
358
}
 
359
 
 
360
 
 
361
void
 
362
fmthist(fmt, ptr, buf, bufsiz)
 
363
    int fmt;
 
364
    ptr_t ptr;
 
365
    char *buf;
 
366
    size_t bufsiz;
 
367
{
 
368
    struct Hist *hp = (struct Hist *) ptr;
 
369
    switch (fmt) {
 
370
    case 'h':
 
371
        (void) xsnprintf(buf, bufsiz, "%6d", hp->Hnum);
 
372
        break;
 
373
    case 'R':
 
374
        if (HistLit && hp->histline)
 
375
            (void) xsnprintf(buf, bufsiz, "%S", hp->histline);
 
376
        else {
 
377
            Char ibuf[INBUFSIZE], *ip;
 
378
            char *p;
 
379
            (void) sprlex(ibuf, sizeof(ibuf), &hp->Hlex);
 
380
            for (p = buf, ip = ibuf; (*p++ = (CHAR & *ip++)) != '\0'; )
 
381
                continue;
 
382
        }
 
383
        break;
 
384
    default:
 
385
        buf[0] = '\0';
 
386
        break;
 
387
    }
 
388
        
 
389
}
 
390
 
 
391
void
 
392
rechist(fname, ref)
 
393
    Char *fname;
 
394
    int ref;
 
395
{
 
396
    Char    *snum;
 
397
    int     fp, ftmp, oldidfds;
 
398
    struct varent *shist;
 
399
    static Char   *dumphist[] = {STRhistory, STRmhT, 0, 0};
 
400
 
 
401
    if (fname == NULL && !ref) 
 
402
        return;
 
403
    /*
 
404
     * If $savehist is just set, we use the value of $history
 
405
     * else we use the value in $savehist
 
406
     */
 
407
    if (((snum = varval(STRsavehist)) == STRNULL) &&
 
408
        ((snum = varval(STRhistory)) == STRNULL))
 
409
        snum = STRmaxint;
 
410
 
 
411
 
 
412
    if (fname == NULL) {
 
413
        if ((fname = varval(STRhistfile)) == STRNULL)
 
414
            fname = Strspl(varval(STRhome), &STRtildothist[1]);
 
415
        else
 
416
            fname = Strsave(fname);
 
417
    }
 
418
    else
 
419
        fname = globone(fname, G_ERROR);
 
420
 
 
421
    /*
 
422
     * The 'savehist merge' feature is intended for an environment
 
423
     * with numerous shells beeing in simultaneous use. Imagine
 
424
     * any kind of window system. All these shells 'share' the same 
 
425
     * ~/.history file for recording their command line history. 
 
426
     * Currently the automatic merge can only succeed when the shells
 
427
     * nicely quit one after another. 
 
428
     *
 
429
     * Users that like to nuke their environment require here an atomic
 
430
     *  loadhist-creat-dohist(dumphist)-close
 
431
     * sequence.
 
432
     *
 
433
     * jw.
 
434
     */ 
 
435
    /*
 
436
     * We need the didfds stuff before loadhist otherwise
 
437
     * exec in a script will fail to print if merge is set.
 
438
     * From: mveksler@iil.intel.com (Veksler Michael)
 
439
     */
 
440
    oldidfds = didfds;
 
441
    didfds = 0;
 
442
    if ((shist = adrof(STRsavehist)) != NULL)
 
443
        if (shist->vec[1] && eq(shist->vec[1], STRmerge))
 
444
            loadhist(fname, 1);
 
445
    fp = creat(short2str(fname), 0600);
 
446
    if (fp == -1) {
 
447
        didfds = oldidfds;
 
448
        return;
 
449
    }
 
450
    ftmp = SHOUT;
 
451
    SHOUT = fp;
 
452
    dumphist[2] = snum;
 
453
    dohist(dumphist, NULL);
 
454
    (void) close(fp);
 
455
    SHOUT = ftmp;
 
456
    didfds = oldidfds;
 
457
    xfree((ptr_t) fname);
 
458
}
 
459
 
 
460
 
 
461
void
 
462
loadhist(fname, mflg)
 
463
    Char *fname;
 
464
    bool mflg;
 
465
{
 
466
    static Char   *loadhist_cmd[] = {STRsource, NULL, NULL, NULL};
 
467
    loadhist_cmd[1] = mflg ? STRmm : STRmh;
 
468
 
 
469
    if (fname != NULL)
 
470
        loadhist_cmd[2] = fname;
 
471
    else if ((fname = varval(STRhistfile)) != STRNULL)
 
472
        loadhist_cmd[2] = fname;
 
473
    else
 
474
        loadhist_cmd[2] = STRtildothist;
 
475
 
 
476
    dosource(loadhist_cmd, NULL);
 
477
}