Merge branch 'master' into my-osx
[paraslash.git] / command.c
1 /*
2  * Copyright (C) 1997-2006 Andre Noll <maan@systemlinux.org>
3  *
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  *
9  *     This program is distributed in the hope that it will be useful,
10  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *     GNU General Public License for more details.
13  *
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17  */
18
19 /** \file command.c does client authentication and executes server commands */
20
21 #include <sys/time.h> /* gettimeofday */
22 #include "crypt.h"
23 #include "server.cmdline.h"
24 #include "db.h"
25 #include "server.h"
26 #include "afs.h"
27 #include "send.h"
28 #include "rc4.h"
29 #include <openssl/rc4.h>
30 #include "error.h"
31 #include "net.h"
32 #include "daemon.h"
33 #include "string.h"
34
35 static RC4_KEY rc4_recv_key;
36 static RC4_KEY rc4_send_key;
37 static unsigned char rc4_buf[2 * RC4_KEY_LEN];
38
39 extern const char *status_item_list[NUM_STAT_ITEMS];
40 extern struct misc_meta_data *mmd;
41 extern struct audio_file_selector selectors[];
42 extern struct sender senders[];
43 extern char *user_list;
44 struct sockaddr_in *in_addr;
45
46 static int com_si(int, int, char **);
47 static int com_version(int, int, char **);
48 static int com_sb(int, int, char **);
49 static int com_sc(int, int, char **);
50 static int com_stat(int, int, char **);
51 static int com_help(int, int, char **);
52 static int com_hup(int, int, char **);
53 static int com_term(int, int, char **);
54 static int com_play(int, int, char **);
55 static int com_stop(int, int, char **);
56 static int com_pause(int, int, char **);
57 static int com_next(int, int, char **);
58 static int com_nomore(int, int, char **);
59 static int com_chs(int, int, char **);
60 static int com_ff(int, int, char **);
61 static int com_jmp(int, int, char **);
62 static int com_sender(int, int, char **);
63
64
65 /* commands that are handled by the server itself */
66 static struct server_command cmd_struct[] = {
67 {
68 .name = "chs",
69 .handler = com_chs,
70 .perms = DB_READ | DB_WRITE,
71 .description = "change the current audio file selector",
72 .synopsis = "chs [new_selector]",
73 .help =
74 "Shutdown the current selector and activate new_selector. If no\n"
75 "argument was given, print the name of the current selector.\n"
76 },
77
78 {
79 .name = "ff",
80 .handler = com_ff,
81 .perms = AFS_READ | AFS_WRITE,
82 .description = "jmp amount of time forwards or backwards "
83         "in current audio file",
84 .synopsis = "ff n[-]",
85 .help =
86
87 "\tSet the 'R' (reposition request) bit of the afs status flags\n"
88 "\tand enqueue a request to jump n seconds forwards or backwards\n"
89 "\tin the current audio file.\n"
90 "\n"
91 "EXAMPLE\n"
92 "\n"
93 "\t\tff 30-\n"
94 "\n"
95 "\tjumps 30 seconds backwards.\n"
96
97 },
98
99 {
100 .name = "help",
101 .handler = com_help,
102 .perms = 0,
103 .description = "print help text",
104 .synopsis = "help [command]",
105 .help =
106
107 "Without any arguments, help prints a list of availible commands. When\n"
108 "issued with a command name as first argument, print out a description\n"
109 "for that command.\n"
110
111 },
112
113 {
114 .name = "hup",
115 .handler = com_hup,
116 .perms = AFS_WRITE,
117 .description = "force reload of config file and log file",
118 .synopsis = "hup",
119 .help =
120
121 "After rereading the config file, a signal is sent to all children\n"
122 "which forces them to close/reopen the log file.\n"
123
124 },
125
126 {
127 .name = "jmp",
128 .handler = com_jmp,
129 .perms = AFS_READ | AFS_WRITE,
130 .description = "jmp to given position in current audio file",
131 .synopsis = "jmp [n]",
132 .help =
133
134 "\tSet the 'R' (reposition request) bit of the afs status flags\n"
135 "\tand enqueue a request to jump to n% of the current audio file,\n"
136 "\twhere 0 <= n <= 100.\n"
137
138 },
139
140 {
141 .name = "next",
142 .handler = com_next,
143 .perms = AFS_READ | AFS_WRITE,
144 .description = "skip rest of current audio file",
145 .synopsis = "next",
146 .help =
147
148 "\tSet the 'N' (next audio file) bit of the afs status flags. When\n"
149 "\tplaying, change audio file immediately. Equivalent to stop\n"
150 "\tif paused, NOP if stopped.\n"
151
152
153 },
154
155 {
156 .name = "nomore",
157 .handler = com_nomore,
158 .perms = AFS_READ | AFS_WRITE,
159 .description = "stop playing after current audio file",
160 .synopsis = "nomore",
161 .help =
162
163 "Set the 'O' (no more) bit of the afs status flags. This instructs\n"
164 "para_server to clear the 'P' (playing) bit as soon as it encounters\n"
165 "the 'N' (next audio file) bit being set.\n"
166 "\n"
167 "Use this command instead of stop if you don't like\n"
168 "sudden endings.\n"
169
170 },
171
172 {
173 .name ="pause",
174 .handler = com_pause,
175 .perms = AFS_READ | AFS_WRITE,
176 .description = "pause current audio file",
177 .synopsis = "pause",
178 .help =
179
180 "\tClear the 'P' (playing) bit of the afs status flags.\n"
181
182 },
183
184 {
185 .name = "play",
186 .handler = com_play,
187 .perms = AFS_READ | AFS_WRITE,
188 .description = "start playing or resume playing when paused",
189 .synopsis = "play",
190 .help =
191
192 "\tSet the 'P' (playing) bit of the afs status flags. This\n"
193 "\tresults in starting/continuing to stream.\n"
194
195 },
196
197 {
198 .name = "sb",
199 .handler = com_sb,
200 .perms = AFS_READ,
201 .description = "print status bar for current audio file",
202 .synopsis = "sb [n]",
203 .help =
204
205 "Without any arguments, sb continuously prints a status bar of the form\n"
206 "\n"
207 "       12:34 [56:12] (56%) filename\n"
208 "\n"
209 "indicating playing time, remaining time, percentage and the name of\n"
210 "the file beeing streamed. Use the optional number n to let stat exit\n"
211 "after having displayed the status bar n times.\n"
212
213 },
214 {
215 .name = "sc",
216 .handler = com_sc,
217 .perms = AFS_READ,
218 .description = "print name of audio file whenever it changes",
219 .synopsis = "sc [n]",
220 .help =
221
222 "\tsc prints exactly one line (the filename of the audio file\n"
223 "\tbeing played) whenever the audio file changes. Stops after\n"
224 "\tn iterations, or never if n is not specified.\n"
225
226 },
227 {
228 .name = "sender",
229 .handler = com_sender,
230 .perms = AFS_READ | AFS_WRITE,
231 .description = "control paraslash internal senders",
232 .synopsis = "sender [s cmd [arguments]]",
233 .help =
234
235 "send command cmd to sender s. cmd may be one of the following:\n"
236 "help, on, off, add, delete, allow, or deny. Note that not all senders\n"
237 "support each command. Try e.g. 'para_client sender http help' for\n"
238 "more information about the http sender. If no argument is given,\n"
239 "print out a list of all senders that are compiled in.\n"
240
241 },
242 {
243 .name = "si",
244 .handler = com_si,
245 .perms = 0,
246 .description = "print server info",
247 .synopsis = "si",
248 .help =
249 "Print server uptime and other information.\n"
250 },
251
252 {
253 .name = "stat",
254 .handler = com_stat,
255 .perms = AFS_READ,
256 .description = "print status info for current audio file",
257 .synopsis = "stat [n]",
258 .help =
259
260 "\tWithout any arguments, stat continuously prints status messages\n"
261 "\tof the audio file being streamed. Use the optional number n\n"
262 "\tto let stat exit after having displayed status n times.\n"
263
264 },
265
266 {
267 .name = "stop",
268 .handler = com_stop,
269 .perms = AFS_READ | AFS_WRITE,
270 .description = "stop playing",
271 .synopsis = "stop",
272 .help =
273
274 "\tClear the 'P' (play) bit and set the 'N' bit of the afs status\n"
275 "\tflags.\n"
276
277 },
278 {
279 .name = "term",
280 .handler = com_term,
281 .perms = AFS_READ | AFS_WRITE,
282 .description = "terminate para_server",
283 .synopsis = "term",
284 .help =
285
286 "Shuts down the server. Instead of this command, you can also send\n"
287 "SIGINT or SIGTERM. It should never be necessary to send SIGKILL.\n"
288
289 },
290 {
291 .name = "version",
292 .handler = com_version,
293 .perms = 0,
294 .description = "print server's version",
295 .synopsis = "version",
296 .help =
297 "Show version and other info\n"
298 },
299 /* this indicates the end of the list. Do not touch. */
300 {
301 .name = NULL,
302 }
303 };
304
305 static void dummy(__a_unused int s)
306 {}
307
308 static void mmd_dup(struct misc_meta_data *new_mmd)
309 {
310         mmd_lock();
311         *new_mmd = *mmd;
312         mmd_unlock();
313 }
314
315 /*
316  * compute human readable string containing
317  * afs_status for given integer value
318  */
319 static char *afs_status_tohuman(unsigned int flags)
320 {
321         if (flags & AFS_PLAYING)
322                 return para_strdup("playing");
323         else if (flags & AFS_NEXT)
324                 return para_strdup("stopped");
325         else
326                 return para_strdup("paused");
327 }
328
329 /*
330  * return human readable permission string. Never returns NULL.
331  */
332 char *cmd_perms_itohuman(unsigned int perms)
333 {
334         char *msg = para_malloc(7 * sizeof(char));
335
336         msg[0] = perms & DB_READ? 'd' : '-';
337         msg[1] = perms & DB_WRITE? 'D' : '-';
338         msg[2] = perms & AFS_READ? 'a' : '-';
339         msg[3] = perms & AFS_WRITE? 'A' : '-';
340         msg[4] = '\0';
341         return msg;
342 }
343
344 /*
345  * Never returns NULL.
346  */
347 static char *afs_get_status_flags(unsigned int flags)
348 {
349         char *msg = para_malloc(5 * sizeof(char));
350
351         msg[0] = (flags & AFS_PLAYING)? 'P' : '_';
352         msg[1] = (flags & AFS_NOMORE)? 'O' : '_';
353         msg[2] = (flags & AFS_NEXT)? 'N' : '_';
354         msg[3] = (flags & AFS_REPOS)? 'R' : '_';
355         msg[4] = '\0';
356         return msg;
357 }
358
359 /*
360  * compute status bar string. Never returns NULL
361  */
362 char *get_sb_string(struct misc_meta_data *nmmd)
363 {
364         char *base, *ret;
365         long long unsigned secs = 0, rsecs = 0, percent = 0;
366
367         base = para_basename(nmmd->filename);
368         if (!base)
369                 return para_strdup("");
370         if (!base[0])
371                 return base;
372         if (nmmd->chunks_total) {
373                 secs = (long long) nmmd->seconds_total * nmmd->chunks_sent
374                         / nmmd->chunks_total;
375                 rsecs = (long long) nmmd->seconds_total *
376                         (nmmd->chunks_total - nmmd->chunks_sent)
377                         / nmmd->chunks_total;
378                 percent = 100 * ((nmmd->chunks_sent + 5) / 10)
379                         / ((nmmd->chunks_total + 5) / 10);
380         }
381         ret = make_message("%llu:%02llu [%llu:%02llu] (%llu%%) %s",
382                 secs / 60, secs % 60,
383                 rsecs / 60, rsecs % 60,
384                 percent,
385                 base
386         );
387         free(base);
388         return ret;
389 }
390
391 static char *get_status(struct misc_meta_data *nmmd)
392 {
393         char *bar, *ret, mtime[30] = "";
394         char *status, *flags; /* afs status info */
395         char *ut = uptime_str();
396         long offset = (nmmd->offset + 500) / 1000;
397         struct timeval now;
398         struct tm mtime_tm;
399
400         if (nmmd->audio_format >= 0) {
401                 localtime_r(&nmmd->mtime, &mtime_tm);
402                 strftime(mtime, 29, "%a %b %d %Y", &mtime_tm);
403         }
404         /* report real status */
405         status = afs_status_tohuman(nmmd->afs_status_flags);
406         flags = afs_get_status_flags(nmmd->afs_status_flags);
407         bar = para_basename(nmmd->filename);
408         gettimeofday(&now, NULL);
409         ret = make_message(
410                 "%s:%lu\n"      "%s:%s\n"               "%s:%i\n"       "%s:%u\n"
411                 "%s:%s\n"       "%s:%s\n"       "%s:%s\n"       "%s:%s\n"
412                 "%s:%li\n"      "%s:%s\n"       "%s"            "%s"
413                 "%s:%s\n"       "%s:%lu.%lu\n"  "%s:%lu.%lu\n",
414                 status_item_list[SI_FILE_SIZE], nmmd->size / 1024,
415                 status_item_list[SI_MTIME], mtime,
416                 status_item_list[SI_LENGTH], nmmd->seconds_total,
417                 status_item_list[SI_NUM_PLAYED], nmmd->num_played,
418
419                 status_item_list[SI_STATUS_BAR], bar ? bar : "(none)",
420                 status_item_list[SI_STATUS], status,
421                 status_item_list[SI_STATUS_FLAGS], flags,
422                 status_item_list[SI_SELECTOR], selectors[nmmd->selector_num].name,
423
424                 status_item_list[SI_OFFSET], offset,
425                 status_item_list[SI_FORMAT], audio_format_name(nmmd->audio_format),
426                 nmmd->selector_info,
427                 nmmd->audio_file_info,
428
429                 status_item_list[SI_UPTIME], ut,
430                 status_item_list[SI_STREAM_START],
431                         (long unsigned)nmmd->stream_start.tv_sec,
432                         (long unsigned)nmmd->stream_start.tv_usec,
433                 status_item_list[SI_CURRENT_TIME],
434                         (long unsigned)now.tv_sec,
435                         (long unsigned)now.tv_usec
436
437         );
438         free(bar);
439         free(flags);
440         free(status);
441         free(ut);
442         return ret;
443 }
444
445 static int check_sender_args(int argc, char **argv, struct sender_command_data *scd)
446 {
447         int i;
448         /* this has to match sender.h */
449         const char *subcmds[] = {"add", "delete", "allow", "deny", "on", "off", NULL};
450
451         scd->sender_num = -1;
452         if (argc < 2)
453                 return -E_COMMAND_SYNTAX;
454         for (i = 0; senders[i].name; i++)
455                 if (!strcmp(senders[i].name, argv[1]))
456                         break;
457         PARA_DEBUG_LOG("%d:%s\n", argc, argv[1]);
458         if (!senders[i].name)
459                 return -E_COMMAND_SYNTAX;
460         scd->sender_num = i;
461         for (i = 0; subcmds[i]; i++)
462                 if (!strcmp(subcmds[i], argv[2]))
463                         break;
464         if (!subcmds[i])
465                 return -E_COMMAND_SYNTAX;
466         scd->cmd_num = i;
467         mmd_lock();
468         if (!senders[scd->sender_num].client_cmds[scd->cmd_num]) {
469                 mmd_unlock();
470                 return -E_SENDER_CMD;
471         }
472         mmd_unlock();
473         switch (scd->cmd_num) {
474         case SENDER_ON:
475         case SENDER_OFF:
476                 if (argc != 3)
477                         return -E_COMMAND_SYNTAX;
478                 break;
479         case SENDER_DENY:
480         case SENDER_ALLOW:
481                 if (argc != 4 && argc != 5)
482                         return -E_COMMAND_SYNTAX;
483                 if (!inet_aton(argv[3], &scd->addr))
484                         return -E_COMMAND_SYNTAX;
485                 scd->netmask = 32;
486                 if (argc == 5) {
487                         scd->netmask = atoi(argv[4]);
488                         if (scd->netmask < 0 || scd->netmask > 32)
489                                 return -E_COMMAND_SYNTAX;
490                 }
491                 break;
492         case SENDER_ADD:
493         case SENDER_DELETE:
494                 if (argc != 4 && argc != 5)
495                         return -E_COMMAND_SYNTAX;
496                 if (!inet_aton(argv[3], &scd->addr))
497                         return -E_COMMAND_SYNTAX;
498                 scd->port = -1;
499                 if (argc == 5) {
500                         scd->port = atoi(argv[4]);
501                         if (scd->port < 0 || scd->port > 65535)
502                                 return -E_COMMAND_SYNTAX;
503                 }
504                 break;
505         default:
506                 return -E_COMMAND_SYNTAX;
507         }
508         return 1;
509 }
510
511 static int com_sender(int fd, int argc, char **argv)
512 {
513         int i, ret;
514         struct sender_command_data scd;
515
516         if (argc < 2) {
517                 char *msg = NULL;
518                 for (i = 0; senders[i].name; i++) {
519                         char *tmp = make_message("%s%s\n",
520                                 msg? msg : "", senders[i].name);
521                         free(msg);
522                         msg = tmp;
523                 }
524                 ret = send_buffer(fd, msg);
525                 free(msg);
526                 return ret;
527         }
528         ret = check_sender_args(argc, argv, &scd);
529         if (ret < 0) {
530                 char *msg;
531                 if (scd.sender_num < 0)
532                         return ret;
533                 msg = senders[scd.sender_num].help();
534                 send_buffer(fd, msg);
535                 free(msg);
536                 return 1;
537         }
538         for (i = 0; i < 10; i++) {
539                 mmd_lock();
540                 if (mmd->sender_cmd_data.cmd_num >= 0) {
541                         mmd_unlock();
542                         usleep(100 * 1000);
543                         continue;
544                 }
545                 mmd->sender_cmd_data = scd;
546                 mmd_unlock();
547                 break;
548         }
549         return (i < 10)? 1 : -E_LOCK;
550 }
551
552 /* server info */
553 static int com_si(int fd, int argc, __a_unused char **argv)
554 {
555         int i, ret;
556         char *ut;
557         char *selector_string = NULL, *sender_info = NULL, *sender_list = NULL;
558
559         if (argc != 1)
560                 return -E_COMMAND_SYNTAX;
561         mmd_lock();
562         for (i = 0; selectors[i].name; i++) {
563                 selector_string = para_strcat(selector_string, selectors[i].name);
564                 selector_string = para_strcat(selector_string, " ");
565         }
566         for (i = 0; senders[i].name; i++) {
567                 char *info = senders[i].info();
568                 sender_info = para_strcat(sender_info, info);
569                 free(info);
570                 sender_list = para_strcat(sender_list, senders[i].name);
571                 sender_list = para_strcat(sender_list, " ");
572         }
573         ut = uptime_str();
574         ret = send_va_buffer(fd, "up: %s\nplayed: %u\n"
575                 "pid: %d\n"
576                 "connections (active/accepted/total): %u/%u/%u\n"
577                 "current loglevel: %i\n"
578                 "supported audio file selectors: %s\n"
579                 "supported audio formats: %s\n"
580                 "supported senders: %s\n"
581                 "%s",
582                 ut, mmd->num_played,
583                 getppid(),
584                 mmd->active_connections,
585                 mmd->num_commands,
586                 mmd->num_connects,
587                 conf.loglevel_arg,
588                 selector_string,
589                 supported_audio_formats(),
590                 sender_list,
591                 sender_info
592         );
593         mmd_unlock();
594         free(ut);
595         free(selector_string);
596         free(sender_list);
597         free(sender_info);
598         return ret;
599 }
600
601 /* version */
602 static int com_version(int socket_fd, int argc, __a_unused char **argv)
603 {
604         if (argc != 1)
605                 return -E_COMMAND_SYNTAX;
606         return send_buffer(socket_fd, "para_server-" VERSION ", \"" CODENAME "\"\n"
607                         COPYRIGHT "\n"
608                         "built: " BUILD_DATE "\n"
609                         SYSTEM ", " CC_VERSION "\n"
610                 );
611 }
612
613 /* sc */
614 static int com_sc(int socket_fd, int argc, char **argv)
615 {
616         char *name = NULL;
617         int ret, old = 0, count = -1; /* print af change forever */
618
619         if (argc > 1)
620                 count = atoi(argv[1]);
621 repeat:
622         mmd_lock();
623         if (old != mmd->num_played) {
624                 old = mmd->num_played;
625                 name = para_strdup(mmd->filename);
626         }
627         mmd_unlock();
628         if (name) {
629                 ret = send_va_buffer(socket_fd, "%s\n", name);
630                 free(name);
631                 name = NULL;
632                 if (ret < 0)
633                         return ret;
634                 if (argc > 1 && !--count)
635                         return 1;
636         }
637         usleep(500000);
638         goto repeat;
639 }
640
641 /* sb */
642 static int com_sb(int socket_fd, int argc, char **argv)
643 {
644         char *sb;
645         int ret, nr = -1;       /* status bar will be printed that many
646                                  * times. Negative value means: print
647                                  * forever
648                                  */
649         if (argc > 1)
650                 nr = atoi(argv[1]);
651         while (nr) {
652                 mmd_lock();
653                 sb = get_sb_string(mmd);
654                 mmd_unlock();
655                 ret = send_va_buffer(socket_fd, "%s\n", sb);
656                 free(sb);
657                 if (ret < 0)
658                         return ret;
659                 if (nr == 1)
660                         return 1;
661                 usleep(500000);
662                 if (nr > 0)
663                         nr--;
664         }
665         return 1;
666 }
667
668 /* stat */
669 static int com_stat(int socket_fd, int argc, char **argv)
670 {
671         int ret, num = 0;/* status will be printed that many
672                           * times. num <= 0 means: print forever
673                           */
674         struct misc_meta_data tmp, *nmmd = &tmp;
675         char *s;
676
677         signal(SIGUSR1, dummy);
678
679         if (argc > 1)
680                 num = atoi(argv[1]);
681         for (;;) {
682
683                 mmd_dup(nmmd);
684                 s = get_status(nmmd);
685                 ret = send_buffer(socket_fd, s);
686                 free(s);
687                 if (ret < 0)
688                         goto out;
689                 ret = 1;
690                 if (num == 1)
691                         goto out;
692                 usleep(500000 * 100);
693         }
694 out:
695         return ret;
696 }
697
698 static int send_description(int fd, struct server_command *cmd, const char *handler, int num)
699 {
700         int ret, i;
701
702         for (i = 1; cmd->name && (!num || i <= num); cmd++, i++) {
703                 char *perms = cmd_perms_itohuman(cmd->perms);
704                 ret = send_va_buffer(fd, "%s\t%s\t%s\t%s\n", cmd->name,
705                         handler,
706                         perms,
707                         cmd->description);
708                 free(perms);
709                 if (ret < 0)
710                         return ret;
711         }
712         return 1;
713 }
714
715 /* always returns string that must be freed by the caller in handler */
716 static struct server_command *get_cmd_ptr(char *name, char **handler)
717 {
718         struct server_command *cmd = cmd_struct;
719
720         for (cmd = cmd_struct; cmd->name; cmd++)
721                 if (!strcmp(cmd->name, name)) {
722                         if (handler)
723                                 *handler = para_strdup("para_server"); /* server commands */
724                         return cmd;
725                 }
726         /* not found, look for commands supported by the current selector */
727         mmd_lock();
728         if (handler)
729                 *handler = make_message("the %s selector",
730                         selectors[mmd->selector_num].name);
731         cmd = selectors[mmd->selector_num].cmd_list;
732         mmd_unlock();
733         for (; cmd->name; cmd++)
734                 if (!strcmp(cmd->name, name))
735                         return cmd;
736         return NULL;
737 }
738
739 /* help */
740 static int com_help(int fd, int argc, char **argv)
741 {
742         struct server_command *cmd;
743         char *perms, *handler;
744         int ret;
745
746         if (argc < 2) {
747                 /* no argument given, print list of commands */
748                 if ((ret = send_description(fd, cmd_struct, "server", 0)) < 0)
749                         return ret;
750                 mmd_lock();
751                 handler = para_strdup(selectors[mmd->selector_num].name);
752                 cmd = selectors[mmd->selector_num].cmd_list;
753                 mmd_unlock();
754                 ret = send_description(fd, cmd, handler, 0);
755                 free(handler);
756                 return ret;
757         }
758         /* argument given for help */
759         cmd = get_cmd_ptr(argv[1], &handler);
760         if (!cmd) {
761                 free(handler);
762                 return -E_BAD_CMD;
763         }
764         perms = cmd_perms_itohuman(cmd->perms);
765         ret = send_va_buffer(fd,
766                 "NAME\n\t%s - %s\n"
767                 "SYNOPSIS\n\t para_client %s\n"
768                 "DESCRIPTION\n%s\n"
769                 "HANDLER\n"
770                 "This command is handled by %s.\n\n"
771                 "PERMISSIONS\n"
772                 "Needed privileges for %s: %s\n",
773                 argv[1],
774                 cmd->description,
775                 cmd->synopsis,
776                 cmd->help,
777                 handler,
778                 argv[1],
779                 perms
780         );
781         free(perms);
782         free(handler);
783         return ret;
784 }
785
786 /* hup */
787 static int com_hup(__a_unused int socket_fd, int argc, __a_unused char **argv)
788 {
789         if (argc != 1)
790                 return -E_COMMAND_SYNTAX;
791         kill(getppid(), SIGHUP);
792         return 1;
793 }
794
795 /* term */
796 static int com_term(__a_unused int socket_fd, int argc, __a_unused char **argv)
797 {
798         if (argc != 1)
799                 return -E_COMMAND_SYNTAX;
800         kill(getppid(), SIGTERM);
801         return 1;
802 }
803
804 static int com_play(__a_unused int socket_fd, int argc, __a_unused char **argv)
805 {
806         if (argc != 1)
807                 return -E_COMMAND_SYNTAX;
808         mmd_lock();
809         mmd->new_afs_status_flags |= AFS_PLAYING;
810         mmd->new_afs_status_flags &= ~AFS_NOMORE;
811         mmd_unlock();
812         return 1;
813
814 }
815
816 /* stop */
817 static int com_stop(__a_unused int socket_fd, int argc, __a_unused char **argv)
818 {
819         if (argc != 1)
820                 return -E_COMMAND_SYNTAX;
821         mmd_lock();
822         mmd->new_afs_status_flags &= ~AFS_PLAYING;
823         mmd->new_afs_status_flags &= ~AFS_REPOS;
824         mmd->new_afs_status_flags |= AFS_NEXT;
825         mmd_unlock();
826         return 1;
827 }
828
829 /* pause */
830 static int com_pause(__a_unused int socket_fd, int argc, __a_unused char **argv)
831 {
832         if (argc != 1)
833                 return -E_COMMAND_SYNTAX;
834         mmd_lock();
835         if (!afs_paused())
836                 mmd->events++;
837         mmd->new_afs_status_flags &= ~AFS_PLAYING;
838         mmd->new_afs_status_flags &= ~AFS_NEXT;
839         mmd_unlock();
840         return 1;
841 }
842
843 static int com_chs(int fd, int argc, char **argv)
844 {
845         int i, ret;
846
847         if (argc == 1) {
848                 char *selector;
849                 mmd_lock();
850                 selector = para_strdup(selectors[mmd->selector_num].name);
851                 mmd_unlock();
852                 ret = send_va_buffer(fd, "%s\n", selector);
853                 free(selector);
854                 return ret;
855         }
856         for (i = 0; selectors[i].name; i++) {
857                 if (strcmp(selectors[i].name, argv[1]))
858                         continue;
859                 mmd_lock();
860                 mmd->selector_change = i;
861                 mmd->events++;
862                 mmd_unlock();
863                 return 1;
864         }
865         return -E_BAD_SELECTOR;
866 }
867
868 /* next */
869 static int com_next(__a_unused int socket_fd, int argc, __a_unused char **argv)
870 {
871         if (argc != 1)
872                 return -E_COMMAND_SYNTAX;
873         mmd_lock();
874         mmd->events++;
875         mmd->new_afs_status_flags |= AFS_NEXT;
876         mmd_unlock();
877         return 1;
878 }
879
880 /* nomore */
881 static int com_nomore(__a_unused int socket_fd, int argc, __a_unused char **argv)
882 {
883         if (argc != 1)
884                 return -E_COMMAND_SYNTAX;
885         mmd_lock();
886         if (afs_playing() || afs_paused())
887                 mmd->new_afs_status_flags |= AFS_NOMORE;
888         mmd_unlock();
889         return 1;
890 }
891
892 /* ff */
893 static int com_ff(__a_unused int socket_fd, int argc, char **argv)
894 {
895         long promille;
896         int ret, backwards = 0;
897         unsigned i;
898         char c;
899
900         if (argc != 2)
901                 return -E_COMMAND_SYNTAX;
902         if (!(ret = sscanf(argv[1], "%u%c", &i, &c)))
903                 return -E_COMMAND_SYNTAX;
904         if (ret > 1 && c == '-')
905                 backwards = 1; /* jmp backwards */
906         mmd_lock();
907         ret = -E_NO_AUDIO_FILE;
908         if (!mmd->chunks_total || !mmd->seconds_total)
909                 goto out;
910         promille = (1000 * mmd->current_chunk) / mmd->chunks_total;
911         if (backwards)
912                 promille -= 1000 * i / mmd->seconds_total;
913         else
914                 promille += 1000 * i / mmd->seconds_total;
915         if (promille < 0)
916                 promille = 0;
917         if (promille >  1000) {
918                 mmd->new_afs_status_flags |= AFS_NEXT;
919                 goto out;
920         }
921         mmd->repos_request = (mmd->chunks_total * promille) / 1000;
922         mmd->new_afs_status_flags |= AFS_REPOS;
923         mmd->new_afs_status_flags &= ~AFS_NEXT;
924         mmd->events++;
925         ret = 1;
926 out:
927         mmd_unlock();
928         return ret;
929 }
930
931 /* jmp */
932 static int com_jmp(__a_unused int socket_fd, int argc, char **argv)
933 {
934         long unsigned int i;
935         int ret;
936
937         if (argc != 2)
938                 return -E_COMMAND_SYNTAX;
939         if (sscanf(argv[1], "%lu", &i) <= 0)
940                 return -E_COMMAND_SYNTAX;
941         mmd_lock();
942         ret = -E_NO_AUDIO_FILE;
943         if (!mmd->chunks_total)
944                 goto out;
945         if (i > 100)
946                 i = 100;
947         PARA_INFO_LOG("jumping to %lu%%\n", i);
948         mmd->repos_request = (mmd->chunks_total * i + 50)/ 100;
949         PARA_INFO_LOG("sent: %lu,  offset before jmp: %lu\n",
950                 mmd->chunks_sent, mmd->offset);
951         mmd->new_afs_status_flags |= AFS_REPOS;
952         mmd->new_afs_status_flags &= ~AFS_NEXT;
953         ret = 1;
954         mmd->events++;
955 out:
956         mmd_unlock();
957         return ret;
958 }
959
960 /*
961  * check if perms are sufficient to exec a command having perms cmd_perms.
962  * Returns 0 if perms are sufficient, -E_PERM otherwise.
963  */
964 static int check_perms(unsigned int perms, struct server_command *cmd_ptr)
965 {
966         PARA_DEBUG_LOG("%s", "checking permissions\n");
967         return (cmd_ptr->perms & perms) < cmd_ptr->perms ? -E_PERM : 0;
968 }
969
970 /*
971  * Parse first string from *cmd and lookup in table of valid commands.
972  * On error, NULL is returned.
973  */
974 static struct server_command *parse_cmd(const char *cmdstr)
975 {
976         char buf[255];
977         int n = 0;
978
979         sscanf(cmdstr, "%200s%n", buf, &n);
980         if (!n)
981                 return NULL;
982         buf[n] = '\0';
983         return get_cmd_ptr(buf, NULL);
984 }
985
986 long int para_rand(long unsigned max)
987 {
988         return (long int) ((max + 0.0) * (random() / (RAND_MAX + 1.0)));
989 }
990
991 /* Open user_list file, returns pointer to opened file on success,
992  * NULL on errors
993  */
994 static FILE *open_user_list(char *file)
995 {
996         PARA_DEBUG_LOG("opening user list %s\n", file);
997         return fopen(file, "r");
998 }
999
1000 /*
1001  * lookup user in user_list file. Fills in a user struct containing
1002  * filename of the user's public key as well as the permissions of that user.
1003  * Returns 1 on success, 0 if user does not exist and < 0 on errors.
1004  */
1005 static int get_user(struct user *user) {
1006         FILE *file_ptr;
1007         char *char_ptr;
1008         char line[MAXLINE];
1009         /* keyword, user, key, perms */
1010         char w[MAXLINE], n[MAXLINE], k[MAXLINE], p[MAXLINE], tmp[4][MAXLINE];
1011         int num;
1012
1013         file_ptr = open_user_list(user_list);
1014         if (!file_ptr)
1015                 return -E_USERLIST;
1016         while (fgets(line, MAXLINE, file_ptr)) {
1017 //              PARA_DEBUG_LOG("%s: Read line (%i bytes) "
1018 //                      "from config file\n", __func__, strlen(line));
1019                 if (sscanf(line,"%200s %200s %200s %200s", w, n, k, p) < 3)
1020                         continue;
1021                 if (!strcmp(w, "user") && !strcmp(user->name, n)) {
1022                         PARA_DEBUG_LOG("found entry for %s\n", n);
1023                         strcpy(user->name, n);
1024                         strcpy(user->pubkey_file, k);
1025                         user->perms = 0;
1026                         char_ptr = p;
1027                         num = sscanf(char_ptr, "%200[A-Z_],%200[A-Z_],%200[A-Z_],%200[A-Z_]",
1028                                 tmp[0], tmp[1], tmp[2], tmp[3]);
1029                         PARA_DEBUG_LOG("found %i perm entries\n",
1030                                 num);
1031                         user->perms = 0;
1032                         while (num > 0) {
1033                                 num--;
1034                                 //PARA_DEBUG_LOG("%s: tmp[%i]=%s\n", __func__,
1035                                 //      num, tmp[num]);
1036                                 if (!strcmp(tmp[num], "AFS_READ"))
1037                                         user->perms =
1038                                                 user->perms | AFS_READ;
1039                                 else if (!strcmp(tmp[num], "AFS_WRITE"))
1040                                         user->perms =
1041                                                 user->perms | AFS_WRITE;
1042                                 else if (!strcmp(tmp[num], "DB_READ"))
1043                                         user->perms = user->perms | DB_READ;
1044                                 else if (!strcmp(tmp[num], "DB_WRITE"))
1045                                         user->perms = user->perms | DB_WRITE;
1046                                 else /* unknown permission */
1047                                         PARA_WARNING_LOG("unknown permission:"
1048                                                 "%s\n", tmp[num]);
1049                         }
1050                         fclose(file_ptr);
1051                         return 1;
1052                 }
1053         }
1054         fclose(file_ptr);
1055         return 0;
1056 }
1057
1058 static void init_rc4_keys(void)
1059 {
1060         int i;
1061
1062         for (i = 0; i < 2 * RC4_KEY_LEN; i++)
1063                 rc4_buf[i] = para_rand(256);
1064         PARA_DEBUG_LOG("rc4 keys initialized (%u:%u)\n",
1065                 (unsigned char) rc4_buf[0],
1066                 (unsigned char) rc4_buf[RC4_KEY_LEN]);
1067         RC4_set_key(&rc4_recv_key, RC4_KEY_LEN, rc4_buf);
1068         RC4_set_key(&rc4_send_key, RC4_KEY_LEN, rc4_buf + RC4_KEY_LEN);
1069 }
1070
1071 static void rc4_recv(unsigned long len, const unsigned char *indata,
1072                 unsigned char *outdata, __a_unused void *private_data)
1073 {
1074         RC4(&rc4_recv_key, len, indata, outdata);
1075 }
1076
1077 static void rc4_send(unsigned long len, const unsigned char *indata,
1078                 unsigned char *outdata, __a_unused void *private_data)
1079 {
1080         RC4(&rc4_send_key, len, indata, outdata);
1081 }
1082
1083 int handle_connect(int fd, struct sockaddr_in *addr)
1084 {
1085         int numbytes, ret, argc, use_rc4 = 0;
1086         char buf[STRINGSIZE];
1087         unsigned char crypt_buf[MAXLINE];
1088         struct user u;
1089         struct server_command *cmd = NULL;
1090         long unsigned challenge_nr, chall_response;
1091         char **argv = NULL;
1092         char *p, *command = NULL;
1093
1094         signal(SIGCHLD, SIG_IGN);
1095         signal(SIGINT, SIG_DFL);
1096         signal(SIGTERM, SIG_DFL);
1097         signal(SIGHUP, SIG_DFL);
1098         signal(SIGUSR1, SIG_IGN);
1099
1100         in_addr = addr;
1101         challenge_nr = random();
1102         /* send Welcome message */
1103         ret = send_va_buffer(fd, "This is para_server, version " VERSION  ".\n" );
1104         if (ret < 0)
1105                 goto err_out;
1106         /* recv auth request line */
1107         ret = recv_buffer(fd, buf, sizeof(buf));
1108         if (ret < 0)
1109                 goto err_out;
1110         if (ret <= 6) {
1111                 ret = -E_AUTH;
1112                 goto err_out;
1113         }
1114         numbytes = ret;
1115         ret = -E_AUTH;
1116         if (strncmp(buf, "auth ", 5))
1117                 goto err_out;
1118
1119         if (numbytes < 9 || strncmp(buf, "auth rc4 ", 9))
1120                 strcpy(u.name, buf + 5); /* client version < 0.2.6 */
1121         else {
1122                 strcpy(u.name, buf + 9); /* client version >= 0.2.6 */
1123                 use_rc4 = 1;
1124         }
1125 //      strcpy(u.name, buf + 5); /* ok, but ugly */
1126         PARA_DEBUG_LOG("received %s request for user %s\n",
1127                 use_rc4? "rc4" : "auth", u.name);
1128         /* lookup user in list file */
1129         if ((ret = get_user(&u)) < 0)
1130                 goto err_out;
1131         if (!ret) { /* user not found */
1132                 PARA_WARNING_LOG("auth request for unknown user %s\n", u.name);
1133                 ret = -E_BAD_USER;
1134                 goto err_out;
1135         }
1136         ret = para_encrypt_challenge(u.pubkey_file, challenge_nr, crypt_buf);
1137         if (ret <= 0)
1138                 goto err_out;
1139         numbytes = ret;
1140         PARA_DEBUG_LOG("sending %d byte challenge\n", numbytes);
1141         /* We can't use send_buffer here since buf may contain null bytes */
1142         ret = send_bin_buffer(fd,(char *) crypt_buf, numbytes);
1143         if (ret < 0)
1144                 goto err_out;
1145         /* recv decrypted number */
1146         numbytes = recv_buffer(fd, buf, sizeof(buf));
1147         ret = numbytes;
1148         if (ret < 0)
1149                 goto err_out;
1150         ret = -E_AUTH;
1151         if (!numbytes)
1152                 goto err_out;
1153         if (sscanf(buf, CHALLENGE_RESPONSE_MSG "%lu", &chall_response) < 1
1154                         || chall_response != challenge_nr)
1155                 goto err_out;
1156         /* auth successful. Send 'Proceed' message */
1157         PARA_INFO_LOG("good auth for %s (%lu)\n", u.name, challenge_nr);
1158         sprintf(buf, "%s", PROCEED_MSG);
1159         if (use_rc4) {
1160                 init_rc4_keys();
1161                 ret = para_encrypt_buffer(u.pubkey_file, rc4_buf, 2 * RC4_KEY_LEN,
1162                         (unsigned char *)buf + PROCEED_MSG_LEN + 1);
1163                 if (ret <= 0)
1164                         goto err_out;
1165                 numbytes = ret + strlen(PROCEED_MSG) + 1;
1166         } else
1167                 numbytes = strlen(buf);
1168         ret = send_bin_buffer(fd, buf, numbytes);
1169         if (ret < 0)
1170                 goto err_out;
1171         if (use_rc4)
1172                 enable_crypt(fd, rc4_recv, rc4_send, NULL);
1173         /* read command */
1174         while ((numbytes = recv_buffer(fd, buf, sizeof(buf))) > 0) {
1175 //              PARA_INFO_LOG("recvd: %s (%d)\n", buf, numbytes);
1176                 ret = -E_COMMAND_SYNTAX;
1177                 if (command && numbytes + strlen(command) > STRINGSIZE) /* DOS */
1178                         goto err_out;
1179                 command = para_strcat(command, buf);
1180                 if ((p = strstr(command, EOC_MSG))) {
1181                         *p = '\0';
1182                         break;
1183                 }
1184         }
1185         ret = numbytes;
1186         if (ret < 0)
1187                 goto err_out;
1188         ret = -E_BAD_CMD;
1189         /* parse command */
1190         if (!(cmd = parse_cmd(command)))
1191                 goto err_out;
1192         /* valid command, check permissions */
1193         ret = check_perms(u.perms, cmd);
1194         if (ret < 0)
1195                 goto err_out;
1196         /* valid command and sufficient perms */
1197         alarm(0);
1198         argc = split_args(command, &argv, "\n");
1199         mmd_lock();
1200         mmd->num_commands++;
1201         mmd_unlock();
1202         PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", cmd->name, u.name,
1203                 inet_ntoa(addr->sin_addr));
1204         ret = cmd->handler(fd, argc, argv);
1205         if (ret >= 0) {
1206                 ret = EXIT_SUCCESS;
1207                 goto out;
1208         }
1209 err_out:
1210         if (ret != -E_SEND && ret != -E_RECV) {
1211                 PARA_NOTICE_LOG("%s\n", PARA_STRERROR(-ret));
1212                 send_va_buffer(fd, "%s\n", PARA_STRERROR(-ret));
1213         }
1214         ret = EXIT_FAILURE;
1215 out:
1216         free(command);
1217         free(argv);
1218         mmd_lock();
1219         if (cmd && (cmd->perms & DB_WRITE) && ret >= 0)
1220                 mmd->events++;
1221         mmd->active_connections--;
1222         mmd_unlock();
1223         return ret;
1224 }