/* Sort the playlist by file names. */ void plist_sort_fname (struct plist *plist) { struct plist_item *sorted; struct rb_node *x; int n; if (plist_count(plist) == 0) return; sorted = (struct plist_item *)xmalloc (plist_count(plist) * sizeof(struct plist_item)); x = rb_min (plist->search_tree); assert (!rb_is_null(x)); while (plist_deleted(plist, (intptr_t)rb_get_data (x))) x = rb_next (x); sorted[0] = plist->items[(intptr_t)rb_get_data (x)]; rb_set_data (x, NULL); n = 1; while (!rb_is_null(x = rb_next(x))) { if (!plist_deleted(plist, (intptr_t)rb_get_data (x))) { sorted[n] = plist->items[(intptr_t)rb_get_data (x)]; rb_set_data (x, (void *)(intptr_t)n++); } } plist->num = n; plist->not_deleted = n; memcpy (plist->items, sorted, sizeof(struct plist_item) * n); free (sorted); }
/* PUBLIC */ int number_of_vars_in_term(Term t) { Plist p = set_of_vars(t, NULL); int n = plist_count(p); zap_plist(p); return n; } /* number_of_vars_in_term */
/* Move to the next file depending on the options set, the user * request and whether or not there are files in the queue. */ static void go_to_another_file () { int shuffle = options_get_int ("Shuffle"); int go_next = (play_next || options_get_int("AutoNext")); int curr_playing_curr_pos; /* XXX: Shouldn't play_next be protected by mutex? */ LOCK (curr_playing_mut); LOCK (plist_mut); /* If we move forward in the playlist and there are some songs in * the queue, then play them. */ if (plist_count(&queue) && go_next) { logit ("Playing file from queue"); if (!before_queue_fname && curr_playing_fname) before_queue_fname = xstrdup (curr_playing_fname); curr_plist = &queue; curr_playing = plist_next (&queue, -1); server_queue_pop (queue.items[curr_playing].file); plist_delete (&queue, curr_playing); } else { /* If we just finished playing files from the queue and the * appropriate option is set, continue with the file played * before playing the queue. */ if (before_queue_fname && options_get_int("QueueNextSongReturn")) { free (curr_playing_fname); curr_playing_fname = before_queue_fname; before_queue_fname = NULL; } if (shuffle) { curr_plist = &shuffled_plist; if (plist_count(&playlist) && !plist_count(&shuffled_plist)) { plist_cat (&shuffled_plist, &playlist); plist_shuffle (&shuffled_plist); if (curr_playing_fname) plist_swap_first_fname (&shuffled_plist, curr_playing_fname); } } else curr_plist = &playlist; curr_playing_curr_pos = plist_find_fname (curr_plist, curr_playing_fname); /* If we came from the queue and the last file in * queue wasn't in the playlist, we try to revert to * the QueueNextSongReturn = 1 behaviour. */ if (curr_playing_curr_pos == -1 && before_queue_fname) { curr_playing_curr_pos = plist_find_fname (curr_plist, before_queue_fname); } if (play_prev && plist_count(curr_plist)) { logit ("Playing previous..."); if (curr_playing_curr_pos == -1 || started_playing_in_queue) { curr_playing = plist_prev (curr_plist, -1); started_playing_in_queue = 0; } else curr_playing = plist_prev (curr_plist, curr_playing_curr_pos); if (curr_playing == -1) { if (options_get_int("Repeat")) curr_playing = plist_last (curr_plist); logit ("Beginning of the list."); } else logit ("Previous item."); } else if (go_next && plist_count(curr_plist)) { logit ("Playing next..."); if (curr_playing_curr_pos == -1 || started_playing_in_queue) { curr_playing = plist_next (curr_plist, -1); started_playing_in_queue = 0; } else curr_playing = plist_next (curr_plist, curr_playing_curr_pos); if (curr_playing == -1 && options_get_int("Repeat")) { if (shuffle) { plist_clear (&shuffled_plist); plist_cat (&shuffled_plist, &playlist); plist_shuffle (&shuffled_plist); } curr_playing = plist_next (curr_plist, -1); logit ("Going back to the first item."); } else if (curr_playing == -1) logit ("End of the list"); else logit ("Next item"); } else if (!options_get_int("Repeat")) { curr_playing = -1; } else debug ("Repeating file"); if (before_queue_fname) free (before_queue_fname); before_queue_fname = NULL; } UNLOCK (plist_mut); UNLOCK (curr_playing_mut); }
int main(int argc, char *argv[]) { lnode *conf; struct sigaction sa; int i; #ifndef DEBUG /* Make sure we are root */ if (getuid() != 0) { fprintf(stderr, "You must be root to run this program.\n"); return 4; } #endif set_aumessage_mode(MSG_SYSLOG, DBG_YES); /* Register sighandlers */ sa.sa_flags = 0; sigemptyset(&sa.sa_mask); /* Ignore all signals by default */ sa.sa_handler = SIG_IGN; for (i=1; i<NSIG; i++) sigaction(i, &sa, NULL); /* Set handler for the ones we care about */ sa.sa_handler = term_handler; sigaction(SIGTERM, &sa, NULL); sa.sa_handler = hup_handler; sigaction(SIGHUP, &sa, NULL); sa.sa_handler = alarm_handler; sigaction(SIGALRM, &sa, NULL); sa.sa_handler = child_handler; sigaction(SIGCHLD, &sa, NULL); /* move stdin to its own fd */ if (argc == 3 && strcmp(argv[1], "--input") == 0) audit_fd = open(argv[2], O_RDONLY); else audit_fd = dup(0); if (audit_fd < 0) { syslog(LOG_ERR, "Failed setting up input, exiting"); return 1; } /* Make all descriptors point to dev null */ i = open("/dev/null", O_RDWR); if (i >= 0) { if (dup2(0, i) < 0 || dup2(1, i) < 0 || dup2(2, i) < 0) { syslog(LOG_ERR, "Failed duping /dev/null %s, exiting", strerror(errno)); return 1; } close(i); } else { syslog(LOG_ERR, "Failed opening /dev/null %s, exiting", strerror(errno)); return 1; } if (fcntl(audit_fd, F_SETFD, FD_CLOEXEC) < 0) { syslog(LOG_ERR, "Failed protecting input %s, exiting", strerror(errno)); return 1; } /* init the daemon's config */ if (load_config(&daemon_config, config_file)) return 6; load_plugin_conf(&plugin_conf); /* if no plugins - exit */ if (plist_count(&plugin_conf) == 0) { syslog(LOG_ERR, "No plugins found, exiting"); return 0; } /* Plugins are started with the auditd priority */ i = start_plugins(&plugin_conf); /* Now boost priority to make sure we are getting time slices */ if (daemon_config.priority_boost != 0) { errno = 0; (void) nice((int)-daemon_config.priority_boost); if (errno) { syslog(LOG_ERR, "Cannot change priority (%s)", strerror(errno)); /* Stay alive as this is better than stopping */ } } /* Let the queue initialize */ init_queue(daemon_config.q_depth); syslog(LOG_NOTICE, "audispd initialized with q_depth=%d and %d active plugins", daemon_config.q_depth, i); /* Tell it to poll the audit fd */ if (add_event(audit_fd, process_inbound_event) < 0) { syslog(LOG_ERR, "Cannot add event, exiting"); return 1; } /* Create inbound thread */ pthread_create(&inbound_thread, NULL, inbound_thread_main, NULL); /* Start event loop */ while (event_loop()) { hup = 0; reconfigure(); } /* Tell plugins we are going down */ signal_plugins(SIGTERM); /* Cleanup builtin plugins */ destroy_af_unix(); destroy_syslog(); /* Give it 5 seconds to clear the queue */ alarm(5); pthread_join(inbound_thread, NULL); /* Release configs */ plist_first(&plugin_conf); conf = plist_get_cur(&plugin_conf); while (conf) { free_pconfig(conf->p); conf = plist_next(&plugin_conf); } plist_clear(&plugin_conf); /* Cleanup the queue */ destroy_queue(); free_config(&daemon_config); return 0; }