Git init
[external/xmlsec1.git] / apps / cmdline.c
1 /** 
2  *
3  * XMLSec library
4  * 
5  * 
6  * See Copyright for the status of this software.
7  * 
8  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
9  */
10 #if defined(_MSC_VER)
11 #define snprintf _snprintf
12 #endif
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <time.h>
17 #include <string.h>
18 #include <assert.h>
19
20 #include "cmdline.h"
21
22 static int                      xmlSecAppCmdLineMatchParam      (const char* argvParam,
23                                                                  const char* paramName,
24                                                                  int canHaveNameString);
25 static xmlSecAppCmdLineParamPtr xmlSecAppCmdLineParamsListFind  (xmlSecAppCmdLineParamPtr* params,
26                                                                  xmlSecAppCmdLineParamTopic topics,
27                                                                  const char* name);
28 static int                      xmlSecAppCmdLineParamRead       (xmlSecAppCmdLineParamPtr param,
29                                                                  const char** argv, 
30                                                                  int argc, 
31                                                                  int pos);
32 static int                      xmlSecAppCmdLineTimeParamRead   (const char* str, 
33                                                                  time_t* t);
34
35 int
36 xmlSecAppCmdLineParamIsSet(xmlSecAppCmdLineParamPtr param) {
37     return(((param != NULL) && (param->value != NULL)) ? 1 : 0);
38 }
39
40 const char* 
41 xmlSecAppCmdLineParamGetString(xmlSecAppCmdLineParamPtr param) {
42     if(param->type != xmlSecAppCmdLineParamTypeString) {
43         fprintf(stderr, "Error: parameter \"%s\" is not string.\n", param->fullName);
44         return(NULL);
45     }
46     return((param->value != NULL) ? param->value->strValue : NULL);
47 }
48
49 const char* 
50 xmlSecAppCmdLineParamGetStringList(xmlSecAppCmdLineParamPtr param) {
51     if(param->type != xmlSecAppCmdLineParamTypeStringList) {
52         fprintf(stderr, "Error: parameter \"%s\" is not string list.\n", param->fullName);
53         return(NULL);
54     }
55     return((param->value != NULL) ? param->value->strListValue : NULL);
56 }
57
58 int 
59 xmlSecAppCmdLineParamGetInt(xmlSecAppCmdLineParamPtr param, int def) {
60     if(param->type != xmlSecAppCmdLineParamTypeNumber) {
61         fprintf(stderr, "Error: parameter \"%s\" is not integer.\n", param->fullName);
62         return(def);
63     }
64     return((param->value != NULL) ? param->value->intValue : def);
65 }
66
67 time_t
68 xmlSecAppCmdLineParamGetTime(xmlSecAppCmdLineParamPtr param, time_t def) {
69     if(param->type != xmlSecAppCmdLineParamTypeTime) {
70         fprintf(stderr, "Error: parameter \"%s\" is not time.\n", param->fullName);
71         return(def);
72     }
73     return((param->value != NULL) ? param->value->timeValue : def);
74 }
75
76 int 
77 xmlSecAppCmdLineParamsListParse(xmlSecAppCmdLineParamPtr* params,
78                                 xmlSecAppCmdLineParamTopic topics,
79                                 const char** argv, int argc, int pos) {
80     xmlSecAppCmdLineParamPtr param;
81     int ii;
82     int ret;
83     
84     assert(params != NULL);
85     assert(argv != NULL);
86     
87     while((pos < argc) && (argv[pos][0] == '-')) {
88         param = xmlSecAppCmdLineParamsListFind(params, topics, argv[pos]);
89         if(param == NULL) {
90             fprintf(stderr, "Error: parameter \"%s\" is not supported or the requested\nfeature might have been disabled during compilation.\n", argv[pos]);
91             return(-1);
92         }
93         
94         ret = xmlSecAppCmdLineParamRead(param, argv, argc, pos);
95         if(ret < pos) {
96             fprintf(stderr, "Error: failed to parse parameter \"%s\".\n", argv[pos]);
97             return(-1);
98         }
99         pos = ret + 1;
100     }
101     
102     /* check that all parameters at the end are filenames */
103     for(ii = pos; (ii < argc); ++ii) {
104         if(argv[ii][0] == '-') {
105             fprintf(stderr, "Error: filename is expected instead of parameter \"%s\".\n", argv[ii]);
106             return(-1);
107             
108         }
109     }
110     
111     
112     
113     return(pos);
114 }
115
116 void 
117 xmlSecAppCmdLineParamsListClean(xmlSecAppCmdLineParamPtr* params) {
118     xmlSecAppCmdLineValuePtr tmp;
119     size_t i;
120     
121     assert(params != NULL);
122     
123     for(i = 0; params[i] != NULL; ++i) {
124         while(params[i]->value != NULL) {
125             tmp = params[i]->value;
126             params[i]->value = params[i]->value->next;
127             xmlSecAppCmdLineValueDestroy(tmp);
128         }
129     }
130 }
131
132 void 
133 xmlSecAppCmdLineParamsListPrint(xmlSecAppCmdLineParamPtr* params,
134                                 xmlSecAppCmdLineParamTopic topics,
135                                 FILE* output) {
136     size_t i;
137
138     assert(params != NULL);
139     assert(output != NULL);
140     
141     for(i = 0; params[i] != NULL; ++i) {
142         if(((params[i]->topics & topics) != 0) && (params[i]->help != NULL)) {
143             fprintf(output, "  %s\n", params[i]->help);
144         }
145     }    
146 }
147
148 xmlSecAppCmdLineValuePtr 
149 xmlSecAppCmdLineValueCreate(xmlSecAppCmdLineParamPtr param, int pos) {
150     xmlSecAppCmdLineValuePtr value;
151     
152     assert(param != NULL);
153     value = (xmlSecAppCmdLineValuePtr) malloc(sizeof(xmlSecAppCmdLineValue));
154     if(value == NULL) {
155         fprintf(stderr, "Error: malloc failed (%d bytes).\n", sizeof(xmlSecAppCmdLineValue));
156         return(NULL);
157     }
158     memset(value, 0, sizeof(xmlSecAppCmdLineValue));
159     
160     value->param = param;
161     value->pos = pos;
162     return(value);
163 }
164
165 void 
166 xmlSecAppCmdLineValueDestroy(xmlSecAppCmdLineValuePtr value) {
167     assert(value != NULL);
168     
169     if(value->strListValue != NULL) {
170         free((void*)value->strListValue);
171     }
172     free(value);
173 }
174
175 static int 
176 xmlSecAppCmdLineMatchParam(const char* argvParam, const char* paramName,
177                            int canHaveNameString) {
178     assert(argvParam != NULL);
179     assert(paramName != NULL);
180     
181     if(canHaveNameString != 0) {
182         int len = strlen(paramName);
183         
184         if((strncmp(argvParam, paramName, len) == 0) &&
185            ((argvParam[len] == '\0') || (argvParam[len] == ':'))) {
186            
187            return(1);
188         }
189     } else if(strcmp(argvParam, paramName) == 0) {
190         return(1);
191     }
192     return(0);
193 }
194
195 static xmlSecAppCmdLineParamPtr 
196 xmlSecAppCmdLineParamsListFind(xmlSecAppCmdLineParamPtr* params, xmlSecAppCmdLineParamTopic topics,
197                                 const char* name) {
198     size_t i;
199     int canHaveNameString;
200
201     assert(params != NULL);
202     assert(name != NULL);
203
204     for(i = 0; params[i] != NULL; ++i) {
205         if((params[i]->topics & topics) == 0) {
206             continue;
207         }
208
209         canHaveNameString = ((params[i]->flags & xmlSecAppCmdLineParamFlagParamNameValue) != 0) ? 1 : 0;
210         if((params[i]->fullName != NULL) && 
211            (xmlSecAppCmdLineMatchParam(name, params[i]->fullName, canHaveNameString) == 1)) {
212         
213             return(params[i]);
214         }
215
216         if((params[i]->shortName != NULL) && 
217            (xmlSecAppCmdLineMatchParam(name, params[i]->shortName, canHaveNameString) == 1)) {
218         
219             return(params[i]);
220         }
221     }
222     
223     return(NULL);
224 }
225
226 static int 
227 xmlSecAppCmdLineParamRead(xmlSecAppCmdLineParamPtr param, const char** argv, int argc, int pos) {
228     xmlSecAppCmdLineValuePtr value;
229     xmlSecAppCmdLineValuePtr prev = NULL;
230     char* buf;
231         
232     assert(param != NULL);
233     assert(argv != NULL);
234     assert(pos < argc);
235     
236     /* first find the previous value in the list */
237     if((param->flags & xmlSecAppCmdLineParamFlagMultipleValues) != 0) {
238         prev = param->value; 
239         while((prev != NULL) && (prev->next != NULL)) {
240             prev = prev->next; 
241         }
242     } else if(param->value != NULL) {
243         fprintf(stderr, "Error: only one parameter \"%s\" is allowed.\n", argv[pos]);
244         return(-1);
245     }
246     
247     /* create new value and add to the list */
248     value = xmlSecAppCmdLineValueCreate(param, pos);
249     if(value == NULL) {
250         fprintf(stderr, "Error: failed to create value for parameter \"%s\".\n", argv[pos]);
251         return(-1);
252     }
253     if(prev != NULL) {
254         assert(prev->next == NULL);
255         prev->next = value;
256     } else {
257         param->value = value;
258     }
259         
260     /* if we can have a string value after the name, parse it */
261     if((param->flags & xmlSecAppCmdLineParamFlagParamNameValue) != 0) {
262         value->paramNameValue = strchr(argv[pos], ':');
263         if(value->paramNameValue != NULL) {
264             ++value->paramNameValue;
265         }
266     }
267     
268     switch(param->type) {
269         case xmlSecAppCmdLineParamTypeFlag:
270             /* do nothing */
271             break;
272         case xmlSecAppCmdLineParamTypeString:
273             if(pos + 1 >= argc) {
274                 fprintf(stderr, "Error: string argument expected for parameter \"%s\".\n", argv[pos]);
275                 return(-1);
276             }
277             value->strValue = argv[++pos];
278             break;
279         case xmlSecAppCmdLineParamTypeStringList:
280             if(pos + 1 >= argc) {
281                 fprintf(stderr, "Error: string list argument expected for parameter \"%s\".\n", argv[pos]);
282                 return(-1);
283             }
284             value->strValue = argv[++pos];
285             buf = (char*)malloc(strlen(value->strValue) + 2);
286             if(buf == NULL) {
287                 fprintf(stderr, "Error: failed to allocate memory (%d bytes).\n", strlen(value->strValue) + 2);
288                 return(-1);
289             }
290             memset(buf, 0, strlen(value->strValue) + 2);
291             memcpy(buf, value->strValue, strlen(value->strValue));
292             value->strListValue = buf;
293             while((*buf) != '\0') {
294                 if((*buf) == ',') {
295                     (*buf) = '\0';
296                 }
297                 ++buf;
298             }
299             break;
300         case xmlSecAppCmdLineParamTypeNumber:
301             if(pos + 1 >= argc) {
302                 fprintf(stderr, "Error: integer argument expected for parameter \"%s\".\n", argv[pos]);
303                 return(-1);
304             }    
305             value->strValue = argv[++pos];
306             if(sscanf(value->strValue, "%d", &(value->intValue)) != 1) {
307                 fprintf(stderr, "Error: integer argument \"%s\" is invalid.\n", value->strValue);
308                 return(-1);
309             }    
310             break;
311         case xmlSecAppCmdLineParamTypeTime:
312             if(pos + 1 >= argc) {
313                 fprintf(stderr, "Error: time argument expected for parameter \"%s\".\n", argv[pos]);
314                 return(-1);
315             }
316             value->strValue = argv[++pos];
317             if(xmlSecAppCmdLineTimeParamRead(value->strValue, &(value->timeValue)) < 0) {
318                 fprintf(stderr, "Error: time argument \"%s\" is invalid, expected format is \"YYYY-MM-DD HH:MM:SS\").\n", value->strValue);
319                 return(-1);
320             }    
321             break;
322     }
323     return(pos);
324 }
325
326 static int  
327 xmlSecAppCmdLineTimeParamRead(const char* str, time_t* t) {
328     struct tm tm;
329     int n;
330     
331     if((str == NULL) || (t == NULL)) {
332         return(-1);
333     }
334     memset(&tm, 0, sizeof(tm));
335     tm.tm_isdst = -1;
336     
337     n = sscanf(str, "%4d-%2d-%2d%*c%2d:%2d:%2d", 
338                             &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
339                             &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
340     if((n != 6) || (tm.tm_year < 1900) 
341                 || (tm.tm_mon  < 1) || (tm.tm_mon  > 12) 
342                 || (tm.tm_mday < 1) || (tm.tm_mday > 31)
343                 || (tm.tm_hour < 0) || (tm.tm_hour > 23)
344                 || (tm.tm_min  < 0) || (tm.tm_min  > 59)
345                 || (tm.tm_sec  < 0) || (tm.tm_sec  > 61)) {
346         return(-1);         
347     }
348
349     tm.tm_year -= 1900; /* tm relative format year */
350     tm.tm_mon  -= 1; /* tm relative format month */
351
352     (*t) = mktime(&tm);
353     return(0);    
354 }
355