X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=afs.c;h=b15f83852e6919c4f0867065d13776c211416087;hb=0b5c29fae8853bac16b91503df70b0e101dccca4;hp=cea8f2707491f00bab0f457a3463fd4762147a21;hpb=9055c71be97f1095dcdbd83da305b600f204f763;p=paraslash.git diff --git a/afs.c b/afs.c index cea8f270..b15f8385 100644 --- a/afs.c +++ b/afs.c @@ -525,53 +525,6 @@ static void flush_and_free_pb(struct para_buffer *pb) free(pb->buf); } -static int com_select_callback(struct afs_callback_arg *aca) -{ - const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SELECT); - const char *arg; - int ret; - - ret = lls_deserialize_parse_result(aca->query.data, cmd, &aca->lpr); - assert(ret >= 0); - arg = lls_input(0, aca->lpr); - score_clear(); - if (current_play_mode == PLAY_MODE_MOOD) - mood_unload(); - else - playlist_unload(); - ret = activate_mood_or_playlist(arg, &aca->pbout); - if (ret >= 0) - goto free_lpr; - /* ignore subsequent errors (but log them) */ - if (current_mop && strcmp(current_mop, arg) != 0) { - int ret2; - para_printf(&aca->pbout, "switching back to %s\n", current_mop); - ret2 = activate_mood_or_playlist(current_mop, &aca->pbout); - if (ret2 >= 0) - goto free_lpr; - para_printf(&aca->pbout, "could not reactivate %s: %s\n", - current_mop, para_strerror(-ret2)); - } - activate_mood_or_playlist(NULL, &aca->pbout); -free_lpr: - lls_free_parse_result(aca->lpr, cmd); - return ret; -} - -static int com_select(struct command_context *cc, struct lls_parse_result *lpr) -{ - const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SELECT); - char *errctx; - int ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx)); - - if (ret < 0) { - send_errctx(cc, errctx); - return ret; - } - return send_lls_callback_request(com_select_callback, cmd, lpr, cc); -} -EXPORT_SERVER_CMD_HANDLER(select); - static void init_admissible_files(const char *arg) { int ret = activate_mood_or_playlist(arg, NULL); @@ -775,6 +728,43 @@ err: return ret; } +/** + * Format and send an error message to the command handler. + * + * To pass an error message from the callback of an afs command to the client, + * this function should be called. It formats the message into a buffer which + * is passed as a shared memory area to the command handler from where it + * propagates to the client. + * + * The message will be tagged with the ERROR_LOG sideband designator so that + * the client writes it to its stderr stream rather than to stdout as with + * aca->pbout. In analogy to the default Unix semantics of stderr, the message + * is sent without buffering. + * + * If sending the error message fails, an error is logged on the server side, + * but no other action is taken. + * + * \param aca Used to obtain the fd to send the shmid to. + * \param fmt Usual format string. + */ +__printf_2_3 void afs_error(const struct afs_callback_arg *aca, + const char *fmt,...) +{ + va_list argp; + char *msg; + unsigned n; + int ret; + + va_start(argp, fmt); + n = xvasprintf(&msg, fmt, argp); + va_end(argp); + ret = pass_buffer_as_shm(aca->fd, SBD_ERROR_LOG, msg, n + 1); + if (ret < 0) + PARA_ERROR_LOG("Could not send %s: %s\n", msg, + para_strerror(-ret)); + free(msg); +} + static int call_callback(int fd, int query_shmid) { void *query_shm; @@ -985,6 +975,53 @@ out: exit(EXIT_FAILURE); } +static int com_select_callback(struct afs_callback_arg *aca) +{ + const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SELECT); + const char *arg; + int ret; + + ret = lls_deserialize_parse_result(aca->query.data, cmd, &aca->lpr); + assert(ret >= 0); + arg = lls_input(0, aca->lpr); + score_clear(); + if (current_play_mode == PLAY_MODE_MOOD) + mood_unload(); + else + playlist_unload(); + ret = activate_mood_or_playlist(arg, &aca->pbout); + if (ret >= 0) + goto free_lpr; + /* ignore subsequent errors (but log them) */ + if (current_mop && strcmp(current_mop, arg) != 0) { + int ret2; + afs_error(aca, "switching back to %s\n", current_mop); + ret2 = activate_mood_or_playlist(current_mop, &aca->pbout); + if (ret2 >= 0) + goto free_lpr; + afs_error(aca, "could not reactivate %s: %s\n", current_mop, + para_strerror(-ret2)); + } + activate_mood_or_playlist(NULL, &aca->pbout); +free_lpr: + lls_free_parse_result(aca->lpr, cmd); + return ret; +} + +static int com_select(struct command_context *cc, struct lls_parse_result *lpr) +{ + const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SELECT); + char *errctx; + int ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx)); + + if (ret < 0) { + send_errctx(cc, errctx); + return ret; + } + return send_lls_callback_request(com_select_callback, cmd, lpr, cc); +} +EXPORT_SERVER_CMD_HANDLER(select); + static int com_init_callback(struct afs_callback_arg *aca) { uint32_t table_mask = *(uint32_t *)aca->query.data; @@ -1001,8 +1038,7 @@ static int com_init_callback(struct afs_callback_arg *aca) continue; ret = t->ops->create(database_dir); if (ret < 0) { - para_printf(&aca->pbout, "cannot create table %s\n", - t->name); + afs_error(aca, "cannot create table %s\n", t->name); goto out; } para_printf(&aca->pbout, "successfully created %s table\n", @@ -1010,7 +1046,7 @@ static int com_init_callback(struct afs_callback_arg *aca) } ret = open_afs_tables(); if (ret < 0) - para_printf(&aca->pbout, "cannot open afs tables: %s\n", + afs_error(aca, "cannot open afs tables: %s\n", para_strerror(-ret)); out: return ret;