1 const char actions_rcs[] = "$Id: actions.c,v 1.13 2001/09/16 15:47:37 jongfoster Exp $";
2 /*********************************************************************
4 * File : $Source: /cvsroot/ijbswa/current/actions.c,v $
6 * Purpose : Declares functions to work with actions files
7 * Functions declared include: FIXME
9 * Copyright : Written by and Copyright (C) 2001 the SourceForge
10 * IJBSWA team. http://ijbswa.sourceforge.net
12 * Based on the Internet Junkbuster originally written
13 * by and Copyright (C) 1997 Anonymous Coders and
14 * Junkbusters Corporation. http://www.junkbusters.com
16 * This program is free software; you can redistribute it
17 * and/or modify it under the terms of the GNU General
18 * Public License as published by the Free Software
19 * Foundation; either version 2 of the License, or (at
20 * your option) any later version.
22 * This program is distributed in the hope that it will
23 * be useful, but WITHOUT ANY WARRANTY; without even the
24 * implied warranty of MERCHANTABILITY or FITNESS FOR A
25 * PARTICULAR PURPOSE. See the GNU General Public
26 * License for more details.
28 * The GNU General Public License should be included with
29 * this file. If not, you can view it at
30 * http://www.gnu.org/copyleft/gpl.html
31 * or write to the Free Software Foundation, Inc., 59
32 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 * Revision 1.13 2001/09/16 15:47:37 jongfoster
37 * First version of CGI-based edit interface. This is very much a
38 * work-in-progress, and you can't actually use it to edit anything
39 * yet. You must #define FEATURE_CGI_EDIT_ACTIONS for these changes
42 * Revision 1.12 2001/09/16 13:21:27 jongfoster
43 * Changes to use new list functions.
45 * Revision 1.11 2001/09/14 00:17:32 jongfoster
46 * Tidying up memory allocation. New function init_action().
48 * Revision 1.10 2001/09/10 10:14:34 oes
49 * Removing unused variable
51 * Revision 1.9 2001/07/30 22:08:36 jongfoster
52 * Tidying up #defines:
53 * - All feature #defines are now of the form FEATURE_xxx
54 * - Permanently turned off WIN_GUI_EDIT
55 * - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
57 * Revision 1.8 2001/06/29 13:19:52 oes
58 * Removed logentry from cancelled commit
60 * Revision 1.7 2001/06/09 10:55:28 jongfoster
61 * Changing BUFSIZ ==> BUFFER_SIZE
63 * Revision 1.6 2001/06/07 23:04:34 jongfoster
64 * Made get_actions() static.
66 * Revision 1.5 2001/06/03 19:11:48 oes
67 * adapted to new enlist_unique arg format
69 * Revision 1.4 2001/06/01 20:03:42 jongfoster
70 * Better memory management - current_action->strings[] now
71 * contains copies of the strings, not the original.
73 * Revision 1.3 2001/06/01 18:49:17 jongfoster
74 * Replaced "list_share" with "list" - the tiny memory gain was not
75 * worth the extra complexity.
77 * Revision 1.2 2001/05/31 21:40:00 jongfoster
78 * Removing some commented out, obsolete blocks of code.
80 * Revision 1.1 2001/05/31 21:16:46 jongfoster
81 * Moved functions to process the action list into this new file.
84 *********************************************************************/
99 #ifdef FEATURE_CGI_EDIT_ACTIONS
101 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
103 const char actions_h_rcs[] = ACTIONS_H_VERSION;
106 /* Turn off everything except forwarding */
107 /* This structure is used to hold user-defined aliases */
111 struct action_spec action[1];
112 struct action_alias * next;
117 * Must declare this in this file for the above structure.
119 static int get_actions (char *line,
120 struct action_alias * alias_list,
121 struct action_spec *cur_action);
124 * We need the main list of options.
126 * First, we need a way to tell between boolean, string, and multi-string
127 * options. For string and multistring options, we also need to be
128 * able to tell the difference between a "+" and a "-". (For bools,
129 * the "+"/"-" information is encoded in "add" and "mask"). So we use
130 * an enumerated type (well, the preprocessor equivalent). Here are
133 #define AV_NONE 0 /* +opt -opt */
134 #define AV_ADD_STRING 1 /* +stropt{string} */
135 #define AV_REM_STRING 2 /* -stropt */
136 #define AV_ADD_MULTI 3 /* +multiopt{string} +multiopt{string2} */
137 #define AV_REM_MULTI 4 /* -multiopt{string} -multiopt{*} */
140 * We need a structure to hold the name, flag changes,
141 * type, and string index.
146 unsigned mask; /* a bit set to "0" = remove action */
147 unsigned add; /* a bit set to "1" = add action */
148 int takes_value; /* an AV_... constant */
149 int index; /* index into strings[] or multi[] */
153 * And with those building blocks in place, here's the array.
155 static const struct action_name action_names[] =
158 * Well actually there's no data here - it's in actionlist.h
159 * This keeps it together to make it easy to change.
161 * Here's the macros used to format it:
163 #define DEFINE_ACTION_MULTI(name,index) \
164 { "+" name, ACTION_MASK_ALL, 0, AV_ADD_MULTI, index }, \
165 { "-" name, ACTION_MASK_ALL, 0, AV_REM_MULTI, index },
166 #define DEFINE_ACTION_STRING(name,flag,index) \
167 { "+" name, ACTION_MASK_ALL, flag, AV_ADD_STRING, index }, \
168 { "-" name, ~flag, 0, AV_REM_STRING, index },
169 #define DEFINE_ACTION_BOOL(name,flag) \
170 { "+" name, ACTION_MASK_ALL, flag }, \
171 { "-" name, ~flag, 0 },
172 #define DEFINE_ACTION_ALIAS 1 /* Want aliases please */
174 #include "actionlist.h"
176 #undef DEFINE_ACTION_MULTI
177 #undef DEFINE_ACTION_STRING
178 #undef DEFINE_ACTION_BOOL
179 #undef DEFINE_ACTION_ALIAS
181 { NULL, 0, 0 } /* End marker */
185 /*********************************************************************
187 * Function : merge_actions
189 * Description : Merge two actions together.
190 * Similar to "cur_action += new_action".
193 * 1 : cur_action = Current actions, to modify.
194 * 2 : new_action = Action to add.
198 *********************************************************************/
199 void merge_actions (struct action_spec *dest,
200 const struct action_spec *src)
204 dest->mask &= src->mask;
205 dest->add &= src->mask;
206 dest->add |= src->add;
208 for (i = 0; i < ACTION_STRING_COUNT; i++)
210 char * str = src->string[i];
213 freez(dest->string[i]);
214 dest->string[i] = strdup(str);
218 for (i = 0; i < ACTION_MULTI_COUNT; i++)
220 if (src->multi_remove_all[i])
222 /* Remove everything from dest */
223 list_remove_all(dest->multi_remove[i]);
224 dest->multi_remove_all[i] = 1;
226 list_duplicate(dest->multi_add[i], src->multi_add[i]);
228 else if (dest->multi_remove_all[i])
231 * dest already removes everything, so we only need to worry
234 list_remove_list(dest->multi_add[i], src->multi_remove[i]);
235 list_append_list_unique(dest->multi_add[i], src->multi_add[i]);
239 /* No "remove all"s to worry about. */
240 list_remove_list(dest->multi_add[i], src->multi_remove[i]);
241 list_append_list_unique(dest->multi_remove[i], src->multi_remove[i]);
242 list_append_list_unique(dest->multi_add[i], src->multi_add[i]);
248 /*********************************************************************
250 * Function : copy_action
252 * Description : Copy an action_specs.
253 * Similar to "cur_action = new_action".
254 * Note that dest better not contain valid data
255 * - it's overwritten, not freed.
258 * 1 : dest = Destination of copy.
259 * 2 : src = Source for copy.
263 *********************************************************************/
264 void copy_action (struct action_spec *dest,
265 const struct action_spec *src)
269 memset(dest, '\0', sizeof(*dest));
271 dest->mask = src->mask;
272 dest->add = src->add;
274 for (i = 0; i < ACTION_STRING_COUNT; i++)
276 char * str = src->string[i];
277 dest->string[i] = (str ? strdup(str) : NULL);
280 for (i = 0; i < ACTION_MULTI_COUNT; i++)
282 dest->multi_remove_all[i] = src->multi_remove_all[i];
283 list_duplicate(dest->multi_remove[i], src->multi_remove[i]);
284 list_duplicate(dest->multi_add[i], src->multi_add[i]);
289 /*********************************************************************
291 * Function : free_action
293 * Description : Destroy an action_spec. Frees memory used by it,
294 * except for the memory used by the struct action_spec
298 * 1 : src = Source to free.
302 *********************************************************************/
303 void free_action (struct action_spec *src)
307 for (i = 0; i < ACTION_STRING_COUNT; i++)
309 freez(src->string[i]);
312 for (i = 0; i < ACTION_MULTI_COUNT; i++)
314 destroy_list(src->multi_remove[i]);
315 destroy_list(src->multi_add[i]);
318 memset(src, '\0', sizeof(*src));
322 /*********************************************************************
324 * Function : get_action_token
326 * Description : Parses a line for the first action.
327 * Modifies it's input array, doesn't allocate memory.
329 * *line=" +abc{def} -ghi "
336 * 1 : line = [in] The line containing the action.
337 * [out] Start of next action on line, or
338 * NULL if we reached the end of line before
339 * we found an action.
340 * 2 : name = [out] Start of action name, null
341 * terminated. NULL on EOL
342 * 3 : value = [out] Start of action value, null
343 * terminated. NULL if none or EOL.
346 * nonzero => Mismatched {} (line was trashed anyway)
348 *********************************************************************/
349 int get_action_token(char **line, char **name, char **value)
354 /* set default returns */
359 /* Eat any leading whitespace */
360 while ((*str == ' ') || (*str == '\t'))
372 /* null name, just value is prohibited */
379 while (((ch = *str) != '\0') &&
380 (ch != ' ') && (ch != '\t') && (ch != '{'))
396 /* EOL - be careful not to run off buffer */
401 /* More to parse next time. */
410 str = strchr(str, '}');
428 /*********************************************************************
430 * Function : get_actions
432 * Description : Parses a list of actions.
435 * 1 : line = The string containing the actions.
436 * Will be written to by this function.
437 * 2 : aliases = Custom alias list, or NULL for none.
438 * 3 : cur_action = Where to store the action. Caller
442 * nonzero => Error (line was trashed anyway)
444 *********************************************************************/
445 static int get_actions(char *line,
446 struct action_alias * alias_list,
447 struct action_spec *cur_action)
449 init_action(cur_action);
450 cur_action->mask = ACTION_MASK_ALL;
454 char * option = NULL;
457 if (get_action_token(&line, &option, &value))
464 /* handle option in 'option' */
466 /* Check for standard action name */
467 const struct action_name * action = action_names;
469 while ( (action->name != NULL) && (0 != strcmpic(action->name, option)) )
473 if (action->name != NULL)
476 cur_action->mask &= action->mask;
477 cur_action->add &= action->mask;
478 cur_action->add |= action->add;
480 switch (action->takes_value)
483 /* ignore any option. */
487 /* add single string. */
489 if ((value == NULL) || (*value == '\0'))
493 /* FIXME: should validate option string here */
494 freez (cur_action->string[action->index]);
495 cur_action->string[action->index] = strdup(value);
500 /* remove single string. */
502 freez (cur_action->string[action->index]);
507 /* append multi string. */
509 struct list * remove = cur_action->multi_remove[action->index];
510 struct list * add = cur_action->multi_add[action->index];
512 if ((value == NULL) || (*value == '\0'))
517 list_remove_item(remove, value);
518 enlist_unique(add, value, 0);
523 /* remove multi string. */
525 struct list * remove = cur_action->multi_remove[action->index];
526 struct list * add = cur_action->multi_add[action->index];
528 if ( (value == NULL) || (*value == '\0')
529 || ((*value == '*') && (value[1] == '\0')) )
532 * no option, or option == "*".
536 list_remove_all(remove);
537 list_remove_all(add);
538 cur_action->multi_remove_all[action->index] = 1;
542 /* Valid option - remove only 1 option */
544 if ( !cur_action->multi_remove_all[action->index] )
546 /* there isn't a catch-all in the remove list already */
547 enlist_unique(remove, value, 0);
549 list_remove_item(add, value);
554 /* Shouldn't get here unless there's memory corruption. */
560 /* try user aliases. */
561 const struct action_alias * alias = alias_list;
563 while ( (alias != NULL) && (0 != strcmpic(alias->name, option)) )
570 merge_actions(cur_action, alias->action);
574 /* Bad action name */
585 /*********************************************************************
587 * Function : actions_to_text
589 * Description : Converts a actionsfile entry from numeric form
590 * ("mask" and "add") to text.
593 * 1 : mask = As from struct url_actions
594 * 2 : add = As from struct url_actions
596 * Returns : A string. Caller must free it.
598 *********************************************************************/
599 char * actions_to_text(struct action_spec *action)
601 unsigned mask = action->mask;
602 unsigned add = action->add;
603 char * result = strdup("");
604 struct list_entry * lst;
606 /* sanity - prevents "-feature +feature" */
610 #define DEFINE_ACTION_BOOL(__name, __bit) \
611 if (!(mask & __bit)) \
613 result = strsav(result, " -" __name); \
615 else if (add & __bit) \
617 result = strsav(result, " +" __name); \
620 #define DEFINE_ACTION_STRING(__name, __bit, __index) \
621 if (!(mask & __bit)) \
623 result = strsav(result, " -" __name); \
625 else if (add & __bit) \
627 result = strsav(result, " +" __name "{"); \
628 result = strsav(result, action->string[__index]); \
629 result = strsav(result, "}"); \
632 #define DEFINE_ACTION_MULTI(__name, __index) \
633 if (action->multi_remove_all[__index]) \
635 result = strsav(result, " -" __name "{*}"); \
639 lst = action->multi_remove[__index]->first; \
642 result = strsav(result, " -" __name "{"); \
643 result = strsav(result, lst->str); \
644 result = strsav(result, "}"); \
648 lst = action->multi_add[__index]->first; \
651 result = strsav(result, " +" __name "{"); \
652 result = strsav(result, lst->str); \
653 result = strsav(result, "}"); \
657 #define DEFINE_ACTION_ALIAS 0 /* No aliases for output */
659 #include "actionlist.h"
661 #undef DEFINE_ACTION_MULTI
662 #undef DEFINE_ACTION_STRING
663 #undef DEFINE_ACTION_BOOL
664 #undef DEFINE_ACTION_ALIAS
670 #ifdef FEATURE_CGI_EDIT_ACTIONS
671 /*********************************************************************
673 * Function : actions_to_html
675 * Description : Converts a actionsfile entry from numeric form
676 * ("mask" and "add") to a <br>-seperated HTML string.
679 * 1 : mask = As from struct url_actions
680 * 2 : add = As from struct url_actions
682 * Returns : A string. Caller must free it.
684 *********************************************************************/
685 char * actions_to_html(struct action_spec *action)
687 unsigned mask = action->mask;
688 unsigned add = action->add;
689 char * result = strdup("");
691 struct list_entry * lst;
693 /* sanity - prevents "-feature +feature" */
697 #define DEFINE_ACTION_BOOL(__name, __bit) \
698 if (!(mask & __bit)) \
700 result = strsav(result, "\n<br>-" __name); \
702 else if (add & __bit) \
704 result = strsav(result, "\n<br>+" __name); \
707 #define DEFINE_ACTION_STRING(__name, __bit, __index) \
708 if (!(mask & __bit)) \
710 result = strsav(result, "\n<br>-" __name); \
712 else if (add & __bit) \
714 result = strsav(result, "\n<br>+" __name "{"); \
715 enc_str = html_encode(action->string[__index]);\
716 result = strsav(result, enc_str); \
718 result = strsav(result, "}"); \
721 #define DEFINE_ACTION_MULTI(__name, __index) \
722 if (action->multi_remove_all[__index]) \
724 result = strsav(result, "\n<br>-" __name "{*}"); \
728 lst = action->multi_remove[__index]->first; \
731 result = strsav(result, "\n<br>-" __name "{");\
732 enc_str = html_encode(lst->str); \
733 result = strsav(result, enc_str); \
735 result = strsav(result, "}"); \
739 lst = action->multi_add[__index]->first; \
742 result = strsav(result, "\n<br>+" __name "{"); \
743 result = strsav(result, lst->str); \
744 result = strsav(result, "}"); \
748 #define DEFINE_ACTION_ALIAS 0 /* No aliases for output */
750 #include "actionlist.h"
752 #undef DEFINE_ACTION_MULTI
753 #undef DEFINE_ACTION_STRING
754 #undef DEFINE_ACTION_BOOL
755 #undef DEFINE_ACTION_ALIAS
757 /* trim leading <br> */
758 if (result && *result)
761 result = strdup(result + 5);
767 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
770 /*********************************************************************
772 * Function : current_actions_to_text
774 * Description : Converts a actionsfile entry to text.
777 * 1 : action = Action
779 * Returns : A string. Caller must free it.
781 *********************************************************************/
782 char * current_action_to_text(struct current_action_spec *action)
784 unsigned flags = action->flags;
785 char * result = strdup("");
786 struct list_entry * lst;
788 #define DEFINE_ACTION_BOOL(__name, __bit) \
791 result = strsav(result, " +" __name); \
795 result = strsav(result, " -" __name); \
798 #define DEFINE_ACTION_STRING(__name, __bit, __index) \
801 result = strsav(result, " +" __name "{"); \
802 result = strsav(result, action->string[__index]); \
803 result = strsav(result, "}"); \
807 result = strsav(result, " -" __name); \
810 #define DEFINE_ACTION_MULTI(__name, __index) \
811 lst = action->multi[__index]->first; \
814 result = strsav(result, " -" __name); \
820 result = strsav(result, " +" __name "{"); \
821 result = strsav(result, lst->str); \
822 result = strsav(result, "}"); \
827 #define DEFINE_ACTION_ALIAS 0 /* No aliases for output */
829 #include "actionlist.h"
831 #undef DEFINE_ACTION_MULTI
832 #undef DEFINE_ACTION_STRING
833 #undef DEFINE_ACTION_BOOL
834 #undef DEFINE_ACTION_ALIAS
840 /*********************************************************************
842 * Function : init_current_action
844 * Description : Zero out an action.
847 * 1 : dest = An uninitialized current_action_spec.
851 *********************************************************************/
852 void init_current_action (struct current_action_spec *dest)
854 memset(dest, '\0', sizeof(*dest));
856 dest->flags = ACTION_MOST_COMPATIBLE;
860 /*********************************************************************
862 * Function : init_action
864 * Description : Zero out an action.
867 * 1 : dest = An uninitialized action_spec.
871 *********************************************************************/
872 void init_action (struct action_spec *dest)
874 memset(dest, '\0', sizeof(*dest));
878 /*********************************************************************
880 * Function : merge_current_action
882 * Description : Merge two actions together.
883 * Similar to "dest += src".
884 * Differences between this and merge_actions()
885 * is that this one doesn't allocate memory for
886 * strings (so "src" better be in memory for at least
887 * as long as "dest" is, and you'd better free
888 * "dest" using "free_current_action").
889 * Also, there is no mask or remove lists in dest.
890 * (If we're applying it to a URL, we don't need them)
893 * 1 : dest = Current actions, to modify.
894 * 2 : src = Action to add.
898 *********************************************************************/
899 void merge_current_action (struct current_action_spec *dest,
900 const struct action_spec *src)
904 dest->flags &= src->mask;
905 dest->flags |= src->add;
907 for (i = 0; i < ACTION_STRING_COUNT; i++)
909 char * str = src->string[i];
912 freez(dest->string[i]);
913 dest->string[i] = strdup(str);
917 for (i = 0; i < ACTION_MULTI_COUNT; i++)
919 if (src->multi_remove_all[i])
921 /* Remove everything from dest, then add src->multi_add */
922 list_duplicate(dest->multi[i], src->multi_add[i]);
926 list_remove_list(dest->multi[i], src->multi_remove[i]);
927 list_append_list_unique(dest->multi[i], src->multi_add[i]);
933 /*********************************************************************
935 * Function : free_current_action
937 * Description : Free memory used by a current_action_spec.
938 * Does not free the current_action_spec itself.
941 * 1 : src = Source to free.
945 *********************************************************************/
946 void free_current_action (struct current_action_spec *src)
950 for (i = 0; i < ACTION_STRING_COUNT; i++)
952 freez(src->string[i]);
955 for (i = 0; i < ACTION_MULTI_COUNT; i++)
957 destroy_list(src->multi[i]);
960 memset(src, '\0', sizeof(*src));
964 /*********************************************************************
966 * Function : unload_actions_file
968 * Description : Unloads an actions module.
971 * 1 : file_data = the data structure associated with the
976 *********************************************************************/
977 void unload_actions_file(void *file_data)
979 struct url_actions * next;
980 struct url_actions * cur = (struct url_actions *)file_data;
985 free_action(cur->action);
993 /*********************************************************************
995 * Function : load_actions_file
997 * Description : Read and parse a action file and add to files
1001 * 1 : csp = Current client state (buffers, headers, etc...)
1003 * Returns : 0 => Ok, everything else is an error.
1005 *********************************************************************/
1006 int load_actions_file(struct client_state *csp)
1008 static struct file_list *current_actions_file = NULL;
1012 struct url_actions *last_perm;
1013 struct url_actions *perm;
1014 char buf[BUFFER_SIZE];
1015 struct file_list *fs;
1016 #define MODE_START_OF_FILE 1
1017 #define MODE_ACTIONS 2
1018 #define MODE_ALIAS 3
1019 int mode = MODE_START_OF_FILE;
1020 struct action_spec cur_action[1];
1021 struct action_alias * alias_list = NULL;
1023 init_action(cur_action);
1025 if (!check_file_changed(current_actions_file, csp->config->actions_file, &fs))
1027 /* No need to load */
1030 csp->actions_list = current_actions_file;
1036 log_error(LOG_LEVEL_FATAL, "can't load actions file '%s': error finding file: %E",
1037 csp->config->actions_file);
1038 return 1; /* never get here */
1041 fs->f = last_perm = (struct url_actions *)zalloc(sizeof(*last_perm));
1042 if (last_perm == NULL)
1044 log_error(LOG_LEVEL_FATAL, "can't load actions file '%s': out of memory!",
1045 csp->config->actions_file);
1046 return 1; /* never get here */
1049 if ((fp = fopen(csp->config->actions_file, "r")) == NULL)
1051 log_error(LOG_LEVEL_FATAL, "can't load actions file '%s': error opening file: %E",
1052 csp->config->actions_file);
1053 return 1; /* never get here */
1056 while (read_config_line(buf, sizeof(buf), fp) != NULL)
1060 /* It's a header block */
1063 /* It's {{settings}} or {{alias}} */
1064 int len = strlen(buf);
1065 char * start = buf + 2;
1066 char * end = buf + len - 1;
1067 if ((len < 5) || (*end-- != '}') || (*end-- != '}'))
1071 log_error(LOG_LEVEL_FATAL,
1072 "can't load actions file '%s': invalid line: %s",
1073 csp->config->actions_file, buf);
1074 return 1; /* never get here */
1077 /* Trim leading and trailing whitespace. */
1085 log_error(LOG_LEVEL_FATAL,
1086 "can't load actions file '%s': invalid line: {{ }}",
1087 csp->config->actions_file);
1088 return 1; /* never get here */
1091 if (0 == strcmpic(start, "alias"))
1093 /* it's an {{alias}} block */
1099 /* invalid {{something}} block */
1101 log_error(LOG_LEVEL_FATAL,
1102 "can't load actions file '%s': invalid line: {{%s}}",
1103 csp->config->actions_file, start);
1104 return 1; /* never get here */
1109 /* It's an actions block */
1111 char actions_buf[BUFFER_SIZE];
1115 mode = MODE_ACTIONS;
1117 /* free old action */
1118 free_action(cur_action);
1121 strcpy(actions_buf, buf + 1);
1123 /* check we have a trailing } and then trim it */
1124 end = actions_buf + strlen(actions_buf) - 1;
1129 log_error(LOG_LEVEL_FATAL,
1130 "can't load actions file '%s': invalid line: %s",
1131 csp->config->actions_file, buf);
1132 return 1; /* never get here */
1136 /* trim any whitespace immediately inside {} */
1139 if (*actions_buf == '\0')
1143 log_error(LOG_LEVEL_FATAL,
1144 "can't load actions file '%s': invalid line: %s",
1145 csp->config->actions_file, buf);
1146 return 1; /* never get here */
1149 if (get_actions(actions_buf, alias_list, cur_action))
1153 log_error(LOG_LEVEL_FATAL,
1154 "can't load actions file '%s': invalid line: %s",
1155 csp->config->actions_file, buf);
1156 return 1; /* never get here */
1160 else if (mode == MODE_ALIAS)
1162 /* define an alias */
1163 char actions_buf[BUFFER_SIZE];
1164 struct action_alias * new_alias;
1166 char * start = strchr(buf, '=');
1169 if ((start == NULL) || (start == buf))
1171 log_error(LOG_LEVEL_FATAL,
1172 "can't load actions file '%s': invalid alias line: %s",
1173 csp->config->actions_file, buf);
1174 return 1; /* never get here */
1177 if ((new_alias = zalloc(sizeof(*new_alias))) == NULL)
1180 log_error(LOG_LEVEL_FATAL,
1181 "can't load actions file '%s': out of memory!",
1182 csp->config->actions_file);
1183 return 1; /* never get here */
1186 /* Eat any the whitespace before the '=' */
1188 while ((*end == ' ') || (*end == '\t'))
1191 * we already know we must have at least 1 non-ws char
1192 * at start of buf - no need to check
1198 /* Eat any the whitespace after the '=' */
1200 while ((*start == ' ') || (*start == '\t'))
1206 log_error(LOG_LEVEL_FATAL,
1207 "can't load actions file '%s': invalid alias line: %s",
1208 csp->config->actions_file, buf);
1209 return 1; /* never get here */
1212 new_alias->name = strdup(buf);
1214 strcpy(actions_buf, start);
1216 if (get_actions(actions_buf, alias_list, new_alias->action))
1220 log_error(LOG_LEVEL_FATAL,
1221 "can't load actions file '%s': invalid alias line: %s = %s",
1222 csp->config->actions_file, buf, start);
1223 return 1; /* never get here */
1227 new_alias->next = alias_list;
1228 alias_list = new_alias;
1230 else if (mode == MODE_ACTIONS)
1232 /* it's a URL pattern */
1234 /* allocate a new node */
1235 if ((perm = zalloc(sizeof(*perm))) == NULL)
1238 log_error(LOG_LEVEL_FATAL,
1239 "can't load actions file '%s': out of memory!",
1240 csp->config->actions_file);
1241 return 1; /* never get here */
1245 copy_action (perm->action, cur_action);
1247 /* Save the URL pattern */
1248 if (create_url_spec(perm->url, buf))
1251 log_error(LOG_LEVEL_FATAL,
1252 "can't load actions file '%s': cannot create URL pattern from: %s",
1253 csp->config->actions_file, buf);
1254 return 1; /* never get here */
1257 /* add it to the list */
1258 last_perm->next = perm;
1261 else if (mode == MODE_START_OF_FILE)
1263 /* oops - please have a {} line as 1st line in file. */
1265 log_error(LOG_LEVEL_FATAL,
1266 "can't load actions file '%s': first line is invalid: %s",
1267 csp->config->actions_file, buf);
1268 return 1; /* never get here */
1272 /* How did we get here? This is impossible! */
1274 log_error(LOG_LEVEL_FATAL,
1275 "can't load actions file '%s': INTERNAL ERROR - mode = %d",
1276 csp->config->actions_file, mode);
1277 return 1; /* never get here */
1283 free_action(cur_action);
1285 while (alias_list != NULL)
1287 struct action_alias * next = alias_list->next;
1288 freez((char *)alias_list->name);
1289 free_action(alias_list->action);
1294 /* the old one is now obsolete */
1295 if (current_actions_file)
1297 current_actions_file->unloader = unload_actions_file;
1300 fs->next = files->next;
1302 current_actions_file = fs;
1306 csp->actions_list = fs;