chiark / gitweb /
Use users.db. trackdb* moves to lib/, as it's now used by client.c to
[disorder] / clients / disorder.c
index f7b413025f14411178227e42e0f68b2059b3055b..7d15afea72d8f54076dc191032134f2f664aae99 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder.
- * Copyright (C) 2004, 2005, 2006 Richard Kettlewell
+ * Copyright (C) 2004, 2005, 2006, 2007 Richard Kettlewell
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,6 +34,8 @@
 #include <stddef.h>
 #include <unistd.h>
 #include <assert.h>
+#include <pcre.h>
+#include <ctype.h>
 
 #include "configuration.h"
 #include "syscalls.h"
@@ -59,7 +61,11 @@ static const struct option options[] = {
   { "version", no_argument, 0, 'V' },
   { "config", required_argument, 0, 'c' },
   { "debug", no_argument, 0, 'd' },
+  { "local", no_argument, 0, 'l' },
+  { "no-per-user-config", no_argument, 0, 'N' },
   { "help-commands", no_argument, 0, 'H' },
+  { "user", required_argument, 0, 'u' },
+  { "password", required_argument, 0, 'p' },
   { 0, 0, 0, 0 }
 };
 
@@ -72,6 +78,7 @@ static void help(void) {
          "  --help-commands, -H     List commands\n"
          "  --version, -V           Display version number\n"
          "  --config PATH, -c PATH  Set configuration file\n"
+         "  --local, -l             Force connection to local server\n"
          "  --debug, -d             Turn on debugging\n");
   xfclose(stdout);
   exit(0);
@@ -79,7 +86,7 @@ static void help(void) {
 
 /* display version number and terminate */
 static void version(void) {
-  xprintf("disorder version %s\n", disorder_version_string);
+  xprintf("%s", disorder_version_string);
   xfclose(stdout);
   exit(0);
 }
@@ -148,6 +155,8 @@ static void cf_shutdown(disorder_client *c,
 
 static void cf_reconfigure(disorder_client *c,
                           char attribute((unused)) **argv) {
+  /* Re-check configuration for server */
+  if(config_read(1)) fatal(0, "cannot read configuration");
   if(disorder_reconfigure(c)) exit(EXIT_FAILURE);
 }
 
@@ -327,9 +336,9 @@ static int isarg_filename(const char *s) {
   return s[0] == '/';
 }
 
-static void cf_authorize(disorder_client attribute((unused)) *c,
+static void cf_authorize(disorder_client *c,
                         char **argv) {
-  if(!authorize(argv[0]))
+  if(!authorize(c, argv[0]))
     auto_reconfigure = 1;
 }
 
@@ -375,6 +384,40 @@ static void cf_unset_global(disorder_client *c, char **argv) {
   if(disorder_unset_global(c, argv[0])) exit(EXIT_FAILURE);
 }
 
+static int isarg_integer(const char *s) {
+  if(!*s) return 0;
+  while(*s) {
+    if(!isdigit((unsigned char)*s))
+      return 0;
+    ++s;
+  }
+  return 1;
+}
+
+static void cf_new(disorder_client *c,
+                  char **argv) {
+  char **vec;
+
+  if(disorder_new_tracks(c, &vec, 0, argv[0] ? atoi(argv[0]) : 0))
+    exit(EXIT_FAILURE);
+  while(*vec)
+    xprintf("%s\n", nullcheck(utf82mb(*vec++)));
+}
+
+static void cf_rtp_address(disorder_client *c,
+                          char attribute((unused)) **argv) {
+  char *address, *port;
+
+  if(disorder_rtp_address(c, &address, &port)) exit(EXIT_FAILURE);
+  xprintf("address: %s\nport: %s\n", address, port);
+}
+
+static void cf_adduser(disorder_client *c,
+                      char **argv) {
+  if(disorder_adduser(c, argv[0], argv[1]))
+    exit(EXIT_FAILURE);
+}
+
 static const struct command {
   const char *name;
   int min, max;
@@ -382,6 +425,8 @@ static const struct command {
   int (*isarg)(const char *);
   const char *argstr, *desc;
 } commands[] = {
+  { "adduser",        2, 2, cf_adduser, 0, "USER PASSWORD",
+                      "Create a new user" },
   { "allfiles",       1, 2, cf_allfiles, isarg_regexp, "DIR [~REGEXP]",
                       "List all files and directories in DIR" },
   { "authorize",      1, 1, cf_authorize, 0, "USER",
@@ -412,6 +457,8 @@ static const struct command {
                       "Copy event log to stdout" },
   { "move",           2, 2, cf_move, 0, "TRACK DELTA",
                       "Move a track in the queue" },
+  { "new",            0, 1, cf_new, isarg_integer, "[MAX]",
+                      "Get the most recently added MAX tracks" },
   { "part",           3, 3, cf_part, 0, "TRACK CONTEXT PART",
                       "Find a track name part" },
   { "pause",          0, 0, cf_pause, 0, "",
@@ -441,6 +488,8 @@ static const struct command {
                       "Resolve alias for TRACK" },
   { "resume",         0, 0, cf_resume, 0, "",
                       "Resume after a pause" },
+  { "rtp-address",    0, 0, cf_rtp_address, 0, "",
+                      "Report server's broadcast address" },
   { "scratch",        0, 0, cf_scratch, 0, "",
                       "Scratch the currently playing track" },
   { "scratch-id",     1, 1, cf_scratch, 0, "ID",
@@ -495,27 +544,41 @@ static void help_commands(void) {
 }
 
 int main(int argc, char **argv) {
-  int n, i, j;
+  int n, i, j, local = 0;
   disorder_client *c = 0;
-  const char *s;
   int status = 0;
   struct vector args;
+  const char *user = 0, *password = 0;
 
-  mem_init(1);
+  mem_init();
+  /* garbage-collect PCRE's memory */
+  pcre_malloc = xmalloc;
+  pcre_free = xfree;
   if(!setlocale(LC_CTYPE, "")) fatal(errno, "error calling setlocale");
-  while((n = getopt_long(argc, argv, "hVc:dHL", options, 0)) >= 0) {
+  while((n = getopt_long(argc, argv, "hVc:dHlNu:p:", options, 0)) >= 0) {
     switch(n) {
     case 'h': help();
     case 'H': help_commands();
     case 'V': version();
     case 'c': configfile = optarg; break;
     case 'd': debugging = 1; break;
+    case 'l': local = 1; break;
+    case 'N': config_per_user = 0; break;
+    case 'u': user = optarg; break;
+    case 'p': password = optarg; break;
     default: fatal(0, "invalid option");
     }
   }
-  if(config_read()) fatal(0, "cannot read configuration");
+  if(config_read(0)) fatal(0, "cannot read configuration");
+  if(user) {
+    config->username = user;
+    config->password = 0;
+  }
+  if(password)
+    config->password = password;
+  if(local)
+    config->connect.n = 0;
   if(!(c = disorder_new(1))) exit(EXIT_FAILURE);
-  s = config_get_file("socket");
   if(disorder_connect(c)) exit(EXIT_FAILURE);
   n = optind;
   /* accumulate command args */