From dcc643ec184160b29f2dbbf6666d8873d3e7de3a Mon Sep 17 00:00:00 2001 From: marschap Date: Sun, 30 Nov 2008 15:30:28 +0000 Subject: [PATCH] extend deletion functions in LL.c, use them to make "bye" client command work --- docs/lcdproc-dev/shared-files.docbook | 2 +- server/client.c | 10 ++++---- server/clients.c | 19 ++++++++------- server/clients.h | 2 +- server/commands/client_commands.c | 2 +- server/input.c | 22 ++++++++---------- server/menu.c | 4 ++-- server/parse.c | 5 ++++ server/screen.c | 2 +- server/screenlist.c | 7 +++--- server/sock.c | 6 ++--- shared/LL.c | 33 ++++++++++++++++++--------- shared/LL.h | 16 ++++++++++--- 13 files changed, 79 insertions(+), 51 deletions(-) diff --git a/docs/lcdproc-dev/shared-files.docbook b/docs/lcdproc-dev/shared-files.docbook index 6fbca40..31689b8 100644 --- a/docs/lcdproc-dev/shared-files.docbook +++ b/docs/lcdproc-dev/shared-files.docbook @@ -188,7 +188,7 @@ LL_Put(list, (void *)new_thingie); my_data * thingie; -thingie = (my_data *)LL_DeleteNode(list); +thingie = (my_data *)LL_DeleteNode(list, NEXT); free(thingie); thingie->number = 666; diff --git a/server/client.c b/server/client.c index f39af65..8886938 100644 --- a/server/client.c +++ b/server/client.c @@ -1,6 +1,8 @@ -/* - * client.c - * This file is part of LCDd, the lcdproc server. +/** \file client.c + * Define all the client data and actions. + */ + +/* This file is part of LCDd, the lcdproc server. * * This file is released under the GNU General Public License. Refer to the * COPYING file distributed with this package. @@ -228,7 +230,7 @@ client_remove_screen(Client *c, Screen *s) debug(RPT_DEBUG, "%s(c=[%d], s=[%s])", __FUNCTION__, c->sock, s->id); /* TODO: Check for errors here?*/ - LL_Remove(c->screenlist, (void *) s); + LL_Remove(c->screenlist, (void *) s, NEXT); /* Now, remove it from the screenlist...*/ screenlist_remove(s); diff --git a/server/clients.c b/server/clients.c index 64336aa..1f11fd5 100644 --- a/server/clients.c +++ b/server/clients.c @@ -1,9 +1,6 @@ -/** \file clients.c - * Manage the list of clients that are connected. - * Init/shut down client system, and search for clients in the list. - */ - -/* This file is part of LCDd, the lcdproc server. +/* + * clients.c + * This file is part of LCDd, the lcdproc server. * * This file is released under the GNU General Public License. Refer to the * COPYING file distributed with this package. @@ -11,6 +8,11 @@ * Copyright (c) 1999, William Ferrell, Scott Scriven * 2002, Joris Robijn * + * + * Inits/shuts down client system, + * and searches for clients in the list. + * On short: manages the list of clients that are connected. + * */ #include @@ -87,9 +89,9 @@ clients_add_client(Client *c) /* Remove the client from the clients list... */ Client * -clients_remove_client(Client *c) +clients_remove_client(Client *c, Direction whereto) { - Client *client = LL_Remove(clientlist, c); + Client *client = LL_Remove(clientlist, c, whereto); return client; } @@ -116,6 +118,7 @@ clients_client_count(void) /* A client is identified by the file descriptor * associated with it. Find one. */ + Client * clients_find_client_by_sock(int sock) { diff --git a/server/clients.h b/server/clients.h index 6db22bd..338b486 100644 --- a/server/clients.h +++ b/server/clients.h @@ -25,7 +25,7 @@ int clients_shutdown(void); /* Add/remove clients (return NULL for error) */ Client *clients_add_client(Client *c); -Client *clients_remove_client(Client *c); +Client *clients_remove_client(Client *c, Direction whereto); /* List functions */ Client *clients_getfirst(void); diff --git a/server/commands/client_commands.c b/server/commands/client_commands.c index 79878c6..07cb97b 100644 --- a/server/commands/client_commands.c +++ b/server/commands/client_commands.c @@ -93,7 +93,7 @@ bye_func(Client *c, int argc, char **argv) debug(RPT_INFO, "Bye, %s!", (c->name != NULL) ? c->name : "unknown client"); c->state = GONE; - sock_send_error(c->sock, "\"bye\" is currently ignored\n"); + //sock_send_error(c->sock, "\"bye\" is currently ignored\n"); } return 0; } diff --git a/server/input.c b/server/input.c index 0497995..bd8a8a8 100644 --- a/server/input.c +++ b/server/input.c @@ -185,7 +185,7 @@ int input_reserve_key(const char *key, bool exclusive, Client *client) /* Find out if this key is already reserved in a way that interferes * with the new reservation. */ - for (kr = LL_GetFirst(keylist); kr; kr = LL_GetNext(keylist)) { + for (kr = LL_GetFirst(keylist); kr != NULL; kr = LL_GetNext(keylist)) { if (strcmp(kr->key, key) == 0) { if (kr->exclusive || exclusive) { /* Sorry ! */ @@ -214,13 +214,12 @@ void input_release_key(const char *key, Client *client) debug(RPT_DEBUG, "%s(key=\"%.40s\", client=[%d])", __FUNCTION__, key, (client ? client->sock : -1)); for (kr = LL_GetFirst(keylist); kr != NULL; kr = LL_GetNext(keylist)) { - if (kr->client == client - && strcmp(kr->key, key) == 0) { - free(kr->key); - free(kr); - LL_DeleteNode(keylist); + if ((kr->client == client) && (strcmp(kr->key, key) == 0)) { report(RPT_INFO, "Key \"%.40s\" reserved %s by client [%d] and is now released", key, (kr->exclusive ? "exclusively" : "shared"), (client ? client->sock : -1)); + free(kr->key); + free(kr); + LL_DeleteNode(keylist, NEXT); return; } } @@ -232,17 +231,14 @@ void input_release_client_keys(Client *client) debug(RPT_DEBUG, "%s(client=[%d])", __FUNCTION__, (client ? client->sock : -1)); - kr = LL_GetFirst(keylist); - while (kr != NULL) { + for (kr = LL_GetFirst(keylist); kr != NULL; kr = LL_GetNext(keylist)) { if (kr->client == client) { report(RPT_INFO, "Key \"%.40s\" reserved %s by client [%d] and is now released", - kr->key, (kr->exclusive ? "exclusive" : "shared"), (client ? client->sock : -1)); + kr->key, (kr->exclusive ? "exclusively" : "shared"), (client ? client->sock : -1)); free(kr->key); free(kr); - LL_DeleteNode(keylist); - kr = LL_Get(keylist); - } else { - kr = LL_GetNext(keylist); + // jump to node before deleted one to not miss any + LL_DeleteNode(keylist, PREV); } } } diff --git a/server/menu.c b/server/menu.c index 97fd0b5..38ca572 100644 --- a/server/menu.c +++ b/server/menu.c @@ -270,7 +270,7 @@ menu_remove_item(Menu *menu, MenuItem *item) item2 != NULL; item2 = LL_GetNext(menu->data.menu.contents), i++) { if (item == item2) { - LL_DeleteNode(menu->data.menu.contents); + LL_DeleteNode(menu->data.menu.contents, NEXT); if (menu->data.menu.selector_pos >= i) { menu->data.menu.selector_pos--; if (menu->data.menu.scroll > 0) @@ -295,7 +295,7 @@ menu_destroy_all_items(Menu *menu) for (item = menu_getfirst_item(menu); item != NULL; item = menu_getfirst_item(menu)) { menuitem_destroy(item); - LL_Remove(menu->data.menu.contents, item); + LL_Remove(menu->data.menu.contents, item, NEXT); } } diff --git a/server/parse.c b/server/parse.c index 0f431fc..8a6aee8 100644 --- a/server/parse.c +++ b/server/parse.c @@ -229,6 +229,11 @@ parse_all_client_messages(void) for (str = client_get_message(c); str != NULL; str = client_get_message(c)) { parse_message(str, c); free(str); + + if (c->state == GONE) { + sock_destroy_client_socket(c); + break; + } } } return 0; diff --git a/server/screen.c b/server/screen.c index e8e036b..df3bb27 100644 --- a/server/screen.c +++ b/server/screen.c @@ -136,7 +136,7 @@ screen_remove_widget(Screen *s, Widget *w) { debug(RPT_DEBUG, "%s(s=[%.40s], widget=[%.40s])", __FUNCTION__, s->id, w->id); - LL_Remove(s->widgetlist, (void *) w); + LL_Remove(s->widgetlist, (void *) w, NEXT); return 0; } diff --git a/server/screenlist.c b/server/screenlist.c index 800234e..76737dc 100644 --- a/server/screenlist.c +++ b/server/screenlist.c @@ -85,13 +85,13 @@ screenlist_remove(Screen *s) screenlist_goto_next(); if (s == current_screen) { /* Hmm, no other screen had same priority */ - void *res = LL_Remove(screenlist, s); + void *res = LL_Remove(screenlist, s, NEXT); /* And now once more */ screenlist_goto_next(); return (res == NULL) ? -1 : 0; } } - return (LL_Remove(screenlist, s) == NULL) ? -1 : 0; + return (LL_Remove(screenlist, s, NEXT) == NULL) ? -1 : 0; } @@ -221,7 +221,8 @@ screenlist_goto_next(void) return -1; /* Find current screen in screenlist */ - for (s = LL_GetFirst(screenlist); s && s != current_screen; s = LL_GetNext(screenlist)); + for (s = LL_GetFirst(screenlist); s && s != current_screen; s = LL_GetNext(screenlist)) + ; /* One step forward */ s = LL_GetNext(screenlist); diff --git a/server/sock.c b/server/sock.c index 7428f70..cabe976 100644 --- a/server/sock.c +++ b/server/sock.c @@ -10,7 +10,7 @@ * Copyright (c) 1999, William Ferrell, Scott Scriven * 2003, Benjamin Tse (blt@ieee.org) - Winsock port * 2004, F5 Networks, Inc. - IP-address input - * 2005-2008, Peter Marschall - error checks, ... + * 2005, Peter Marschall - error checks, ... * */ @@ -478,7 +478,7 @@ sock_destroy_socket(void) report(RPT_NOTICE, "Client on socket %i disconnected", entry->socket); client_destroy(entry->client); - clients_remove_client(entry->client); + clients_remove_client(entry->client, PREV); entry->client = NULL; } else { @@ -490,7 +490,7 @@ sock_destroy_socket(void) close(entry->socket); /* re-add socket to the free socket pool */ - entry = (ClientSocketMap *) LL_DeleteNode(openSocketList); + entry = (ClientSocketMap *) LL_DeleteNode(openSocketList, PREV); LL_Push(freeClientSocketList, (void*) entry); } } diff --git a/shared/LL.c b/shared/LL.c index 20437e7..98f2c59 100644 --- a/shared/LL.c +++ b/shared/LL.c @@ -242,7 +242,7 @@ LL_Prev(LinkedList *list) * Return pointer to list's \c current node's data. * \param list List object. * \return Pointer to \c current node's payload data; - * \c NULL may be empty payload or an error. + * \c NULL may be empty payload or an error. */ void * LL_Get(LinkedList *list) @@ -469,12 +469,13 @@ LL_InsertNode(LinkedList *list, void *add) /** Remove current node from the list. - * Set the list's \c current pointer to the node after the deleted one. - * \param list List object. - * \return Pointer to data of deleted node; \c NULL on error. + * Set the list's \c current pointer to the one denoted by \c whereto. + * \param list List object. + * \param whereto Direction where to set the list's \c current pointer + * \return Pointer to data of deleted node; \c NULL on error. */ void * -LL_DeleteNode(LinkedList *list) +LL_DeleteNode(LinkedList *list, Direction whereto) { LL_node *next, *prev; void *data; @@ -506,7 +507,16 @@ LL_DeleteNode(LinkedList *list) free(list->current); - list->current = next; + switch (whereto) { + case FIRST: list->current = list->head.next; + break; + case LAST: list->current = list->tail.prev; + break; + case PREV: list->current = prev; + break; + default: + case NEXT: list->current = next; + } return data; } @@ -514,13 +524,14 @@ LL_DeleteNode(LinkedList *list) /** Remove a specific node from the list. * Find a node by a pointer to its data and remove it. - * After the deletion the \c current pointer is on the node after the deleted one. + * Set the list's \c current pointer to the one denoted by \c whereto. * \param list List object. * \param data Pointer to data of node to delete. + * \param whereto Direction where to set the list's \c current pointer * \return Pointer to data of deleted node; \c NULL on error. */ void * -LL_Remove(LinkedList *list, void *data) +LL_Remove(LinkedList *list, void *data, Direction whereto) { if (!list) return NULL; @@ -530,7 +541,7 @@ LL_Remove(LinkedList *list, void *data) void *find = LL_Get(list); if (find == data) - return LL_DeleteNode(list); + return LL_DeleteNode(list, whereto); } while (LL_Next(list) == 0); return NULL; @@ -574,7 +585,7 @@ LL_Pop(LinkedList *list) // Remove node from end of list if (0 > LL_End(list)) return NULL; - return LL_DeleteNode(list); + return LL_DeleteNode(list, PREV); } @@ -604,7 +615,7 @@ LL_Shift(LinkedList *list) // Remove node from start of list if (0 > LL_Rewind(list)) return NULL; - return LL_DeleteNode(list); + return LL_DeleteNode(list, NEXT); } diff --git a/shared/LL.h b/shared/LL.h index 1ec163b..5a86f42 100644 --- a/shared/LL.h +++ b/shared/LL.h @@ -57,7 +57,7 @@ my_data * thingie; - thingie = (my_data *)LL_DeleteNode(list); + thingie = (my_data *)LL_DeleteNode(list, NEXT); free(thingie); thingie->number = 666; @@ -116,6 +116,16 @@ // See LL.c for more detailed descriptions of these functions. +/** Symbolic values for directions */ +typedef enum _direction { + FIRST = -2, + PREV = -1, + CURRENT = 0, + NEXT = +1, + LAST = +2 +} Direction; + + /** Structure for a node in a linked list */ typedef struct LL_node { struct LL_node *prev; /**< Pointer to previous node */ @@ -164,9 +174,9 @@ void *LL_GetLast(LinkedList *list); // ... last node int LL_AddNode(LinkedList *list, void *add); // Adds node AFTER current one int LL_InsertNode(LinkedList *list, void *add); // Adds node BEFORE current one // Removes a node from the link; returns the data from the node -void *LL_DeleteNode(LinkedList *list); +void *LL_DeleteNode(LinkedList *list, Direction whereto); // Removes a specific node... -void *LL_Remove(LinkedList *list, void *data); +void *LL_Remove(LinkedList *list, void *data, Direction whereto); // Stack operations int LL_Push(LinkedList *list, void *add); // Add node to end of list