1/*
2  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.
3
4  See the accompanying file LICENSE, version 2000-Apr-09 or later
5  (the contents of which are also included in unzip.h) for terms of use.
6  If, for some reason, all these files are missing, the Info-ZIP license
7  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
8*/
9/*
10 * _setargv.c - derived from an command argument expander
11 *
12 * Author  : Jean-Michel Dubois
13 * Date    : 13-Dec-98
14 *
15 * Function: Looks for member names (fn.ft.mb) and add the libraries names
16 *           (fn.ft) to the list of files to zip to force inclusion of
17 *           libraries if necessary.
18 *           Strings beginning by a dash are considered as options and left
19 *           unchanged.
20 *
21 * Syntax  : void _setargv(int *argc, char ***argv);
22 *
23 * Returns : new argc. Caller's argc and argv are updated.
24 *       If a insufficient memory condition occurs, return 0 and errno
25 *       is set to ENOMEM.
26 *
27 * Example :
28 *      main(int argc, char **argv)
29 *      {
30 *          if (_setargv(&argc, &argv)) {
31 *              ...
32 */
33#pragma library
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <malloc.h>
39#include <errno.h>
40#include <scr.h>
41#include <peek.h>
42
43/* Allocate argv array in 16 entries chunks */
44
45static int allocarg(int n, int asize, char ***nargv, char *s)
46{
47    if ((n+1) > asize) {    /* If array full */
48        asize += 16;        /* increase size and reallocate */
49        if (!(*nargv = (char **) realloc(*nargv, asize * sizeof (void *)))) {
50            errno = _errnum = ENOMEM;    /* Not enough memory */
51            return 0;
52        }
53    }
54    (*nargv)[n] = strdup(s);    /* Save argument */
55    return asize;               /* Return new maxsize */
56}
57
58/* check if file is a member of a library */
59
60static int ismember(char* path)
61{
62    char* p;
63
64    if ((p = strrchr(path, '/')) == NULL)
65        p = path;
66    return ((p = strchr(p, '.')) && (p = strchr(p + 1, '.')));
67}
68
69/* extract library name from a file name */
70
71static char* libname(char* path)
72{
73    char* p;
74    static char lib[256];
75    char disk[3];
76
77    strcpy(lib, path);
78    if (p = strrchr(lib, ':')) {
79        strncpy(disk, p, 2);
80        disk[2] = '\0';
81        *p = '\0' ;
82    } else
83        disk[0] = '\0';
84
85    if ((p = strrchr(lib, '/')) == NULL)
86        p = lib;
87
88    p = strchr(p, '.');
89    p = strchr(p + 1, '.');
90    *p = 0;
91    strcat(lib, disk);
92    return lib;
93}
94
95/* Main body of the function */
96
97int _setargv(int *argc, char ***argv)
98{
99    register int nargc;     /* New arguments counter */
100    char **nargv;           /* New arguments pointers */
101    register int i, j;
102    int asize;              /* argv array size */
103    char *arg;
104    char lib[256];
105
106    _errnum = 0;
107    nargc = 0;          /* Initialise counter, size counter */
108    asize = *argc;      /* and new argument vector to the */
109                        /* current argv array size */
110
111    if ((nargv = (char **) calloc((size_t) *argc, sizeof (void *))) != NULL) {
112        /* For each initial argument */
113        for (i = 0; i < *argc; i++) {
114            arg = (*argv)[i];
115#ifdef DEBUG
116            fprintf(stderr, "checking arg: %s", arg);
117#endif
118            if (i == 0 || *arg == '-' || ! ismember(arg)) {
119                /* if it begins with a dash or doesn't include
120                 * a library name simply add it to the new array */
121                if (! (asize = allocarg(nargc, asize, &nargv, arg)))
122                    return 0;   /* Not enough memory */
123                nargc++;
124            } else {
125                short insert;
126                strcpy(lib, libname(arg));
127                /* add library name if necessary */
128                for (j = 2, insert = 1; i < nargc; i++) {
129                    if (ismember(nargv[i])
130                     && ! strcmp(lib, libname(nargv[i]))) {
131                        insert = 0;
132                        break;
133                    }
134                }
135                if (insert) {
136#ifdef DEBUG
137                    fprintf(stderr, "inserting lib %s ", lib);
138#endif
139                    if (! (asize = allocarg(nargc, asize, &nargv, lib)))
140                        return 0;   /* Not enough memory */
141                    nargc++;
142                }
143                /* add file name */
144#ifdef DEBUG
145                fprintf(stderr, "inserting file %s", arg);
146#endif
147                if (! (asize = allocarg(nargc, asize, &nargv, arg)))
148                    return 0;   /* Not enough memory */
149                nargc++;
150            }
151#ifdef DEBUG
152            fprintf(stderr, "\n");
153#endif
154        }
155        /* Update caller's parameters */
156        *argc = nargc;
157        *argv = nargv;
158        /* and sign on success */
159        return nargc;
160    }
161
162    /* If it is not possible to allocate initial array, sign on error */
163    _errnum = ENOMEM;
164    return 0;
165}
166