source: trunk/third/tcsh/tw.init.c @ 10519

Revision 10519, 23.0 KB checked in by lcs, 27 years ago (diff)
CVS: CVS: Fixed problem with referencing beyond the end of mesg array when NSIG was greater than its length. Use separate "sizeof" counter so the code is not vulnerable to misconfiguration due to broken ifdefs, since the ifdefs are very brittle.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/tw.init.c,v 1.2 1997-10-14 21:25:17 lcs Exp $ */
2/*
3 * tw.init.c: Handle lists of things to complete
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
39RCSID("$Id: tw.init.c,v 1.2 1997-10-14 21:25:17 lcs Exp $")
40
41#include "tw.h"
42#include "ed.h"
43#include "tc.h"
44#include "sh.proc.h"
45
46#if !defined(NSIG) && defined(SIGMAX)
47# define NSIG (SIGMAX+1)
48#endif /* !NSIG && SIGMAX */
49#if !defined(NSIG) && defined(_NSIG)
50# define NSIG _NSIG
51#endif /* !NSIG && _NSIG */
52
53#define TW_INCR 128
54
55typedef struct {
56    Char **list,                        /* List of command names        */
57          *buff;                        /* Space holding command names  */
58    int    nlist,                       /* Number of items              */
59           nbuff,                       /* Current space in name buf    */
60           tlist,                       /* Total space in list          */
61           tbuff;                       /* Total space in name buf      */
62} stringlist_t;
63
64
65static struct varent *tw_vptr = NULL;   /* Current shell variable       */
66static Char **tw_env = NULL;            /* Current environment variable */
67static Char  *tw_word;                  /* Current word pointer         */
68static struct KeyFuncs *tw_bind = NULL; /* List of the bindings         */
69#ifndef HAVENOLIMIT
70static struct limits *tw_limit = NULL;  /* List of the resource limits  */
71#endif /* HAVENOLIMIT */
72static int tw_index = 0;                /* signal and job index         */
73static DIR   *tw_dir_fd = NULL;         /* Current directory descriptor */
74static Char   tw_retname[MAXPATHLEN+1]; /* Return buffer                */
75static int    tw_cmd_got = 0;           /* What we need to do           */
76static stringlist_t tw_cmd  = { NULL, NULL, 0, 0, 0, 0 };
77static stringlist_t tw_item = { NULL, NULL, 0, 0, 0, 0 };
78#define TW_FL_CMD       0x01
79#define TW_FL_ALIAS     0x02
80#define TW_FL_BUILTIN   0x04
81#define TW_FL_SORT      0x08
82#define TW_FL_REL       0x10
83
84static struct {                         /* Current element pointer      */
85    int    cur;                         /* Current element number       */
86    Char **pathv;                       /* Current element in path      */
87    DIR   *dfd;                         /* Current directory descriptor */
88} tw_cmd_state;
89
90
91#ifdef BSDSIGS
92static sigmask_t tw_omask;
93# define TW_HOLD()      tw_omask = sigblock(sigmask(SIGINT))
94# define TW_RELS()      (void) sigsetmask(tw_omask)
95#else /* !BSDSIGS */
96# define TW_HOLD()      (void) sighold(SIGINT)
97# define TW_RELS()      (void) sigrelse(SIGINT)
98#endif /* BSDSIGS */
99
100#define SETDIR(dfd) \
101    { \
102        tw_dir_fd = dfd; \
103        if (tw_dir_fd != NULL) \
104            rewinddir(tw_dir_fd); \
105    }
106
107#define CLRDIR(dfd) \
108    if (dfd != NULL) { \
109        TW_HOLD(); \
110        (void) closedir(dfd); \
111        dfd = NULL; \
112        TW_RELS(); \
113    }
114
115static Char     *tw_str_add             __P((stringlist_t *, int));
116static void      tw_str_free            __P((stringlist_t *));
117static Char     *tw_dir_next            __P((DIR *));
118static void      tw_cmd_add             __P((Char *name));
119static void      tw_cmd_cmd             __P((void));
120static void      tw_cmd_builtin         __P((void));
121static void      tw_cmd_alias           __P((void));
122static void      tw_cmd_sort            __P((void));
123static void      tw_vptr_start          __P((struct varent *));
124
125
126/* tw_str_add():
127 *      Add an item to the string list
128 */
129static Char *
130tw_str_add(sl, len)
131    stringlist_t *sl;
132    int len;
133{
134    Char *ptr;
135
136    if (sl->tlist <= sl->nlist) {
137        TW_HOLD();
138        sl->tlist += TW_INCR;
139        sl->list = sl->list ?
140                    (Char **) xrealloc((ptr_t) sl->list,
141                                       (size_t) (sl->tlist * sizeof(Char *))) :
142                    (Char **) xmalloc((size_t) (sl->tlist * sizeof(Char *)));
143        TW_RELS();
144    }
145    if (sl->tbuff <= sl->nbuff + len) {
146        int i;
147        ptr = sl->buff;
148
149        TW_HOLD();
150        sl->tbuff += TW_INCR + len;
151        sl->buff = sl->buff ?
152                    (Char *) xrealloc((ptr_t) sl->buff,
153                                      (size_t) (sl->tbuff * sizeof(Char))) :
154                    (Char *) xmalloc((size_t) (sl->tbuff * sizeof(Char)));
155        /* Re-thread the new pointer list, if changed */
156        if (ptr != NULL && ptr != sl->buff) {
157            int offs = sl->buff - ptr;
158            for (i = 0; i < sl->nlist; i++)
159                sl->list[i] += offs;
160        }
161        TW_RELS();
162    }
163    ptr = sl->list[sl->nlist++] = &sl->buff[sl->nbuff];
164    sl->nbuff += len;
165    return ptr;
166} /* tw_str_add */
167
168
169/* tw_str_free():
170 *      Free a stringlist
171 */
172static void
173tw_str_free(sl)
174    stringlist_t *sl;
175{
176    TW_HOLD();
177    if (sl->list) {
178        xfree((ptr_t) sl->list);
179        sl->list = NULL;
180        sl->tlist = sl->nlist = 0;
181    }
182    if (sl->buff) {
183        xfree((ptr_t) sl->buff);
184        sl->buff = NULL;
185        sl->tbuff = sl->nbuff = 0;
186    }
187    TW_RELS();
188} /* end tw_str_free */
189
190
191static Char *
192tw_dir_next(dfd)
193    DIR *dfd;
194{
195    register struct dirent *dirp;
196
197    if (dfd == NULL)
198        return NULL;
199
200    if ((dirp = readdir(dfd)) != NULL) {
201        (void) Strcpy(tw_retname, str2short(dirp->d_name));
202        return (tw_retname);
203    }
204    return NULL;
205} /* end tw_dir_next */
206
207
208/* tw_cmd_add():
209 *      Add the name to the command list
210 */
211static void
212tw_cmd_add(name)
213    Char *name;
214{
215    int len;
216
217    if (name[0] == '#' || name[0] == '.')       /* emacs temp's, .files */
218        return;
219    len = Strlen(name) + 2;
220    if (name[len - 3] == '~')                   /* No emacs backups */
221        return;
222   
223    (void) Strcpy(tw_str_add(&tw_cmd, len), name);
224} /* end tw_cmd_add */
225
226
227/* tw_cmd_free():
228 *      Free the command list
229 */
230void
231tw_cmd_free()
232{
233    CLRDIR(tw_dir_fd)
234    tw_str_free(&tw_cmd);
235    tw_cmd_got = 0;
236} /* end tw_cmd_free */
237
238/* tw_cmd_cmd():
239 *      Add system commands to the command list
240 */
241static void
242tw_cmd_cmd()
243{
244    register DIR *dirp;
245    register struct dirent *dp;
246    register Char *dir = NULL, *name;
247    register Char **pv;
248    struct varent *v = adrof(STRpath);
249    struct varent *recexec = adrof(STRrecognize_only_executables);
250
251
252    if (v == NULL) /* if no path */
253        return;
254
255    for (pv = v->vec; *pv; pv++) {
256        if (pv[0][0] != '/') {
257            tw_cmd_got |= TW_FL_REL;
258            continue;
259        }
260
261        if ((dirp = opendir(short2str(*pv))) == NULL)
262            continue;
263
264        if (recexec)
265            dir = Strspl(*pv, STRslash);
266        while ((dp = readdir(dirp)) != NULL) {
267            /* the call to executable() may make this a bit slow */
268            name = str2short(dp->d_name);
269            if (dp->d_ino == 0 || (recexec && !executable(dir, name, 0)))
270                continue;
271            tw_cmd_add(name);
272        }
273        (void) closedir(dirp);
274        if (recexec)
275            xfree((ptr_t) dir);
276    }
277} /* end tw_cmd_cmd */
278
279
280/* tw_cmd_builtin():
281 *      Add builtins to the command list
282 */
283static void
284tw_cmd_builtin()
285{
286    register struct biltins *bptr;
287
288    for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++)
289        if (bptr->bname)
290            tw_cmd_add(str2short(bptr->bname));
291} /* end tw_cmd_builtin */
292
293
294/* tw_cmd_alias():
295 *      Add aliases to the command list
296 */
297static void
298tw_cmd_alias()
299{
300    register struct varent *p;
301    register struct varent *c;
302
303    p = &aliases;
304    for (;;) {
305        while (p->v_left)
306            p = p->v_left;
307x:
308        if (p->v_parent == 0) /* is it the header? */
309            return;
310        if (p->v_name)
311            tw_cmd_add(p->v_name);
312        if (p->v_right) {
313            p = p->v_right;
314            continue;
315        }
316        do {
317            c = p;
318            p = p->v_parent;
319        } while (p->v_right == c);
320        goto x;
321    }
322} /* end tw_cmd_alias */
323
324
325/* tw_cmd_sort():
326 *      Sort the command list removing duplicate elements
327 */
328static void
329tw_cmd_sort()
330{
331    int fwd, i;
332
333    TW_HOLD();
334    /* sort the list. */
335    qsort((ptr_t) tw_cmd.list, (size_t) tw_cmd.nlist, sizeof(Char *),
336          (int (*) __P((const void *, const void *))) fcompare);
337
338    /* get rid of multiple entries */
339    for (i = 0, fwd = 0; i < tw_cmd.nlist - 1; i++) {
340        if (Strcmp(tw_cmd.list[i], tw_cmd.list[i + 1]) == 0) /* garbage */
341            fwd++;              /* increase the forward ref. count */
342        else if (fwd)
343            tw_cmd.list[i - fwd] = tw_cmd.list[i];
344    }
345    /* Fix fencepost error -- Theodore Ts'o <tytso@athena.mit.edu> */
346    if (fwd)
347        tw_cmd.list[i - fwd] = tw_cmd.list[i];
348    tw_cmd.nlist -= fwd;
349    TW_RELS();
350} /* end tw_cmd_sort */
351
352
353/* tw_cmd_start():
354 *      Get the command list and sort it, if not done yet.
355 *      Reset the current pointer to the beginning of the command list
356 */
357/*ARGSUSED*/
358void
359tw_cmd_start(dfd, pat)
360    DIR *dfd;
361    Char *pat;
362{
363    static Char *defpath[] = { STRNULL, 0 };
364    SETDIR(dfd)
365    if ((tw_cmd_got & TW_FL_CMD) == 0) {
366        tw_cmd_free();
367        tw_cmd_cmd();
368        tw_cmd_got |= TW_FL_CMD;
369    }
370    if ((tw_cmd_got & TW_FL_ALIAS) == 0) {
371        tw_cmd_alias();
372        tw_cmd_got &= ~TW_FL_SORT;
373        tw_cmd_got |= TW_FL_ALIAS;
374    }
375    if ((tw_cmd_got & TW_FL_BUILTIN) == 0) {
376        tw_cmd_builtin();
377        tw_cmd_got &= ~TW_FL_SORT;
378        tw_cmd_got |= TW_FL_BUILTIN;
379    }
380    if ((tw_cmd_got & TW_FL_SORT) == 0) {
381        tw_cmd_sort();
382        tw_cmd_got |= TW_FL_SORT;
383    }
384
385    tw_cmd_state.cur = 0;
386    CLRDIR(tw_cmd_state.dfd)
387    if (tw_cmd_got & TW_FL_REL) {
388        struct varent *vp = adrof(STRpath);
389        if (vp && vp->vec)
390            tw_cmd_state.pathv = vp->vec;
391        else
392            tw_cmd_state.pathv = defpath;
393    }
394    else
395        tw_cmd_state.pathv = defpath;
396} /* tw_cmd_start */
397
398
399/* tw_cmd_next():
400 *      Return the next element in the command list or
401 *      Look for commands in the relative path components
402 */
403Char *
404tw_cmd_next(dir, flags)
405    Char *dir;
406    int  *flags;
407{
408    Char *ptr = NULL;
409
410    if (tw_cmd_state.cur < tw_cmd.nlist) {
411        *flags = TW_DIR_OK;
412        return tw_cmd.list[tw_cmd_state.cur++];
413    }
414
415    /*
416     * We need to process relatives in the path.
417     */
418    while (((tw_cmd_state.dfd == NULL) ||
419            ((ptr = tw_dir_next(tw_cmd_state.dfd)) == NULL)) &&
420           (*tw_cmd_state.pathv != NULL)) {
421
422        CLRDIR(tw_cmd_state.dfd)
423
424        while (*tw_cmd_state.pathv && tw_cmd_state.pathv[0][0] == '/')
425            tw_cmd_state.pathv++;
426        if ((ptr = *tw_cmd_state.pathv) != 0) {
427            /*
428             * We complete directories only on '.' should that
429             * be changed?
430             */
431            if (ptr[0] == '\0' || (ptr[0] == '.' && ptr[1] == '\0')) {
432                *dir = '\0';
433                tw_cmd_state.dfd = opendir(".");
434                *flags = TW_DIR_OK | TW_EXEC_CHK;
435            }
436            else {
437                copyn(dir, *tw_cmd_state.pathv, FILSIZ);
438                catn(dir, STRslash, FILSIZ);
439                tw_cmd_state.dfd = opendir(short2str(*tw_cmd_state.pathv));
440                *flags = TW_EXEC_CHK;
441            }
442            tw_cmd_state.pathv++;
443        }
444    }
445    return ptr;
446} /* end tw_cmd_next */
447
448
449/* tw_vptr_start():
450 *      Find the first variable in the variable list
451 */
452static void
453tw_vptr_start(c)
454    struct varent *c;
455{
456    tw_vptr = c;                /* start at beginning of variable list */
457
458    for (;;) {
459        while (tw_vptr->v_left)
460            tw_vptr = tw_vptr->v_left;
461x:
462        if (tw_vptr->v_parent == 0) {   /* is it the header? */
463            tw_vptr = NULL;
464            return;
465        }
466        if (tw_vptr->v_name)
467            return;             /* found first one */
468        if (tw_vptr->v_right) {
469            tw_vptr = tw_vptr->v_right;
470            continue;
471        }
472        do {
473            c = tw_vptr;
474            tw_vptr = tw_vptr->v_parent;
475        } while (tw_vptr->v_right == c);
476        goto x;
477    }
478} /* end tw_shvar_start */
479
480
481/* tw_shvar_next():
482 *      Return the next shell variable
483 */
484/*ARGSUSED*/
485Char *
486tw_shvar_next(dir, flags)
487    Char *dir;
488    int  *flags;
489{
490    register struct varent *p;
491    register struct varent *c;
492    register Char *cp;
493
494    if ((p = tw_vptr) == NULL)
495        return (NULL);          /* just in case */
496
497    cp = p->v_name;             /* we know that this name is here now */
498
499    /* now find the next one */
500    for (;;) {
501        if (p->v_right) {       /* if we can go right */
502            p = p->v_right;
503            while (p->v_left)
504                p = p->v_left;
505        }
506        else {                  /* else go up */
507            do {
508                c = p;
509                p = p->v_parent;
510            } while (p->v_right == c);
511        }
512        if (p->v_parent == 0) { /* is it the header? */
513            tw_vptr = NULL;
514            return (cp);
515        }
516        if (p->v_name) {
517            tw_vptr = p;        /* save state for the next call */
518            return (cp);
519        }
520    }
521} /* end tw_shvar_next */
522
523
524/* tw_envvar_next():
525 *      Return the next environment variable
526 */
527/*ARGSUSED*/
528Char *
529tw_envvar_next(dir, flags)
530    Char *dir;
531    int *flags;
532{
533    Char   *ps, *pd;
534
535    if (tw_env == NULL || *tw_env == NULL)
536        return (NULL);
537    for (ps = *tw_env, pd = tw_retname;
538         *ps && *ps != '=' && pd <= &tw_retname[MAXPATHLEN]; *pd++ = *ps++)
539        continue;
540    *pd = '\0';
541    tw_env++;
542    return (tw_retname);
543} /* end tw_envvar_next */
544
545
546/* tw_var_start():
547 *      Begin the list of the shell and environment variables
548 */
549/*ARGSUSED*/
550void
551tw_var_start(dfd, pat)
552    DIR *dfd;
553    Char *pat;
554{
555    SETDIR(dfd)
556    tw_vptr_start(&shvhed);
557    tw_env = STR_environ;
558} /* end tw_var_start */
559
560
561/* tw_alias_start():
562 *      Begin the list of the shell aliases
563 */
564/*ARGSUSED*/
565void
566tw_alias_start(dfd, pat)
567    DIR *dfd;
568    Char *pat;
569{
570    SETDIR(dfd)
571    tw_vptr_start(&aliases);
572    tw_env = NULL;
573} /* tw_alias_start */
574
575
576/* tw_complete_start():
577 *      Begin the list of completions
578 */
579/*ARGSUSED*/
580void
581tw_complete_start(dfd, pat)
582    DIR *dfd;
583    Char *pat;
584{
585    extern struct varent completions;
586    SETDIR(dfd)
587    tw_vptr_start(&completions);
588    tw_env = NULL;
589} /* end tw_complete_start */
590
591
592/* tw_var_next():
593 *      Return the next shell or environment variable
594 */
595Char *
596tw_var_next(dir, flags)
597    Char *dir;
598    int  *flags;
599{
600    Char *ptr = NULL;
601
602    if (tw_vptr)
603        ptr = tw_shvar_next(dir, flags);
604    if (!ptr && tw_env)
605        ptr = tw_envvar_next(dir, flags);
606    return ptr;
607} /* end tw_var_next */
608
609
610/* tw_logname_start():
611 *      Initialize lognames to the beginning of the list
612 */
613/*ARGSUSED*/
614void
615tw_logname_start(dfd, pat)
616    DIR *dfd;
617    Char *pat;
618{
619    SETDIR(dfd)
620#ifndef _VMS_POSIX
621    (void) setpwent();  /* Open passwd file */
622#endif /* atp vmsposix */
623} /* end tw_logname_start */
624
625
626/* tw_logname_next():
627 *      Return the next entry from the passwd file
628 */
629/*ARGSUSED*/
630Char *
631tw_logname_next(dir, flags)
632    Char *dir;
633    int  *flags;
634{
635    static Char retname[MAXPATHLEN];
636    struct passwd *pw;
637    /*
638     * We don't want to get interrupted inside getpwent()
639     * because the yellow pages code is not interruptible,
640     * and if we call endpwent() immediatetely after
641     * (in pintr()) we may be freeing an invalid pointer
642     */
643    TW_HOLD();
644#ifndef _VMS_POSIX
645    /* ISC does not declare getpwent()? */
646    pw = (struct passwd *) getpwent();
647#endif /* atp vmsposix */
648    TW_RELS();
649
650    if (pw == NULL) {
651#ifdef YPBUGS
652        fix_yp_bugs();
653#endif
654        return (NULL);
655    }
656    (void) Strcpy(retname, str2short(pw->pw_name));
657    return (retname);
658} /* end tw_logname_next */
659
660
661/* tw_logname_end():
662 *      Close the passwd file to finish th logname list
663 */
664void
665tw_logname_end()
666{
667#ifdef YPBUGS
668    fix_yp_bugs();
669#endif
670#ifndef _VMS_POSIX
671   (void) endpwent();
672#endif /* atp vmsposix */
673} /* end tw_logname_end */
674
675
676/* tw_file_start():
677 *      Initialize the directory for the file list
678 */
679/*ARGSUSED*/
680void
681tw_file_start(dfd, pat)
682    DIR *dfd;
683    Char *pat;
684{
685    struct varent *vp;
686    SETDIR(dfd)
687    if ((vp = adrof(STRcdpath)) != NULL)
688        tw_env = vp->vec;
689} /* end tw_file_start */
690
691
692/* tw_file_next():
693 *      Return the next file in the directory
694 */
695Char *
696tw_file_next(dir, flags)
697    Char *dir;
698    int  *flags;
699{
700    Char *ptr = tw_dir_next(tw_dir_fd);
701    if (ptr == NULL && (*flags & TW_DIR_OK) != 0) {
702        CLRDIR(tw_dir_fd)
703        while (tw_env && *tw_env)
704            if ((tw_dir_fd = opendir(short2str(*tw_env))) != NULL)
705                break;
706            else
707                tw_env++;
708               
709        if (tw_dir_fd) {
710            copyn(dir, *tw_env++, MAXPATHLEN);
711            catn(dir, STRslash, MAXPATHLEN);
712            ptr = tw_dir_next(tw_dir_fd);
713        }
714    }
715    return ptr;
716} /* end tw_file_next */
717
718
719/* tw_dir_end():
720 *      Clear directory related lists
721 */
722void
723tw_dir_end()
724{
725   CLRDIR(tw_dir_fd)
726   CLRDIR(tw_cmd_state.dfd)
727} /* end tw_dir_end */
728
729
730/* tw_item_free():
731 *      Free the item list
732 */
733void
734tw_item_free()
735{
736    tw_str_free(&tw_item);
737} /* end tw_item_free */
738
739
740/* tw_item_get():
741 *      Return the list of items
742 */
743Char **
744tw_item_get()
745{
746    return tw_item.list;
747} /* end tw_item_get */
748
749
750/* tw_item_add():
751 *      Return a new item
752 */
753Char *
754tw_item_add(len)
755    int len;
756{
757     return tw_str_add(&tw_item, len);
758} /* tw_item_add */
759
760
761/* tw_item_find():
762 *      Find the string if it exists in the item list
763 *      end return it.
764 */
765Char *
766tw_item_find(str)
767    Char    *str;
768{
769    int i;
770
771    if (tw_item.list == NULL || str == NULL)
772        return NULL;
773
774    for (i = 0; i < tw_item.nlist; i++)
775        if (tw_item.list[i] != NULL && Strcmp(tw_item.list[i], str) == 0)
776            return tw_item.list[i];
777    return NULL;
778} /* end tw_item_find */
779
780
781/* tw_vl_start():
782 *      Initialize a variable list
783 */
784void
785tw_vl_start(dfd, pat)
786    DIR *dfd;
787    Char *pat;
788{
789    SETDIR(dfd)
790    if ((tw_vptr = adrof(pat)) != NULL) {
791        tw_env = tw_vptr->vec;
792        tw_vptr = NULL;
793    }
794    else
795        tw_env = NULL;
796} /* end tw_vl_start */
797
798
799/*
800 * Initialize a word list
801 */
802void
803tw_wl_start(dfd, pat)
804    DIR *dfd;
805    Char *pat;
806{
807    SETDIR(dfd);
808    tw_word = pat;
809} /* end tw_wl_start */
810
811
812/*
813 * Return the next word from the word list
814 */
815/*ARGSUSED*/
816Char *
817tw_wl_next(dir, flags)
818    Char *dir;
819    int *flags;
820{
821    if (tw_word == NULL || tw_word[0] == '\0')
822        return NULL;
823   
824    while (*tw_word && Isspace(*tw_word)) tw_word++;
825
826    for (dir = tw_word; *tw_word && !Isspace(*tw_word); tw_word++)
827        continue;
828    if (*tw_word)
829        *tw_word++ = '\0';
830    return *dir ? dir : NULL;
831} /* end tw_wl_next */
832
833
834/* tw_bind_start():
835 *      Begin the list of the shell bindings
836 */
837/*ARGSUSED*/
838void
839tw_bind_start(dfd, pat)
840    DIR *dfd;
841    Char *pat;
842{
843    SETDIR(dfd)
844    tw_bind = FuncNames;
845} /* end tw_bind_start */
846
847
848/* tw_bind_next():
849 *      Begin the list of the shell bindings
850 */
851/*ARGSUSED*/
852Char *
853tw_bind_next(dir, flags)
854    Char *dir;
855    int *flags;
856{
857    char *ptr;
858    if (tw_bind && tw_bind->name) {
859        for (ptr = tw_bind->name, dir = tw_retname; (*dir++ = *ptr++) != '\0';)
860            continue;
861        tw_bind++;
862        return(tw_retname);
863    }
864    return NULL;
865} /* end tw_bind_next */
866
867
868/* tw_limit_start():
869 *      Begin the list of the shell limitings
870 */
871/*ARGSUSED*/
872void
873tw_limit_start(dfd, pat)
874    DIR *dfd;
875    Char *pat;
876{
877    SETDIR(dfd)
878#ifndef HAVENOLIMIT
879    tw_limit = limits;
880#endif /* ! HAVENOLIMIT */
881} /* end tw_limit_start */
882
883
884/* tw_limit_next():
885 *      Begin the list of the shell limitings
886 */
887/*ARGSUSED*/
888Char *
889tw_limit_next(dir, flags)
890    Char *dir;
891    int *flags;
892{
893#ifndef HAVENOLIMIT
894    char *ptr;
895    if (tw_limit && tw_limit->limname) {
896        for (ptr = tw_limit->limname, dir = tw_retname;
897             (*dir++ = *ptr++) != '\0';)
898            continue;
899        tw_limit++;
900        return(tw_retname);
901    }
902#endif /* ! HAVENOLIMIT */
903    return NULL;
904} /* end tw_limit_next */
905
906
907/* tw_sig_start():
908 *      Begin the list of the shell sigings
909 */
910/*ARGSUSED*/
911void
912tw_sig_start(dfd, pat)
913    DIR *dfd;
914    Char *pat;
915{
916    SETDIR(dfd)
917    tw_index = 0;
918} /* end tw_sig_start */
919
920
921/* tw_sig_next():
922 *      Begin the list of the shell sigings
923 */
924/*ARGSUSED*/
925Char *
926tw_sig_next(dir, flags)
927    Char *dir;
928    int *flags;
929{
930    char *ptr;
931
932    for (;tw_index < NSIG && tw_index < mesg_size; tw_index++) {
933
934        if (mesg[tw_index].iname == NULL)
935            continue;
936
937        for (ptr = mesg[tw_index].iname, dir = tw_retname;
938             (*dir++ = *ptr++) != '\0';)
939            continue;
940        tw_index++;
941        return(tw_retname);
942    }
943    return NULL;
944} /* end tw_sig_next */
945
946
947/* tw_job_start():
948 *      Begin the list of the shell jobings
949 */
950/*ARGSUSED*/
951void
952tw_job_start(dfd, pat)
953    DIR *dfd;
954    Char *pat;
955{
956    SETDIR(dfd)
957    tw_index = 1;
958} /* end tw_job_start */
959
960
961/* tw_job_next():
962 *      Begin the list of the shell jobings
963 */
964/*ARGSUSED*/
965Char *
966tw_job_next(dir, flags)
967    Char *dir;
968    int *flags;
969{
970    Char *ptr;
971    struct process *j;
972    for (;tw_index <= pmaxindex; tw_index++) {
973        for (j = proclist.p_next; j != NULL; j = j->p_next)
974            if (j->p_index == tw_index && j->p_procid == j->p_jobid)
975                break;
976        if (j == NULL)
977            continue;
978        for (ptr = j->p_command, dir = tw_retname; (*dir++ = *ptr++) != '\0';)
979            continue;
980        *dir = '\0';
981        tw_index++;
982        return(tw_retname);
983    }
984    return NULL;
985} /* end tw_job_next */
Note: See TracBrowser for help on using the repository browser.