Bug Summary

File:vitunes.c
Location:line 521, column 4
Description:Value stored to 'argv' is never read

Annotated Source Code

1/*
2 * Copyright (c) 2010, 2011 Ryan Flannery <ryan.flannery@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "vitunes.h"
18#include "config.h" /* NOTE: must be after vitunes.h */
19#include "socket.h"
20
21/*****************************************************************************
22 * GLOBALS, EXPORTED
23 ****************************************************************************/
24
25/* key playlists to keep track of */
26playlist *viewing_playlist;
27playlist *playing_playlist;
28
29/* visual mode start position */
30int visual_mode_start = -1;
31
32/* signal flags */
33volatile sig_atomic_t VSIG_QUIT = 0; /* 1 = quit vitunes */
34volatile sig_atomic_t VSIG_RESIZE = 0; /* 1 = resize display */
35volatile sig_atomic_t VSIG_SIGCHLD = 0; /* 1 = got sigchld */
36volatile sig_atomic_t VSIG_PLAYER_MONITOR = 0; /* 1 = update player stats */
37
38/*
39 * enum used for QUIT_CAUSE values. Currently only one is used, but might add
40 * more. see the end of the main function and the signal_handler for how/why
41 * this is used.
42 */
43enum { EXIT_NORMAL, BAD_PLAYER };
44volatile sig_atomic_t QUIT_CAUSE = EXIT_NORMAL;
45
46/* used with -DDEBUG */
47FILE *debug_log;
48
49
50/*****************************************************************************
51 * GLOBALS, LOCAL
52 ****************************************************************************/
53
54/* location patterns of various things (%s is user's home directory) */
55const char *VITUNES_DIR_FMT = "%s/.vitunes";
56const char *CONF_FILE_FMT = "%s/.vitunes/vitunes.conf";
57const char *DB_FILE_FMT = "%s/.vitunes/vitunes.db";
58const char *PLAYLIST_DIR_FMT = "%s/.vitunes/playlists";
59
60/* absolute paths of key stuff */
61char *vitunes_dir;
62char *conf_file;
63char *db_file;
64char *playlist_dir;
65char *player_backend;
66
67/* program name with directories removed */
68char *progname;
69
70
71/*****************************************************************************
72 * local functions
73 ****************************************************************************/
74
75/* misc. functions */
76int handle_switches(int argc, char *argv[]);
77void usage(void);
78void signal_handler(int);
79void setup_timer();
80
81
82int
83main(int argc, char *argv[])
84{
85 char *home;
86 int previous_command;
87 int input;
88 int sock = -1;
89 fd_set fds;
90 struct passwd *pw;
91
92 /* save program name for later use */
93 if ((progname = strrchr(argv[0], '/')) == NULL((void *)0))
94 progname = argv[0];
95 else
96 progname++;
97
98#ifdef DEBUG
99 if ((debug_log = fopen("vitunes-debug.log", "w")) == NULL((void *)0))
100 err(1, "failed to open debug log");
101#endif
102
103 /*------------------------------------------------------------------------
104 * build paths names needed by vitunes & handle switches
105 *----------------------------------------------------------------------*/
106
107 /* get home dir */
108 if ((home = getenv("HOME")) == NULL((void *)0) || *home == '\0') {
109 if ((pw = getpwuid(getuid())) == NULL((void *)0))
110 errx(1, "Couldn't determine home directory. Can't find my config files.");
111 home = pw->pw_dir;
112 }
113
114 /* build paths & other needed strings */
115 if (asprintf(&vitunes_dir, VITUNES_DIR_FMT, home) == -1)
116 err(1, "main: asprintf failed");
117 if (asprintf(&conf_file, CONF_FILE_FMT, home) == -1)
118 err(1, "main: asprintf failed");
119 if (asprintf(&db_file, DB_FILE_FMT, home) == -1)
120 err(1, "main: asprintf failed");
121 if (asprintf(&playlist_dir, PLAYLIST_DIR_FMT, home) == -1)
122 err(1, "main: asprintf failed");
123 if (asprintf(&player_backend, "%s", DEFAULT_PLAYER_BACKEND) == -1)
124 err(1, "main: asprintf failed");
125
126 /* handle command-line switches & e-commands */
127 handle_switches(argc, argv);
128
129 if(sock_send_msg(VITUNES_RUNNING"WHOWASPHONE?") != -1) {
130 printf("Vitunes appears to be running already. Won't open socket.");
131 } else {
132 if((sock = sock_listen()) == -1)
133 errx(1, "failed to open socket.");
134 }
135
136
137 /*
138 * IF we've reached here, then there were no e-commands.
139 * start vitunes normally...
140 */
141
142
143 /*------------------------------------------------------------------------
144 * initialize stuff
145 *--------------------------------------------------------------------- */
146
147 /* setup signal handlers (XXX must be before player_init) */
148 signal(SIGPIPE13, SIG_IGN(void (*)(int))1); /* broken pipe with child (ignore) */
149 signal(SIGCHLD20, signal_handler); /* child died */
150 signal(SIGHUP1, signal_handler); /* quit */
151 signal(SIGINT2, signal_handler); /* quit */
152 signal(SIGQUIT3, signal_handler); /* quit */
153 signal(SIGTERM15, signal_handler); /* quit */
154 signal(SIGWINCH28, signal_handler); /* resize */
155 setup_timer(); /* periodic timer to update player */
156
157 /* init small stuff (XXX some must be done before medialib_load) */
158 mi_query_init(); /* global query description */
159 mi_sort_init(); /* global sort description */
160 mi_display_init(); /* global display description */
161 ybuffer_init(); /* global yank/copy buffer */
162 toggleset_init(); /* global toggleset (list of toggle-lists) */
163
164 /* load media library (database and all playlists) & sort */
165 medialib_load(db_file, playlist_dir);
166 if (mdb.library->nfiles == 0) {
167 printf("The vitunes database is currently empty.\n");
168 printf("See 'vitunes -e help add' for how to add files.\n");
169 return 0;
170 }
171
172 /* apply default sort to library */
173 qsort(mdb.library->files, mdb.library->nfiles, sizeof(meta_info*), mi_compare);
174
175 /* start media player child */
176 player_init(player_backend, paint_message, paint_error);
177 player_info.mode = DEFAULT_PLAYER_MODE;
178 atexit(player_destroy);
179
180 /* setup user interface and default colors */
181 kb_init();
182 ui_init(DEFAULT_LIBRARY_WINDOW_WIDTH);
183 paint_setup_colors();
184
185 /* basic ui setup to get ui started */
186 setup_viewing_playlist(mdb.library);
187 ui.library->nrows = mdb.nplaylists;
188 playing_playlist = NULL((void *)0);
189
190 /* load config file and run commands in it now */
191 load_config();
192
193 /* initial painting of the display */
194 paint_all();
195
196 /* -----------------------------------------------------------------------
197 * begin input loop
198 * -------------------------------------------------------------------- */
199
200 previous_command = -1;
201 while (!VSIG_QUIT) {
202 struct timeval tv;
203
204 /* handle any signal flags */
205 process_signals();
206
207 tv.tv_sec = 1;
208 tv.tv_usec = 0;
209
210 FD_ZERO(&fds)do { fd_set *_p = (&fds); __size_t _n = (((1024) + ((((unsigned
)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)(sizeof(__fd_mask
) * 8)))); while (_n > 0) _p->fds_bits[--_n] = 0; } while
(0)
;
211 FD_SET(0, &fds)((&fds)->fds_bits[(0) / ((unsigned)(sizeof(__fd_mask) *
8))] |= (1U << ((0) % ((unsigned)(sizeof(__fd_mask) * 8
)))))
;
212 if(sock > 0)
213 FD_SET(sock, &fds)((&fds)->fds_bits[(sock) / ((unsigned)(sizeof(__fd_mask
) * 8))] |= (1U << ((sock) % ((unsigned)(sizeof(__fd_mask
) * 8)))))
;
214 errno(*__errno()) = 0;
215 if(select((sock > 0 ? sock : 0) + 1, &fds, NULL((void *)0), NULL((void *)0), &tv) == -1) {
216 if(errno(*__errno()) == 0 || errno(*__errno()) == EINTR4)
217 continue;
218 break;
219 }
220
221 if(sock > 0) {
222 if(FD_ISSET(sock, &fds)((&fds)->fds_bits[(sock) / ((unsigned)(sizeof(__fd_mask
) * 8))] & (1U << ((sock) % ((unsigned)(sizeof(__fd_mask
) * 8)))))
)
223 sock_recv_and_exec(sock);
224 }
225
226 if(FD_ISSET(0, &fds)((&fds)->fds_bits[(0) / ((unsigned)(sizeof(__fd_mask) *
8))] & (1U << ((0) % ((unsigned)(sizeof(__fd_mask)
* 8)))))
) {
227 /* handle any available input */
228 if ((input = getch()wgetch(stdscr)) && input != ERR(-1)) {
229 if (isdigit(input) && (input != '0' || gnum_get() > 0))
230 gnum_add(input - '0');
231 else if (input == '\n' && gnum_get() > 0 && previous_command >= 0)
232 kb_execute(previous_command);
233 else
234 kb_execute(input);
235 }
236 }
237 }
238
239 /* -----------------------------------------------------------------------
240 * cleanup
241 * -------------------------------------------------------------------- */
242
243 ui_destroy();
244 player_destroy();
245 medialib_destroy();
246
247 mi_query_clear();
248 ybuffer_free();
249 toggleset_free();
250
251 /* do we have any odd cause for quitting? */
252 if (QUIT_CAUSE != EXIT_NORMAL) {
253 switch (QUIT_CAUSE) {
254 case BAD_PLAYER:
255 warnx("It appears the media player is misbehaving. Apologies.");
256 break;
257 }
258 }
259
260 return 0;
261}
262
263/* print proper usage */
264void
265usage(void)
266{
267 fprintf(stderr(&__sF[2]),"\
268usage: %s [-f config-file] [-d database-file] [-p playlist-dir] [-m player-path] [-e COMMAND ...]\n\
269See \"%s -e help\" for information about what e-commands are available.\n\
270",
271 progname, progname);
272 exit(1);
273}
274
275/* actual signal handler */
276void
277signal_handler(int sig)
278{
279 switch (sig) {
280 case SIGHUP1:
281 case SIGINT2:
282 case SIGQUIT3:
283 case SIGTERM15:
284 VSIG_QUIT = 1;
285 break;
286 case SIGALRM14:
287 VSIG_PLAYER_MONITOR = 1;
288 break;
289 case SIGWINCH28:
290 VSIG_RESIZE = 1;
291 break;
292 case SIGCHLD20:
293 VSIG_SIGCHLD = 1;
294 break;
295 }
296}
297
298/* handle any signal flags */
299void
300process_signals()
301{
302 /* cppcheck-suppress variableScope */
303 static playlist *prev_queue = NULL((void *)0);
304 /* cppcheck-suppress variableScope */
305 static int prev_qidx = -1;
306 /* cppcheck-suppress variableScope */
307 static bool_Bool prev_is_playing = false0;
308 /* cppcheck-suppress variableScope */
309 static float prev_volume = -1;
310
311 /* handle resize event */
312 if (VSIG_RESIZE) {
313 ui_resize();
314 ui_clear();
315 paint_all();
316 VSIG_RESIZE = 0;
317 }
318
319 /* monitor player */
320 if (VSIG_PLAYER_MONITOR) {
321 player_monitor();
322
323 if (prev_is_playing || player.playing())
324 paint_player();
325
326 /* need to repaint anything else? */
327 if (prev_is_playing != player.playing()) {
328 paint_library();
329 paint_playlist();
330 } else if (prev_queue != player_info.queue) {
331 paint_library();
332 if (prev_queue == viewing_playlist) {
333 paint_playlist();
334 }
335 }
336 if (player_info.queue == viewing_playlist
337 && prev_qidx != player_info.qidx) {
338 paint_playlist();
339 }
340 if (prev_volume != player.volume()) {
341 paint_message("volume: %3.0f%%", player.volume());
342 prev_volume = player.volume();
343 }
344
345 prev_queue = player_info.queue;
346 prev_qidx = player_info.qidx;
347 prev_is_playing = player.playing();
348 VSIG_PLAYER_MONITOR = 0;
349 }
350
351 /* restart player if needed */
352 if (VSIG_SIGCHLD) {
353 if (player.sigchld != NULL((void *)0)) player.sigchld();
354 VSIG_SIGCHLD = 0;
355 }
356}
357
358/* setup timer signal handler above */
359void
360setup_timer()
361{
362 struct sigaction sig_act;
363 struct itimerval timer;
364
365 /* create timer signal handler */
366 if (sigemptyset(&sig_act.sa_mask)(*(&sig_act.sa_mask) = 0, 0) < 0)
367 err(1, "setup_timer: sigemptyset failed");
368
369 sig_act.sa_flags = 0;
370 sig_act.sa_handler__sigaction_u.__sa_handler = signal_handler;
371 if (sigaction(SIGALRM14, &sig_act, NULL((void *)0)) < 0)
372 err(1, "setup_timer: sigaction failed");
373
374 /* setup timer details */
375 timer.it_value.tv_sec = 0;
376 timer.it_value.tv_usec = 500000; /* 1 half-second */
377 timer.it_interval.tv_sec = 0;
378 timer.it_interval.tv_usec = 500000; /* 1 half-second */
379
380 /* register timer */
381 if (setitimer(ITIMER_REAL0, &timer, NULL((void *)0)) < 0)
382 err(1, "setup_timer: setitimer failed");
383}
384
385/*
386 * load config file and execute all command-mode commands within.
387 * XXX note that this requires mdb, ui, and player to all be loaded/setup
388 */
389void
390load_config()
391{
392 const char *errmsg = NULL((void *)0);
393 size_t length, linenum;
394 FILE *fin;
395 char *line;
396 char *copy;
397 char **argv;
398 int argc;
399 bool_Bool found;
400 int found_idx = 0;
401 int num_matches;
402 int i, ret;
403
404 if ((fin = fopen(conf_file, "r")) == NULL((void *)0))
405 return;
406
407 linenum = 0;
408 while (!feof(fin)(!__isthreaded ? (((fin)->_flags & 0x0020) != 0) : (feof
)(fin))
) {
409
410 /* get next line */
411 if ((line = fparseln(fin, &length, &linenum, NULL((void *)0), 0)) == NULL((void *)0)) {
412 if (ferror(fin)(!__isthreaded ? (((fin)->_flags & 0x0040) != 0) : (ferror
)(fin))
)
413 err(1, "error reading config file '%s'", conf_file);
414 else
415 break;
416 }
417
418 /* skip whitespace */
419 copy = line;
420 copy += strspn(copy, " \t\n");
421 if (copy[0] == '\0') {
422 free(line);
423 continue;
424 }
425
426 /* parse line into argc/argv */
427 if (str2argv(copy, &argc, &argv, &errmsg) != 0) {
428 endwin();
429 errx(1, "%s line %zd: parse error: %s", conf_file, linenum, errmsg);
430 }
431
432 /* run command */
433 found = false0;
434 num_matches = 0;
435 for (i = 0; i < CommandPathSize; i++) {
436 if (match_command_name(argv[0], CommandPath[i].name)) {
437 found = true1;
438 found_idx = i;
439 num_matches++;
440 }
441 }
442
443 if (found && num_matches == 1) {
444 if ((ret = (CommandPath[found_idx].func)(argc, argv)) != 0) {
445 endwin();
446 errx(1, "%s line %zd: error with command '%s' [%i]",
447 conf_file, linenum, argv[0], ret);
448 }
449 } else if (num_matches > 1) {
450 endwin();
451 errx(1, "%s line %zd: ambiguous abbreviation '%s'",
452 conf_file, linenum, argv[0]);
453 } else {
454 endwin();
455 errx(1, "%s line %zd: unknown command '%s'",
456 conf_file, linenum, argv[0]);
457 }
458
459 argv_free(&argc, &argv);
460 free(line);
461 }
462
463 fclose(fin);
464}
465
466/*
467 * parse the command line and handle all switches.
468 * this also handles all of the e-commands.
469 */
470int
471handle_switches(int argc, char *argv[])
472{
473 int ch;
474
475 while ((ch = getopt(argc, argv, "he:f:d:p:m:c:")) != -1) {
476 switch (ch) {
477 case 'c':
478 if(sock_send_msg(optarg) == -1)
479 errx(1, "Failed to send message. Vitunes not running?");
480 exit(0);
481
482 case 'd':
483 free(db_file);
484 if ((db_file = strdup(optarg)) == NULL((void *)0))
485 err(1, "handle_switches: strdup db_file failed");
486 break;
487
488 case 'e':
489 /* an e-command */
490 argc -= optind - 1;
491 argv += optind - 1;
492
493 exit(ecmd_exec(optarg, argc, argv));
494
495 case 'f':
496 free(conf_file);
497 if ((conf_file = strdup(optarg)) == NULL((void *)0))
498 err(1, "handle_switches: strdup conf_file failed");
499 break;
500
501 case 'm':
502 free(player_backend);
503 if ((player_backend = strdup(optarg)) == NULL((void *)0))
504 err(1, "handle_switches: strdup player_backend failed");
505 break;
506
507 case 'p':
508 free(playlist_dir);
509 if ((playlist_dir = strdup(optarg)) == NULL((void *)0))
510 err(1, "handle_switches: strdup playlist_dir failed");
511 break;
512
513 case 'h':
514 case '?':
515 default:
516 usage();
517 /* NOT REACHED */
518 }
519 }
520 argc -= optind;
521 argv += optind;
Value stored to 'argv' is never read
522
523 if (argc)
524 usage();
525
526 return 0;
527}