OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [userland/] [ftp/] [ftp/] [glob.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 763 simons
/*
2
 * Copyright (c) 1980 Regents of the University of California.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. All advertising materials mentioning features or use of this software
14
 *    must display the following acknowledgement:
15
 *      This product includes software developed by the University of
16
 *      California, Berkeley and its contributors.
17
 * 4. 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.
20
 *
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.
32
 */
33
 
34
/*
35
 * From: @(#)glob.c     5.9 (Berkeley) 2/25/91
36
 */
37
char glob_rcsid[] =
38
  "$Id: glob.c,v 1.1 2002-03-25 22:32:01 simons Exp $";
39
 
40
/*
41
 * C-shell glob for random programs.
42
 */
43
 
44
#include <sys/param.h>
45
#include <sys/stat.h>
46
#include <dirent.h>
47
 
48
#include <pwd.h>
49
#include <errno.h>
50
#include <stdio.h>
51
#include <stdlib.h>
52
#include <string.h>
53
 
54
#include "ftp_var.h"  /* for protos only */
55
#include "glob.h"
56
 
57
#define QUOTE 0200
58
#define TRIM 0177
59
#define eq(a,b)         (strcmp(a, b)==0)
60
#define GAVSIZ          (ARG_MAX/6)
61
#define isdir(d)        ((d.st_mode & S_IFMT) == S_IFDIR)
62
 
63
const char *globerr;
64
extern const char *home;
65
 
66
typedef struct {
67
    const char *text;
68
} centry;
69
 
70
typedef struct {
71
    char *text;
72
} entry;
73
 
74
static entry *gargv;    /* Pointer to the (stack) arglist */
75
static entry *sortbas;
76
static int gargc;       /* Number args in gargv */
77
static int gnleft;      /* space left before we hit max args length */
78
 
79
static short gflag;
80
 
81
static int globcnt;
82
static const char *globchars = "`{[*?";
83
 
84
static char *gpath;
85
static char *gpathp, *lastgpathp;
86
static int globbed;
87
static const char *entp;
88
 
89
static int tglob(char c);
90
static char *strspl(const char *, const char *);
91
static char *strend(char *);
92
static char **copyblk(entry *);
93
static char **cloneblk(const centry *);
94
 
95
static void addpath(char c);
96
static void acollect(const char *);
97
static void collect(const char *);
98
static void expand(const char *);
99
static void Gcat(const char *, const char *);
100
static void ginit(entry *);
101
static void matchdir(const char *);
102
static void rscan(centry *, int (*f)(char));
103
static void sort(void);
104
static void efree(entry *);
105
static int amatch(const char *, const char *);
106
static int execbrc(const char *, const char *);
107
static int match(const char *, const char *);
108
 
109
static int gethdir(char *homedir);
110
static int letter(char c);
111
static int digit(char c);
112
static int any(int c, const char *s);
113
 
114
char **
115
ftpglob(const char *v)
116
{
117
        char agpath[BUFSIZ];
118
        entry agargv[GAVSIZ];
119
        centry vv[2];
120
        vv[0].text = v;
121
        vv[1].text = NULL;
122
        gflag = 0;
123
        rscan(vv, tglob);
124
        if (gflag == 0) {
125
                return cloneblk(vv);
126
        }
127
 
128
        globerr = 0;
129
 
130
        gpath = agpath;
131
        gpathp = gpath;
132
        *gpathp = 0;
133
        /* added ()'s to sizeof, (ambigious math for the compiler) */
134
        lastgpathp = agpath + (sizeof(agpath)- 2);
135
 
136
        ginit(agargv);
137
        globcnt = 0;
138
        collect(v);
139
        if (globcnt == 0 && (gflag&1)) {
140
                efree(gargv);
141
                gargv = NULL;
142
                return NULL;
143
        }
144
        else {
145
                char **rv = copyblk(gargv);
146
                gargv = NULL;
147
                return rv;
148
        }
149
}
150
 
151
static
152
void
153
ginit(entry *agargv)
154
{
155
        agargv[0].text = NULL;
156
        gargv = agargv;
157
        sortbas = agargv;
158
        gargc = 0;
159
        gnleft = ARG_MAX - 4;
160
}
161
 
162
static
163
void
164
collect(const char *as)
165
{
166
        if (eq(as, "{") || eq(as, "{}")) {
167
                Gcat(as, "");
168
                sort();
169
        }
170
        else {
171
                acollect(as);
172
        }
173
}
174
 
175
static
176
void
177
acollect(const char *as)
178
{
179
        int ogargc = gargc;
180
 
181
        gpathp = gpath; *gpathp = 0; globbed = 0;
182
        expand(as);
183
        if (gargc != ogargc)
184
                sort();
185
}
186
 
187
static
188
void
189
sort(void)
190
{
191
        entry *p1, *p2, c;
192
        entry *Gvp = &gargv[gargc];
193
 
194
        p1 = sortbas;
195
        while (p1 < Gvp-1) {
196
                p2 = p1;
197
                while (++p2 < Gvp)
198
                        if (strcmp(p1->text, p2->text) > 0)
199
                                c = *p1, *p1 = *p2, *p2 = c;
200
                p1++;
201
        }
202
        sortbas = Gvp;
203
}
204
 
205
static
206
void
207
expand(const char *as)
208
{
209
        const char *cs;
210
        const char *oldcs;
211
        char *sgpathp;
212
        struct stat stb;
213
 
214
        sgpathp = gpathp;
215
        cs = as;
216
        if (*cs == '~' && gpathp == gpath) {
217
                addpath('~');
218
                for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
219
                        addpath(*cs++);
220
                if (!*cs || *cs == '/') {
221
                        if (gpathp != gpath + 1) {
222
                                *gpathp = 0;
223
                                if (gethdir(gpath + 1))
224
                                        globerr = "Unknown user name after ~";
225
                                /*
226
                                 * Was: strcpy(gpath, gpath + 1);
227
                                 * but that's WRONG
228
                                 */
229
                                memmove(gpath, gpath+1, strlen(gpath+1)+1);
230
                        }
231
                        else {
232
                                (void) strcpy(gpath, home);
233
                        }
234
                        gpathp = strend(gpath);
235
                }
236
        }
237
        while (!any(*cs, globchars)) {
238
                if (*cs == 0) {
239
                        if (!globbed)
240
                                Gcat(gpath, "");
241
                        else if (stat(gpath, &stb) >= 0) {
242
                                Gcat(gpath, "");
243
                                globcnt++;
244
                        }
245
                        goto endit;
246
                }
247
                addpath(*cs++);
248
        }
249
        oldcs = cs;
250
        while (cs > as && *cs != '/')
251
                cs--, gpathp--;
252
        if (*cs == '/')
253
                cs++, gpathp++;
254
        *gpathp = 0;
255
        if (*oldcs == '{') {
256
                (void) execbrc(cs, ((char *)0));
257
                return;
258
        }
259
        matchdir(cs);
260
endit:
261
        gpathp = sgpathp;
262
        *gpathp = 0;
263
}
264
 
265
static
266
void
267
matchdir(const char *pattern)
268
{
269
        struct stat stb;
270
        register struct dirent *dp;
271
        DIR *dirp;
272
 
273
#if 0
274
#ifdef  __linux__
275
        if (gpath == NULL || *gpath == '\0')
276
                gpath = "./";
277
#endif
278
#endif
279
        dirp = opendir((!gpath || !*gpath) ? "./" : gpath);
280
        if (dirp == NULL) {
281
                if (globbed)
282
                        return;
283
                goto patherr2;
284
        }
285
        if (fstat(dirfd(dirp), &stb) < 0)
286
                goto patherr1;
287
        if (!isdir(stb)) {
288
                errno = ENOTDIR;
289
                goto patherr1;
290
        }
291
        while ((dp = readdir(dirp)) != NULL) {
292
                if (dp->d_ino == 0)
293
                        continue;
294
                if (match(dp->d_name, pattern)) {
295
                        Gcat(gpath, dp->d_name);
296
                        globcnt++;
297
                }
298
        }
299
        closedir(dirp);
300
        return;
301
 
302
patherr1:
303
        closedir(dirp);
304
patherr2:
305
        globerr = "Bad directory components";
306
}
307
 
308
static
309
int
310
execbrc(const char *p, const char *s)
311
{
312
        char restbuf[BUFSIZ + 2];
313
        const char *pe, *pm, *pl;
314
        int brclev = 0;
315
        char *lm, *sgpathp;
316
 
317
        for (lm = restbuf; *p != '{'; *lm++ = *p++)
318
                continue;
319
        for (pe = ++p; *pe; pe++)
320
        switch (*pe) {
321
 
322
        case '{':
323
                brclev++;
324
                continue;
325
 
326
        case '}':
327
                if (brclev == 0)
328
                        goto pend;
329
                brclev--;
330
                continue;
331
 
332
        case '[':
333
                for (pe++; *pe && *pe != ']'; pe++)
334
                        continue;
335
                continue;
336
        }
337
pend:
338
        brclev = 0;
339
        for (pl = pm = p; pm <= pe; pm++)
340
        switch (*pm & (QUOTE|TRIM)) {
341
 
342
        case '{':
343
                brclev++;
344
                continue;
345
 
346
        case '}':
347
                if (brclev) {
348
                        brclev--;
349
                        continue;
350
                }
351
                goto doit;
352
 
353
        case ','|QUOTE:
354
        case ',':
355
                if (brclev)
356
                        continue;
357
doit:
358
#if 0
359
                savec = *pm;
360
                *pm = 0;
361
                strcpy(lm, pl);
362
                *pm = savec;
363
#else
364
                strncpy(lm, pl, pm-pl);
365
                lm[pm-pl] = 0;
366
#endif
367
                (void) strcat(restbuf, pe + 1);
368
                if (s == 0) {
369
                        sgpathp = gpathp;
370
                        expand(restbuf);
371
                        gpathp = sgpathp;
372
                        *gpathp = 0;
373
                }
374
                else if (amatch(s, restbuf)) {
375
                        return (1);
376
                }
377
                sort();
378
                pl = pm + 1;
379
                if (brclev)
380
                        return (0);
381
                continue;
382
 
383
        case '[':
384
                for (pm++; *pm && *pm != ']'; pm++)
385
                        continue;
386
                if (!*pm)
387
                        pm--;
388
                continue;
389
        }
390
        if (brclev)
391
                goto doit;
392
        return (0);
393
}
394
 
395
static
396
int
397
match(const char *s, const char *p)
398
{
399
        int c;
400
        const char *sentp;
401
        char sglobbed = globbed;
402
 
403
        if (*s == '.' && *p != '.')
404
                return (0);
405
        sentp = entp;
406
        entp = s;
407
        c = amatch(s, p);
408
        entp = sentp;
409
        globbed = sglobbed;
410
        return (c);
411
}
412
 
413
static
414
int
415
amatch(const char *s, const char *p)
416
{
417
        register int scc;
418
        int ok, lc;
419
        char *sgpathp;
420
        struct stat stb;
421
        int c, cc;
422
 
423
        globbed = 1;
424
        for (;;) {
425
                scc = *s++ & TRIM;
426
                switch (c = *p++) {
427
 
428
                case '{':
429
                        return (execbrc(p - 1, s - 1));
430
 
431
                case '[':
432
                        ok = 0;
433
                        lc = 077777;
434
                        while ((cc = *p++) != 0) {
435
                                if (cc == ']') {
436
                                        if (ok)
437
                                                break;
438
                                        return (0);
439
                                }
440
                                if (cc == '-') {
441
                                        if (lc <= scc && scc <= *p++)
442
                                                ok++;
443
                                } else
444
                                        if (scc == (lc = cc))
445
                                                ok++;
446
                        }
447
                        if (cc == 0) {
448
                                if (ok)
449
                                        p--;
450
                                else
451
                                        return 0;
452
                        }
453
                        continue;
454
 
455
                case '*':
456
                        if (!*p)
457
                                return (1);
458
                        if (*p == '/') {
459
                                p++;
460
                                goto slash;
461
                        }
462
                        s--;
463
                        do {
464
                                if (amatch(s, p))
465
                                        return (1);
466
                        } while (*s++);
467
                        return (0);
468
 
469
                case 0:
470
                        return (scc == 0);
471
 
472
                default:
473
                        if (c != scc)
474
                                return (0);
475
                        continue;
476
 
477
                case '?':
478
                        if (scc == 0)
479
                                return (0);
480
                        continue;
481
 
482
                case '/':
483
                        if (scc)
484
                                return (0);
485
slash:
486
                        s = entp;
487
                        sgpathp = gpathp;
488
                        while (*s)
489
                                addpath(*s++);
490
                        addpath('/');
491
                        if (stat(gpath, &stb) == 0 && isdir(stb)) {
492
                                if (*p == 0) {
493
                                        Gcat(gpath, "");
494
                                        globcnt++;
495
                                } else {
496
                                        expand(p);
497
                                }
498
                        }
499
                        gpathp = sgpathp;
500
                        *gpathp = 0;
501
                        return (0);
502
                }
503
        }
504
}
505
 
506
#if 0 /* dead code */
507
static
508
int
509
Gmatch(const char *s, const char *p)
510
{
511
        register int scc;
512
        int ok, lc;
513
        int c, cc;
514
 
515
        for (;;) {
516
                scc = *s++ & TRIM;
517
                switch (c = *p++) {
518
 
519
                case '[':
520
                        ok = 0;
521
                        lc = 077777;
522
                        while ((cc = *p++) != 0) {
523
                                if (cc == ']') {
524
                                        if (ok)
525
                                                break;
526
                                        return (0);
527
                                }
528
                                if (cc == '-') {
529
                                        if (lc <= scc && scc <= *p++)
530
                                                ok++;
531
                                } else
532
                                        if (scc == (lc = cc))
533
                                                ok++;
534
                        }
535
                        if (cc == 0)
536
                                if (ok)
537
                                        p--;
538
                                else
539
                                        return 0;
540
                        continue;
541
 
542
                case '*':
543
                        if (!*p)
544
                                return (1);
545
                        for (s--; *s; s++)
546
                                if (Gmatch(s, p))
547
                                        return (1);
548
                        return (0);
549
 
550
                case 0:
551
                        return (scc == 0);
552
 
553
                default:
554
                        if ((c & TRIM) != scc)
555
                                return (0);
556
                        continue;
557
 
558
                case '?':
559
                        if (scc == 0)
560
                                return (0);
561
                        continue;
562
 
563
                }
564
        }
565
}
566
#endif
567
 
568
static
569
void
570
Gcat(const char *s1, const char *s2)
571
{
572
        int len = strlen(s1) + strlen(s2) + 1;
573
 
574
        if (len >= gnleft || gargc >= GAVSIZ - 1) {
575
                globerr = "Arguments too long";
576
        }
577
        else {
578
                gargc++;
579
                gnleft -= len;
580
                gargv[gargc].text = NULL;
581
                gargv[gargc - 1].text = strspl(s1, s2);
582
        }
583
}
584
 
585
static
586
void
587
addpath(char c)
588
{
589
 
590
        if (gpathp >= lastgpathp)
591
                globerr = "Pathname too long";
592
        else {
593
                *gpathp++ = c;
594
                *gpathp = 0;
595
        }
596
}
597
 
598
static void
599
rscan(centry *t, int (*f)(char))
600
{
601
        const char *p;
602
        char c;
603
 
604
        while ((p = (t++)->text) != NULL) {
605
                if (f == tglob) {
606
                        if (*p == '~')
607
                                gflag |= 2;
608
                        else if (eq(p, "{") || eq(p, "{}"))
609
                                continue;
610
                }
611
                while ((c = *p++) != 0)
612
                        (*f)(c);
613
        }
614
}
615
 
616
static
617
int
618
tglob(char c)
619
{
620
 
621
        if (any(c, globchars))
622
                gflag |= c == '{' ? 2 : 1;
623
        return (c);
624
}
625
 
626
static int
627
letter(char c)
628
{
629
        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
630
}
631
 
632
static int
633
digit(char c)
634
{
635
        return (c >= '0' && c <= '9');
636
}
637
 
638
static
639
int
640
any(int c, const char *s)
641
{
642
        while (*s) if (*s++ == c) return 1;
643
        return 0;
644
}
645
 
646
static
647
int
648
cblklen(const centry *av)
649
{
650
        int i = 0;
651
        while ((av++)->text) i++;
652
        return i;
653
}
654
 
655
static
656
int
657
blklen(const entry *av)
658
{
659
        int i = 0;
660
        while ((av++)->text) i++;
661
        return i;
662
}
663
 
664
void
665
blkfree(char **av)
666
{
667
        int i;
668
        for (i=0; av[i]; i++) free(av[i]);
669
}
670
 
671
static
672
void
673
efree(entry *av)
674
{
675
    int i;
676
    for (i=0; av[i].text; i++) free(av[i].text);
677
}
678
 
679
static
680
char *
681
strspl(const char *cp, const char *dp)
682
{
683
        char *ep = malloc(strlen(cp) + strlen(dp) + 1);
684
        if (ep == NULL) fatal("Out of memory");
685
 
686
        strcpy(ep, cp);
687
        strcat(ep, dp);
688
        return ep;
689
}
690
 
691
static
692
char **
693
copyblk(entry *v)
694
{
695
        int i;
696
        char **nv = malloc((blklen(v) + 1) * sizeof(char **));
697
        if (nv == NULL) fatal("Out of memory");
698
 
699
        for (i=0; v[i].text; i++) {
700
            nv[i] = v[i].text;
701
            v[i].text = NULL;
702
        }
703
        nv[i] = NULL;
704
 
705
        return nv;
706
}
707
 
708
static
709
char **
710
cloneblk(const centry *v)
711
{
712
        int i;
713
        char **nv = malloc((cblklen(v) + 1) * sizeof(char **));
714
        if (nv == NULL) fatal("Out of memory");
715
 
716
        for (i=0; v[i].text; i++) {
717
            nv[i] = strdup(v[i].text);
718
        }
719
        nv[i] = NULL;
720
 
721
        return nv;
722
}
723
 
724
static
725
char *
726
strend(char *cp)
727
{
728
        while (*cp)
729
                cp++;
730
        return (cp);
731
}
732
/*
733
 * Extract a home directory from the password file
734
 * The argument points to a buffer where the name of the
735
 * user whose home directory is sought is currently.
736
 * We write the home directory of the user back there.
737
 *
738
 * XXX, this needs buffer length checking and stuff.
739
 */
740
static
741
int
742
gethdir(char *homedir)
743
{
744
        register struct passwd *pp = getpwnam(homedir);
745
 
746
        if (!pp || homedir + strlen(pp->pw_dir) >= lastgpathp)
747
                return 1;
748
        strcpy(homedir, pp->pw_dir);
749
        return 0;
750
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.