Implement ls --admissible=m/foo. Currently there can be only one score table at a time because the functions of score.c refer to the global score_table variable. To implement the new feature, we need to overcome this restriction so that the callback of the ls command can populate an independent score table to print its output without interfering with the score table that is currently active. This commit changes most functions of score.c to receive an additional table pointer argument. All current users of the score table pass a NULL pointer to instruct the functions to operate on the global score table as before. However, if the ls command is invoked with an optional mood argument to -a. the callback calls mood_load(), followed by mood_loop() and mood_unload(). The former returns an opaque handle which is then passed to the other two functions to instruct them to operate on the temporary score table instead of the global one. To make the feature work for playlists as well, analogous functionality is implemented in playlist.c. The new mop_loop() of aft.c performs the disambiguation in a similar way as the activate_mood_or_playlist() does. It is a bit simpler though, since the ls command does not have to deal with NULL arguments and does not need to fall back to the dummy mood.
afs.h: Improve documentation of typedefs. Doxygen expects the comments to consist of a one-line summary and an optional long description.
Introduce afs_error(). The callbacks of some afs commands employ the normal ->pbpout para buffer to send an error message to the client on failure. These messages are therefore tagged with the OUTPUT sideband designator just as regular command output. The receiving client writes such messages to stdout, so applications which call para_client have no other way than parsing the output to guess whether it is normal command output or an error message. This commit improves on this by providing a public helper in afs.c to format and send an error message that is tagged with the ERROR sideband designator and thus gets written to stderr on the client side. All afs callbacks which currently use ->pbout for error messages are converted to call the new helper.
Rename mood_switch(), mood_close(), playlist_{open/close}. This naming is unfortunate because we also have the static {mood,pl}_{open,close}() in blob.c which operate on the osl table. In contrast, the functions renamed in this commit operate on blob objects and change the current mood or playlist. Let's call these operations load/unload to avoid confusion.
Assume that score_open() and score_clear() always succeed. Since the score table has only volatile columns, the only possible error is memory exhaustion, in which case we can only abort anyway. This patch changes score_open() to abort if osl_open() fails. This allows us to let score_clear() return void. We can't get rid of the return value of score_open(), however, since a pointer to this function is stored the afs table operations structure.
Simplify and improve activate_mood_or_playlist(). The logic of this function can be simplified to match the four possible cases for the argument. Each of the four conditional blocks now initializes ret, mode and the message pointer. The message is then printed into the para buffer, which is now passed to the function instead of a char ** because this simplifies the select callback a bit. The other callers (for init and SIGHUP handling) pass NULL and don't need to be adjusted. To make this work we have to make sure that the message pointer is properly initialized in all cases, not only in the error case as before. Thus, playlist_open() and mood_switch() are changed to return a suitable message also on success. For playlists, the message only contains the number of files in the playlist. For moods we also include the afs statistics of the mood and no longer write this information to the server log. We omit the correction factors and the normalization divisor, however, as these are not very interesting. The only purpose of the num_admissible parameter of activate_mood_or_playlist() was to let the caller log this information. This task is now performed by playlist_open() and mood_switch(), so the parameter can be dropped.
afs: Replace ->init of afs tables by table operations. This is simpler, avoids the run-time initialization, and allows us to mark the instances of the operations structures constant. Improve the documentation a bit while at it.
Simplify row_belongs_to_score_table(). This function was over-engineered because only one caller passed a non-NULL rank pointer without actually using the rank for anything other than printing it in a log message. So drop the rank parameter and adjust the callers and the log message accordingly. Moreover, the function returned int rather than bool to be able to also return an error code in case the osl lookup function fails. This should never happen though, because the only possible errors are invalid row or table pointers, and these indicate a bug. So abort in this case and let the function return bool.
Remove mood.h. It's too small to be useful. Simply move the three function declarations to afs.h, next to the playlist related functions.
Improve playlist_open(). It's easier to let playlist_open() fill in the error text than to do this in the caller. This is also how the counterpart of playlist_open(), change_current_mood(), is implemented. Drop the server log message because this error is usually caused by a client passing a misspelt playlist name. Fix the documentation of the return value of the function while at it: It returns the playlist length on success, and activate_mood_or_playlist(), its single caller in afs.c, depends on that.
blob: Constify name argument of blob_get_def_by_name(). This function does not modify the string, although the char pointer is used as the ->data pointer of an osl object, which is non-constant. We need to cast away the const qualifier to avoid a compiler warning, but that's still better than accepting only non-constant strings, as this means to put the cast into the callers.
Rename admissible_file_loop() -> score_loop(). The function simply iterates the entries of the score table. The new name is shorter, more to the point, and indicates that the function is implemented in score.c. Streamline the documentation while at it and swap the arguments, as the reversed order is more natural.
Remove get_num_admissible_files(). This public function had only one caller outside of score.c and this caller already knows the number of admissible files because this number is also stored in the afs statistics structure. Open-coding the remaining caller in score.c allows us to remove the public function.
Remove ->fd of struct audio file data. This structure contains information about the next audio file. It is stored in a shared memory area, and a reference to this area is sent through a pipe from the afs process to the server process. The file descriptor of the next audio file, however, must be passed via Unix socket magic (SCM_RIGHTS) and thus does not need to be part of the structure. Moreover, it's easier to define the afd structure in open_and_update_audio_file() of aft.c rather than in its caller, open_next_audio_file() of afs.c, because the caller only needs the fd of the audio file and the shared memory ID but not the audio file data structure itself. Expand the documentation of open_and_update_audio_file() a bit while at it.
doc: Silence doxygen warnings. This gets rid of many warnings of the form warning: Member lyr_get_def_by_id(uint32_t id, struct osl_object *def) (function) of file afs.h is not documented. which show up if EXTRACT_ALL is set to "no".
Merge branch 'refs/heads/t/clean_server_exit' This series removes many memory leaks of para_server by refactoring the shutdown and signal handling code. Most of the leaks happen only at shutdown and are hence harmless. But it is still good to plug the leaks because this puts more focus on real memory leaks in the valgrind output. The merge conflicted rather badly due to the changes introduced with the crypt branch that was merged last week. The resolution has been thoroughly tested, though. * refs/heads/t/clean_server_exit: (32 commits) command.c: Document return value of handle_connect(). user_list: Make list head static. afs: Allow database switching on sighup. afs: Free current mood or playlist on exit. afs: Free status items on exit. afs: Shutdown signals on exit. server: Free parse result also in afs. afs: Deplete user list at startup. server: Free audio file header on exit. sender: Deplete ACLs on exit. Remove some unused includes from {dccp,http}_send.c. server: Make argument of user_list_init() constant. server: Deplete user list on exit. server: Combine user_list_init() and populate(). server: Move para_fgets() to user_list.c. server: Initialize user list at compile time. server: Rename functions related to user lists. server: Constify return value of lookup_user(). server: Let stat command handler perform cleanup on signals. server: Have afs process close the current mood on exit(). ...
afs: Document ->lpr of struct afs_callback_arg. This should have been documented when the ->lpr member was introduced two years ago in commit ba0a963f (server: Convert com_add() to lopsub).
afs: Free status items on exit. The server process frees the memory allocated for the status items on exit but the afs process does not. To avoid the leak we have to make free_status_items() public.
server: Simplify afs socket cookie code. Currently, the afs_socket_cookie value is passed to afs_init() and is stored in the commmand task structure of the afs process. This is unnecessary since the variable defined in server.c is non-static, and declared as extern in afs.c. We may thus refer to this variable from afs.c. The variable was also documented twice. Get rid of one comment.
Shorten copyright notice. The GPLv2 line does not add any additional information, so drop it. This leaves a single line of legalese text for most files, which is about the amount of screen real estate it deserves. This patch was created with the following script (plus some manual fixups): awk '{ if (NR <= 5) { gs = gensub(/.*Copyright.* ([0-9]+).*Andre Noll.*/, "\\1", "g") if (gs != $0) year = gs next } if (NR == 6 && year != "") printf("/* Copyright (C) %s Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */\n", year) print }'