1 /** \ingroup rpmio
2  * \file rpmio/argv.c
3  */
4 
5 #include "system.h"
6 
7 #include <stdlib.h>
8 #include <rpm/argv.h>
9 #include <rpm/rpmstring.h>
10 
11 #include "debug.h"
12 
argvPrint(const char * msg,ARGV_const_t argv,FILE * fp)13 void argvPrint(const char * msg, ARGV_const_t argv, FILE * fp)
14 {
15     ARGV_const_t av;
16 
17     if (fp == NULL) fp = stderr;
18 
19     if (msg)
20 	fprintf(fp, "===================================== %s\n", msg);
21 
22     if (argv)
23     for (av = argv; *av; av++)
24 	fprintf(fp, "%s\n", *av);
25 
26 }
27 
argvNew(void)28 ARGV_t argvNew(void)
29 {
30     ARGV_t argv = xcalloc(1, sizeof(*argv));
31     return argv;
32 }
33 
argiFree(ARGI_t argi)34 ARGI_t argiFree(ARGI_t argi)
35 {
36     if (argi) {
37 	argi->nvals = 0;
38 	free(argi->vals);
39 	free(argi);
40     }
41     return NULL;
42 }
43 
argvFree(ARGV_t argv)44 ARGV_t argvFree(ARGV_t argv)
45 {
46     if (argv) {
47 	for (ARGV_t av = argv; *av; av++)
48 	    free(*av);
49 	free(argv);
50     }
51     return NULL;
52 }
53 
argiCount(ARGI_const_t argi)54 int argiCount(ARGI_const_t argi)
55 {
56     int nvals = 0;
57     if (argi)
58 	nvals = argi->nvals;
59     return nvals;
60 }
61 
argiData(ARGI_const_t argi)62 ARGint_t argiData(ARGI_const_t argi)
63 {
64     ARGint_t vals = NULL;
65     if (argi && argi->nvals > 0)
66 	vals = argi->vals;
67     return vals;
68 }
69 
argvCount(ARGV_const_t argv)70 int argvCount(ARGV_const_t argv)
71 {
72     int argc = 0;
73     if (argv)
74     while (argv[argc] != NULL)
75 	argc++;
76     return argc;
77 }
78 
argvData(ARGV_t argv)79 ARGV_t argvData(ARGV_t argv)
80 {
81     return argv;
82 }
83 
argvCmp(const void * a,const void * b)84 int argvCmp(const void * a, const void * b)
85 {
86     const char *astr = *(ARGV_t)a;
87     const char *bstr = *(ARGV_t)b;
88     return strcmp(astr, bstr);
89 }
90 
argvSort(ARGV_t argv,int (* compar)(const void *,const void *))91 int argvSort(ARGV_t argv, int (*compar)(const void *, const void *))
92 {
93     if (compar == NULL)
94 	compar = argvCmp;
95     if (argv)
96 	qsort(argv, argvCount(argv), sizeof(*argv), compar);
97     return 0;
98 }
99 
argvSearch(ARGV_const_t argv,const char * val,int (* compar)(const void *,const void *))100 ARGV_t argvSearch(ARGV_const_t argv, const char *val,
101 		int (*compar)(const void *, const void *))
102 {
103     if (argv == NULL)
104 	return NULL;
105     if (compar == NULL)
106 	compar = argvCmp;
107     return bsearch(&val, argv, argvCount(argv), sizeof(*argv), compar);
108 }
109 
argiAdd(ARGI_t * argip,int ix,int val)110 int argiAdd(ARGI_t * argip, int ix, int val)
111 {
112     ARGI_t argi;
113 
114     if (argip == NULL)
115 	return -1;
116     if (*argip == NULL)
117 	*argip = xcalloc(1, sizeof(**argip));
118     argi = *argip;
119     if (ix < 0)
120 	ix = argi->nvals;
121     if (ix >= argi->nvals) {
122 	argi->vals = xrealloc(argi->vals, (ix + 1) * sizeof(*argi->vals));
123 	memset(argi->vals + argi->nvals, 0,
124 		(ix - argi->nvals) * sizeof(*argi->vals));
125 	argi->nvals = ix + 1;
126     }
127     argi->vals[ix] = val;
128     return 0;
129 }
130 
argvAdd(ARGV_t * argvp,const char * val)131 int argvAdd(ARGV_t * argvp, const char *val)
132 {
133     ARGV_t argv;
134     int argc;
135 
136     if (argvp == NULL)
137 	return -1;
138     argc = argvCount(*argvp);
139     *argvp = xrealloc(*argvp, (argc + 1 + 1) * sizeof(**argvp));
140     argv = *argvp;
141     argv[argc++] = xstrdup(val);
142     argv[argc  ] = NULL;
143     return 0;
144 }
145 
argvAddNum(ARGV_t * argvp,int val)146 int argvAddNum(ARGV_t *argvp, int val)
147 {
148     char *valstr = NULL;
149     int rc;
150     rasprintf(&valstr, "%d", val);
151     rc = argvAdd(argvp, valstr);
152     free(valstr);
153     return rc;
154 }
155 
argvAppend(ARGV_t * argvp,ARGV_const_t av)156 int argvAppend(ARGV_t * argvp, ARGV_const_t av)
157 {
158     ARGV_t argv = *argvp;
159     int argc = argvCount(argv);
160     int ac = argvCount(av);
161     int i;
162 
163     argv = xrealloc(argv, (argc + ac + 1) * sizeof(*argv));
164     for (i = 0; i < ac; i++)
165 	argv[argc + i] = xstrdup(av[i]);
166     argv[argc + ac] = NULL;
167     *argvp = argv;
168     return 0;
169 }
170 
argvSplitString(const char * str,const char * seps,argvFlags flags)171 ARGV_t argvSplitString(const char * str, const char * seps, argvFlags flags)
172 {
173     char *dest = NULL;
174     ARGV_t argv;
175     int argc = 1;
176     const char * s;
177     char * t;
178     int c;
179 
180     if (str == NULL || seps == NULL)
181 	return NULL;
182 
183     dest = xmalloc(strlen(str) + 1);
184     for (argc = 1, s = str, t = dest; (c = *s); s++, t++) {
185 	if (strchr(seps, c)) {
186 	    argc++;
187 	    c = '\0';
188 	}
189 	*t = c;
190     }
191     *t = '\0';
192 
193     argv = xmalloc( (argc + 1) * sizeof(*argv));
194 
195     for (c = 0, s = dest; s < t; s+= strlen(s) + 1) {
196 	if (*s == '\0' && (flags & ARGV_SKIPEMPTY))
197 	    continue;
198 	argv[c] = xstrdup(s);
199 	c++;
200     }
201     argv[c] = NULL;
202     free(dest);
203     return argv;
204 }
205 
206 /* Backwards compatibility */
argvSplit(ARGV_t * argvp,const char * str,const char * seps)207 int argvSplit(ARGV_t * argvp, const char * str, const char * seps)
208 {
209     if (argvp) {
210 	*argvp = argvSplitString(str, seps, ARGV_SKIPEMPTY);
211     }
212     return 0;
213 }
214 
argvJoin(ARGV_const_t argv,const char * sep)215 char *argvJoin(ARGV_const_t argv, const char *sep)
216 {
217     int argc = 0;
218     size_t argvlen = 0;
219     char *dest = NULL;
220 
221     if (argv) {
222 	ARGV_const_t arg;
223 	for (arg = argv; *arg; arg++)
224 	    argvlen += strlen(*arg);
225 	argc = arg - argv;
226     }
227 
228     if (argc > 0) {
229 	size_t seplen = (sep != NULL) ? strlen(sep) : 0;
230 	char *p;
231 
232 	dest = xmalloc(argvlen + (seplen * (argc - 1)) + 1);
233 
234 	p = stpcpy(dest, argv[0]);
235 	for (int i = 1; i < argc; i++) {
236 	    if (seplen)
237 		p = stpcpy(p, sep);
238 	    p = stpcpy(p, argv[i]);
239 	}
240 	*p = '\0';
241     }
242 
243     return dest;
244 }
245 
246