Obtain afs status items directly from afs.
[paraslash.git] / command.c
index 9abe04a341f94520a3720167e6610f1940e9fb24..e6a16e53e5f3367cd9b10bf959ace284d8086ebd 100644 (file)
--- a/command.c
+++ b/command.c
@@ -11,6 +11,7 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <openssl/rc4.h>
+#include <osl.h>
 
 #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)
@@ -113,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 */
@@ -123,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(&current_time, NULL);
        ret = make_message(
                "%s: %zu\n" /* file size */
                "%s: %s\n" /* mtime */
@@ -132,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,
@@ -146,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);
@@ -192,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) {
@@ -200,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;
        }
@@ -254,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;
        }
@@ -316,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)
 {
@@ -325,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]);
@@ -337,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;
@@ -662,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.
  *
@@ -701,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)
@@ -794,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: