X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=command.c;h=e6a16e53e5f3367cd9b10bf959ace284d8086ebd;hp=1f9dd857e689530cc6e7ee6fa1c125aee73b8031;hb=e752cdeab213b329552e1eecd5687bca512217c5;hpb=d79c420304e9ae7e0dec89ca2644f2e04a7134e2 diff --git a/command.c b/command.c index 1f9dd857..e6a16e53 100644 --- a/command.c +++ b/command.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1997-2008 Andre Noll + * Copyright (C) 1997-2009 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -11,6 +11,7 @@ #include #include #include +#include #include "para.h" #include "error.h" @@ -30,6 +31,8 @@ #include "user_list.h" #include "server_command_list.h" #include "afs_command_list.h" +#include "sched.h" +#include "signal.h" /** Commands including options must be shorter than this. */ #define MAX_COMMAND_LEN 32768 @@ -42,15 +45,8 @@ extern int mmd_mutex; extern struct misc_meta_data *mmd; extern struct sender senders[]; -static void dummy(int s) +static void dummy(__a_unused int s) { - /* - * At least on Solaris, SIGUSR1 is one-shot, i.e. the signal action is - * restored to the default state once the signal handler has been - * called. - */ - if (s == SIGUSR1) - signal(SIGUSR1, dummy); } static void mmd_dup(struct misc_meta_data *new_mmd) @@ -61,17 +57,20 @@ static void mmd_dup(struct misc_meta_data *new_mmd) } /* - * compute human readable string containing - * vss status for given integer value + * Compute human readable string containing vss status for given integer value. + * + * We don't want to use vss_playing() and friends here because we take a + * snapshot of the mmd struct and use the copy for computing the state of the + * vss. If the real data were used, we would take the mmd lock for a rather + * long time or risk to get an inconsistent view. */ static char *vss_status_tohuman(unsigned int flags) { if (flags & VSS_PLAYING) return para_strdup("playing"); - else if (flags & VSS_NEXT) + if (flags & VSS_NEXT) return para_strdup("stopped"); - else - return para_strdup("paused"); + return para_strdup("paused"); } /* @@ -110,7 +109,7 @@ static char *get_status(struct misc_meta_data *nmmd) char *status, *flags; /* vss status info */ char *ut = uptime_str(); long offset = (nmmd->offset + 500) / 1000; - struct timeval now; + struct timeval current_time; struct tm mtime_tm; /* report real status */ @@ -120,7 +119,7 @@ static char *get_status(struct misc_meta_data *nmmd) localtime_r(&nmmd->mtime, &mtime_tm); strftime(mtime, 29, "%b %d %Y", &mtime_tm); } - gettimeofday(&now, NULL); + gettimeofday(¤t_time, NULL); ret = make_message( "%s: %zu\n" /* file size */ "%s: %s\n" /* mtime */ @@ -129,8 +128,7 @@ static char *get_status(struct misc_meta_data *nmmd) "%s: %li\n" /* offset */ "%s: %s\n" /* afs mode */ "%s: %lu.%lu\n" /* stream start */ - "%s: %lu.%lu\n" /* current server time */ - "%s", /* afs status info */ + "%s: %lu.%lu\n", /* current server time */ status_item_list[SI_FILE_SIZE], nmmd->size / 1024, status_item_list[SI_MTIME], mtime, status_item_list[SI_STATUS], status, @@ -143,11 +141,8 @@ static char *get_status(struct misc_meta_data *nmmd) (long unsigned)nmmd->stream_start.tv_sec, (long unsigned)nmmd->stream_start.tv_usec, status_item_list[SI_CURRENT_TIME], - (long unsigned)now.tv_sec, - (long unsigned)now.tv_usec, - - nmmd->afd.verbose_ls_output - + (long unsigned)current_time.tv_sec, + (long unsigned)current_time.tv_usec ); free(flags); free(status); @@ -177,12 +172,8 @@ static int check_sender_args(int argc, char * const * argv, struct sender_comman if (!subcmds[i]) return -E_COMMAND_SYNTAX; scd->cmd_num = i; - mutex_lock(mmd_mutex); - if (!senders[scd->sender_num].client_cmds[scd->cmd_num]) { - mutex_unlock(mmd_mutex); + if (!senders[scd->sender_num].client_cmds[scd->cmd_num]) return -E_SENDER_CMD; - } - mutex_unlock(mmd_mutex); switch (scd->cmd_num) { case SENDER_ON: case SENDER_OFF: @@ -193,7 +184,7 @@ static int check_sender_args(int argc, char * const * argv, struct sender_comman case SENDER_ALLOW: if (argc != 4 && argc != 5) return -E_COMMAND_SYNTAX; - if (!inet_pton(AF_INET, argv[3], &scd->addr)) + if (!is_valid_ipv4_address(argv[3])) return -E_COMMAND_SYNTAX; scd->netmask = 32; if (argc == 5) { @@ -201,20 +192,13 @@ static int check_sender_args(int argc, char * const * argv, struct sender_comman if (scd->netmask < 0 || scd->netmask > 32) return -E_COMMAND_SYNTAX; } + strncpy(scd->host, argv[3], sizeof(scd->host)); break; case SENDER_ADD: case SENDER_DELETE: - if (argc != 4 && argc != 5) - return -E_COMMAND_SYNTAX; - if (!inet_pton(AF_INET, argv[3], &scd->addr)) + if (argc != 4) return -E_COMMAND_SYNTAX; - scd->port = -1; - if (argc == 5) { - scd->port = atoi(argv[4]); - if (scd->port < 0 || scd->port > 65535) - return -E_COMMAND_SYNTAX; - } - break; + return parse_fec_url(argv[3], scd); default: return -E_COMMAND_SYNTAX; } @@ -255,7 +239,7 @@ int com_sender(int fd, int argc, char * const * argv) usleep(100 * 1000); continue; } - mmd->sender_cmd_data = scd; + memcpy(&mmd->sender_cmd_data, &scd, sizeof(scd)); mutex_unlock(mmd_mutex); break; } @@ -281,14 +265,16 @@ int com_si(int fd, int argc, __a_unused char * const * argv) } ut = uptime_str(); ret = send_va_buffer(fd, "up: %s\nplayed: %u\n" - "pid: %d\n" + "server_pid: %d\n" + "afs_pid: %d\n" "connections (active/accepted/total): %u/%u/%u\n" - "current loglevel: %i\n" + "current loglevel: %s\n" "supported audio formats: %s\n" "supported senders: %s\n" "%s", ut, mmd->num_played, (int)getppid(), + (int)mmd->afs_pid, mmd->active_connections, mmd->num_commands, mmd->num_connects, @@ -315,6 +301,70 @@ int com_version(int fd, int argc, __a_unused char * const * argv) ); } +/** + * Write a list of audio-file related status items with empty values. + * + * This is used by vss when currently no audio file is open. + */ +static char *empty_status_items(void) +{ + return make_message( + "%s: \n" /* path */ + "%s: \n" /* dirname */ + "%s: \n" /* basename */ + "%s: \n" /* score */ + "%s: \n" /* attributes bitmap */ + "%s: \n" /* attributes txt */ + "%s: \n" /* hash */ + "%s: \n" /* image id */ + "%s: \n" /* image name */ + "%s: \n" /* lyrics id */ + "%s: \n" /* lyrics name */ + "%s: \n" /* bitrate */ + "%s: \n" /* format */ + "%s: \n" /* frequency */ + "%s: \n" /* channels */ + "%s: \n" /* duration */ + "%s: \n" /* seconds total */ + "%s: \n" /* num played */ + "%s: \n" /* last played */ + "%s: \n" /* techinfo */ + "%s: \n" /* artist */ + "%s: \n" /* title */ + "%s: \n" /* year */ + "%s: \n" /* album */ + "%s: \n" /* comment */ + "%s: \n" /* amplification */ + , + status_item_list[SI_PATH], + status_item_list[SI_DIRECTORY], + status_item_list[SI_BASENAME], + status_item_list[SI_SCORE], + status_item_list[SI_ATTRIBUTES_BITMAP], + status_item_list[SI_ATTRIBUTES_TXT], + status_item_list[SI_HASH], + status_item_list[SI_IMAGE_ID], + status_item_list[SI_IMAGE_NAME], + status_item_list[SI_LYRICS_ID], + status_item_list[SI_LYRICS_NAME], + status_item_list[SI_BITRATE], + status_item_list[SI_FORMAT], + status_item_list[SI_FREQUENCY], + status_item_list[SI_CHANNELS], + status_item_list[SI_DURATION], + status_item_list[SI_SECONDS_TOTAL], + status_item_list[SI_NUM_PLAYED], + status_item_list[SI_LAST_PLAYED], + status_item_list[SI_TECHINFO], + status_item_list[SI_ARTIST], + status_item_list[SI_TITLE], + status_item_list[SI_YEAR], + status_item_list[SI_ALBUM], + status_item_list[SI_COMMENT], + status_item_list[SI_AMPLIFICATION] + ); +} + /* stat */ int com_stat(int fd, int argc, char * const * argv) { @@ -324,7 +374,7 @@ int com_stat(int fd, int argc, char * const * argv) struct misc_meta_data tmp, *nmmd = &tmp; char *s; - signal(SIGUSR1, dummy); + para_sigaction(SIGUSR1, dummy); if (argc > 1) num = atoi(argv[1]); @@ -336,6 +386,15 @@ int com_stat(int fd, int argc, char * const * argv) free(s); if (ret < 0) goto out; + if (nmmd->vss_status_flags & VSS_NEXT) { + static char *esi; + if (!esi) + esi = empty_status_items(); + ret = send_buffer(fd, esi); + if (ret < 0) + goto out; + } else + send_afs_status(fd); ret = 1; if (num > 0 && !--num) goto out; @@ -661,6 +720,14 @@ out: } +static void reset_signals(void) +{ + para_sigaction(SIGCHLD, SIG_IGN); + para_sigaction(SIGINT, SIG_DFL); + para_sigaction(SIGTERM, SIG_DFL); + para_sigaction(SIGHUP, SIG_DFL); +} + /** * Perform user authentication and execute a command. * @@ -700,11 +767,7 @@ __noreturn void handle_connect(int fd, const char *peername) char *p, *command = NULL; size_t numbytes; - signal(SIGCHLD, SIG_IGN); - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGHUP, SIG_DFL); - + reset_signals(); /* we need a blocking fd here as recv() might return EAGAIN otherwise. */ ret = mark_fd_blocking(fd); if (ret < 0) @@ -793,12 +856,12 @@ __noreturn void handle_connect(int fd, const char *peername) /* valid command and sufficient perms */ alarm(0); argc = split_args(command, &argv, "\n"); - mutex_lock(mmd_mutex); - mmd->num_commands++; - mutex_unlock(mmd_mutex); PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", cmd->name, u->name, peername); ret = cmd->handler(fd, argc, argv); + mutex_lock(mmd_mutex); + mmd->num_commands++; + mutex_unlock(mmd_mutex); if (ret >= 0) goto out; err_out: