1 /*
2 * $Id$
3 *
4 * (c) 2004 by Kalle Wallin <kaw@linux.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <glib.h>
26 #include "config.h"
27 #include "ncmpc.h"
28 #include "support.h"
29 #include "options.h"
31 #define MAX_LONGOPT_LENGTH 32
33 typedef struct
34 {
35 int shortopt;
36 char *longopt;
37 char *argument;
38 char *descrition;
39 } arg_opt_t;
42 typedef void (*option_callback_fn_t) (int c, char *arg);
45 options_t options;
47 static arg_opt_t option_table[] = {
48 { '?', "help", NULL, "Show this help message" },
49 { 'V', "version", NULL, "Display version information" },
50 { 'c', "colors", NULL, "Enable colors" },
51 { 'C', "no-colors", NULL, "Disable colors" },
52 { 'e', "exit", NULL, "Exit on connection errors" },
53 { 'p', "port", "PORT", "Connect to server on port [" DEFAULT_PORT_STR "]" },
54 { 'h', "host", "HOST", "Connect to server on host [" DEFAULT_HOST "]" },
55 { 'P', "password","PASSWORD", "Connect with password" },
56 { 'f', "config", "FILE", "Read configuration from file" },
57 { 'k', "key-file","FILE", "Read configuration from file" },
58 #ifdef DEBUG
59 { 'D', "debug", NULL, "Enable debug output on stderr" },
60 #endif
61 { 0, NULL, NULL, NULL },
62 };
64 static arg_opt_t *
65 lookup_option(int s, char *l)
66 {
67 int i;
69 i=0;
70 while( option_table[i].descrition )
71 {
72 if( l && strcmp(l, option_table[i].longopt) == 0 )
73 return &option_table[i];;
74 if( s && s==option_table[i].shortopt )
75 return &option_table[i];;
76 i++;
77 }
78 return NULL;
79 }
81 static void
82 display_help(void)
83 {
84 int i = 0;
86 printf("Usage: %s [OPTION]...\n", PACKAGE);
87 while( option_table[i].descrition )
88 {
89 char tmp[MAX_LONGOPT_LENGTH];
91 if( option_table[i].argument )
92 g_snprintf(tmp, MAX_LONGOPT_LENGTH, "%s=%s",
93 option_table[i].longopt,
94 option_table[i].argument);
95 else
96 g_strlcpy(tmp, option_table[i].longopt, 64);
98 printf(" -%c, --%-20s %s\n",
99 option_table[i].shortopt,
100 tmp,
101 option_table[i].descrition);
102 i++;
103 }
104 }
106 static void
107 handle_option(int c, char *arg)
108 {
109 switch(c)
110 {
111 case '?': /* --help */
112 display_help();
113 exit(EXIT_SUCCESS);
114 case 'V': /* --version */
115 printf("Version %s\n", VERSION);
116 exit(EXIT_SUCCESS);
117 case 'c': /* --colors */
118 options.enable_colors = TRUE;
119 break;
120 case 'C': /* --no-colors */
121 options.enable_colors = FALSE;
122 break;
123 case 'e': /* --exit */
124 options.reconnect = FALSE;
125 break;
126 case 'p': /* --port */
127 options.port = atoi(arg);
128 break;
129 case 'h': /* --host */
130 if( options.host )
131 g_free(options.host);
132 options.host = g_strdup(arg);
133 break;
134 case 'P': /* --password */
135 if( options.password )
136 g_free(options.password);
137 options.password = locale_to_utf8(arg);
138 break;
139 case 'f': /* --config */
140 if( options.config_file )
141 g_free(options.config_file);
142 options.config_file = g_strdup(arg);
143 break;
144 case 'k': /* --key-file */
145 if( options.key_file )
146 g_free(options.key_file);
147 options.key_file = g_strdup(arg);
148 break;
149 case 'D': /* --debug */
150 options.debug = TRUE;
151 break;
152 default:
153 fprintf(stderr,"Unknown Option %c = %s\n", c, arg);
154 break;
155 }
156 }
158 options_t *
159 options_get(void)
160 {
161 return &options;
162 }
164 options_t *
165 options_parse(int argc, const char *argv[])
166 {
167 int i;
168 arg_opt_t *opt = NULL;
169 option_callback_fn_t option_cb = handle_option;
171 i=1;
172 while( i<argc )
173 {
174 char *arg = (char *) argv[i];
175 size_t len=strlen(arg);
177 /* check for a long option */
178 if( g_str_has_prefix(arg, "--") )
179 {
180 char *value;
182 /* retreive a option argument */
183 if( (value=g_strrstr(arg+2, "=")) )
184 {
185 *value = '\0';
186 value++;
187 }
188 /* check if the option exists */
189 if( (opt=lookup_option(0, arg+2)) == NULL )
190 {
191 fprintf(stderr, PACKAGE ": invalid option %s\n", arg);
192 exit(EXIT_FAILURE);
193 }
194 /* abort if we got an argument to the option and dont want one */
195 if( value && opt->argument==NULL )
196 {
197 fprintf(stderr, PACKAGE ": invalid option argument %s=%s\n",
198 arg, value);
199 exit(EXIT_FAILURE);
200 }
201 /* execute option callback */
202 if( value || opt->argument==NULL )
203 {
204 option_cb (opt->shortopt, value);
205 opt = NULL;
206 }
207 }
208 /* check for a short option */
209 else if( len==2 && g_str_has_prefix(arg, "-") )
210 {
211 /* check if the option exists */
212 if( (opt=lookup_option(arg[1], NULL))==NULL )
213 {
214 fprintf(stderr, PACKAGE ": invalid option %s\n",arg);
215 exit(EXIT_FAILURE);
216 }
217 /* if no option argument is needed execute callback */
218 if( opt->argument==NULL )
219 {
220 option_cb (opt->shortopt, NULL);
221 opt = NULL;
222 }
223 }
224 else
225 {
226 /* is this a option argument? */
227 if( opt && opt->argument)
228 {
229 option_cb (opt->shortopt, arg);
230 }
231 else
232 {
233 fprintf(stderr, PACKAGE ": bad argument: %s\n", arg);
234 exit(EXIT_FAILURE);
235 }
236 opt = NULL;
237 }
239 i++;
240 }
241 return &options;
242 }
245 options_t *
246 options_init( void )
247 {
248 const char *value;
249 char *tmp;
251 memset(&options, 0, sizeof(options_t));
253 if( (value=g_getenv(MPD_HOST_ENV)) )
254 options.host = g_strdup(value);
255 else
256 options.host = g_strdup(DEFAULT_HOST);
257 if( (tmp=g_strstr_len(options.host, strlen(options.host), "@")) )
258 {
259 char *oldhost = options.host;
260 *tmp = '\0';
261 options.password = locale_to_utf8(oldhost);
262 options.host = g_strdup(tmp+1);
263 g_free(oldhost);
264 }
266 if( (value=g_getenv(MPD_PORT_ENV)) )
267 options.port = atoi(value);
268 else
269 options.port = DEFAULT_PORT;
271 options.list_format = NULL;
272 options.status_format = NULL;
273 options.xterm_title_format = NULL;
275 options.reconnect = TRUE;
276 options.find_wrap = TRUE;
277 options.wide_cursor = TRUE;
278 options.audible_bell = TRUE;
280 return &options;
281 }