diff options
author | 2006-06-05 20:00:03 +0000 | |
---|---|---|
committer | 2006-06-05 20:00:03 +0000 | |
commit | dd6984872d04dd19e76aa7cdc847bde886c47ece (patch) | |
tree | 6572b979e97ec9bf806bf5547bed692bc69fe2c3 | |
parent | Merging r2079 (diff) | |
download | baselayout-vserver-master.tar.gz baselayout-vserver-master.tar.bz2 baselayout-vserver-master.zip |
svn path=/baselayout-vserver/trunk/; revision=373
-rw-r--r-- | src/core/librcscripts/Makefile.am | 27 | ||||
-rw-r--r-- | src/core/librcscripts/api/debug.h | 136 | ||||
-rw-r--r-- | src/core/librcscripts/api/depend.h | 76 | ||||
-rw-r--r-- | src/core/librcscripts/api/dynbuf.h | 66 | ||||
-rw-r--r-- | src/core/librcscripts/api/list.h | 446 | ||||
-rw-r--r-- | src/core/librcscripts/api/misc.h | 107 | ||||
-rw-r--r-- | src/core/librcscripts/api/parse.h | 84 | ||||
-rw-r--r-- | src/core/librcscripts/api/rctypes.h | 43 | ||||
-rw-r--r-- | src/core/librcscripts/api/runlevels.h | 44 | ||||
-rw-r--r-- | src/core/librcscripts/api/scripts.h | 43 | ||||
-rw-r--r-- | src/core/librcscripts/api/simple-regex.h | 87 | ||||
-rw-r--r-- | src/core/librcscripts/api/str_list.h | 212 | ||||
-rw-r--r-- | src/core/librcscripts/debug.c | 297 | ||||
-rw-r--r-- | src/core/librcscripts/depend.c | 672 | ||||
-rw-r--r-- | src/core/librcscripts/dynbuf.c | 407 | ||||
-rw-r--r-- | src/core/librcscripts/misc.c | 721 | ||||
-rw-r--r-- | src/core/librcscripts/parse.c | 828 | ||||
-rw-r--r-- | src/core/librcscripts/rcscripts.h | 72 | ||||
-rw-r--r-- | src/core/librcscripts/runlevels.c | 218 | ||||
-rw-r--r-- | src/core/librcscripts/scripts.c | 254 | ||||
-rw-r--r-- | src/core/librcscripts/simple-regex.c | 869 |
21 files changed, 0 insertions, 5709 deletions
diff --git a/src/core/librcscripts/Makefile.am b/src/core/librcscripts/Makefile.am deleted file mode 100644 index 27da323..0000000 --- a/src/core/librcscripts/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -AUTOMAKE_OPTIONS = foreign - -INCLUDES = $(RCSCRIPTS_DEFINES) - -lib_LTLIBRARIES = librcscripts.la - -librcscripts_la_SOURCES = \ - rcscripts.h \ - api/rctypes.h \ - debug.c \ - api/debug.h \ - misc.c \ - api/misc.h \ - api/list.h \ - api/str_list.h \ - dynbuf.c \ - api/dynbuf.h \ - simple-regex.c \ - api/simple-regex.h \ - scripts.c \ - api/scripts.h \ - runlevels.c \ - api/runlevels.h \ - parse.c \ - api/parse.h \ - depend.c \ - api/depend.h diff --git a/src/core/librcscripts/api/debug.h b/src/core/librcscripts/api/debug.h deleted file mode 100644 index 14e3dc6..0000000 --- a/src/core/librcscripts/api/debug.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * debug.h - * - * Simle debugging/logging macro's and functions. - * - * 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$ - */ - -#ifndef __DEBUG_H__ -#define __DEBUG_H__ - -#include <errno.h> -#include <stdio.h> - -#define save_errno() int old_errno = errno; -#define restore_errno() errno = old_errno; -#define saved_errno old_errno - -void -debug_message (const char *file, const char *func, int line, - const char *format, ...); - -#define DBG_MSG(_format, _arg...) \ - do { \ - debug_message (__FILE__, __FUNCTION__, __LINE__, _format, ## _arg); \ - } while (0) - -#define FATAL_ERROR() \ - do { \ - save_errno (); \ - fprintf(stderr, "ERROR: file '%s', function '%s', line %i.\n", \ - __FILE__, __FUNCTION__, __LINE__); \ - restore_errno (); \ - if (0 != errno) \ - { \ - perror("ERROR"); \ - } \ - exit(EXIT_FAILURE); \ - } while (0) - -#define NEG_FATAL_ERROR(_x) \ - do { \ - if (-1 == _x) \ - { \ - FATAL_ERROR(); \ - } \ - } while (0) - -#define NULL_FATAL_ERROR(_x) \ - do { \ - if (NULL == _x) \ - { \ - FATAL_ERROR(); \ - } \ - } while (0) - -/* - * Functions to check validity of some types. - * They do not set errno. - */ - -inline bool check_ptr (const void *ptr); -inline bool check_str (const char *str); -inline bool check_strv (char **str); -inline bool check_fd (int fd); -inline bool check_fp (FILE * fp); - -/* - * Functions and macro's to check validity of some types. - * They DO set errno to EINVAL. - */ - -inline bool __check_arg_ptr (const void *ptr, const char *file, const char *func, - size_t line); -inline bool __check_arg_str (const char *str, const char *file, const char *func, - size_t line); -inline bool __check_arg_strv (char **str, const char *file, const char *func, - size_t line); -inline bool __check_arg_fd (int fd, const char *file, const char *func, - size_t line); -inline bool __check_arg_fp (FILE * fp, const char *file, const char *func, - size_t line); - -#define check_arg_ptr(_ptr) \ - __check_arg_ptr (_ptr, __FILE__, __FUNCTION__, __LINE__) -#define check_arg_str(_str) \ - __check_arg_str (_str, __FILE__, __FUNCTION__, __LINE__) -#define check_arg_strv(_str) \ - __check_arg_strv (_str, __FILE__, __FUNCTION__, __LINE__) -#define check_arg_fd(_fd) \ - __check_arg_fd (_fd, __FILE__, __FUNCTION__, __LINE__) -#define check_arg_fp(_fp) \ - __check_arg_fp (_fp, __FILE__, __FUNCTION__, __LINE__) - -/* - * Various memory allocation functions and macro's. - * They set errno to ENOMEM and print debug info. - */ - -inline void *__xcalloc (size_t nmemb, size_t size, const char *file, - const char *func, size_t line); -inline void *__xmalloc (size_t size, const char *file, const char *func, - size_t line); -inline void *__xrealloc (void *ptr, size_t size, const char *file, - const char *func, size_t line); - -#define xcalloc(_nmemb, _size) \ - __xcalloc (_nmemb, _size, __FILE__, __FUNCTION__, __LINE__) -#define xmalloc(_size) \ - __xmalloc (_size, __FILE__, __FUNCTION__, __LINE__) -#define xrealloc(_ptr, _size) \ - __xrealloc (_ptr, _size, __FILE__, __FUNCTION__, __LINE__) - -inline char *__xstrndup (const char *str, size_t size, const char *file, - const char *func, size_t line); - -#define xstrndup(_str, _size) \ - __xstrndup (_str, _size, __FILE__, __FUNCTION__, __LINE__) - -#endif /* __DEBUG_H__ */ diff --git a/src/core/librcscripts/api/depend.h b/src/core/librcscripts/api/depend.h deleted file mode 100644 index d6662c6..0000000 --- a/src/core/librcscripts/api/depend.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * depend.h - * - * 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$ - */ - -#ifndef __DEPEND_H__ -#define __DEPEND_H__ - -/* Dependency types supported or still to be implemented */ -typedef enum -{ - NEED, /* All dependencies needed by specified service */ - NEED_ME, /* All dependencies that need specified service */ - USE, /* All dependencies used by specified service */ - USE_ME, /* All dependencies that use specified service */ - BEFORE, /* All services started before specified service */ - AFTER, /* All services started after specified service */ - BROKEN, /* All dependencies of type NEED missing for - specified service */ - PROVIDE, /* All virtual services provided by specified service */ - ALL_SERVICE_TYPE_T -} service_type_t; - -/* Names for above service types (service_type_t). - * Note that this should sync with above service_type_t */ -extern char *service_type_names[]; - -typedef struct -{ - struct list_head node; - - char *name; /* Name of service */ - char **depend_info[ALL_SERVICE_TYPE_T]; /* String lists for each service - type */ - char *provide; /* Name of virtual service it - provides. This is only valid - after we resolving - thus after - service_resolve_dependencies() */ - time_t mtime; /* Modification time of script */ -} service_info_t; - -struct list_head service_info_list; - -service_info_t *service_get_info (char *servicename); -int service_add (char *servicename); -int service_is_dependency (char *servicename, char *dependency, - service_type_t type); -int service_add_dependency (char *servicename, char *dependency, - service_type_t type); -int service_del_dependency (char *servicename, char *dependency, - service_type_t type); -service_info_t *service_get_virtual (char *virtual); -int service_add_virtual (char *servicename, char *virtual); -int service_set_mtime (char *servicename, time_t mtime); -int service_resolve_dependencies (void); - -#endif /* __DEPEND_H__ */ diff --git a/src/core/librcscripts/api/dynbuf.h b/src/core/librcscripts/api/dynbuf.h deleted file mode 100644 index 5c937b6..0000000 --- a/src/core/librcscripts/api/dynbuf.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * dynbuf.h - * - * Dynamic allocated buffers. - * - * 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$ - */ - -#ifndef __DYNBUF_H__ -#define __DYNBUF_H__ - -#define DYNAMIC_BUFFER_SIZE (sizeof (char) * 2 * 1024) - -typedef struct -{ - char *data; /* Actual data */ - size_t length; /* Length of data block */ - size_t rd_index; /* Current read index */ - size_t wr_index; /* Current write index */ - bool file_map; /* File mapped as dynbuf */ -} dyn_buf_t; - -dyn_buf_t *new_dyn_buf (void); - -dyn_buf_t *new_dyn_buf_mmap_file (const char *name); - -void free_dyn_buf (dyn_buf_t *dynbuf); - -int write_dyn_buf (dyn_buf_t *dynbuf, const char *buf, size_t length); - -int write_dyn_buf_from_fd (int fd, dyn_buf_t *dynbuf, size_t length); - -int sprintf_dyn_buf (dyn_buf_t *dynbuf, const char *format, ...); - -int read_dyn_buf (dyn_buf_t *dynbuf, char *buf, size_t length); - -int read_dyn_buf_to_fd (int fd, dyn_buf_t *dynbuf, size_t length); - -char *read_line_dyn_buf (dyn_buf_t *dynbuf); - -bool dyn_buf_rd_eof (dyn_buf_t *dynbuf); - -inline bool check_dyn_buf (dyn_buf_t *dynbuf); -inline bool __check_arg_dyn_buf (dyn_buf_t *dynbuf, const char *file, - const char *func, size_t line); - -#define check_arg_dyn_buf(_dynbuf) \ - __check_arg_dyn_buf (_dynbuf, __FILE__, __FUNCTION__, __LINE__) - -#endif /* __DYNBUF_H__ */ diff --git a/src/core/librcscripts/api/list.h b/src/core/librcscripts/api/list.h deleted file mode 100644 index e4c7a74..0000000 --- a/src/core/librcscripts/api/list.h +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copied from the Linux kernel source tree, version 2.6.0-test1. - * - * Licensed under the GPL v2 as per the whole kernel source tree. - * - * Ripped out the rcu stuff, as it's not needed. - * - * $Header$ - */ - -#ifndef __LINUX_LIST_H__ -#define __LINUX_LIST_H__ - -//#include <linux/stddef.h> -/** - * container_of - cast a member of a structure out to the containing structure - * - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -//#include <linux/prefetch.h> -static inline void prefetch(const void *x) {;} - -//#include <asm/system.h> - -/* - * These are non-NULL pointers that will result in page faults - * under normal circumstances, used to verify that nobody uses - * non-initialized list entries. - */ -#define LIST_POISON1 ((void *) 0x00100100) -#define LIST_POISON2 ((void *) 0x00200200) - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(struct list_head *head) -{ - return head->next == head; -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, prefetch(pos->next)) - -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This variant differs from list_for_each() in that it's the - * simplest possible list iteration code, no prefetching is done. - * Use this for code that knows the list to be very short (empty - * or 1 entry) most of the time. - */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ - pos = pos->prev, prefetch(pos->prev)) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - prefetch(pos->member.prev); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member), \ - prefetch(pos->member.prev)) - - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/* - * Double linked lists with a single pointer list head. - * Mostly useful for hash tables where the two pointer list head is - * too wasteful. - * You lose the ability to access the tail in O(1). - */ - -struct hlist_head { - struct hlist_node *first; -}; - -struct hlist_node { - struct hlist_node *next, **pprev; -}; - -#define HLIST_HEAD_INIT { .first = NULL } -#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } -#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) -#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) - -static __inline__ int hlist_unhashed(struct hlist_node *h) -{ - return !h->pprev; -} - -static __inline__ int hlist_empty(struct hlist_head *h) -{ - return !h->first; -} - -static __inline__ void __hlist_del(struct hlist_node *n) -{ - struct hlist_node *next = n->next; - struct hlist_node **pprev = n->pprev; - *pprev = next; - if (next) - next->pprev = pprev; -} - -static __inline__ void hlist_del(struct hlist_node *n) -{ - __hlist_del(n); - n->next = LIST_POISON1; - n->pprev = LIST_POISON2; -} - -static __inline__ void hlist_del_init(struct hlist_node *n) -{ - if (n->pprev) { - __hlist_del(n); - INIT_HLIST_NODE(n); - } -} - -static __inline__ void hlist_add_head(struct hlist_node *n, struct hlist_head *h) -{ - struct hlist_node *first = h->first; - n->next = first; - if (first) - first->pprev = &n->next; - h->first = n; - n->pprev = &h->first; -} - -/* next must be != NULL */ -static __inline__ void hlist_add_before(struct hlist_node *n, struct hlist_node *next) -{ - n->pprev = next->pprev; - n->next = next; - next->pprev = &n->next; - *(n->pprev) = n; -} - -static __inline__ void hlist_add_after(struct hlist_node *n, - struct hlist_node *next) -{ - next->next = n->next; - *(next->pprev) = n; - n->next = next; -} - -#define hlist_entry(ptr, type, member) container_of(ptr,type,member) - -/* Cannot easily do prefetch unfortunately */ -#define hlist_for_each(pos, head) \ - for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ - pos = pos->next) - -#define hlist_for_each_safe(pos, n, head) \ - for (pos = (head)->first; n = pos ? pos->next : 0, pos; \ - pos = n) - -/** - * hlist_for_each_entry - iterate over list of given type - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_continue(tpos, pos, member) \ - for (pos = (pos)->next; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_from - iterate over a hlist continuing from existing point - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_from(tpos, pos, member) \ - for (; pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @n: another &struct hlist_node to use as temporary storage - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ - for (pos = (head)->first; \ - pos && ({ n = pos->next; 1; }) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = n) - -#endif diff --git a/src/core/librcscripts/api/misc.h b/src/core/librcscripts/api/misc.h deleted file mode 100644 index 67eb214..0000000 --- a/src/core/librcscripts/api/misc.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * misc.h - * - * Miscellaneous macro's and functions. - * - * 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$ - */ - -#ifndef __MISC_H__ -#define __MISC_H__ - -#include <stdio.h> - -#include "config.h" - -/* Gentoo style e* printing macro's */ -#define EINFO(_args...) \ - do { \ - save_errno (); \ - printf (" \033[32;01m*\033[0m " _args); \ - restore_errno (); \ - } while (0) - -#define EWARN(_args...) \ - do { \ - save_errno (); \ - printf (" \033[33;01m*\033[0m " _args); \ - restore_errno (); \ - } while (0) - -#define EERROR(_args...) \ - do { \ - save_errno (); \ - fprintf (stderr, " \033[31;01m*\033[0m " _args); \ - restore_errno (); \ - } while (0) - -/* Return true if filename '_name' ends in '_ext' */ -#define CHECK_FILE_EXTENSION(_name, _ext) \ - ((check_str (_name)) && (check_str (_ext)) \ - && (strlen (_name) > strlen (_ext)) \ - && (0 == strncmp (&(_name[strlen(_name) - strlen(_ext)]), \ - _ext, strlen(_ext)))) - -/* String functions. Return a string on success, or NULL on error - * or no action taken. On error errno will be set.*/ -char *memrepchr (char **str, char old, char _new, size_t size); -/* Concat two paths adding '/' if needed. Memory will be allocated - * with the malloc() call. */ -char *strcatpaths (const char *pathname1, const char *pathname2); - -/* Compat functions for GNU extensions */ -char *strndup (const char *str, size_t size); -/* Same as basename(3), but do not modify path */ -char *gbasename (const char *path); - -/* The following functions do not care about errors - they only return - * 1 if 'pathname' exist, and is the type requested, or else 0. - * This is only if pathname is valid ... They also might clear errno */ -int exists (const char *pathname); -int is_file (const char *pathname, int follow_link); -int is_link (const char *pathname); -int is_dir (const char *pathname, int follow_link); - -/* The following function do not care about errors - it only returns - * the mtime of 'pathname' if it exists, and is the type requested, - * or else 0. It also might clear errno */ -time_t get_mtime (const char *pathname, int follow_link); - -/* The following functions return 0 on success, or -1 with errno set on error. */ -#if !defined(HAVE_REMOVE) -int remove (const char *pathname); -#endif -int mktree (const char *pathname, mode_t mode); -int rmtree (const char *pathname); - -/* The following return a pointer on success, or NULL with errno set on error. - * If it returned NULL, but errno is not set, then there was no error, but - * there is nothing to return. */ -char **ls_dir (const char *pathname, int hidden); -char *get_cnf_entry (const char *pathname, const char *entry); -char ** get_list_file (char **list, char *filename); - -/* Below three functions (file_map, file_unmap and buf_get_line) are from - * udev-050 (udev_utils.c). Please see misc.c for copyright info. - * (Some are slightly modified, please check udev for originals.) */ -int file_map (const char *filename, char **buf, size_t * bufsize); -void file_unmap (char *buf, size_t bufsize); -size_t buf_get_line (char *buf, size_t buflen, size_t cur); - -#endif /* __MISC_H__ */ diff --git a/src/core/librcscripts/api/parse.h b/src/core/librcscripts/api/parse.h deleted file mode 100644 index b5e07fa..0000000 --- a/src/core/librcscripts/api/parse.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * parse.h - * - * Parser 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$ - */ - -#ifndef __PARSE_H__ -#define __PARSE_H__ - -#define LEGACY_CACHE_FILE_NAME "deptree" - -#define FIELD_RCSCRIPT "RCSCRIPT" -#define FIELD_NEED "NEED" -#define FIELD_USE "USE" -#define FIELD_BEFORE "BEFORE" -#define FIELD_AFTER "AFTER" -#define FIELD_PROVIDE "PROVIDE" -#define FIELD_FAILED "FAILED" - -size_t generate_stage1 (dyn_buf_t *data); -size_t generate_stage2 (dyn_buf_t *data); -size_t read_stage2 (char **data); -int write_stage2 (FILE * outfile); -size_t generate_stage3 (char **data); -size_t read_stage3 (char **data); -int write_stage3 (FILE * outfile); -int write_legacy_stage3 (FILE * output); -int parse_cache (const dyn_buf_t *data); - -/* - * get_rcscripts() - * | - * V - * check_rcscripts_mtime() ------------------------------> read_stage3() - * | | - * | | - * V V - * generate_stage1() (Called by generate_stage2()) parse_cache() - * | | - * | | - * V | - * generate_stage2() ----> write_stage2() (Debugging) | - * | | - * | | - * | === parse_cache() | - * V | | | - * generate_stage3() ==| | | - * | | | | - * | | V | - * | === service_resolve_dependencies() | - * | | - * | | - * |-------> write_legacy_stage3() (Proof of Concept | - * | or Debugging) | - * | | - * V | - * write_stage3() | - * | | - * | V - * |<------------------------------------------------------- - * | - * V - * - */ - -#endif /* __PARSE_H__ */ diff --git a/src/core/librcscripts/api/rctypes.h b/src/core/librcscripts/api/rctypes.h deleted file mode 100644 index 6efab4a..0000000 --- a/src/core/librcscripts/api/rctypes.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * rctypes.h - * - * Misc types and macro's. - * - * 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$ - */ - -#ifndef __RCTYPES_H__ -#define __RCTYPES_H__ - -/* Min/Max macro's */ -#ifdef MAX -# undef MAX -#endif -#define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b)) -#ifdef MIN -# undef MIN -#endif -#define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a)) - -typedef enum { - FALSE, - TRUE -} bool; - -#endif /* __RCTYPES_H__ */ diff --git a/src/core/librcscripts/api/runlevels.h b/src/core/librcscripts/api/runlevels.h deleted file mode 100644 index ccc9ed0..0000000 --- a/src/core/librcscripts/api/runlevels.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * runlevels.h - * - * Functions dealing with runlevels. - * - * 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$ - */ - -#ifndef __RUNLEVELS_H__ -#define __RUNLEVELS_H__ - -typedef struct -{ - struct list_head node; - - char *dirname; /* Name of this runlevel */ - struct list_head entries; /* rcscript_info_t list of rc-scripts */ -} runlevel_info_t; - -struct list_head runlevel_list; - -int get_runlevels (void); - -runlevel_info_t *get_runlevel_info (const char *runlevel); - -bool is_runlevel (const char *runlevel); - -#endif /* __RUNLEVELS_H__ */ diff --git a/src/core/librcscripts/api/scripts.h b/src/core/librcscripts/api/scripts.h deleted file mode 100644 index 75003b4..0000000 --- a/src/core/librcscripts/api/scripts.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * scripts.h - * - * Get info etc 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$ - */ - -#ifndef __SCRIPTS_H__ -#define __SCRIPTS_H__ - -typedef struct -{ - struct list_head node; - - char *filename; - time_t mtime; - time_t confd_mtime; -} rcscript_info_t; - -struct list_head rcscript_list; - -int get_rcscripts (void); -int check_rcscripts_mtime (const char *cachefile); -rcscript_info_t *get_rcscript_info (const char *scriptname); - -#endif /* __SCRIPTS_H__ */ diff --git a/src/core/librcscripts/api/simple-regex.h b/src/core/librcscripts/api/simple-regex.h deleted file mode 100644 index 1ae746f..0000000 --- a/src/core/librcscripts/api/simple-regex.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * simple_regex.h - * - * Simle regex library. - * - * 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$ - */ - -#ifndef __SIMPLE_REGEX_H__ -#define __SIMPLE_REGEX_H__ - -#define REGEX_NO_MATCH 0 /* We have no match */ -#define REGEX_PARTIAL_MATCH 1 /* Some of the string matches the regex */ -#define REGEX_FULL_MATCH 2 /* The whole string matches the regex */ - -/* Macro to fill in .data and .regex */ -#define FILL_REGEX_DATA(_regex_data, _string, _regex) \ - do { \ - _regex_data.data = _string; \ - _regex_data.regex = _regex; \ - } while (0) - -/* Fill in _regex_data with _data and _regex, on failure goto _error */ -#define DO_REGEX(_regex_data, _data, _regex, _error) \ - do { \ - FILL_REGEX_DATA(_regex_data, _data, _regex); \ - if (-1 == match(&_regex_data)) \ - { \ - DBG_MSG("Could not do regex match!\n"); \ - goto _error; \ - } \ - } while (0) - -/* Evaluate to true if we have some kind of match */ -#define REGEX_MATCH(_regex_data) \ - ((REGEX_FULL_MATCH == _regex_data.match) \ - || (REGEX_PARTIAL_MATCH == _regex_data.match)) - -/* Same as above, but for use when _regex_data is a pointer */ -#define REGEX_MATCH_P(_regex_data) \ - ((REGEX_FULL_MATCH == _regex_data->match) \ - || (REGEX_PARTIAL_MATCH == _regex_data->match)) - -typedef struct -{ - char *data; /* String to perform regex operation on */ - char *regex; /* String containing regex to use */ - int match; /* Will be set if there was a match. Check - * REGEX_*_MATCH above for possible values */ - char *where; /* Pointer to where match starts in data */ - size_t count; /* Count characters from data matched by regex */ - size_t r_count; /* Count characters of regex used for match. This - * should normally be the lenght of regex, but might - * not be for some internal functions ... */ -} regex_data_t; - -/* - * Return: - * - * 0 - There was no error. If there was a match, regex_data->match - * - will be > 0 (this is the definitive check - if not true, the - * - other values of the struct may be bogus), regex_data->count - * - will be the amount of data that was matched (might be 0 for - * - some wildcards), and regex_data->r_count will be > 0. - * - * -1 - An error occured. Check errno for more info. - * - */ -int match (regex_data_t * regex_data); - -#endif /* __SIMPLE_REGEX_H__ */ diff --git a/src/core/librcscripts/api/str_list.h b/src/core/librcscripts/api/str_list.h deleted file mode 100644 index 538ab82..0000000 --- a/src/core/librcscripts/api/str_list.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * str_list.h - * - * String list macros. - * - * 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$ - */ - -#ifndef __STR_LIST_H__ -#define __STR_LIST_H__ - -/* Add a new item to a string list. If the pointer to the list is NULL, - * allocate enough memory for the amount of entries needed. Ditto for - * when it already exists, but we add one more entry than it can - * contain. The list is NULL terminated. - * NOTE: _only_ memory for the list are allocated, and not for the items - that - * should be done by relevant code (unlike str_list_del_item() that will - * free the memory) */ -#define str_list_add_item(_string_list, _item, _error) \ - do { \ - char **_tmp_p; \ - int _i = 0; \ - if (!check_str (_item)) \ - { \ - goto _error; \ - } \ - while ((NULL != _string_list) && (NULL != _string_list[_i])) \ - { \ - _i++; \ - } \ - /* Amount of entries + new + terminator */ \ - _tmp_p = xrealloc (_string_list, sizeof (char *) * (_i + 2)); \ - if (NULL == _tmp_p) \ - { \ - goto _error; \ - } \ - _string_list = _tmp_p; \ - _string_list[_i] = _item; \ - /* Terminator */ \ - _string_list[_i+1] = NULL; \ - } while (0) - -/* Add a new item to a string list (foundamental the same as above), but make - * sure we have all the items alphabetically sorted. */ -#define str_list_add_item_sorted(_string_list, _item, _error) \ - do { \ - char **_tmp_p; \ - char *_str_p1; \ - char *_str_p2; \ - int _i = 0; \ - if (!check_str (_item)) \ - { \ - goto _error; \ - } \ - while ((NULL != _string_list) && (NULL != _string_list[_i])) \ - { \ - _i++; \ - } \ - /* Amount of entries + new + terminator */ \ - _tmp_p = xrealloc (_string_list, sizeof (char *) * (_i + 2)); \ - if (NULL == _tmp_p) \ - { \ - goto _error; \ - } \ - _string_list = _tmp_p; \ - if (0 == _i) \ - { \ - /* Needed so that the end NULL will propagate - * (iow, make sure our 'NULL != _str_p1' test below - * do not fail) */ \ - _string_list[_i] = NULL; \ - } \ - /* Actual terminator that needs adding */ \ - _string_list[_i+1] = NULL; \ - _i = 0; \ - /* See where we should insert the new item to have it all \ - * alphabetically sorted */ \ - while (NULL != _string_list[_i]) \ - { \ - if (strcmp (_string_list[_i], _item) > 0) \ - { \ - break; \ - } \ - _i++; \ - } \ - /* Now just insert the new item, and shift the rest one over. - * '_str_p2' is temporary storage to swap the indexes in a loop, - * and 'str_p1' is used to store the old value across the loop */ \ - _str_p1 = _string_list[_i]; \ - _string_list[_i] = _item; \ - do { \ - _i++;\ - _str_p2 = _string_list[_i]; \ - _string_list[_i] = _str_p1; \ - _str_p1 = _str_p2; \ - } while (NULL != _str_p1); \ - } while (0) - -/* Delete one entry from the string list, and shift the rest down if the entry - * was not at the end. For now we do not resize the amount of entries the - * string list can contain, and free the memory for the matching item */ -#define str_list_del_item(_string_list, _item, _error) \ - do { \ - int _i = 0; \ - if (!check_str (_item)) \ - { \ - goto _error; \ - } \ - if (NULL == _string_list) \ - { \ - errno = EINVAL; \ - DBG_MSG ("Invalid string list passed!\n"); \ - goto _error; \ - } \ - while (NULL != _string_list[_i]) \ - { \ - if (0 == strcmp (_item, _string_list[_i])) \ - { \ - break; \ - } \ - else \ - { \ - _i++; \ - } \ - } \ - if (NULL == _string_list[_i]) \ - { \ - errno = EINVAL; \ - DBG_MSG ("Invalid string list item passed!\n"); \ - goto _error; \ - } \ - free (_string_list[_i]); \ - /* Shift all the following items one forward */ \ - do { \ - _string_list[_i] = _string_list[_i+1]; \ - /* This stupidity is to shutup gcc */ \ - _i++; \ - } while (NULL != _string_list[_i]); \ - } while (0) - -/* Step through each entry in the string list, setting '_pos' to the - * beginning of the entry. '_counter' is used by the macro as index, - * but should not be used by code as index (or if really needed, then - * it should usually by +1 from what you expect, and should only be - * used in the scope of the macro) */ -#define str_list_for_each_item(_string_list, _pos, _counter) \ - if ((NULL != _string_list) && (0 == (_counter = 0))) \ - while (NULL != (_pos = _string_list[_counter++])) - -/* Same as above (with the same warning about '_counter'). Now we just - * have '_next' that are also used for indexing. Once again rather refrain - * from using it if not absolutely needed. The major difference to above, - * is that it should be safe from having the item removed from under you. */ -#define str_list_for_each_item_safe(_string_list, _pos, _next, _counter) \ - if ((NULL != _string_list) && (0 == (_counter = 0))) \ - /* First part of the while checks if this is the - * first loop, and if so setup _pos and _next - * and increment _counter */ \ - while ((((0 == _counter) \ - && (NULL != (_pos = _string_list[_counter])) \ - && (_pos != (_next = _string_list[++_counter]))) \ - /* Second part is when it is not the first loop - * and _pos was not removed from under us. We - * just increment _counter, and setup _pos and - * _next */ \ - || ((0 != _counter) \ - && (_pos == _string_list[_counter-1]) \ - && (_next == _string_list[_counter]) \ - && (NULL != (_pos = _string_list[_counter])) \ - && (_pos != (_next = _string_list[++_counter]))) \ - /* Last part is when _pos was removed from under - * us. We basically just setup _pos and _next, - * but leave _counter alone */ \ - || ((0 != _counter) \ - && (_pos != _string_list[_counter-1]) \ - && (_next == _string_list[_counter-1]) \ - && (NULL != (_pos = _string_list[_counter-1])) \ - && (_pos != (_next = _string_list[_counter]))))) - -/* Just free the whole string list */ -#define str_list_free(_string_list) \ - do { \ - if (NULL != _string_list) \ - { \ - int _i = 0; \ - while (NULL != _string_list[_i]) \ - { \ - free (_string_list[_i]); \ - _string_list[_i++] = NULL; \ - } \ - free (_string_list); \ - _string_list = NULL; \ - } \ - } while (0) - -#endif /* __STR_LIST_H__ */ diff --git a/src/core/librcscripts/debug.c b/src/core/librcscripts/debug.c deleted file mode 100644 index 959ddf9..0000000 --- a/src/core/librcscripts/debug.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * debug.c - * - * Simle debugging/logging macro's and functions. - * - * 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 <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> - -#include "rcscripts.h" - -static char log_domain[] = "rcscripts"; - -void -debug_message (const char *file, const char *func, int line, - const char *format, ...) -{ - va_list arg; - char *format_str; - int length; - - save_errno (); - - length = strlen (log_domain) + strlen ("(): ") + 1; - /* Do not use xmalloc() here, else we may have recursive issues */ - format_str = malloc (length); - if (NULL == format_str) - { - fprintf (stderr, "(%s) error: in %s, function %s(), line %i:\n", - log_domain, __FILE__, __FUNCTION__, __LINE__); - fprintf (stderr, "(%s) Failed to allocate buffer!\n", - log_domain); - abort (); - } - - snprintf (format_str, length, "(%s) ", log_domain); - - va_start (arg, format); - -#if !defined(RC_DEBUG) - /* Bit of a hack, as how we do things tend to cause seek - * errors when reading the parent/child pipes */ - /* if ((0 != errno) && (ESPIPE != errno)) { */ - if (0 != saved_errno) - { -#endif - if (0 != saved_errno) - fprintf (stderr, "(%s) error: ", log_domain); - else - fprintf (stderr, "(%s) debug: ", log_domain); - - fprintf (stderr, "in %s, function %s(), line %i:\n", file, func, line); - - fprintf (stderr, "%s ", format_str); - vfprintf (stderr, format, arg); - -#if defined(RC_DEBUG) - if (0 != saved_errno) - { -#endif - perror (format_str); -#if defined(RC_DEBUG) - } -#endif -#if !defined(RC_DEBUG) - } -#endif - - va_end (arg); - - free (format_str); - restore_errno (); -} - -inline bool -check_ptr (const void *ptr) -{ - if (NULL == ptr) - return FALSE; - - return TRUE; -} - -inline bool -check_str (const char *str) -{ - if ((NULL == str) || (0 == strlen (str))) - return FALSE; - - return TRUE; -} - -inline bool -check_strv (char **str) -{ - if ((NULL == str) || (NULL == *str) || (0 == strlen (*str))) - return FALSE; - - return TRUE; -} - -inline bool -check_fd (int fd) -{ - if ((0 >= fd) || (-1 == fcntl (fd, F_GETFL))) - return FALSE; - - return TRUE; -} - -inline bool -check_fp (FILE *fp) -{ - if ((NULL == fp) || (-1 == fileno (fp))) - return FALSE; - - return TRUE; -} - -inline bool -__check_arg_ptr (const void *ptr, const char *file, const char *func, size_t line) -{ - if (!check_ptr (ptr)) - { - errno = EINVAL; - - debug_message (file, func, line, "Invalid pointer passed!\n"); - - return FALSE; - } - - return TRUE; -} - -inline bool -__check_arg_str (const char *str, const char *file, const char *func, size_t line) -{ - if (!check_str (str)) - { - errno = EINVAL; - - debug_message (file, func, line, "Invalid string passed!\n"); - - return FALSE; - } - - return TRUE; -} - -inline bool -__check_arg_strv (char **str, const char *file, const char *func, size_t line) -{ - if (!check_strv (str)) - { - errno = EINVAL; - - debug_message (file, func, line, "Invalid string array passed!\n"); - - return FALSE; - } - - return TRUE; -} - -inline bool -__check_arg_fd (int fd, const char *file, const char *func, size_t line) -{ - if (!check_fd (fd)) - { - errno = EBADF; - - debug_message (file, func, line, "Invalid file descriptor passed!\n"); - - return FALSE; - } - - return TRUE; -} - -inline bool -__check_arg_fp (FILE *fp, const char *file, const char *func, size_t line) -{ - if (!check_fp (fp)) - { - errno = EBADF; - - debug_message (file, func, line, "Invalid file descriptor passed!\n"); - - return FALSE; - } - - return TRUE; -} - -inline void * -__xcalloc(size_t nmemb, size_t size, const char *file, - const char *func, size_t line) -{ - void *new_ptr; - - new_ptr = calloc (nmemb, size); - if (NULL == new_ptr) - { - /* Set errno in case specific malloc() implementation does not */ - errno = ENOMEM; - - debug_message (file, func, line, "Failed to allocate buffer!\n"); - - return NULL; - } - - return new_ptr; -} - -inline void * -__xmalloc (size_t size, const char *file, const char *func, size_t line) -{ - void *new_ptr; - - new_ptr = malloc (size); - if (NULL == new_ptr) - { - /* Set errno in case specific malloc() implementation does not */ - errno = ENOMEM; - - debug_message (file, func, line, "Failed to allocate buffer!\n"); - - return NULL; - } - - return new_ptr; -} - -inline void * -__xrealloc (void *ptr, size_t size, const char *file, - const char *func, size_t line) -{ - void *new_ptr; - - new_ptr = realloc (ptr, size); - if (NULL == new_ptr) - { - /* Set errno in case specific realloc() implementation does not */ - errno = ENOMEM; - - debug_message (file, func, line, "Failed to reallocate buffer!\n"); - - return NULL; - } - - return new_ptr; -} - -inline char * -__xstrndup (const char *str, size_t size, const char *file, - const char *func, size_t line) -{ - char *new_ptr; - - new_ptr = strndup (str, size); - if (NULL == new_ptr) - { - /* Set errno in case specific realloc() implementation does not */ - errno = ENOMEM; - - debug_message (file, func, line, - "Failed to duplicate string via strndup() !\n"); - - return NULL; - } - - return new_ptr; -} - 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; -} diff --git a/src/core/librcscripts/dynbuf.c b/src/core/librcscripts/dynbuf.c deleted file mode 100644 index 5fc156e..0000000 --- a/src/core/librcscripts/dynbuf.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * dynbuf.c - * - * Dynamic allocated buffers. - * - * 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 <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "rcscripts.h" - -static dyn_buf_t *reallocate_dyn_buf (dyn_buf_t *dynbuf, size_t needed); - -dyn_buf_t * -new_dyn_buf (void) -{ - dyn_buf_t *dynbuf = NULL; - - dynbuf = xmalloc (sizeof (dyn_buf_t)); - if (NULL == dynbuf) - return NULL; - - dynbuf->data = xmalloc (DYNAMIC_BUFFER_SIZE); - if (NULL == dynbuf->data) - { - free (dynbuf); - return NULL; - } - - dynbuf->length = DYNAMIC_BUFFER_SIZE; - dynbuf->rd_index = 0; - dynbuf->wr_index = 0; - dynbuf->file_map = FALSE; - - return dynbuf; -} - -dyn_buf_t * -new_dyn_buf_mmap_file (const char *name) -{ - dyn_buf_t *dynbuf = NULL; - - dynbuf = xmalloc (sizeof (dyn_buf_t)); - if (NULL == dynbuf) - return NULL; - - if (-1 == file_map (name, &dynbuf->data, &dynbuf->length)) - { - DBG_MSG ("Failed to mmap file '%s'\n", name); - free (dynbuf); - - return NULL; - } - - dynbuf->wr_index = dynbuf->length; - dynbuf->rd_index = 0; - dynbuf->file_map = TRUE; - - return dynbuf; -} - -dyn_buf_t * -reallocate_dyn_buf (dyn_buf_t *dynbuf, size_t needed) -{ - int len; - - if (!check_arg_dyn_buf (dynbuf)) - return NULL; - - if (dynbuf->file_map) - { - errno = EPERM; - DBG_MSG ("Cannot reallocate mmap()'d file!\n"); - - return NULL; - } - - len = sizeof (char) * (dynbuf->wr_index + needed + 1); - - if (dynbuf->length < len) - { - char *new_ptr; - - /* Increase size in chunks to minimize reallocations */ - if (len < (dynbuf->length + DYNAMIC_BUFFER_SIZE)) - len = dynbuf->length + DYNAMIC_BUFFER_SIZE; - - new_ptr = xrealloc (dynbuf->data, len); - if (NULL == new_ptr) - return NULL; - - dynbuf->data = new_ptr; - dynbuf->length = len; - } - - return dynbuf; -} - -void -free_dyn_buf (dyn_buf_t *dynbuf) -{ - if (NULL == dynbuf) - return; - - if (!dynbuf->file_map) - { - if (NULL != dynbuf->data) - { - free (dynbuf->data); - dynbuf->data = NULL; - } - } - else - { - save_errno (); - file_unmap (dynbuf->data, dynbuf->length); - restore_errno (); - } - - dynbuf->length = 0; - dynbuf->rd_index = 0; - dynbuf->wr_index = 0; - - free (dynbuf); - dynbuf = NULL; -} - -int -write_dyn_buf (dyn_buf_t *dynbuf, const char *buf, size_t length) -{ - int len; - - if (!check_arg_dyn_buf (dynbuf)) - return -1; - - if (!check_arg_str (buf)) - return -1; - - if (dynbuf->file_map) - { - errno = EPERM; - DBG_MSG ("Cannot write to readonly mmap()'d file!\n"); - - return -1; - } - - if (NULL == reallocate_dyn_buf (dynbuf, length)) - { - DBG_MSG ("Could not reallocate dynamic buffer!\n"); - return -1; - } - - len = snprintf ((dynbuf->data + dynbuf->wr_index), length + 1, "%s", buf); - - /* If len is less than length, it means the string was shorter than - * given length */ - if (length > len) - length = len; - - if (0 < length) - dynbuf->wr_index += length; - - if (-1 == length) - DBG_MSG ("Failed to write to dynamic buffer!\n"); - - return length; -} - -int write_dyn_buf_from_fd (int fd, dyn_buf_t *dynbuf, size_t length) -{ - int len = length; - - if (!check_arg_dyn_buf (dynbuf)) - return -1; - - if (!check_arg_fd (fd)) - return -1; - - if (dynbuf->file_map) - { - errno = EPERM; - DBG_MSG ("Cannot write to readonly mmap()'d file!\n"); - - return -1; - } - - if (NULL == reallocate_dyn_buf (dynbuf, length)) - { - DBG_MSG ("Could not reallocate dynamic buffer!\n"); - return -1; - } - - len = read (fd, (dynbuf->data + dynbuf->wr_index), len); - - if (length > len) - length = len; - - if (0 < length) - dynbuf->wr_index += length; - - dynbuf->data[dynbuf->wr_index] = '\0'; - - if (-1 == length) - DBG_MSG ("Failed to write to dynamic buffer!\n"); - - return length; -} - -int -sprintf_dyn_buf (dyn_buf_t *dynbuf, const char *format, ...) -{ - va_list arg1, arg2; - char test_str[10]; - int needed, written = 0; - - if (!check_arg_dyn_buf (dynbuf)) - return -1; - - if (!check_arg_str (format)) - return -1; - - if (dynbuf->file_map) - { - errno = EPERM; - DBG_MSG ("Cannot write to readonly mmap()'d file!\n"); - - return -1; - } - - va_start (arg1, format); - va_copy (arg2, arg1); - - /* XXX: Lame way to try and figure out how much space we need */ - needed = vsnprintf (test_str, sizeof (test_str), format, arg2); - va_end (arg2); - - if (NULL == reallocate_dyn_buf (dynbuf, needed)) - { - DBG_MSG ("Could not reallocate dynamic buffer!\n"); - return -1; - } - - written = vsnprintf ((dynbuf->data + dynbuf->wr_index), needed + 1, - format, arg1); - va_end (arg1); - - if (0 < written) - dynbuf->wr_index += written; - - if (-1 == written) - DBG_MSG ("Failed to write to dynamic buffer!\n"); - - return written; -} - -int -read_dyn_buf (dyn_buf_t *dynbuf, char *buf, size_t length) -{ - int len = length; - - if (!check_arg_dyn_buf (dynbuf)) - return -1; - - if (!check_arg_ptr (buf)) - return -1; - - if (dynbuf->rd_index >= dynbuf->length) - return 0; - - if (dynbuf->wr_index < (dynbuf->rd_index + length)) - len = dynbuf->wr_index - dynbuf->rd_index; - - len = snprintf (buf, len + 1, "%s", (dynbuf->data + dynbuf->rd_index)); - - /* If len is less than length, it means the string was shorter than - * given length */ - if (length > len) - length = len; - - if (0 < length) - dynbuf->rd_index += length; - - if (-1 == length) - DBG_MSG ("Failed to write from dynamic buffer!\n"); - - return length; -} - -int -read_dyn_buf_to_fd (int fd, dyn_buf_t *dynbuf, size_t length) -{ - int len = length; - - if (!check_arg_dyn_buf (dynbuf)) - return -1; - - if (!check_arg_fd (fd)) - return -1; - - if (dynbuf->rd_index >= dynbuf->length) - return 0; - - if (dynbuf->wr_index < (dynbuf->rd_index + length)) - len = dynbuf->wr_index - dynbuf->rd_index; - - len = write (fd, (dynbuf->data + dynbuf->rd_index), len); - if (length > len) - length = len; - - if (0 < length) - dynbuf->rd_index += length; - - if (-1 == length) - DBG_MSG ("Failed to write from dynamic buffer!\n"); - - return length; -} - -char * -read_line_dyn_buf (dyn_buf_t *dynbuf) -{ - char *buf = NULL; - size_t count = 0; - - if (!check_arg_dyn_buf (dynbuf)) - return NULL; - - if (dynbuf->rd_index == dynbuf->wr_index) - return NULL; - - for (count = dynbuf->rd_index; count < dynbuf->wr_index && dynbuf->data[count] != '\n'; count++); - - if (count <= dynbuf->wr_index) - { - buf = xstrndup ((dynbuf->data + dynbuf->rd_index), - (count - dynbuf->rd_index)); - if (NULL == buf) - return NULL; - - dynbuf->rd_index = count; - - /* Also skip the '\n' .. */ - if (dynbuf->rd_index < dynbuf->wr_index) - dynbuf->rd_index++; - } - - return buf; -} - -bool -dyn_buf_rd_eof (dyn_buf_t *dynbuf) -{ - if (!check_arg_dyn_buf (dynbuf)) - return FALSE; - - if (dynbuf->rd_index >= dynbuf->wr_index) - return TRUE; - - return FALSE; -} - -inline bool -check_dyn_buf (dyn_buf_t *dynbuf) -{ - if ((NULL == dynbuf) || (NULL == dynbuf->data) || (0 == dynbuf->length)) - return FALSE; - - return TRUE; -} - -inline bool -__check_arg_dyn_buf (dyn_buf_t *dynbuf, const char *file, const char *func, - size_t line) -{ - if (!check_dyn_buf (dynbuf)) - { - errno = EINVAL; - - debug_message (file, func, line, "Invalid dynamic buffer passed!\n"); - - return FALSE; - } - - return TRUE; -} - diff --git a/src/core/librcscripts/misc.c b/src/core/librcscripts/misc.c deleted file mode 100644 index 37edc5f..0000000 --- a/src/core/librcscripts/misc.c +++ /dev/null @@ -1,721 +0,0 @@ -/* - * misc.c - * - * Miscellaneous macro's and functions. - * - * 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 <stdio.h> -#include <stdlib.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <dirent.h> -#include <unistd.h> -#include <fcntl.h> - -#include "rcscripts.h" - -char * -memrepchr (char **str, char old, char new, size_t size) -{ - char *str_p; - - if (!check_arg_strv (str)) - return NULL; - - str_p = memchr (*str, old, size); - - while (NULL != str_p) - { - str_p[0] = new; - str_p = memchr (&str_p[1], old, size - (str_p - *str) - 1); - } - - return *str; -} - -char * -strcatpaths (const char *pathname1, const char *pathname2) -{ - char *new_path = NULL; - int lenght; - - if ((!check_arg_str (pathname1)) || (!check_arg_str (pathname2))) - return 0; - - /* Lenght of pathname1 + lenght of pathname2 + '/' if needed */ - lenght = strlen (pathname1) + strlen (pathname2) + 2; - /* lenght + '\0' */ - new_path = xmalloc (lenght); - if (NULL == new_path) - return NULL; - - snprintf (new_path, lenght, "%s%s%s", pathname1, - (new_path[strlen (new_path) - 1] != '/') ? "/" : "", - pathname2); - - return new_path; -} - -char * -strndup (const char *str, size_t size) -{ - char *new_str = NULL; - size_t len; - - /* We cannot check if its a valid string here, as it might - * not be '\0' terminated ... */ - if (!check_arg_ptr (str)) - return NULL; - - /* Check lenght of str without breaching the size limit */ - for (len = 0; (len < size) && ('\0' != str[len]); len++); - - new_str = xmalloc (len + 1); - if (NULL == new_str) - return NULL; - - /* Make sure our string is NULL terminated */ - new_str[len] = '\0'; - - return (char *) memcpy (new_str, str, len); -} - -char * -gbasename (const char *path) -{ - char *new_path = NULL; - - if (!check_arg_str (path)) - return NULL; - - /* Copied from glibc */ - new_path = strrchr (path, '/'); - return new_path ? new_path + 1 : (char *) path; -} - - -int -exists (const char *pathname) -{ - struct stat buf; - int retval; - - if (!check_arg_str (pathname)) - return -1; - - retval = lstat (pathname, &buf); - if (-1 != retval) - return 1; - - /* Clear errno, as we do not want debugging to trigger */ - errno = 0; - - return 0; -} - -int -is_file (const char *pathname, int follow_link) -{ - struct stat buf; - int retval; - - if (!check_arg_str (pathname)) - return -1; - - retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf); - if ((-1 != retval) && (S_ISREG (buf.st_mode))) - return 1; - - /* Clear errno, as we do not want debugging to trigger */ - errno = 0; - - return 0; -} - -int -is_link (const char *pathname) -{ - struct stat buf; - int retval; - - if (!check_arg_str (pathname)) - return -1; - - retval = lstat (pathname, &buf); - if ((-1 != retval) && (S_ISLNK (buf.st_mode))) - return 1; - - /* Clear errno, as we do not want debugging to trigger */ - errno = 0; - - return 0; -} - -int -is_dir (const char *pathname, int follow_link) -{ - struct stat buf; - int retval; - - if (!check_arg_str (pathname)) - return -1; - - retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf); - if ((-1 != retval) && (S_ISDIR (buf.st_mode))) - return 1; - - /* Clear errno, as we do not want debugging to trigger */ - errno = 0; - - return 0; -} - -time_t -get_mtime (const char *pathname, int follow_link) -{ - struct stat buf; - int retval; - - if (!check_arg_str (pathname)) - return -1; - - retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf); - if (-1 != retval) - return buf.st_mtime; - - /* Clear errno, as we do not want debugging to trigger */ - errno = 0; - - return 0; -} - -#if !defined(HAVE_REMOVE) -int -remove (const char *pathname) -{ - int retval; - - if (!check_arg_str (pathname)) - return -1; - - if (1 == is_dir (pathname, 0)) - retval = rmdir (pathname); - else - retval = unlink (pathname); - - return retval; -} -#endif - -int -mktree (const char *pathname, mode_t mode) -{ - char *temp_name = NULL; - char *temp_token = NULL; - char *token_p; - char *token; - int retval; - int lenght; - - if (!check_arg_str (pathname)) - return -1; - - /* Lenght of 'pathname' + extra for "./" if needed */ - lenght = strlen (pathname) + 2; - /* lenght + '\0' */ - temp_name = xmalloc (lenght + 1); - if (NULL == temp_name) - return -1; - - temp_token = xstrndup (pathname, strlen (pathname)); - if (NULL == temp_token) - goto error; - - token_p = temp_token; - - if (pathname[0] == '/') - temp_name[0] = '\0'; - else - /* If not an absolute path, make it local */ - strncpy (temp_name, ".", lenght); - - token = strsep (&token_p, "/"); - /* First token might be "", but that is OK as it will be when the - * pathname starts with '/' */ - while (NULL != token) - { - strncat (temp_name, "/", lenght - strlen (temp_name)); - strncat (temp_name, token, lenght - strlen (temp_name)); - - /* If it does not exist, create the dir. If it does exit, - * but is not a directory, we will catch it below. */ - if (1 != exists (temp_name)) - { - retval = mkdir (temp_name, mode); - if (-1 == retval) - { - DBG_MSG ("Failed to create directory!\n"); - goto error; - } - /* Not a directory or symlink pointing to a directory */ - } - else if (1 != is_dir (temp_name, 1)) - { - errno = ENOTDIR; - DBG_MSG ("Component in pathname is not a directory!\n"); - goto error; - } - - do - { - token = strsep (&token_p, "/"); - /* The first "" was Ok, but rather skip double '/' after that */ - } - while ((NULL != token) && (0 == strlen (token))); - } - - free (temp_name); - free (temp_token); - - return 0; - -error: - free (temp_name); - free (temp_token); - - return -1; -} - -int -rmtree (const char *pathname) -{ - char **dirlist = NULL; - int i = 0; - - if (!check_arg_str (pathname)) - return -1; - - if (1 != exists (pathname)) - { - errno = ENOENT; - DBG_MSG ("'%s' does not exists!\n", pathname); - return -1; - } - - dirlist = ls_dir (pathname, 1); - if ((NULL == dirlist) && (0 != errno)) - { - /* Do not error out - caller should decide itself if it - * it is an issue */ - DBG_MSG ("Could not get listing for '%s'!\n", pathname); - return -1; - } - - while ((NULL != dirlist) && (NULL != dirlist[i])) - { - /* If it is a directory, call rmtree() again with - * it as argument */ - if (1 == is_dir (dirlist[i], 0)) - { - if (-1 == rmtree (dirlist[i])) - { - DBG_MSG ("Failed to delete sub directory!\n"); - goto error; - } - } - - /* Now actually remove it. Note that if it was a directory, - * it should already be removed by above rmtree() call */ - if ((1 == exists (dirlist[i]) && (-1 == remove (dirlist[i])))) - { - DBG_MSG ("Failed to remove '%s'!\n", dirlist[i]); - goto error; - } - i++; - } - - str_list_free (dirlist); - - /* Now remove the parent */ - if (-1 == remove (pathname)) - { - DBG_MSG ("Failed to remove '%s'!\n", pathname); - goto error; - } - - return 0; -error: - str_list_free (dirlist); - - return -1; -} - -char ** -ls_dir (const char *pathname, int hidden) -{ - DIR *dp; - struct dirent *dir_entry; - char **dirlist = NULL; - - if (!check_arg_str (pathname)) - return NULL; - - dp = opendir (pathname); - if (NULL == dp) - { - DBG_MSG ("Failed to call opendir()!\n"); - /* errno will be set by opendir() */ - goto error; - } - - do - { - /* Clear errno to distinguish between EOF and error */ - errno = 0; - dir_entry = readdir (dp); - /* Only an error if 'errno' != 0, else EOF */ - if ((NULL == dir_entry) && (0 != errno)) - { - DBG_MSG ("Failed to call readdir()!\n"); - goto error; - } - if ((NULL != dir_entry) - /* Should we display hidden files? */ - && (hidden ? 1 : dir_entry->d_name[0] != '.')) - { - char *d_name = dir_entry->d_name; - char *str_ptr; - - /* Do not list current or parent entries */ - if ((0 == strcmp (d_name, ".")) || (0 == strcmp (d_name, ".."))) - continue; - - str_ptr = strcatpaths (pathname, d_name); - if (NULL == str_ptr) - { - DBG_MSG ("Failed to allocate buffer!\n"); - goto error; - } - - str_list_add_item (dirlist, str_ptr, error); - } - } - while (NULL != dir_entry); - - if (!check_strv (dirlist)) - { - if (NULL != dirlist) - str_list_free (dirlist); - - DBG_MSG ("Directory is empty.\n"); - } - - closedir (dp); - - return dirlist; - -error: - /* Free dirlist on error */ - str_list_free (dirlist); - - if (NULL != dp) - { - save_errno (); - closedir (dp); - /* closedir() might have changed it */ - restore_errno (); - } - - return NULL; -} - -/* This handles simple 'entry="bar"' type variables. If it is more complex - * ('entry="$(pwd)"' or such), it will obviously not work, but current behaviour - * should be fine for the type of variables we want. */ -char * -get_cnf_entry (const char *pathname, const char *entry) -{ - dyn_buf_t *dynbuf = NULL; - char *buf = NULL; - char *str_ptr; - char *value = NULL; - char *token; - - - if ((!check_arg_str (pathname)) || (!check_arg_str (entry))) - return NULL; - - /* If it is not a file or symlink pointing to a file, bail */ - if (1 != is_file (pathname, 1)) - { - errno = ENOENT; - DBG_MSG ("Given pathname is not a file or do not exist!\n"); - return NULL; - } - - dynbuf = new_dyn_buf_mmap_file (pathname); - if (NULL == dynbuf) - { - DBG_MSG ("Could not open config file for reading!\n"); - return NULL; - } - - while (NULL != (buf = read_line_dyn_buf (dynbuf))) - { - str_ptr = buf; - - /* Strip leading spaces/tabs */ - while ((str_ptr[0] == ' ') || (str_ptr[0] == '\t')) - str_ptr++; - - /* Get entry and value */ - token = strsep (&str_ptr, "="); - /* Bogus entry or value */ - if (NULL == token) - goto _continue; - - /* Make sure we have a string that is larger than 'entry', and - * the first part equals 'entry' */ - if ((strlen (token) > 0) && (0 == strcmp (entry, token))) - { - do - { - /* Bash variables are usually quoted */ - token = strsep (&str_ptr, "\"\'"); - /* If quoted, the first match will be "" */ - } - while ((NULL != token) && (0 == strlen (token))); - - /* We have a 'entry='. We respect bash rules, so NULL - * value for now (if not already) */ - if (NULL == token) - { - /* We might have 'entry=' and later 'entry="bar"', - * so just continue for now ... we will handle - * it below when 'value == NULL' */ - if (NULL != value) - { - free (value); - value = NULL; - } - goto _continue; - } - - /* If we have already allocated 'value', free it */ - if (NULL != value) - free (value); - - value = xstrndup (token, strlen (token)); - if (NULL == value) - { - free_dyn_buf (dynbuf); - free (buf); - - return NULL; - } - - /* We do not break, as there might be more than one entry - * defined, and as bash uses the last, so should we */ - /* break; */ - } - -_continue: - free (buf); - } - - /* read_line_dyn_buf() returned NULL with errno set */ - if ((NULL == buf) && (0 != errno)) - { - DBG_MSG ("Failed to read line from dynamic buffer!\n"); - free_dyn_buf (dynbuf); - if (NULL != value) - free (value); - - return NULL; - } - - - if (NULL == value) - DBG_MSG ("Failed to get value for config entry '%s'!\n", entry); - - free_dyn_buf (dynbuf); - - return value; -} - -char ** -get_list_file (char **list, char *filename) -{ - dyn_buf_t *dynbuf = NULL; - char *buf = NULL; - char *tmp_p = NULL; - char *token = NULL; - - if (!check_arg_str (filename)) - return NULL; - - dynbuf = new_dyn_buf_mmap_file (filename); - if (NULL == dynbuf) - return NULL; - - while (NULL != (buf = read_line_dyn_buf (dynbuf))) - { - tmp_p = buf; - - /* Strip leading spaces/tabs */ - while ((tmp_p[0] == ' ') || (tmp_p[0] == '\t')) - tmp_p++; - - /* Get entry - we do not want comments, and only the first word - * on a line is valid */ - token = strsep (&tmp_p, "# \t"); - if (check_str (token)) - { - tmp_p = xstrndup (token, strlen (token)); - if (NULL == tmp_p) - { - if (NULL != list) - str_list_free (list); - free_dyn_buf (dynbuf); - free (buf); - - return NULL; - } - - str_list_add_item (list, tmp_p, error); - } - - free (buf); - } - - /* read_line_dyn_buf() returned NULL with errno set */ - if ((NULL == buf) && (0 != errno)) - { - DBG_MSG ("Failed to read line from dynamic buffer!\n"); -error: - if (NULL != list) - str_list_free (list); - free_dyn_buf (dynbuf); - - return NULL; - } - - free_dyn_buf (dynbuf); - - return list; -} - - -/* - * Below three functions (file_map, file_unmap and buf_get_line) are - * from udev-050 (udev_utils.c). - * (Some are slightly modified, please check udev for originals.) - * - * Copyright (C) 2004 Kay Sievers <kay@vrfy.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. - * - */ - -int -file_map (const char *filename, char **buf, size_t * bufsize) -{ - struct stat stats; - int fd; - - fd = open (filename, O_RDONLY); - if (fd < 0) - { - DBG_MSG ("Failed to open file!\n"); - return -1; - } - - if (fstat (fd, &stats) < 0) - { - DBG_MSG ("Failed to stat file!\n"); - - save_errno (); - close (fd); - restore_errno (); - - return -1; - } - - if (0 == stats.st_size) - { - errno = EINVAL; - DBG_MSG ("Failed to mmap file with 0 size!\n"); - - save_errno (); - close (fd); - restore_errno (); - - return -1; - } - - *buf = mmap (NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (*buf == MAP_FAILED) - { - DBG_MSG ("Failed to mmap file!\n"); - - save_errno (); - close (fd); - restore_errno (); - - return -1; - } - *bufsize = stats.st_size; - - close (fd); - - return 0; -} - -void -file_unmap (char *buf, size_t bufsize) -{ - munmap (buf, bufsize); -} - -size_t -buf_get_line (char *buf, size_t buflen, size_t cur) -{ - size_t count = 0; - - for (count = cur; count < buflen && buf[count] != '\n'; count++); - - return count - cur; -} diff --git a/src/core/librcscripts/parse.c b/src/core/librcscripts/parse.c deleted file mode 100644 index 2711c3b..0000000 --- a/src/core/librcscripts/parse.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - * parse.c - * - * Parser 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 <signal.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/poll.h> -#include <unistd.h> -#include <fcntl.h> -#include <signal.h> - -#include "rcscripts.h" - -#define READ_PIPE 0 -#define WRITE_PIPE 1 - -/* _pipe[0] is used to send data to the parent (thus the parent only use the - * read pipe, and the child uses the write pipe) - * _pipe[1] is used to send data to the child (thus the child only use the read - * pipe, and the parent uses the write pipe) - */ -#define PARENT_READ_PIPE(_pipe) (_pipe[0][READ_PIPE]) -#define PARENT_WRITE_PIPE(_pipe) (_pipe[1][WRITE_PIPE]) -#define CHILD_READ_PIPE(_pipe) (_pipe[1][READ_PIPE]) -#define CHILD_WRITE_PIPE(_pipe) (_pipe[0][WRITE_PIPE]) - -#define PARSE_BUFFER_SIZE 256 - -static size_t parse_rcscript (char *scriptname, dyn_buf_t *data); - -static size_t parse_print_start (dyn_buf_t *data); -static size_t parse_print_header (char *scriptname, dyn_buf_t *data); -static size_t parse_print_body (char *scriptname, dyn_buf_t *data); - -/* Return count on success, -1 on error. If it was critical, errno will be set. */ -size_t -parse_rcscript (char *scriptname, dyn_buf_t *data) -{ - regex_data_t tmp_data; - dyn_buf_t *dynbuf = NULL; - char *buf = NULL; - size_t write_count = 0; - size_t tmp_count; - - if (!check_arg_dyn_buf (data)) - return -1; - - if (!check_arg_str (scriptname)) - return -1; - - dynbuf = new_dyn_buf_mmap_file (scriptname); - if (NULL == dynbuf) - { - DBG_MSG ("Could not open '%s' for reading!\n", gbasename (scriptname)); - return -1; - } - - DBG_MSG ("Parsing '%s'.\n", gbasename (scriptname)); - - tmp_count = parse_print_header (gbasename (scriptname), data); - if (-1 == tmp_count) - { - DBG_MSG ("Failed to call parse_print_header()!\n"); - goto error; - } - write_count += tmp_count; - - while (NULL != (buf = read_line_dyn_buf(dynbuf))) - { - /* Check for lines with comments, and skip them */ - DO_REGEX (tmp_data, buf, "^[ \t]*#", error); - if (REGEX_MATCH (tmp_data)) - { - free (buf); - continue; - } - - /* If the line contains 'depend()', call parse_print_body () and break */ - DO_REGEX (tmp_data, buf, "depend[ \t]*()[ \t]*{?", error); - if (REGEX_MATCH (tmp_data)) - { - DBG_MSG ("Got 'depend()' function.\n"); - - tmp_count = parse_print_body (gbasename (scriptname), data); - if (-1 == tmp_count) - { - DBG_MSG ("Failed to call parse_print_body()!\n"); - goto error; - } - - write_count += tmp_count; - - /* This is the last loop */ - free (buf); - break; - } - - free (buf); - } - - /* read_line_dyn_buf() returned NULL with errno set */ - if ((NULL == buf) && (0 != errno)) - { - DBG_MSG ("Failed to read line from dynamic buffer!\n"); - free_dyn_buf (dynbuf); - - return -1; - } - - free_dyn_buf (dynbuf); - - return write_count; - -error: - if (NULL != buf) - free (buf); - if (NULL != dynbuf) - free_dyn_buf (dynbuf); - - return -1; -} - - -size_t -generate_stage1 (dyn_buf_t *data) -{ - rcscript_info_t *info; - size_t write_count = 0; - size_t tmp_count; - - if (!check_arg_dyn_buf (data)) - return -1; - - write_count = parse_print_start (data); - if (-1 == write_count) - { - DBG_MSG ("Failed to call parse_print_start()!\n"); - return -1; - } - - list_for_each_entry (info, &rcscript_list, node) - { - tmp_count = parse_rcscript (info->filename, data); - if (-1 == tmp_count) - { - DBG_MSG ("Failed to parse '%s'!\n", gbasename (info->filename)); - - /* If 'errno' is set, it is critical (hopefully) */ - if (0 != errno) - return -1; - } - else - { - write_count += tmp_count; - } - } - - return write_count; -} - -/* Empty signal handler for SIGPIPE */ -static void -sig_handler (int signum) -{ - return; -} - -/* Returns data's lenght on success, else -1 on error. */ -size_t -generate_stage2 (dyn_buf_t *data) -{ - int pipe_fds[2][2] = { {0, 0}, {0, 0} }; - pid_t child_pid; - size_t write_count = 0; - int old_errno = 0; - - if (!check_arg_dyn_buf (data)) - return -1; - - /* Pipe to send data to parent */ - if (-1 == pipe (pipe_fds[0])) - { - DBG_MSG ("Failed to open pipe!\n"); - goto error; - } - /* Pipe to send data to child */ - if (-1 == pipe (pipe_fds[1])) - { - DBG_MSG ("Failed to open pipe!\n"); - /* Close parent_pfds */ - goto error; - } - - child_pid = fork (); - if (-1 == child_pid) - { - DBG_MSG ("Failed to fork()!\n"); - /* Close all pipes */ - goto error; - } - if (0 == child_pid) - { - /*** - *** In child - ***/ - - char *const argv[] = { - "bash", - "--noprofile", - "--norc", - "--", - NULL - }; - - /* Close the sides of the pipes we do not use */ - close (PARENT_WRITE_PIPE (pipe_fds)); - close (PARENT_READ_PIPE (pipe_fds)); - - /* dup2 child side read pipe to STDIN */ - dup2 (CHILD_READ_PIPE (pipe_fds), STDIN_FILENO); - /* dup2 child side write pipe to STDOUT */ - dup2 (CHILD_WRITE_PIPE (pipe_fds), STDOUT_FILENO); - - /* We need to be in RCSCRIPTS_INITDDIR for 'before'/'after' '*' to work */ - if (-1 == chdir (RCSCRIPTS_INITDDIR)) - { - DBG_MSG ("Failed to chdir to '%s'!\n", RCSCRIPTS_INITDDIR); - exit (EXIT_FAILURE); - } - - if (-1 == execv (SHELL_PARSER, argv)) - { - DBG_MSG ("Failed to execv %s!\n", SHELL_PARSER); - exit (EXIT_FAILURE); - } - } - else - { - /*** - *** In parent - ***/ - - dyn_buf_t *stage1_data; - struct sigaction act_new; - struct sigaction act_old; - struct pollfd poll_fds[2]; - int status = 0; - - DBG_MSG ("Child pid = %i\n", child_pid); - - /* Set signal handler for SIGPIPE to empty in case bash errors - * out. It will then close the write pipe, and instead of us - * getting SIGPIPE, we can handle the write error like normal. - */ - memset (&act_new, 0x00, sizeof (act_new)); - act_new.sa_handler = (void (*)(int)) sig_handler; - sigemptyset (&act_new.sa_mask); - act_new.sa_flags = 0; - sigaction (SIGPIPE, &act_new, &act_old); - - /* Close the sides of the pipes we do not use */ - close (CHILD_WRITE_PIPE (pipe_fds)); - CHILD_WRITE_PIPE (pipe_fds) = 0; - close (CHILD_READ_PIPE (pipe_fds)); - CHILD_READ_PIPE (pipe_fds) = 0; - - stage1_data = new_dyn_buf (); - if (NULL == stage1_data) - { - DBG_MSG ("Failed to allocate dynamic buffer!\n"); - goto error; - } - - /* Pipe parse_rcscripts() to bash */ - if (-1 == generate_stage1 (stage1_data)) - { - DBG_MSG ("Failed to generate stage1!\n"); - goto error; - } - -#if 0 - int tmp_fd = open ("bar", O_CREAT | O_TRUNC | O_RDWR, 0600); - write (tmp_fd, stage1_data->data, stage1_data->wr_index); - close (tmp_fd); -#endif - - do - { - int tmp_count = 0; - int do_write = 0; - int do_read = 0; - - /* Check if we can write or read */ - poll_fds[WRITE_PIPE].fd = PARENT_WRITE_PIPE (pipe_fds); - poll_fds[WRITE_PIPE].events = POLLOUT; - poll_fds[READ_PIPE].fd = PARENT_READ_PIPE (pipe_fds); - poll_fds[READ_PIPE].events = POLLIN | POLLPRI; - if (!dyn_buf_rd_eof (stage1_data)) - { - poll (poll_fds, 2, -1); - if (poll_fds[WRITE_PIPE].revents & POLLOUT) - do_write = 1; - } - else - { - poll (&(poll_fds[READ_PIPE]), 1, -1); - } - if ((poll_fds[READ_PIPE].revents & POLLIN) - || (poll_fds[READ_PIPE].revents & POLLPRI)) - do_read = 1; - - do - { - /* While we can write, or there is nothing to - * read, keep feeding the write pipe */ - if ((dyn_buf_rd_eof (stage1_data)) - || (1 == do_read) - || (1 != do_write)) - break; - - tmp_count = read_dyn_buf_to_fd (PARENT_WRITE_PIPE (pipe_fds), - stage1_data, PARSE_BUFFER_SIZE); - if ((-1 == tmp_count) && (EINTR != errno)) - { - DBG_MSG ("Error writing to PARENT_WRITE_PIPE!\n"); - goto failed; - } - /* We were interrupted, try to write again */ - if (-1 == tmp_count) - { - errno = 0; - /* Make sure we retry */ - tmp_count = 1; - continue; - } - - /* Close the write pipe if we done - * writing to get a EOF signaled to - * bash */ - if (dyn_buf_rd_eof (stage1_data)) - { - close (PARENT_WRITE_PIPE (pipe_fds)); - PARENT_WRITE_PIPE (pipe_fds) = 0; - } - } - while ((tmp_count > 0) && (!dyn_buf_rd_eof (stage1_data))); - - /* Reset tmp_count for below read loop */ - tmp_count = 0; - - do - { - if (1 != do_read) - continue; - - tmp_count = write_dyn_buf_from_fd (PARENT_READ_PIPE (pipe_fds), - data, PARSE_BUFFER_SIZE); - if ((-1 == tmp_count) && (EINTR != errno)) - { - DBG_MSG ("Error reading PARENT_READ_PIPE!\n"); - goto failed; - } - /* We were interrupted, try to read again */ - if ((-1 == tmp_count) || (0 == tmp_count)) - { - errno = 0; - continue; - } - - write_count += tmp_count; - } - while (tmp_count > 0); - } - while (!(poll_fds[READ_PIPE].revents & POLLHUP)); - -failed: - /* Set old_errno to disable child exit code checking below */ - if (0 != errno) - old_errno = errno; - - free_dyn_buf (stage1_data); - - if (0 != PARENT_WRITE_PIPE (pipe_fds)) - close (PARENT_WRITE_PIPE (pipe_fds)); - close (PARENT_READ_PIPE (pipe_fds)); - - /* Restore the old signal handler for SIGPIPE */ - sigaction (SIGPIPE, &act_old, NULL); - - /* Wait for bash to finish */ - waitpid (child_pid, &status, 0); - /* If old_errno is set, we had an error in the read loop, so do - * not worry about the child's exit code */ - if (0 == old_errno) - { - if ((!WIFEXITED (status)) || (0 != WEXITSTATUS (status))) - { - /* FIXME: better errno ? */ - errno = ECANCELED; - DBG_MSG ("Bash failed with status 0x%x!\n", status); - - return -1; - } - } - else - { - /* Right, we had an error, so set errno, and exit */ - errno = old_errno; - return -1; - } - } - - return write_count; - - /* Close parent side pipes */ -error: - /* Close all pipes */ - old_errno = errno; - if (0 != CHILD_READ_PIPE (pipe_fds)) - close (CHILD_READ_PIPE (pipe_fds)); - if (0 != CHILD_WRITE_PIPE (pipe_fds)) - close (CHILD_WRITE_PIPE (pipe_fds)); - if (0 != PARENT_READ_PIPE (pipe_fds)) - close (PARENT_READ_PIPE (pipe_fds)); - if (0 != PARENT_WRITE_PIPE (pipe_fds)) - close (PARENT_WRITE_PIPE (pipe_fds)); - /* close() might have changed it */ - errno = old_errno; - - return -1; -} - -int -write_legacy_stage3 (FILE * output) -{ - service_info_t *info; - char *service; - int count; - int sindex = 0; - int dep_count; - int i; - - if (!check_arg_fp (output)) - return -1; - - fprintf (output, "rc_type_ineed=2\n"); - fprintf (output, "rc_type_needsme=3\n"); - fprintf (output, "rc_type_iuse=4\n"); - fprintf (output, "rc_type_usesme=5\n"); - fprintf (output, "rc_type_ibefore=6\n"); - fprintf (output, "rc_type_iafter=7\n"); - fprintf (output, "rc_type_broken=8\n"); - fprintf (output, "rc_type_mtime=9\n"); - fprintf (output, "rc_index_scale=10\n\n"); - fprintf (output, "declare -a RC_DEPEND_TREE\n\n"); - - list_for_each_entry (info, &service_info_list, node) - { - sindex++; - } - if (0 == sindex) - { - EERROR ("No services to generate dependency tree for!\n"); - return -1; - } - - fprintf (output, "RC_DEPEND_TREE[0]=%i\n\n", sindex); - - sindex = 1; - - list_for_each_entry (info, &service_info_list, node) - { - fprintf (output, "RC_DEPEND_TREE[%i]=\"%s\"\n", sindex * 10, info->name); - - for (i = 0; i <= BROKEN; i++) - { - dep_count = 0; - - fprintf (output, "RC_DEPEND_TREE[%i+%i]=", (sindex * 10), (i + 2)); - - str_list_for_each_item (info->depend_info[i], service, count) - { - if (0 == dep_count) - fprintf (output, "\"%s", service); - else - fprintf (output, " %s", service); - - dep_count++; - } - - if (dep_count > 0) - fprintf (output, "\"\n"); - else - fprintf (output, "\n"); - } - - fprintf (output, "RC_DEPEND_TREE[%i+9]=\"%li\"\n\n", - sindex * 10, info->mtime); - sindex++; - } - - fprintf (output, "RC_GOT_DEPTREE_INFO=\"yes\"\n"); - - info = service_get_virtual ("logger"); - if (NULL == info) - { - DBG_MSG ("No service provides the 'logger' logger virtual!\n"); - fprintf (output, "\nLOGGER_SERVICE=\n"); - } - else - { - fprintf (output, "\nLOGGER_SERVICE=\"%s\"\n", info->name); - } - - - return 0; -} - -int -parse_cache (const dyn_buf_t *data) -{ - service_info_t *info; - service_type_t type = ALL_SERVICE_TYPE_T; - rcscript_info_t *rs_info; - char *buf = NULL; - char *rc_name = NULL; - char *str_ptr; - char *token; - char *field; - int retval; - - if (!check_arg_dyn_buf ((dyn_buf_t *) data)) - goto error; - - while (NULL != (buf = read_line_dyn_buf ((dyn_buf_t *) data))) - { - str_ptr = buf; - - /* Strip leading spaces/tabs */ - while ((str_ptr[0] == ' ') || (str_ptr[0] == '\t')) - str_ptr++; - - /* Get FIELD name and FIELD value */ - token = strsep (&str_ptr, " "); - - /* FIELD name empty/bogus? */ - if ((!check_str (token)) - /* We got an empty FIELD value */ - || (!check_str (str_ptr))) - { - errno = EMSGSIZE; - DBG_MSG ("Parsing stopped due to short read!\n"); - - goto error; - } - - if (0 == strcmp (token, FIELD_RCSCRIPT)) - { - DBG_MSG ("Field = '%s', value = '%s'\n", token, str_ptr); - - /* Add the service to the list, and initialize all data */ - retval = service_add (str_ptr); - if (-1 == retval) - { - DBG_MSG ("Failed to add %s to service list!\n", str_ptr); - goto error; - } - - info = service_get_info (str_ptr); - if (NULL == info) - { - DBG_MSG ("Failed to get info for '%s'!\n", str_ptr); - goto error; - } - /* Save the rc-script name for next passes of loop */ - rc_name = info->name; - - goto _continue; - } - - if (NULL == rc_name) - { - DBG_MSG ("Other fields should come after '%s'!\n", FIELD_RCSCRIPT); - goto error; - } - - if (0 == strcmp (token, FIELD_NEED)) - type = NEED; - else if (0 == strcmp (token, FIELD_USE)) - type = USE; - else if (0 == strcmp (token, FIELD_BEFORE)) - type = BEFORE; - else if (0 == strcmp (token, FIELD_AFTER)) - type = AFTER; - else if (0 == strcmp (token, FIELD_PROVIDE)) - type = PROVIDE; - else if (0 == strcmp (token, FIELD_FAILED)) - { - type = BROKEN; - - /* FIXME: Need to think about what to do syntax BROKEN - * services */ - EWARN ("'%s' has syntax errors, please correct!\n", rc_name); - } - - if (type < ALL_SERVICE_TYPE_T) - { - /* Get the first value * - * As the values are passed to a bash function, and we - * then use 'echo $*' to parse them, they should only - * have one space between each value ... */ - token = strsep (&str_ptr, " "); - - /* Get the correct type name */ - field = service_type_names[type]; - - while (NULL != token) - { - DBG_MSG ("Field = '%s', service = '%s', value = '%s'\n", - field, rc_name, token); - - retval = service_add_dependency (rc_name, token, type); - if (-1 == retval) - { - DBG_MSG - ("Failed to add dependency '%s' to service '%s', type '%s'!\n", - token, rc_name, field); - goto error; - } - - /* Get the next value (if any) */ - token = strsep (&str_ptr, " "); - } - - goto _continue; - } - - /* Fall through */ - DBG_MSG ("Unknown FIELD in data!\n"); - -_continue: - type = ALL_SERVICE_TYPE_T; - free (buf); - /* Do not free 'rc_name', as it should be consistant - * across loops */ - } - - /* read_line_dyn_buf() returned NULL with errno set */ - if ((NULL == buf) && (0 != errno)) - { - DBG_MSG ("Failed to read line from dynamic buffer!\n"); - return -1; - } - - /* Set the mtimes - * FIXME: Can drop this when we no longer need write_legacy_stage3() */ - list_for_each_entry (rs_info, &rcscript_list, node) - { - rc_name = gbasename (rs_info->filename); - if (NULL == service_get_info (rc_name)) - continue; - - retval = service_set_mtime (rc_name, rs_info->mtime); - if (-1 == retval) - { - DBG_MSG ("Failed to set mtime for service '%s'!\n", rc_name); - return -1; - } - } - - return 0; - -error: - free (buf); - - return -1; -} - -size_t -parse_print_start (dyn_buf_t *data) -{ - size_t write_count; - - if (!check_arg_dyn_buf (data)) - return -1; - - write_count = - sprintf_dyn_buf (data, - ". /sbin/functions.sh\n" - "[ -e /etc/rc.conf ] && . /etc/rc.conf\n" - "\n" - /* "set -e\n" */ - "\n"); - - return write_count; -} - -size_t -parse_print_header (char *scriptname, dyn_buf_t *data) -{ - size_t write_count; - - if (!check_arg_dyn_buf (data)) - return -1; - - write_count = - sprintf_dyn_buf (data, - "#*** %s ***\n" - "\n" - "myservice=\"%s\"\n" - "echo \"RCSCRIPT ${myservice}\"\n" - "\n", scriptname, scriptname); - - return write_count; -} - -size_t -parse_print_body (char *scriptname, dyn_buf_t *data) -{ - size_t write_count; - char *buf = NULL; - char *str_ptr; - char *base; - char *ext; - - if (!check_arg_dyn_buf (data)) - return -1; - - buf = xstrndup (scriptname, strlen (scriptname)); - if (NULL == buf) - return -1; - - /* - * Rather do the next block in C than bash, in case we want to - * use ash or another shell in the place of bash - */ - - /* bash: base="${myservice%%.*}" */ - base = buf; - str_ptr = strchr (buf, '.'); - if (NULL != str_ptr) - { - str_ptr[0] = '\0'; - str_ptr++; - } - else - { - str_ptr = buf; - } - /* bash: ext="${myservice##*.}" */ - ext = strrchr (str_ptr, '.'); - if (NULL == ext) - ext = str_ptr; - - write_count = - sprintf_dyn_buf (data, - "\n" - "(\n" - " # Get settings for rc-script ...\n" - " [ -e \"/etc/conf.d/${myservice}\" ] && \\\n" - " . \"/etc/conf.d/${myservice}\"\n" - " [ -e /etc/conf.d/net ] && \\\n" - " [ \"%s\" = \"net\" ] && \\\n" - " [ \"%s\" != \"${myservice}\" ] && \\\n" - " . /etc/conf.d/net\n" - " depend() {\n" - " return 0\n" - " }\n" - " \n" - " # Actual depend() function ...\n" - " (\n" - " set -e\n" - " . \"/etc/init.d/%s\" >/dev/null 2>&1\n" - " set +e\n" - " \n" - " need() {\n" - " [ \"$#\" -gt 0 ] && echo \"NEED $*\"; return 0\n" - " }\n" - " \n" - " use() {\n" - " [ \"$#\" -gt 0 ] && echo \"USE $*\"; return 0\n" - " }\n" - " \n" - " before() {\n" - " [ \"$#\" -gt 0 ] && echo \"BEFORE $*\"; return 0\n" - " }\n" - " \n" - " after() {\n" - " [ \"$#\" -gt 0 ] && echo \"AFTER $*\"; return 0\n" - " }\n" - " \n" - " provide() {\n" - " [ \"$#\" -gt 0 ] && echo \"PROVIDE $*\"; return 0\n" - " }\n" - " \n" - " depend\n" - " ) || echo \"FAILED ${myservice}\"\n" - ")\n" "\n\n", base, ext, scriptname); - - return write_count; -} diff --git a/src/core/librcscripts/rcscripts.h b/src/core/librcscripts/rcscripts.h deleted file mode 100644 index 3740832..0000000 --- a/src/core/librcscripts/rcscripts.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * rcscripts.h - * - * Core defines. - * - * 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$ - */ - -#ifndef __RCSCRIPTS_H__ -#define __RCSCRIPTS_H__ - -#include <stddef.h> -#include <sys/types.h> - -#include "config.h" - -#include "api/rctypes.h" -#include "api/debug.h" -#include "api/misc.h" -#include "api/list.h" -#include "api/str_list.h" -#include "api/dynbuf.h" -#include "api/simple-regex.h" -#include "api/scripts.h" -#include "api/runlevels.h" -#include "api/parse.h" -#include "api/depend.h" - -#define RCSCRIPTS_CONFDDIR ETCDIR "/conf.d" -#define RCSCRIPTS_INITDDIR ETCDIR "/init.d" -#define RCSCRIPTS_LIBDIR LIBDIR "/rcscripts" - -#define RUNLEVELS_DIR ETCDIR "/runlevels" - -#define SBIN_RC SBINDIR "/rc" -#define PROFILE_ENV ETCDIR "/profile.env" - -#define RC_CONF_FILE_NAME ETCDIR "/rc.conf" -#define RC_CONFD_FILE_NAME ETCDIR "/conf.d/rc" - -#define RCSCRIPT_HELP RCSCRIPTS_LIBDIR "/sh/rc-help.sh" - -#define SVCDIR_CONFIG_ENTRY "svcdir" - -#define SHELL_PARSER BINDIR "/bash" - -#define DEFAULT_PATH "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin" - -#define SELINUX_LIB RCSCRIPTS_LIBDIR "/runscript_selinux.so" - -#define SYS_WHITELIST RCSCRIPTS_LIBDIR "/conf.d/env_whitelist" -#define USR_WHITELIST RCSCRIPTS_CONFDDIR "/env_whitelist" - -#define SOFTLEVEL "SOFTLEVEL" - -#endif /* __RCSCRIPTS_H__ */ diff --git a/src/core/librcscripts/runlevels.c b/src/core/librcscripts/runlevels.c deleted file mode 100644 index 914f7ab..0000000 --- a/src/core/librcscripts/runlevels.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * runlevels.c - * - * Functions dealing with runlevels. - * - * 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 <stddef.h> -#include <stdlib.h> -#include <string.h> - -#include "rcscripts.h" - -static char **get_runlevel_dirs (void); - -LIST_HEAD (runlevel_list); - -char ** -get_runlevel_dirs (void) -{ - char **dir_list = NULL; - char **runlvl_list = NULL; - char *dir_item; - int count; - - dir_list = ls_dir (RUNLEVELS_DIR, 0); - if (NULL == dir_list) - { - errno = ENOENT; - DBG_MSG ("Failed to get any entries in '%' !\n", RUNLEVELS_DIR); - - return NULL; - } - - str_list_for_each_item (dir_list, dir_item, count) - { - if (is_dir (dir_item, 0)) - { - char *tmp_str; - - tmp_str = xstrndup (dir_item, strlen (dir_item)); - if (NULL == tmp_str) - goto error; - - str_list_add_item (runlvl_list, tmp_str, error); - } - } - - str_list_free (dir_list); - - if (!check_strv (runlvl_list)) - { - if (NULL != runlvl_list) - str_list_free (runlvl_list); - } - - return runlvl_list; - -error: - if (NULL != dir_list) - str_list_free (dir_list); - if (NULL != runlvl_list) - str_list_free (runlvl_list); - - return NULL; -} - -int -get_runlevels (void) -{ - char **runlvl_list = NULL; - char *runlevel; - int count; - - runlvl_list = get_runlevel_dirs (); - if (NULL == runlvl_list) - { - DBG_MSG ("Failed to get any runlevels\n"); - - return -1; - } - - str_list_for_each_item (runlvl_list, runlevel, count) - { - runlevel_info_t *runlevel_info; - char **dir_list = NULL; - char *dir_item; - int dir_count; - - DBG_MSG ("Adding runlevel '%s'\n", gbasename (runlevel)); - - runlevel_info = xmalloc (sizeof (runlevel_info_t)); - if (NULL == runlevel_info) - goto error; - - runlevel_info->dirname = xstrndup (runlevel, strlen (runlevel)); - if (NULL == runlevel_info->dirname) - goto error; - - INIT_LIST_HEAD (&runlevel_info->entries); - - dir_list = ls_dir (runlevel, 0); - if (NULL == dir_list) - { - if (0 != errno) - goto error; - - goto no_entries; - } - - str_list_for_each_item (dir_list, dir_item, dir_count) - { - rcscript_info_t *script_info; - rcscript_info_t *new_script_info = NULL; - - if (!is_link (dir_item)) - { - DBG_MSG ("Skipping non symlink '%s' !\n", dir_item); - continue; - } - - script_info = get_rcscript_info (gbasename (dir_item)); - if (NULL == script_info) - { - DBG_MSG ("Skipping invalid entry '%s' !\n", dir_item); - continue; - } - - new_script_info = xmalloc (sizeof (rcscript_info_t)); - if (NULL == new_script_info) - { - str_list_free (dir_list); - goto error; - } - - DBG_MSG ("Adding '%s' to runlevel '%s'\n", - gbasename (script_info->filename), - gbasename (runlevel)); - - /* Add a copy, as the next and prev pointers will be changed */ - memcpy (new_script_info, script_info, sizeof (rcscript_info_t)); - list_add_tail (&new_script_info->node, &runlevel_info->entries); - } - - str_list_free (dir_list); - -no_entries: - list_add_tail (&runlevel_info->node, &runlevel_list); - } - - str_list_free (runlvl_list); - - return 0; - -error: - if (NULL != runlvl_list) - str_list_free (runlvl_list); - - return -1; -} - -runlevel_info_t * -get_runlevel_info (const char *runlevel) -{ - runlevel_info_t *info; - - if (!check_arg_str (runlevel)) - return NULL; - - list_for_each_entry (info, &runlevel_list, node) - { - if ((strlen (runlevel) == strlen (gbasename (info->dirname))) - && (0 == strncmp (runlevel, gbasename (info->dirname), - strlen (runlevel)))) - return info; - } - - return NULL; -} - -bool -is_runlevel (const char *runlevel) -{ - char *runlevel_dir = NULL; - int len; - - /* strlen (RUNLEVELS_DIR) + strlen (runlevel) + "/" + '\0' */ - len = strlen (RUNLEVELS_DIR) + strlen (runlevel) + 2; - runlevel_dir = xmalloc (sizeof (char) * len); - if (NULL == runlevel_dir) - return FALSE; - - snprintf (runlevel_dir, len, "%s/%s", RUNLEVELS_DIR, runlevel); - - if (is_dir (runlevel_dir, 0)) - return TRUE; - - return FALSE; -} - diff --git a/src/core/librcscripts/scripts.c b/src/core/librcscripts/scripts.c deleted file mode 100644 index 040bd8f..0000000 --- a/src/core/librcscripts/scripts.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * scripts.c - * - * Get info etc 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 <stddef.h> -#include <stdlib.h> -#include <string.h> - -#include "rcscripts.h" - -LIST_HEAD (rcscript_list); - -int -get_rcscripts (void) -{ - rcscript_info_t *info; - char **file_list = NULL; - char *rcscript; - char *confd_file = NULL; - int count; - - file_list = ls_dir (RCSCRIPTS_INITDDIR, 0); - if (NULL == file_list) - { - errno = ENOENT; - DBG_MSG ("'%s' is empty!\n", RCSCRIPTS_INITDDIR); - - return -1; - } - - str_list_for_each_item (file_list, rcscript, count) - { - /* Is it a file? */ - if (!(is_file (rcscript, 1)) - /* Do not process scripts, source or backup files. */ - || (CHECK_FILE_EXTENSION (rcscript, ".c")) - || (CHECK_FILE_EXTENSION (rcscript, ".bak")) - || (CHECK_FILE_EXTENSION (rcscript, "~"))) - { - DBG_MSG ("'%s' is not a valid rc-script!\n", gbasename (rcscript)); - } - else - { - regex_data_t tmp_data; - dyn_buf_t *dynbuf = NULL; - char *buf = NULL; - - dynbuf = new_dyn_buf_mmap_file (rcscript); - if (NULL == dynbuf) - { - DBG_MSG ("Could not open '%s' for reading!\n", - gbasename (rcscript)); - goto error; - } - - buf = read_line_dyn_buf (dynbuf); - free_dyn_buf (dynbuf); - if ((NULL == buf) && (0 != errno)) - goto error; - if (NULL == buf) - { - DBG_MSG ("'%s' is not a valid rc-script!\n", - gbasename (rcscript)); - continue; - } - - /* Check if it starts with '#!/sbin/runscript' */ - DO_REGEX (tmp_data, buf, "[ \t]*#![ \t]*/sbin/runscript[ \t]*.*", - check_error); - free (buf); - if (REGEX_FULL_MATCH != tmp_data.match) - { - DBG_MSG ("'%s' is not a valid rc-script!\n", - gbasename (rcscript)); - continue; - } - - /* We do not want rc-scripts ending in '.sh' */ - if (CHECK_FILE_EXTENSION (rcscript, ".sh")) - { - EWARN ("'%s' is invalid (should not end with '.sh')!\n", - gbasename (rcscript)); - continue; - } - - DBG_MSG ("Adding rc-script '%s' to list.\n", gbasename (rcscript)); - - info = xmalloc (sizeof (rcscript_info_t)); - if (NULL == info) - goto error; - - /* Copy the name */ - info->filename = xstrndup (rcscript, strlen (rcscript)); - if (NULL == info->filename) - goto loop_error; - - /* Get the modification time */ - info->mtime = get_mtime (rcscript, 1); - if (0 == info->mtime) - { - DBG_MSG ("Failed to get modification time for '%s'!\n", rcscript); - /* We do not care if it fails - we will pick up - * later if there is a problem with the file */ - } - - /* File name for the conf.d config file (if any) */ - confd_file = strcatpaths (RCSCRIPTS_CONFDDIR, gbasename (rcscript)); - if (NULL == confd_file) - { - DBG_MSG ("Failed to allocate temporary buffer!\n"); - goto loop_error; - } - - /* Get the modification time of the conf.d file - * (if any exists) */ - info->confd_mtime = get_mtime (confd_file, 1); - if (0 == info->confd_mtime) - { - DBG_MSG ("Failed to get modification time for '%s'!\n", - confd_file); - /* We do not care that it fails, as not all - * rc-scripts will have conf.d config files */ - } - - free (confd_file); - - list_add_tail (&info->node, &rcscript_list); - - continue; - -check_error: - free (buf); - goto error; - -loop_error: - if (NULL != info) - free (info->filename); - free (info); - - goto error; - } - } - - /* Final check if we have some entries */ - if (!check_strv (file_list)) - { - errno = ENOENT; - DBG_MSG ("No rc-scripts to parse!\n"); - goto error; - } - - str_list_free (file_list); - - return 0; - -error: - str_list_free (file_list); - - return -1; -} - -/* Returns 0 if we do not need to regen the cache file, else -1 with - * errno set if something went wrong */ -int -check_rcscripts_mtime (const char *cachefile) -{ - rcscript_info_t *info; - time_t cache_mtime; - time_t rc_conf_mtime; - time_t rc_confd_mtime; - - if (!check_arg_str (cachefile)) - return -1; - - cache_mtime = get_mtime (cachefile, 1); - if (0 == cache_mtime) - { - DBG_MSG ("Could not get modification time for cache file '%s'!\n", - cachefile); - return -1; - } - - /* Get and compare mtime for RC_CONF_FILE_NAME with that of cachefile */ - rc_conf_mtime = get_mtime (RC_CONF_FILE_NAME, 1); - if (rc_conf_mtime > cache_mtime) - { - DBG_MSG ("'%s' have a later modification time than '%s'.\n", - RC_CONF_FILE_NAME, cachefile); - return -1; - } - /* Get and compare mtime for RC_CONFD_FILE_NAME with that of cachefile */ - rc_confd_mtime = get_mtime (RC_CONFD_FILE_NAME, 1); - if (rc_confd_mtime > cache_mtime) - { - DBG_MSG ("'%s' have a later modification time than '%s'.\n", - RC_CONFD_FILE_NAME, cachefile); - return -1; - } - - /* Get and compare mtime for each rc-script and its conf.d config file - * with that of cachefile */ - list_for_each_entry (info, &rcscript_list, node) - { - if ((info->mtime > cache_mtime) || (info->confd_mtime > cache_mtime)) - { - DBG_MSG ("'%s' have a later modification time than '%s'.\n", - info->filename, cachefile); - return -1; - } - } - - return 0; -} - -rcscript_info_t * -get_rcscript_info (const char *scriptname) -{ - rcscript_info_t *info; - - if (!check_arg_str (scriptname)) - return NULL; - - list_for_each_entry (info, &rcscript_list, node) - { - if ((strlen (scriptname) == strlen (gbasename (info->filename))) - && (0 == strncmp (scriptname, gbasename (info->filename), - strlen (scriptname)))) - return info; - } - - return NULL; -} - diff --git a/src/core/librcscripts/simple-regex.c b/src/core/librcscripts/simple-regex.c deleted file mode 100644 index fc365de..0000000 --- a/src/core/librcscripts/simple-regex.c +++ /dev/null @@ -1,869 +0,0 @@ -/* - * simple_regex.c - * - * Simle regex library. - * - * 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$ - */ - -/* - * Some notes: - * - * - This is a very simple regex library (read: return a match if some string - * matches some regex). It is probably not POSIX (if there are a POSIX or - * other standard) compatible. - * - * - I primarily wrote it to _not_ use glibc type regex functions, in case we - * might want to use it in code that have to be linked agaist klibc, etc. - * - * - It really is not optimized in any way yet. - * - * - Supported operators are: - * - * '.', '?', '*', '+' - So called 'wildcards' - * '[a-z]', '[^a-z]' - Basic 'lists'. Note that 'a-z' just specify that - * it supports basic lists as well as sequences .. - * The '^' is for an inverted list of course. - * '^', '$' - The 'from start' and 'to end' operators. If these - * are not used at the start ('^') or end ('$') of the - * regex, they will be treated as normal characters - * (this of course exclude the use of '^' in a 'list'). - * - * - If an invalid argument was passed, the functions returns 0 with - * 'regex_data-match == 0' (no error with no match) rather than -1. It may - * not be consistant with other practices, but I personally do not feel it is - * a critical error for these types of functions, and there are debugging you - * can enable to verify that there are no such issues. - * - * - __somefunction() is usually a helper function for somefunction(). I guess - * recursion might be an alternative, but I try to avoid it. - * - * - In general if we are matching a 'wildcard' ('*', '+' or '?'), a 'word' - * (read: some part of the regex that do not contain a 'wildcard' or 'list') - * will have a greater 'weight' than the 'wildcard'. This means that we - * will only continue to evaluate the 'wildcard' until the following 'word' - * (if any) matches. Currently this do not hold true for a 'list' not - * followed by a 'wildcard' - I might fix this in future. - * - */ - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "rcscripts.h" - -/* Macro to check if a regex_data_t pointer is valid */ -#define CHECK_REGEX_DATA_P(_regex_data, _on_error) \ - do { \ - if ((NULL == _regex_data) \ - || (NULL == _regex_data->data) \ - /* We do not check for this, as it might still \ - * provide a match ('*' or '?' wildcard) */ \ - /* || (0 == strlen(_regex_data->data)) */ \ - || (NULL == _regex_data->regex) \ - || (0 == strlen(_regex_data->regex))) \ - { \ - errno = EINVAL; \ - DBG_MSG("Invalid argument passed!\n"); \ - goto _on_error; \ - } \ - } while (0) - -static size_t get_word (const char *regex, char **r_word); -static int match_word (regex_data_t * regex_data); -static size_t get_list_size (const char *regex); -static size_t get_list (const char *regex, char **r_list); -static int __match_list (regex_data_t * regex_data); -static int match_list (regex_data_t * regex_data); -static size_t get_wildcard (const char *regex, char *r_wildcard); -static int __match_wildcard (regex_data_t * regex_data, - int (*match_func) (regex_data_t * regex_data), - const char *regex); -static int match_wildcard (regex_data_t * regex_data); -static int __match (regex_data_t * regex_data); - -/* - * Return values for match_* functions - * - * 0 - There was no error. If there was a match, regex_data->match - * - will be > 0 (this is the definitive check - if not true, the - * - other values of the struct may be bogus), regex_data->count - * - will be the amount of data that was matched (might be 0 for - * - some wildcards), and regex_data->r_count will be > 0. - * - * -1 - An error occured. Check errno for more info. - * - */ - -size_t -get_word (const char *regex, char **r_word) -{ - char *r_list; - char *str_ptr; - size_t count = 0; - size_t tmp_count; - - if (!check_arg_str (regex)) - return 0; - - *r_word = xmalloc (strlen (regex) + 1); - if (NULL == r_word) - return 0; - - str_ptr = *r_word; - - while (strlen (regex) > 0) - { - switch (regex[0]) - { - case '*': - case '+': - case '?': - /* If its a wildcard, backup one step */ - *(--str_ptr) = '\0'; - count--; - return count; - case '[': - tmp_count = get_list (regex, &r_list); - free (r_list); - /* In theory should not happen, but you never know - * what may happen in future ... */ - if (-1 == tmp_count) - goto error; - - /* Bail if we have a list */ - if (tmp_count > 0) - { - str_ptr[0] = '\0'; - return count; - } - default: - *str_ptr++ = *regex++; - count++; - break; - } - } - - str_ptr[0] = '\0'; - - return count; - -error: - free (*r_word); - - return -1; -} - -int -match_word (regex_data_t * regex_data) -{ - char *data_p = regex_data->data; - char *r_word = NULL, *r_word_p; - size_t count = 0; - - CHECK_REGEX_DATA_P (regex_data, exit); - - count = get_word (regex_data->regex, &r_word); - if (-1 == count) - goto error; - if (0 == count) - goto exit; - r_word_p = r_word; - - while ((strlen (data_p) > 0) && (strlen (r_word_p) > 0)) - { - /* If 'r_word' is not 100% part of 'string', we do not have - * a match. If its a '.', it matches no matter what. */ - if ((data_p[0] != r_word_p[0]) && ('.' != r_word_p[0])) - { - count = 0; - goto exit; - } - - data_p++; - r_word_p++; - } - - /* If 'string' is shorter than 'r_word', we do not have a match */ - if ((0 == strlen (data_p)) && (0 < strlen (r_word_p))) - { - count = 0; - goto exit; - } - -exit: - /* Fill in our structure */ - if (0 == count) - regex_data->match = REGEX_NO_MATCH; - else if (strlen (regex_data->data) == count) - regex_data->match = REGEX_FULL_MATCH; - else - regex_data->match = REGEX_PARTIAL_MATCH; - if (regex_data->match != REGEX_NO_MATCH) - regex_data->where = regex_data->data; - else - regex_data->where = NULL; - regex_data->count = count; - regex_data->r_count = count; - - free (r_word); - return 0; - -error: - regex_data->match = REGEX_NO_MATCH; - - free (r_word); - return -1; -} - -size_t -get_list_size (const char *regex) -{ - size_t count = 0; - - if (!check_arg_str (regex)) - return 0; - - if ('[' != regex[0]) - { - errno = EINVAL; - DBG_MSG ("Invalid argument passed!\n"); - return 0; - } - - regex++; - - while ((strlen (regex) > 0) && (']' != regex[0])) - { - /* We have a sequence (x-y) */ - if (('-' == regex[0]) - && (']' != regex[1]) - && (strlen (regex) >= 2) && (regex[-1] < regex[1])) - { - /* Add current + diff in sequence */ - count += regex[1] - regex[-1]; - /* Take care of '-' and next char */ - regex += 2; - } - else - { - regex++; - count++; - } - } - - return count; -} - -size_t -get_list (const char *regex, char **r_list) -{ - char *buf = NULL; - size_t count = 0; - size_t size; - - if (!check_arg_str (regex)) - return 0; - - /* Bail if we do not have a list. Do not add debugging, as - * it is very noisy (used a lot when we call match_list() in - * __match() and match() to test for list matching) */ - if ('[' != regex[0]) - return 0; - - size = get_list_size (regex); - if (0 == size) - { - /* Should not be an issue, but just in case */ - DBG_MSG ("0 returned by get_list_size.\n"); - return 0; - } - - *r_list = xmalloc (size + 1); - if (NULL == *r_list) - return -1; - - buf = *r_list; - - /* Take care of '[' */ - regex++; - count++; - - while ((strlen (regex) > 0) && (']' != regex[0])) - { - /* We have a sequence (x-y) */ - if (('-' == regex[0]) - && (']' != regex[1]) - && (strlen (regex) >= 2) && (regex[-1] < regex[1])) - { - /* Fill in missing chars in sequence */ - while (buf[-1] < regex[1]) - { - buf[0] = (char) (buf[-1] + 1); - buf++; - /* We do not increase count */ - } - /* Take care of '-' and next char */ - count += 2; - regex += 2; - } - else - { - *buf++ = *regex++; - count++; - } - } - - buf[0] = '\0'; - /* Take care of ']' */ - count++; - - /* We do not have a list as it does not end in ']' */ - if (']' != regex[0]) - { - count = 0; - free (*r_list); - } - - return count; -} - -/* If the first is the '^' character, everything but the list is matched - * NOTE: We only evaluate _ONE_ data character at a time!! */ -int -__match_list (regex_data_t * regex_data) -{ - regex_data_t tmp_data; - char *data_p = regex_data->data; - char *list_p = regex_data->regex; - char test_regex[2] = { '\0', '\0' }; - int invert = 0; - int lmatch; - int retval; - - CHECK_REGEX_DATA_P (regex_data, failed); - - if ('^' == list_p[0]) - { - /* We need to invert the match */ - invert = 1; - /* Make sure '^' is not part of our list */ - list_p++; - } - - if (invert) - /* All should be a match if not in the list */ - lmatch = 1; - else - /* We only have a match if in the list */ - lmatch = 0; - - while (strlen (list_p) > 0) - { - test_regex[0] = list_p[0]; - - FILL_REGEX_DATA (tmp_data, data_p, test_regex); - retval = match_word (&tmp_data); - if (-1 == retval) - goto error; - - if (REGEX_MATCH (tmp_data)) - { - if (invert) - /* If we exclude the list from - * characters we try to match, we - * have a match until one of the - * list is found. */ - lmatch = 0; - else - /* If not, we have to keep looking - * until one from the list match - * before we have a match */ - lmatch = 1; - break; - } - list_p++; - } - - /* Fill in our structure */ - if (lmatch) - { - regex_data->match = REGEX_PARTIAL_MATCH; - regex_data->where = regex_data->data; - regex_data->count = 1; - /* This one is more cosmetic, as match_list() will - * do the right thing */ - regex_data->r_count = 0; /* strlen(regex_data->regex); */ - } - else - { -failed: - regex_data->match = REGEX_NO_MATCH; - regex_data->where = NULL; - regex_data->count = 0; - regex_data->r_count = 0; - } - - return 0; - -error: - regex_data->match = REGEX_NO_MATCH; - - return -1; -} - -int -match_list (regex_data_t * regex_data) -{ - regex_data_t tmp_data; - char *data_p = regex_data->data; - char *list_p = regex_data->regex; - char *r_list = NULL; - size_t r_count = 0; - int retval; - - CHECK_REGEX_DATA_P (regex_data, failed); - - r_count = get_list (list_p, &r_list); - if (-1 == r_count) - goto error; - if (0 == r_count) - goto failed; - - FILL_REGEX_DATA (tmp_data, data_p, &list_p[r_count - 1]); - retval = __match_wildcard (&tmp_data, __match_list, r_list); - if (-1 == retval) - goto error; - if (REGEX_MATCH (tmp_data)) - { - /* This should be 2 ('word' + 'wildcard'), so just remove - * the wildcard */ - tmp_data.r_count--; - goto exit; - } - - FILL_REGEX_DATA (tmp_data, data_p, r_list); - retval = __match_list (&tmp_data); - if (-1 == retval) - goto error; - if (REGEX_MATCH (tmp_data)) - goto exit; - -failed: - /* We will fill in regex_data below */ - tmp_data.match = REGEX_NO_MATCH; - tmp_data.where = NULL; - tmp_data.count = 0; - tmp_data.r_count = 0; - -exit: - /* Fill in our structure */ - regex_data->match = tmp_data.match; - regex_data->where = tmp_data.where; - regex_data->count = tmp_data.count; - if (regex_data->match != REGEX_NO_MATCH) - /* tmp_data.r_count for __match_wildcard will take care of the - * wildcard, and tmp_data.r_count for __match_list will be 0 */ - regex_data->r_count = r_count + tmp_data.r_count; - else - regex_data->r_count = 0; - - free (r_list); - return 0; - -error: - regex_data->match = REGEX_NO_MATCH; - - free (r_list); - return -1; -} - -size_t -get_wildcard (const char *regex, char *r_wildcard) -{ - if (!check_arg_str (regex)) - return 0; - - r_wildcard[0] = regex[0]; - r_wildcard[2] = '\0'; - - switch (regex[1]) - { - case '*': - case '+': - case '?': - r_wildcard[1] = regex[1]; - break; - default: - r_wildcard[0] = '\0'; - return 0; - } - - return strlen (r_wildcard); -} - -int -__match_wildcard (regex_data_t * regex_data, - int (*match_func) (regex_data_t * regex_data), - const char *regex) -{ - regex_data_t tmp_data; - char *data_p = regex_data->data; - char *wildcard_p = regex_data->regex; - char r_wildcard[3]; - size_t count = 0; - size_t r_count = 0; - int is_match = 0; - int retval; - - CHECK_REGEX_DATA_P (regex_data, exit); - - if (NULL == match_func) - { - errno = EINVAL; - DBG_MSG ("NULL match_func was passed!\n"); - goto exit; - } - - r_count = get_wildcard (wildcard_p, r_wildcard); - if (0 == r_count) - goto exit; - - FILL_REGEX_DATA (tmp_data, data_p, (char *) regex); - retval = match_func (&tmp_data); - if (-1 == retval) - goto error; - - switch (r_wildcard[1]) - { - case '*': - case '?': - /* '*' and '?' always matches */ - is_match = 1; - case '+': - /* We need to match all of them */ - do - { - /* If we have at least one match for '+', or none - * for '*' or '?', check if we have a word or list match. - * We do this because a word weights more than a wildcard */ - if ((strlen (wildcard_p) > 2) - && ((count > 0) - || ('*' == r_wildcard[1]) - || ('?' == r_wildcard[1]))) - { - regex_data_t tmp_data2; -#if 0 - printf ("data_p = %s, wildcard_p = %s\n", data_p, wildcard_p); -#endif - - FILL_REGEX_DATA (tmp_data2, data_p, &wildcard_p[2]); - retval = match (&tmp_data2); - if (-1 == retval) - goto error; - - if ( - /* '.' might be a special case ... */ - /* ('.' != wildcard_p[2]) && */ - ((REGEX_MATCH (tmp_data2)) - && (REGEX_FULL_MATCH == tmp_data2.match))) - { - goto exit; - } - } - - if (REGEX_MATCH (tmp_data)) - { - data_p += tmp_data.count; - count += tmp_data.count; - is_match = 1; - - FILL_REGEX_DATA (tmp_data, data_p, (char *) regex); - retval = match_func (&tmp_data); - if (-1 == retval) - goto error; - } - /* Only once for '?' */ - } - while ((REGEX_MATCH (tmp_data)) && ('?' != r_wildcard[1])); - - break; - default: - /* No wildcard */ - break; - } - -exit: - /* Fill in our structure */ - /* We can still have a match ('*' and '?'), although count == 0 */ - if ((0 == count) && (0 == is_match)) - regex_data->match = REGEX_NO_MATCH; - else if (strlen (regex_data->data) == count) - regex_data->match = REGEX_FULL_MATCH; - else - regex_data->match = REGEX_PARTIAL_MATCH; - if (regex_data->match != REGEX_NO_MATCH) - regex_data->where = regex_data->data; - else - regex_data->where = NULL; - regex_data->count = count; - regex_data->r_count = r_count; - - return 0; - -error: - regex_data->match = REGEX_NO_MATCH; - - return -1; -} - -int -match_wildcard (regex_data_t * regex_data) -{ - regex_data_t tmp_data; - char *data_p = regex_data->data; - char *wildcard_p = regex_data->regex; - char r_wildcard[3]; - size_t r_count; - int retval; - - CHECK_REGEX_DATA_P (regex_data, failed); - - /* Invalid wildcard - we need a character + a regex operator */ - if (strlen (wildcard_p) < 2) - goto failed; - - r_count = get_wildcard (wildcard_p, r_wildcard); - if (0 == r_count) - goto failed; - - /* Needed so that match_word() will not bail if it sees the wildcard */ - r_wildcard[1] = '\0'; - - FILL_REGEX_DATA (tmp_data, data_p, wildcard_p); - retval = __match_wildcard (&tmp_data, match_word, r_wildcard); - if (-1 == retval) - goto error; - if (REGEX_MATCH (tmp_data)) - goto exit; - -failed: - /* We will fill in regex_data below */ - tmp_data.match = REGEX_NO_MATCH; - tmp_data.where = NULL; - tmp_data.count = 0; - tmp_data.r_count = 0; - -exit: - /* Fill in our structure */ - regex_data->match = tmp_data.match; - regex_data->where = tmp_data.where; - regex_data->count = tmp_data.count; - regex_data->r_count = tmp_data.r_count; - - return 0; - -error: - regex_data->match = REGEX_NO_MATCH; - - return -1; -} - -int -__match (regex_data_t * regex_data) -{ - regex_data_t tmp_data; - char *data_p = regex_data->data; - char *regex_p = regex_data->regex; - size_t count = 0; - size_t r_count = 0; - int rmatch = 0; - int retval; - - CHECK_REGEX_DATA_P (regex_data, failed); - - while (strlen (regex_p) > 0) - { -#if 0 - printf ("data_p = '%s', regex_p = '%s'\n", data_p, regex_p); -#endif - - FILL_REGEX_DATA (tmp_data, data_p, regex_p); - retval = match_list (&tmp_data); - if (-1 == retval) - goto error; - if (REGEX_MATCH (tmp_data)) - goto have_match; - - FILL_REGEX_DATA (tmp_data, data_p, regex_p); - retval = match_wildcard (&tmp_data); - if (-1 == retval) - goto error; - if (REGEX_MATCH (tmp_data)) - goto have_match; - - FILL_REGEX_DATA (tmp_data, data_p, regex_p); - retval = match_word (&tmp_data); - if (-1 == retval) - goto error; - if (REGEX_MATCH (tmp_data)) - goto have_match; - - break; - -have_match: - data_p += tmp_data.count; - count += tmp_data.count; - regex_p += tmp_data.r_count; - r_count += tmp_data.r_count; - rmatch = 1; - - /* Check that we do not go out of bounds */ - if (((data_p - regex_data->data) > strlen (regex_data->data)) - || ((regex_p - regex_data->regex) > strlen (regex_data->regex))) - goto failed; - } - - /* We could not match the whole regex (data too short?) */ - if (0 != strlen (regex_p)) - goto failed; - - goto exit; - -failed: - /* We will fill in regex_data below */ - count = 0; - r_count = 0; - rmatch = 0; - -exit: - /* Fill in our structure */ - /* We can still have a match ('*' and '?'), although count == 0 */ - if ((0 == count) && (0 == rmatch)) - regex_data->match = REGEX_NO_MATCH; - else if (strlen (regex_data->data) == count) - regex_data->match = REGEX_FULL_MATCH; - else - regex_data->match = REGEX_PARTIAL_MATCH; - if (regex_data->match != REGEX_NO_MATCH) - regex_data->where = regex_data->data; - else - regex_data->where = NULL; - regex_data->count = count; - regex_data->r_count = r_count; - - return 0; - -error: - regex_data->match = REGEX_NO_MATCH; - - return -1; -} - -int -match (regex_data_t * regex_data) -{ - regex_data_t tmp_data; - char *data_p = regex_data->data; - char *regex_p; - char *buf = NULL; - int from_start = 0; - int to_end = 0; - int retval; - - CHECK_REGEX_DATA_P (regex_data, failed); - - /* We might be modifying regex_p, so make a copy */ - buf = xstrndup (regex_data->regex, strlen (regex_data->regex)); - if (NULL == buf) - goto error; - - regex_p = buf; - - /* Should we only match from the start? */ - if ('^' == regex_p[0]) - { - regex_p++; - from_start = 1; - } - - /* Should we match up to the end? */ - if ('$' == regex_p[strlen (regex_p) - 1]) - { - regex_p[strlen (regex_p) - 1] = '\0'; - to_end = 1; - } - - do - { - FILL_REGEX_DATA (tmp_data, data_p, regex_p); - retval = __match (&tmp_data); - if (-1 == retval) - goto error; - } - while ((strlen (data_p++) > 0) - && (!REGEX_MATCH (tmp_data)) && (0 == from_start)); - - /* Compensate for above extra inc */ - data_p--; - - /* Fill in our structure */ - if (REGEX_MATCH (tmp_data)) - { - /* Check if we had an '$' at the end of the regex, and - * verify that we still have a match */ - if ((1 == to_end) && (tmp_data.count != strlen (data_p))) - { - goto failed; - } - - if ((data_p == regex_data->data) - && (tmp_data.match == REGEX_FULL_MATCH)) - regex_data->match = REGEX_FULL_MATCH; - else - regex_data->match = REGEX_PARTIAL_MATCH; - regex_data->where = data_p; - regex_data->count = tmp_data.count; - regex_data->r_count = tmp_data.r_count; - if (1 == from_start) - regex_data->r_count++; - if (1 == to_end) - regex_data->r_count++; - } - else - { -failed: - regex_data->match = REGEX_NO_MATCH; - regex_data->where = NULL; - regex_data->count = 0; - regex_data->r_count = 0; - } - - free (buf); - - return 0; - -error: - regex_data->match = REGEX_NO_MATCH; - free (buf); - - return -1; -} |