Code

Add extra-opts argument parsing with tests
[nagiosplug.git] / lib / extra_opts.c
1 /*****************************************************************************
2
3 * Nagios-plugins extra_opts library
4
5 * License: GPL
6 * Copyright (c) 2007 Nagios Plugins Development Team
7
8 * Last Modified: $Date: 2008-03-15 18:42:01 -0400 (Sat, 15 Mar 2008) $
9
10
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20
21 * You should have received a copy of the GNU General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
24 * $Id: parse_ini.c 1950 2008-03-15 22:42:01Z dermoth $
25
26 *****************************************************************************/
28 #include "common.h"
29 #include "extra_opts.h"
30 #include "parse_ini.h"
31 #include "utils_base.h"
32 #include <ctype.h>
34 /* FIXME: copied from utils.h; we should move a bunch of libs! */
35 int
36 is_option (char *str)
37 {
38         if (!str)
39                 return 0;
40         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
41                 return 1;
42         else
43                 return 0;
44 }
46 /* this is the externally visible function used by plugins */
47 /* Shouldn't se modify directly **argv (passed as a char ***) and argc
48  * (as int *) ?
49  */
50 char **np_extra_opts(int argc, char **argv, const char *plugin_name, int *argc_new){
51         np_arg_list *extra_args=NULL, *ea_tmp1=NULL, *ea_tmp2=NULL;
52         char **argv_new=NULL;
53         char *argptr=NULL;
54         int i, j, optfound, ea_num=argc;
56         if(argc<2) {
57                 /* No arguments provided */
58                 *argc_new=argc;
59                 argv_new=argv;
60                 return argv_new;
61         }
63         for(i=1; i<argc; i++){
64                 argptr=NULL;
65                 optfound=0;
67                 /* Do we have an extra-opts parameter? */
68                 if(strncmp(argv[i], "--extra-opts=", 13)==0){
69                         /* It is a single argument with value */
70                         argptr=argv[i]+13;
71                         /* Delete the extra opts argument */
72                         for(j=i;j<argc;j++) argv[j]=argv[j+1];
73                         i--;
74                         argc--;
75                 }else if(strcmp(argv[i], "--extra-opts")==0){
76                         if(!is_option(argv[i+1])){
77                                 /* It is a argument with separate value */
78                                 argptr=argv[i+1];
79                                 /* Delete the extra-opts argument/value */
80                                 for(j=i;j<argc-1;j++) argv[j]=argv[j+2];
81                                 i-=2;
82                                 argc-=2;
83                                 ea_num--;
84                         }else{
85                                 /* It has no value */
86                                 optfound=1;
87                                 /* Delete the extra opts argument */
88                                 for(j=i;j<argc;j++) argv[j]=argv[j+1];
89                                 i--;
90                                 argc--;
91                         }
92                 }
94                 if(argptr||optfound){
95                         /* Process ini section, returning a linked list of arguments */
96                         ea_tmp1=np_get_defaults(argptr, plugin_name);
97                         if(ea_tmp1==NULL) {
98                                 /* no extra args? */
99                                 ea_num--;
100                                 continue;
101                         }
103                         /* append the list to extra_args */
104                         if(extra_args==NULL){
105                                 extra_args=ea_tmp2=ea_tmp1;
106                                 while(ea_tmp2->next) {
107                                         ea_tmp2=ea_tmp2->next;
108                                         ea_num++;
109                                 }
110                         }else{
111                                 ea_tmp2=extra_args;
112                                 while(ea_tmp2->next) {
113                                         ea_tmp2=ea_tmp2->next;
114                                         ea_num++;
115                                 }
116                                 ea_tmp2->next=ea_tmp1;
117                         }
118                         ea_tmp1=ea_tmp2=NULL;
119                 }
120                 /* lather, rince, repeat */
121         }
123         if(ea_num==argc && extra_args==NULL){
124                 /* No extra-opts */
125                 *argc_new=argc;
126                 argv_new=argv;
127                 return argv_new;
128         }
130         /* done processing arguments. now create a new argc/argv set... */
131         argv_new=(char**)malloc((ea_num+1)*sizeof(char**));
132         if(argv_new==NULL) die(STATE_UNKNOWN, _("malloc() failed!\n"));
134         /* starting with program name (Should we strdup or just use the poiter?) */
135         argv_new[0]=strdup(argv[0]);
136         *argc_new=1;
137         /* then parsed ini opts (frying them up in the same run) */
138         while(extra_args){
139                 argv_new[*argc_new]=strdup(extra_args->arg);
140                 *argc_new+=1;
141                 ea_tmp1=extra_args;
142                 extra_args=extra_args->next;
143                 free(ea_tmp1);
144         }
145         /* finally the rest of the argv array (Should we strdup or just use the poiter?) */
146         for (i=1; i<argc; i++){
147                 argv_new[*argc_new]=strdup(argv[i]);
148                 *argc_new+=1;
149         }
150         /* and terminate. */
151         argv_new[*argc_new]=NULL;
153         return argv_new;