diff options
Diffstat (limited to 'src/core/librcscripts/depend.c')
-rw-r--r-- | src/core/librcscripts/depend.c | 672 |
1 files changed, 0 insertions, 672 deletions
diff --git a/src/core/librcscripts/depend.c b/src/core/librcscripts/depend.c deleted file mode 100644 index a5a2629..0000000 --- a/src/core/librcscripts/depend.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - * depend.c - * - * Dependancy engine for Gentoo style rc-scripts. - * - * Copyright (C) 2004,2005 Martin Schlemmer <azarah@nosferatu.za.org> - * - * - * 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 the - * Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Header$ - */ - -#include <errno.h> -#include <string.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -#include "rcscripts.h" - -LIST_HEAD (service_info_list); - -/* Names for service types (service_type_t) in depend.h. - * Note that this should sync with service_type_t */ -char *service_type_names[] = { - "NEED", - "NEED_ME", - "USE", - "USE_ME", - "BEFORE", - "AFTER", - "BROKEN", - "PROVIDE", - NULL -}; - -static char *service_is_recursive_dependency (char *servicename, - char *dependency, - bool checkuse); -static int __service_resolve_dependency (char *servicename, char *dependency, - service_type_t type); - -service_info_t * -service_get_info (char *servicename) -{ - service_info_t *info; - - if (!check_arg_str (servicename)) - return NULL; - - list_for_each_entry (info, &service_info_list, node) - { - if (NULL != info->name) - if (0 == strcmp (info->name, servicename)) - return info; - } - - /* We use this to check if a service exists, so rather do not - * add debugging, otherwise it is very noisy! */ - /* DBG_MSG("Invalid service name '%s'!\n", servicename); */ - - return NULL; -} - -int -service_add (char *servicename) -{ - service_info_t *info; - service_info_t *sorted; - int count; - - if (!check_arg_str (servicename)) - return -1; - - info = service_get_info (servicename); - if (NULL == info) - { - DBG_MSG ("Adding service '%s'.\n", servicename); - - info = xmalloc (sizeof (service_info_t)); - if (NULL == info) - return -1; - - info->name = xstrndup (servicename, strlen (servicename)); - if (NULL == info->name) - { - free (info); - return -1; - } - - for (count = 0; count < ALL_SERVICE_TYPE_T; count++) - info->depend_info[count] = NULL; - info->provide = NULL; - - /* We want to keep the list sorted */ - list_for_each_entry (sorted, &service_info_list, node) - { - if (strcmp (sorted->name, servicename) > 0) - { - break; - } - } - - list_add_tail (&info->node, &sorted->node); - - return 0; - } - else - { - DBG_MSG ("Tried to add duplicate service '%s'!\n", servicename); - } - - return -1; -} - -int -service_is_dependency (char *servicename, char *dependency, - service_type_t type) -{ - service_info_t *info; - char *service; - int count = 0; - - if ((!check_arg_str (servicename)) || (!check_arg_str (dependency))) - return -1; - - info = service_get_info (servicename); - if (NULL != info) - { - str_list_for_each_item (info->depend_info[type], service, count) - { - if (0 == strcmp (dependency, service)) - return 0; - } - } - else - { - DBG_MSG ("Invalid service name '%s'!\n", servicename); - } - - return -1; -} - -char * -service_is_recursive_dependency (char *servicename, char *dependency, - bool checkuse) -{ - service_info_t *info; - char *depend; - int count = 0; - - if ((!check_arg_str (servicename)) || (!check_arg_str (dependency))) - return NULL; - - info = service_get_info (dependency); - if (NULL != info) - { - str_list_for_each_item (info->depend_info[NEED_ME], depend, count) - { - if ((0 == service_is_dependency (servicename, depend, NEED)) - || (0 == service_is_dependency (servicename, depend, USE))) - return depend; - } - if (checkuse) - { - str_list_for_each_item (info->depend_info[USE_ME], depend, count) - { - if ((0 == service_is_dependency (servicename, depend, NEED)) - || (0 == service_is_dependency (servicename, depend, USE))) - return depend; - } - } - } - else - { - DBG_MSG ("Invalid service name '%s'!\n", servicename); - } - - return NULL; -} - -int -service_add_dependency (char *servicename, char *dependency, - service_type_t type) -{ - service_info_t *info; - char *buf; - - if ((!check_arg_str (servicename)) || (!check_arg_str (dependency))) - return -1; - - info = service_get_info (servicename); - if (NULL != info) - { - /* Do not add duplicates */ - if (-1 == service_is_dependency (servicename, dependency, type)) - { - DBG_MSG ("Adding dependency '%s' of service '%s', type '%s'.\n", - dependency, servicename, service_type_names[type]); - - buf = xstrndup (dependency, strlen (dependency)); - if (NULL == buf) - return -1; - - str_list_add_item_sorted (info->depend_info[type], buf, error); - } - else - { - DBG_MSG ("Duplicate dependency '%s' for service '%s', type '%s'!\n", - dependency, servicename, service_type_names[type]); - /* Rather do not fail here, as we add a lot of doubles - * during resolving of dependencies */ - } - - return 0; - } - else - { - DBG_MSG ("Invalid service name '%s'!\n", servicename); - } - -error: - return -1; -} - -int -service_del_dependency (char *servicename, char *dependency, - service_type_t type) -{ - service_info_t *info; - - if ((!check_arg_str (servicename)) || (!check_arg_str (dependency))) - return -1; - - if (-1 == service_is_dependency (servicename, dependency, type)) - { - DBG_MSG ("Tried to remove invalid dependency '%s'!\n", dependency); - return -1; - } - - info = service_get_info (servicename); - if (NULL != info) - { - DBG_MSG ("Removing dependency '%s' of service '%s', type '%s'.\n", - dependency, servicename, service_type_names[type]); - - str_list_del_item (info->depend_info[type], dependency, error); - return 0; - } - else - { - DBG_MSG ("Invalid service name '%s'!\n", servicename); - } - -error: - return -1; -} - -service_info_t * -service_get_virtual (char *virtual) -{ - service_info_t *info; - - if (!check_arg_str (virtual)) - return NULL; - - list_for_each_entry (info, &service_info_list, node) - { - if (NULL != info->provide) - if (0 == strcmp (info->provide, virtual)) - return info; - } - - /* We use this to check if a virtual exists, so rather do not - * add debugging, otherwise it is very noisy! */ - /* DBG_MSG("Invalid service name '%s'!\n", virtual); */ - - return NULL; -} - -int -service_add_virtual (char *servicename, char *virtual) -{ - service_info_t *info; - - if ((!check_arg_str (servicename)) || (!check_arg_str (virtual))) - return -1; - - if (NULL != service_get_info (virtual)) - { - EERROR - (" Cannot add provide '%s', as a service with the same name exists!\n", - virtual); - /* Do not fail here as we do have a service that resolves - * the virtual */ - } - - info = service_get_virtual (virtual); - if (NULL != info) - { - /* We cannot have more than one service Providing a virtual */ - EWARN (" Service '%s' already provides '%s'!;\n", info->name, virtual); - EWARN (" Not adding service '%s'...\n", servicename); - /* Do not fail here as we do have a service that resolves - * the virtual */ - } - else - { - info = service_get_info (servicename); - if (NULL != info) - { - DBG_MSG ("Adding virtual '%s' of service '%s'.\n", - virtual, servicename); - - info->provide = xstrndup (virtual, strlen (virtual)); - if (NULL == info->provide) - return -1; - } - else - { - DBG_MSG ("Invalid service name '%s'!\n", servicename); - return -1; - } - } - - return 0; -} - -int -service_set_mtime (char *servicename, time_t mtime) -{ - service_info_t *info; - - if (!check_arg_str (servicename)) - return -1; - - info = service_get_info (servicename); - if (NULL != info) - { - DBG_MSG ("Setting mtime '%li' of service '%s'.\n", mtime, servicename); - - info->mtime = mtime; - - return 0; - } - else - { - DBG_MSG ("Invalid service name '%s'!\n", servicename); - } - - return -1; -} - -int -__service_resolve_dependency (char *servicename, char *dependency, - service_type_t type) -{ - service_info_t *info; - int retval; - - if ((!check_arg_str (servicename)) || (!check_arg_str (dependency))) - return -1; - - info = service_get_info (servicename); - if (NULL == info) - { - DBG_MSG ("Invalid service name passed!\n"); - return -1; - } - - DBG_MSG ("Checking dependency '%s' of service '%s', type '%s'.\n", - dependency, servicename, service_type_names[type]); - - /* If there are no existing service 'dependency', try to resolve - * possible virtual services */ - info = service_get_info (dependency); - if (NULL == info) - { - info = service_get_virtual (dependency); - if (NULL != info) - { - DBG_MSG ("Virtual '%s' -> '%s' for service '%s', type '%s'.\n", - dependency, info->name, servicename, - service_type_names[type]); - - retval = service_del_dependency (servicename, dependency, type); - if (-1 == retval) - { - DBG_MSG ("Failed to delete dependency!\n"); - return -1; - } - - /* Add the actual service name for the virtual */ - dependency = info->name; - retval = service_add_dependency (servicename, dependency, type); - if (-1 == retval) - { - DBG_MSG ("Failed to add dependency!\n"); - return -1; - } - } - } - - /* Handle 'need', as it is the only dependency type that should - * handle invalid database entries currently. */ - if (NULL == info) - { - if ((type == NEED) || (type == NEED_ME)) - { - EWARN (" Can't find service '%s' needed by '%s'; continuing...\n", - dependency, servicename); - - retval = service_add_dependency (servicename, dependency, BROKEN); - if (-1 == retval) - { - DBG_MSG ("Failed to add dependency!\n"); - return -1; - } - - /* Delete invalid entry */ - goto remove; - } - - /* For the rest, if the dependency is not 'net', just silently - * die without error. Should not be needed as we add a 'net' - * service manually before we start, but you never know ... */ - if (0 != strcmp (dependency, "net")) - { - /* Delete invalid entry */ - goto remove; - } - } - - /* Ugly bug ... if a service depends on itself, it creates a - * 'mini fork bomb' effect, and breaks things horribly ... */ - if (0 == strcmp (servicename, dependency)) - { - /* Dont work too well with the '*' before and after */ - if ((type != BEFORE) && (type != AFTER)) - EWARN (" Service '%s' can't depend on itself; continuing...\n", - servicename); - - /* Delete invalid entry */ - goto remove; - } - - /* Currently only these depend/order types are supported */ - if ((type == NEED) || (type == USE) || (type == BEFORE) || (type == AFTER)) - { - if (type == BEFORE) - { - char *depend; - - /* NEED and USE override BEFORE - * ('servicename' BEFORE 'dependency') */ - if ((0 == service_is_dependency (servicename, dependency, NEED)) - || (0 == service_is_dependency (servicename, dependency, USE))) - { - /* Delete invalid entry */ - goto remove; - } - - depend = service_is_recursive_dependency (servicename, dependency, - TRUE); - if (NULL != depend) - { - EWARN (" Service '%s' should be BEFORE service '%s', but '%s'\n", - servicename, dependency, depend); - EWARN (" needed by '%s', depends in return on '%s'!\n", - servicename, dependency); - - /* Delete invalid entry */ - goto remove; - } - } - - if (type == AFTER) - { - char *depend; - - /* NEED and USE override AFTER - * ('servicename' AFTER 'dependency') */ - if ((0 == service_is_dependency (dependency, servicename, NEED)) - || (0 == service_is_dependency (dependency, servicename, USE))) - { - /* Delete invalid entry */ - goto remove; - } - - depend = service_is_recursive_dependency (dependency, servicename, - TRUE); - if (NULL != depend) - { - EWARN (" Service '%s' should be AFTER service '%s', but '%s'\n", - servicename, dependency, depend); - EWARN (" needed by '%s', depends in return on '%s'!\n", - dependency, servicename); - - /* Delete invalid entry */ - goto remove; - } - } - - /* We do not want to add circular dependencies ... */ - if (0 == service_is_dependency (dependency, servicename, type)) - { - EWARN (" Services '%s' and '%s' have circular\n", - servicename, dependency); - EWARN (" dependency of type '%s'; continuing...\n", - service_type_names[type]); - - /* For now remove this dependency */ - goto remove; - } - - /* Reverse mapping */ - if (type == NEED) - { - retval = service_add_dependency (dependency, servicename, NEED_ME); - if (-1 == retval) - { - DBG_MSG ("Failed to add dependency!\n"); - return -1; - } - } - - /* Reverse mapping */ - if (type == USE) - { - retval = service_add_dependency (dependency, servicename, USE_ME); - if (-1 == retval) - { - DBG_MSG ("Failed to add dependency!\n"); - return -1; - } - } - - /* Reverse mapping */ - if (type == BEFORE) - { - retval = service_add_dependency (dependency, servicename, AFTER); - if (-1 == retval) - { - DBG_MSG ("Failed to add dependency!\n"); - return -1; - } - } - - /* Reverse mapping */ - if (type == AFTER) - { - retval = service_add_dependency (dependency, servicename, BEFORE); - if (-1 == retval) - { - DBG_MSG ("Failed to add dependency!\n"); - return -1; - } - } - } - - return 0; - -remove: - /* Delete invalid entry */ - DBG_MSG ("Removing invalid dependency '%s' of service '%s', type '%s'.\n", - dependency, servicename, service_type_names[type]); - - retval = service_del_dependency (servicename, dependency, type); - if (-1 == retval) - { - DBG_MSG ("Failed to delete dependency!\n"); - return -1; - } - - /* Here we should not die with error */ - return 0; -} - -int -service_resolve_dependencies (void) -{ - service_info_t *info; - char *service; - char *next = NULL; - int count; - - /* Add our 'net' service */ - if (NULL == service_get_info ("net")) - { - if (-1 == service_add ("net")) - { - DBG_MSG ("Failed to add virtual!\n"); - return -1; - } - service_set_mtime ("net", 0); - } - - /* Calculate all virtuals */ - list_for_each_entry (info, &service_info_list, node) - { - str_list_for_each_item_safe (info->depend_info[PROVIDE], service, next, - count) - { - if (-1 == service_add_virtual (info->name, service)) - { - DBG_MSG ("Failed to add virtual!\n"); - return -1; - } - } - } - - /* Now do NEED, USE, BEFORE and AFTER */ - list_for_each_entry (info, &service_info_list, node) - { - str_list_for_each_item_safe (info->depend_info[NEED], service, next, count) - { - if (-1 == __service_resolve_dependency (info->name, service, NEED)) - { - DBG_MSG ("Failed to resolve dependency!\n"); - return -1; - } - } - } - list_for_each_entry (info, &service_info_list, node) - { - str_list_for_each_item_safe (info->depend_info[USE], service, next, count) - { - if (-1 == __service_resolve_dependency (info->name, service, USE)) - { - DBG_MSG ("Failed to resolve dependency!\n"); - return -1; - } - } - } - list_for_each_entry (info, &service_info_list, node) - { - str_list_for_each_item_safe (info->depend_info[BEFORE], service, next, - count) - { - if (-1 == __service_resolve_dependency (info->name, service, BEFORE)) - { - DBG_MSG ("Failed to resolve dependency!\n"); - return -1; - } - } - } - list_for_each_entry (info, &service_info_list, node) - { - str_list_for_each_item_safe (info->depend_info[AFTER], service, next, count) - { - if (-1 == __service_resolve_dependency (info->name, service, AFTER)) - { - DBG_MSG ("Failed to resolve dependency!\n"); - return -1; - } - } - } - - return 0; -} |