X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod.c;h=bd87cf870203613648aec2261d501835062b4ade;hp=695a6cfd32077e0ee0477078076ab2f8b8f11d29;hb=95488d221ea22f761a6a4b78410c4e0e89f522b8;hpb=ea8b1e10bc7b8b1cc01e0908a2e404d1b5409604 diff --git a/audiod.c b/audiod.c index 695a6cfd..bd87cf87 100644 --- a/audiod.c +++ b/audiod.c @@ -34,6 +34,7 @@ #include "net.h" #include "daemon.h" #include "string.h" +#include "fd.h" /** define the array of error lists needed by para_audiod */ INIT_AUDIOD_ERRLISTS; @@ -267,17 +268,7 @@ void para_log(int ll, const char* fmt,...) if (ll < conf.loglevel_arg) return; - if (!logfile && conf.logfile_given) - logfile = open_log(conf.logfile_arg); - if (!logfile && conf.daemon_given) - return; - if (!logfile) { - if (ll < WARNING) - outfd = stdout; - else - outfd = stderr; - } else - outfd = logfile; + outfd = logfile? logfile : stderr; time(&t1); tm = localtime(&t1); strftime(str, MAXLINE, "%b %d %H:%M:%S", tm); @@ -618,17 +609,14 @@ __malloc static char *glob_cmd(char *cmd) else tv_diff(&server_stream_start, &sa_time_diff, &rss); tv_add(&rss, &delay, &tmp); - replacement = make_message("%lu:%lu", tmp.tv_sec, tmp.tv_usec); + replacement = make_message("%lu:%lu", + (long unsigned)tmp.tv_sec, + (long unsigned)tmp.tv_usec); ret = s_a_r(cmd, "STREAM_START", replacement); free(replacement); if (!ret) goto out; PARA_INFO_LOG("cmd: %s, repl: %s\n", cmd, ret); - { - struct timeval now; - gettimeofday(&now, NULL); - PARA_INFO_LOG("now: %lu:%lu\n", now.tv_sec, now.tv_usec); - } out: return ret; } @@ -708,7 +696,7 @@ static void start_stream_writer(int slot_num) if (a->write_cmd) glob = glob_cmd(a->write_cmd); if (!glob) - glob = para_strdup("para_play"); + glob = para_strdup("para_write -w alsa"); PARA_INFO_LOG("starting stream writer: %s\n", glob); open_filters(slot_num); ret = para_exec_cmdline_pid(&s->wpid, glob, fds); @@ -720,7 +708,7 @@ static void start_stream_writer(int slot_num) s->write_fd = fds[0]; add_close_on_fork_list(s->write_fd); /* we write to this fd in do_select, so we need non-blocking */ - fcntl(s->write_fd, F_SETFL, O_NONBLOCK); + mark_fd_nonblock(s->write_fd); gettimeofday(&s->wstime, NULL); current_decoder = slot_num; activate_inactive_grab_clients(slot_num, s->format, &s->fci->filters); @@ -806,20 +794,22 @@ static void compute_time_diff(const struct timeval *status_time) count > 10? sign : sign * time_smooth, &diff, &tmp); sa_time_diff = tmp; - PARA_INFO_LOG("time diff (cur/avg): " - "%li:%lu/%li:%lu\n", - sign * diff.tv_sec, (diff.tv_usec + 500) / 1000, - sa_time_diff_sign * sa_time_diff.tv_sec, - (sa_time_diff.tv_usec + 500)/ 1000); + PARA_INFO_LOG("time diff (cur/avg): %s%lums/%s%lums\n", + sign > 0? "+" : "-", + tv2ms(&diff), + sa_time_diff_sign ? "+" : "-", + tv2ms(&sa_time_diff) + ); } static void check_stat_line(char *line) { int itemnum; size_t ilen = 0; - struct timeval tv; + long unsigned sec, usec; char *tmp; +// PARA_INFO_LOG("line: %s\n", line); if (!line) return; itemnum = stat_line_valid(line); @@ -848,14 +838,16 @@ static void check_stat_line(char *line) length_seconds = atoi(line + ilen + 1); break; case SI_STREAM_START: - if (sscanf(line + ilen + 1, "%lu.%lu", - &tv.tv_sec, &tv.tv_usec) == 2) - server_stream_start = tv; + if (sscanf(line + ilen + 1, "%lu.%lu", &sec, &usec) == 2) { + server_stream_start.tv_sec = sec; + server_stream_start.tv_usec = usec; + } break; case SI_CURRENT_TIME: - if (sscanf(line + ilen + 1, "%lu.%lu", &tv.tv_sec, - &tv.tv_usec) == 2) + if (sscanf(line + ilen + 1, "%lu.%lu", &sec, &usec) == 2) { + struct timeval tv = {sec, usec}; compute_time_diff(&tv); + } break; } } @@ -960,9 +952,9 @@ static void close_decoder_if_idle(int slot_num) clear_slot(slot_num); } -static int set_stream_fds(fd_set *wfds) +static void set_stream_fds(fd_set *wfds, int *max_fileno) { - int i, max_fileno = -1; + int i; check_timeouts(); FOR_EACH_SLOT(i) { @@ -984,12 +976,9 @@ static int set_stream_fds(fd_set *wfds) continue; if (!get_loaded_bytes(i)) continue; - FD_SET(s->write_fd, wfds); + para_fd_set(s->write_fd, wfds, max_fileno); s->wcheck = 1; - max_fileno = MAX(s->write_fd, max_fileno); } -// PARA_INFO_LOG("return %d\n", max_fileno); - return max_fileno; } static int write_audio_data(int slot_num) @@ -1107,8 +1096,9 @@ static int setup_default_filters(void) free(tmp); if (ret < 0) goto out; - PARA_INFO_LOG("%s -> default filter: %s\n", audio_formats[i], filters[j].name); - ret = add_filter(i, para_strdup("wav")); + PARA_INFO_LOG("%s -> default filter: %s\n", audio_formats[i], + filters[j].name); + ret = add_filter(i, "wav"); if (ret < 0) goto out; PARA_INFO_LOG("%s -> default filter: wav\n", audio_formats[i]); @@ -1119,7 +1109,7 @@ out: static int init_stream_io(void) { - int i, ret, receiver_num; + int i, ret, receiver_num, nf; char *cmd; for (i = 0; i < conf.stream_write_cmd_given; i++) { @@ -1168,9 +1158,11 @@ static int init_stream_io(void) free(cmd); /* filters */ filter_init(filters); + nf = PARA_MAX(2, conf.filter_given) + 1; + PARA_INFO_LOG("allocating space for %d filters\n", nf); FOR_EACH_AUDIO_FORMAT(i) { - afi[i].filter_conf = para_malloc((conf.filter_given + 1) * sizeof(char *)); - afi[i].filters = para_malloc((conf.filter_given + 1) * sizeof(struct filter *)); + afi[i].filter_conf = para_malloc(nf * sizeof(char *)); + afi[i].filters = para_malloc(nf * sizeof(struct filter *)); } if (!conf.no_default_filters_given) return setup_default_filters(); @@ -1252,7 +1244,7 @@ out: return ret; } -static int com_stat(int fd, __unused int argc, __unused char **argv) +static int com_stat(int fd, __a_unused int argc, __a_unused char **argv) { int i, ret; char *buf = NULL; @@ -1382,27 +1374,27 @@ err_out: return 1; } -static int __noreturn com_term(int fd, __unused int argc, __unused char **argv) +static int __noreturn com_term(int fd, __a_unused int argc, __a_unused char **argv) { close(fd); clean_exit(EXIT_SUCCESS, "terminating on user request"); } -static int com_on(int fd, __unused int argc, __unused char **argv) +static int com_on(int fd, __a_unused int argc, __a_unused char **argv) { audiod_status = AUDIOD_ON; close(fd); return 1; } -static int com_off(int fd, __unused int argc, __unused char **argv) +static int com_off(int fd, __a_unused int argc, __a_unused char **argv) { audiod_status = AUDIOD_OFF; close(fd); return 1; } -static int com_sb(int fd, __unused int argc, __unused char **argv) +static int com_sb(int fd, __a_unused int argc, __a_unused char **argv) { audiod_status = AUDIOD_STANDBY; close(fd); @@ -1426,14 +1418,14 @@ static int com_cycle(int fd, int argc, char **argv) return 1; } -static int check_perms(struct ucred *c) +static int check_perms(uid_t uid) { int i; if (!conf.user_allow_given) return 1; for (i = 0; i < conf.user_allow_given; i++) - if (c->uid == conf.user_allow_arg[i]) + if (uid == conf.user_allow_arg[i]) return 1; return -E_UCRED_PERM; } @@ -1441,7 +1433,6 @@ static int check_perms(struct ucred *c) static int handle_connect(void) { int i, argc, ret, clifd = -1; - struct ucred c; char *buf = para_malloc(MAXLINE), **argv = NULL; struct sockaddr_un unix_addr; @@ -1449,20 +1440,19 @@ static int handle_connect(void) if (ret < 0) goto out; clifd = ret; - ret = recv_cred_buffer(clifd, buf, MAXLINE - 1, &c); + ret = recv_cred_buffer(clifd, buf, MAXLINE - 1); if (ret < 0) goto out; - PARA_INFO_LOG("pid: %i, uid: %i, gid: %i, ret: %i, buf: %s\n", c.pid, c.uid, c.gid, ret, buf); - buf[ret] = '\0'; - ret = check_perms(&c); + PARA_INFO_LOG("connection from user %i\n", ret); + ret = check_perms(ret); if (ret < 0) goto out; - argc = split_args(buf, &argv, '\n'); - PARA_INFO_LOG("argv[0]: %s\n", argv[0]); + argc = split_args(buf, &argv, "\n"); + PARA_INFO_LOG("argv[0]: %s, argc= %d\n", argv[0], argc); for (i = 0; cmds[i].name; i++) { if (strcmp(cmds[i].name, argv[0])) continue; - ret = cmds[i].handler(clifd, argc + 1, argv); + ret = cmds[i].handler(clifd, argc, argv); goto out; } ret = -E_INVALID_AUDIOD_CMD; /* cmd not found */ @@ -1520,9 +1510,10 @@ static int open_stat_pipe(void) return ret; } -static int audiod_pre_select(fd_set *rfds, fd_set *wfds, struct timeval *tv) +static void audiod_pre_select(fd_set *rfds, fd_set *wfds, struct timeval *tv, + int *max_fileno) { - int i, ret, max = -1; + int i, ret; FOR_EACH_SLOT(i) { struct slot_info *s = &slot[i]; @@ -1533,10 +1524,8 @@ static int audiod_pre_select(fd_set *rfds, fd_set *wfds, struct timeval *tv) a = &afi[s->format]; ret = a->receiver->pre_select(rn, rfds, wfds, tv); // PARA_NOTICE_LOG("%s preselect: %d\n", a->receiver->name, ret); - max = MAX(max, ret); + *max_fileno = PARA_MAX(*max_fileno, ret); } - return max; - } static void audiod_post_select(int select_ret, fd_set *rfds, fd_set *wfds) { @@ -1573,18 +1562,17 @@ static void __noreturn audiod_mainloop(void) repeat: FD_ZERO(&wfds); FD_ZERO(&rfds); + max_fileno = -1; /* always check signal pipe and the local socket */ - FD_SET(signal_pipe, &rfds); - max_fileno = signal_pipe; - FD_SET(audiod_socket, &rfds); - max_fileno = MAX(max_fileno, audiod_socket); + para_fd_set(signal_pipe, &rfds, &max_fileno); + para_fd_set(audiod_socket, &rfds, &max_fileno); if (audiod_status != AUDIOD_ON) kill_all_decoders(); else if (playing) start_current_receiver(); - max_fileno = MAX(max_fileno, set_stream_fds(&wfds)); + set_stream_fds(&wfds, &max_fileno); /* status pipe */ if (stat_pipe >= 0 && audiod_status == AUDIOD_OFF) close_stat_pipe(); @@ -1593,24 +1581,17 @@ repeat: sbo = 0; status_buf[0] = '\0'; } - if (stat_pipe >= 0 && audiod_status != AUDIOD_OFF) { - FD_SET(stat_pipe, &rfds); - max_fileno = MAX(max_fileno, stat_pipe); - } + if (stat_pipe >= 0 && audiod_status != AUDIOD_OFF) + para_fd_set(stat_pipe, &rfds, &max_fileno); /* local socket */ tv.tv_sec = 0; tv.tv_usec = 200 * 1000; - ret = audiod_pre_select(&rfds, &wfds, &tv); - max_fileno = MAX(max_fileno, ret); - - ret = select(max_fileno + 1, &rfds, &wfds, NULL, &tv); - if (ret < 0 && errno != EINTR) - PARA_ERROR_LOG("select returned %d (%s)\n", ret, - strerror(errno)); - if (audiod_status != AUDIOD_OFF) - audiod_status_dump(); + audiod_pre_select(&rfds, &wfds, &tv, &max_fileno); + ret = para_select(max_fileno + 1, &rfds, &wfds, &tv); if (ret < 0) goto repeat; + if (audiod_status != AUDIOD_OFF) + audiod_status_dump(); audiod_post_select(ret, &rfds, &wfds); /* read status pipe */ if (stat_pipe >=0 && FD_ISSET(stat_pipe, &rfds)) { @@ -1667,19 +1648,20 @@ int __noreturn main(int argc, char *argv[]) valid_fd_012(); hostname = para_hostname(); cmdline_parser(argc, argv, &conf); - para_drop_privileges(conf.user_arg); + para_drop_privileges(conf.user_arg, conf.group_arg); cf = configfile_exists(); if (cf) { if (cmdline_parser_configfile(cf, &conf, 0, 0, 0)) { - fprintf(stderr, "parse error in config file\n"); + PARA_EMERG_LOG("%s", "parse error in config file\n"); exit(EXIT_FAILURE); } } + if (conf.logfile_given) + logfile = open_log(conf.logfile_arg); log_welcome("para_audiod", conf.loglevel_arg); i = init_stream_io(); if (i < 0) { - fprintf(stderr, "init stream io error: %s\n", - PARA_STRERROR(-i)); + PARA_EMERG_LOG("init stream io error: %s\n", PARA_STRERROR(-i)); exit(EXIT_FAILURE); } server_uptime(UPTIME_SET);