summaryrefslogtreecommitdiff
path: root/theos/_setargv.c
blob: d76f955dd667f1fe85bf85a008de02d4af53b1f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.

  See the accompanying file LICENSE, version 1999-Oct-05 or later
  (the contents of which are also included in zip.h) for terms of use.
  If, for some reason, both of these files are missing, the Info-ZIP license
  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
*/
/*
 * __setargv.c - command argument expander
 *
 * Author  : Jean-Michel Dubois
 * Date    : 09/26/92
 *
 * Function: Expands the command line arguments by replacing any filename
 *           including wilcards by the sorted list of matching files name.
 *           Strings beginning by a dash are considered as options and left
 *           unchanged.
 *
 * Syntax  : void _setargv(int *argc, char ***argv);
 *
 * Returns : new argc. Caller's argc and argv are updated.
 *           If a insufficient memory condition occurs, return 0 and errno
 *           is set to ENOMEM.
 *
 * Example :
 *              main(int argc, char **argv)
 *              {
 *                      if (_setargv(&argc, &argv)) {
 *                              ...
 */
#pragma library

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <scr.h>
#include <peek.h>

/* Allocate argv array in 16 entries chunks */

static int allocarg(int n, int l, char ***nargv, char *s)
{
    if ((n+1) > l) {    /* If array full */
        l += 16;        /* increase size and reallocate */
        if (!(*nargv = (char **) realloc(*nargv,l * sizeof (void *)))) {
            errno = _errnum = ENOMEM;    /* Not enough memory */
            return 0;
        }
    }
    (*nargv)[n] = strdup(s);    /* Save argument */
    return l;            /* Return new maxsize */
}

/* Comparison function for qsort */

static int sortcmp(char **p, char **q)
{
    return stricmp(*p,*q);
}

/* Main body of the function */

int _setargv(int *argc, char ***argv)
{
    register int nargc;     /* New arguments counter */
    char **nargv;           /* New arguments pointers */
    register int i, l, base;
    char *p, *q, *r;
    char path[FILENAME_MAX];

    _errnum = 0;
    nargc = 0;          /* Initialise counter, size counter */
    l = *argc;          /* and new argument vector to the */
                        /* current argv array size */

    if ((nargv = (char **) calloc((size_t) *argc, sizeof (void *))) != NULL) {
        /* For each initial argument */
        for (i = 0; i < *argc; i++) {
            q = (*argv)[i];
            if (q[0] == '-' || ! testwild(q)) {
                /* if it begins with a dash or doesnt include
                 * wildcard simply add it to the new array
                 */
                if (! (l = allocarg(nargc, l, &nargv, q)))
                    return 0;    /* Not enough memory */
                nargc++;
            } else {
                /* else keep current counter for qsort */
                base = nargc;
                /* open directory with argument */
                diropen(q);
                while ((r = dirread()) != NULL) {
                    /* reduce path to given one */
                    if ((p = strrchr(q, '/')) != NULL) {
                        strncpy(path, q, p-q+1);
                        path[p-q+1] = '\0';
                    } else
                        path[0] = '\0';

                    if ((p = strrchr(r, '/')) != NULL)
                        strcat(path, p+1);
                    else
                        strcat(path, r);

                    if (peekscr(&SCR->searchseq[1]) == 255
                     && strchr(q, ':') == NULL) {
                        *strchr(path, ':') = '\0';
                    }
                    /* and add each matching filename. */
                    if (! (l = allocarg(nargc,l,&nargv,path)))
                        return 0;/* Not enough memory */
                    nargc++;
                }
                if (nargc == base) {
                    /* if no match found include wild card name */
                    if (! (l = allocarg(nargc, l, &nargv, q)))
                        return 0;    /* Not enough memory */
                    nargc++;
                } else if ((nargc - base) > 1)
                    /* If more than one file name matchs */
                    /* sort arguments. */
                    qsort(&(nargv[base]),(size_t)nargc-base,
                        sizeof(void *),sortcmp);
                dirclose();
            }
        }
        /* Update caller's parameters */
        *argc = nargc;
        *argv = nargv;
        /* and sign on success */
        return nargc;
    }

    /* If it is not possible to allocate initial array, sign on error */
    _errnum = ENOMEM;
    return 0;
}