From 0e74f780545b1aa8f6a5277b3cfdc9887c37ed5e Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Wed, 8 Jun 2011 17:27:42 +0200 Subject: split libreport to a separate package --- src/include/Makefile.am | 10 +- src/include/abrtlib.h | 207 +------------------------------------- src/include/report/dump_dir.h | 80 --------------- src/include/report/event_config.h | 107 -------------------- src/include/report/problem_data.h | 99 ------------------ src/include/report/report.h | 42 -------- src/include/report/run_event.h | 82 --------------- 7 files changed, 3 insertions(+), 624 deletions(-) delete mode 100644 src/include/report/dump_dir.h delete mode 100644 src/include/report/event_config.h delete mode 100644 src/include/report/problem_data.h delete mode 100644 src/include/report/report.h delete mode 100644 src/include/report/run_event.h (limited to 'src/include') diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 4d31d1a9..357debd7 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -1,12 +1,6 @@ -libreport_includedir = $(includedir)/report -libreport_include_HEADERS = \ - report/problem_data.h \ - report/dump_dir.h \ - report/run_event.h \ - report/event_config.h \ - report/report.h +libabrt_includedir = \ + $(includedir)/abrt -libabrt_includedir = $(includedir)/abrt libabrt_include_HEADERS = \ abrtlib.h \ abrt_types.h \ diff --git a/src/include/abrtlib.h b/src/include/abrtlib.h index 1e68a661..52e05fa2 100644 --- a/src/include/abrtlib.h +++ b/src/include/abrtlib.h @@ -71,19 +71,8 @@ int vdprintf(int d, const char *format, va_list ap); #undef ARRAY_SIZE #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0]))) -#include "xfuncs.h" -#include "logging.h" -#include "read_write.h" -#include "strbuf.h" -#include "hash_sha1.h" -#include "parse_options.h" - -#include "abrt_problem_data.h" -#include "abrt_types.h" -#include "dump_dir.h" +#include #include "hooklib.h" -#include "run_event.h" -#include "event_config.h" #include "abrt_conf.h" @@ -91,201 +80,7 @@ int vdprintf(int d, const char *format, va_list ap); extern "C" { #endif -#define prefixcmp abrt_prefixcmp -int prefixcmp(const char *str, const char *prefix); -#define suffixcmp abrt_suffixcmp -int suffixcmp(const char *str, const char *suffix); -#define strtrim abrt_strtrim -char *strtrim(char *str); -#define concat_path_file abrt_concat_path_file -char *concat_path_file(const char *path, const char *filename); -#define append_to_malloced_string abrt_append_to_malloced_string -char *append_to_malloced_string(char *mstr, const char *append); -#define skip_whitespace abrt_skip_whitespace -char* skip_whitespace(const char *s); -#define skip_non_whitespace abrt_skip_non_whitespace -char* skip_non_whitespace(const char *s); -/* Like strcpy but can copy overlapping strings. */ -#define overlapping_strcpy abrt_overlapping_strcpy -void overlapping_strcpy(char *dst, const char *src); - -/* A-la fgets, but malloced and of unlimited size */ -#define xmalloc_fgets abrt_xmalloc_fgets -char *xmalloc_fgets(FILE *file); -/* Similar, but removes trailing \n */ -#define xmalloc_fgetline abrt_xmalloc_fgetline -char *xmalloc_fgetline(FILE *file); - -/* On error, copyfd_XX prints error messages and returns -1 */ -enum { - COPYFD_SPARSE = 1 << 0, -}; -#define copyfd_eof abrt_copyfd_eof -off_t copyfd_eof(int src_fd, int dst_fd, int flags); -#define copyfd_size abrt_copyfd_size -off_t copyfd_size(int src_fd, int dst_fd, off_t size, int flags); -#define copyfd_exact_size abrt_copyfd_exact_size -void copyfd_exact_size(int src_fd, int dst_fd, off_t size); -#define copy_file abrt_copy_file -off_t copy_file(const char *src_name, const char *dst_name, int mode); -#define copy_file_recursive abrt_copy_file_recursive -int copy_file_recursive(const char *source, const char *dest); - -/* Returns malloc'ed block */ -#define encode_base64 abrt_encode_base64 -char *encode_base64(const void *src, int length); - -#define xatou abrt_xatou -unsigned xatou(const char *numstr); -#define xatoi abrt_xatoi -int xatoi(const char *numstr); -/* Using xatoi() instead of naive atoi() is not always convenient - - * in many places people want *non-negative* values, but store them - * in signed int. Therefore we need this one: - * dies if input is not in [0, INT_MAX] range. Also will reject '-0' etc. - * It should really be named xatoi_nonnegative (since it allows 0), - * but that would be too long. - */ -#define xatoi_positive abrt_xatoi_positive -int xatoi_positive(const char *numstr); - -//unused for now -//unsigned long long monotonic_ns(void); -//unsigned long long monotonic_us(void); -//unsigned monotonic_sec(void); - -enum { - /* on return, pipefds[1] is fd to which parent may write - * and deliver data to child's stdin: */ - EXECFLG_INPUT = 1 << 0, - /* on return, pipefds[0] is fd from which parent may read - * child's stdout: */ - EXECFLG_OUTPUT = 1 << 1, - /* open child's stdin to /dev/null: */ - EXECFLG_INPUT_NUL = 1 << 2, - /* open child's stdout to /dev/null: */ - EXECFLG_OUTPUT_NUL = 1 << 3, - /* redirect child's stderr to stdout: */ - EXECFLG_ERR2OUT = 1 << 4, - /* open child's stderr to /dev/null: */ - EXECFLG_ERR_NUL = 1 << 5, - /* suppress perror_msg("Can't execute 'foo'") if exec fails */ - EXECFLG_QUIET = 1 << 6, - EXECFLG_SETGUID = 1 << 7, - EXECFLG_SETSID = 1 << 8, -}; -/* - * env_vec: list of variables to set in environment (if string has - * "VAR=VAL" form) or unset in environment (if string has no '=' char). - * - * Returns pid. - */ -#define fork_execv_on_steroids abrt_fork_execv_on_steroids -pid_t fork_execv_on_steroids(int flags, - char **argv, - int *pipefds, - char **env_vec, - const char *dir, - uid_t uid); -/* Returns malloc'ed string. NULs are retained, and extra one is appended - * after the last byte (this NUL is not accounted for in *size_p) */ -#define run_in_shell_and_save_output abrt_run_in_shell_and_save_output -char *run_in_shell_and_save_output(int flags, - const char *cmd, - const char *dir, - size_t *size_p); - -/* Random utility functions */ - -#define is_in_string_list abrt_is_in_string_list -bool is_in_string_list(const char *name, char **v); - -/* Frees every element'd data using free(), - * then frees list itself using g_list_free(list): - */ -#define list_free_with_free abrt_list_free_with_free -void list_free_with_free(GList *list); - -#define get_dirsize abrt_get_dirsize -double get_dirsize(const char *pPath); -#define get_dirsize_find_largest_dir abrt_get_dirsize_find_largest_dir -double get_dirsize_find_largest_dir( - const char *pPath, - char **worst_dir, /* can be NULL */ - const char *excluded /* can be NULL */ -); - -/* Emit a string of hex representation of bytes */ -#define bin2hex abrt_bin2hex -char* bin2hex(char *dst, const char *str, int count); -/* Convert "xxxxxxxx" hex string to binary, no more than COUNT bytes */ -#define hex2bin abrt_hex2bin -char* hex2bin(char *dst, const char *str, int count); - -/* Returns command line of running program. - * Caller is responsible to free() the returned value. - * If the pid is not valid or command line can not be obtained, - * empty string is returned. - */ -#define get_cmdline abrt_get_cmdline -char* get_cmdline(pid_t pid); -#define get_environ abrt_get_environ -char* get_environ(pid_t pid); - -/* Returns 1 if abrtd daemon is running, 0 otherwise. */ -#define daemon_is_ok abrt_daemon_is_ok -int daemon_is_ok(); - -/* Takes ptr to time_t, or NULL if you want to use current time. - * Returns "YYYY-MM-DD-hh:mm:ss" string. - */ -#define iso_date_string abrt_iso_date_string -char *iso_date_string(time_t *pt); - -enum { - MAKEDESC_SHOW_FILES = (1 << 0), - MAKEDESC_SHOW_MULTILINE = (1 << 1), - MAKEDESC_SHOW_ONLY_LIST = (1 << 2), -}; -#define make_description abrt_make_description -char *make_description(problem_data_t *problem_data, char **names_to_skip, unsigned max_text_size, unsigned desc_flags); -#define make_description_bz abrt_make_description_bz -char* make_description_bz(problem_data_t *problem_data); -#define make_description_logger abrt_make_description_logger -char* make_description_logger(problem_data_t *problem_data); -#define make_description_mailx abrt_make_description_mailx -char* make_description_mailx(problem_data_t *problem_data); - -#define parse_release_for_bz abrt_parse_release_for_bz -void parse_release_for_bz(const char *pRelease, char **product, char **version); -#define parse_release_for_rhts abrt_parse_release_for_rhts -void parse_release_for_rhts(const char *pRelease, char **product, char **version); - -/** - * Loads settings and stores it in second parameter. On success it - * returns true, otherwise returns false. - * - * @param path A path of config file. - * Config file consists of "key=value" lines. - * @param settings A read plugin's settings. - * @param skipKeysWithoutValue - * If true, lines in format "key=" (without value) are skipped. - * Otherwise empty value "" is inserted into pSettings. - * @return if it success it returns true, otherwise it returns false. - */ -#define load_conf_file abrt_load_conf_file -bool load_conf_file(const char *pPath, map_string_h *settings, bool skipKeysWithoutValue); - -/* Tries to create a copy of dump_dir_name in base_dir, with same or similar basename. - * Returns NULL if copying failed. In this case, logs a message before returning. */ -#define steal_directory abrt_steal_directory -struct dump_dir *steal_directory(const char *base_dir, const char *dump_dir_name); - -#define kernel_tainted_short abrt_kernel_tainted_short -char *kernel_tainted_short(unsigned tainted); -#define kernel_tainted_long abrt_kernel_tainted_long -GList *kernel_tainted_long(unsigned tainted); #ifdef __cplusplus } diff --git a/src/include/report/dump_dir.h b/src/include/report/dump_dir.h deleted file mode 100644 index c88ebe7f..00000000 --- a/src/include/report/dump_dir.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - On-disk storage of problem data - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 RedHat inc. - - 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; either version 2 of the License, or - (at your option) any later version. - - 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#ifndef DUMP_DIR_H_ -#define DUMP_DIR_H_ - -/* For DIR */ -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - DD_FAIL_QUIETLY_ENOENT = (1 << 0), - DD_FAIL_QUIETLY_EACCES = (1 << 1), - DD_OPEN_READONLY = (1 << 2), -}; - -struct dump_dir { - char *dd_dirname; - DIR *next_dir; - int locked; - uid_t dd_uid; - gid_t dd_gid; - /* mode fo saved files */ - mode_t mode; -}; - -void dd_close(struct dump_dir *dd); - -struct dump_dir *dd_opendir(const char *dir, int flags); -/* Pass uid = (uid_t)-1L to disable chown'ing of newly created files - * (IOW: if you aren't running under root): - */ -struct dump_dir *dd_create(const char *dir, uid_t uid, mode_t mode); - -void dd_create_basic_files(struct dump_dir *dd, uid_t uid); -int dd_exist(struct dump_dir *dd, const char *path); -void dd_sanitize_mode_and_owner(struct dump_dir *dd); - -DIR *dd_init_next_file(struct dump_dir *dd); -int dd_get_next_file(struct dump_dir *dd, char **short_name, char **full_name); - -enum { - /* DD_FAIL_QUIETLY_ENOENT bit is valid for dd_load_text_ext too, */ - DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE = (DD_OPEN_READONLY << 1), -}; -char* dd_load_text_ext(const struct dump_dir *dd, const char *name, unsigned flags); -char* dd_load_text(const struct dump_dir *dd, const char *name); -void dd_save_text(struct dump_dir *dd, const char *name, const char *data); -void dd_save_binary(struct dump_dir *dd, const char *name, const char *data, unsigned size); -/* Returns 0 if directory is deleted or not found */ -int dd_delete(struct dump_dir *dd); - -void delete_dump_dir(const char *dirname); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/include/report/event_config.h b/src/include/report/event_config.h deleted file mode 100644 index 8ab9477d..00000000 --- a/src/include/report/event_config.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - Copyright (C) 2011 ABRT team - - 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; either version 2 of the License, or - (at your option) any later version. - - 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include - -#ifndef EVENT_CONFIG_H -#define EVENT_CONFIG_H - - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum -{ - OPTION_TYPE_TEXT, - OPTION_TYPE_BOOL, - OPTION_TYPE_PASSWORD, - OPTION_TYPE_NUMBER, - OPTION_TYPE_HINT_HTML, - OPTION_TYPE_INVALID, -} option_type_t; - -/* - * struct to hold information about config options - * it's supposed to hold information about: - * type -> which designates the widget used to display it and we can do some test based on the type - * label - * allowed value(s) -> regexp? - * name -> env variable name - * value -> value retrieved from the gui, so when we want to set the env - * evn variables, we can just traverse the list of the options - * and set the env variables according to name:value in this structure - */ -typedef struct -{ - char *eo_name; //name of the value which should be used for env variable - char *eo_value; - char *eo_label; - char *eo_note_html; - option_type_t eo_type; - int eo_allow_empty; - //char *description; //can be used as tooltip in gtk app - //char *allowed_value; - //int required; -} event_option_t; - -event_option_t *new_event_option(void); -void free_event_option(event_option_t *p); - -//structure to hold the option data -typedef struct -{ - char *screen_name; //ui friendly name of the event: "Bugzilla" "RedHat Support Upload" - char *description; // "Report to..."/"Save to file". Should be one sentence, not long - char *long_descr; // Long(er) explanation, if needed - - char *ec_creates_items; - char *ec_requires_items; - char *ec_exclude_items_by_default; - char *ec_include_items_by_default; - char *ec_exclude_items_always; - bool ec_exclude_binary_items; - - GList *options; -} event_config_t; - -event_config_t *new_event_config(void); -void free_event_config(event_config_t *p); - - -void load_event_description_from_file(event_config_t *event_config, const char* filename); - -// (Re)loads data from /etc/abrt/events/*.{conf,xml} -void load_event_config_data(void); -/* Frees all loaded data */ -void free_event_config_data(void); -event_config_t *get_event_config(const char *event_name); -event_option_t *get_event_option_from_list(const char *option_name, GList *event_options); - -extern GHashTable *g_event_config_list; // for iterating through entire list of all loaded configs - -GList *export_event_config(const char *event_name); -void unexport_event_config(GList *env_list); - -GHashTable *validate_event(const char *event_name); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/include/report/problem_data.h b/src/include/report/problem_data.h deleted file mode 100644 index 31ef7d25..00000000 --- a/src/include/report/problem_data.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - Copyright (C) 2009 Abrt team. - Copyright (C) 2009 RedHat inc. - - 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; either version 2 of the License, or - (at your option) any later version. - - 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#ifndef PROBLEM_DATA_H_ -#define PROBLEM_DATA_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct dump_dir; - -enum { - CD_FLAG_BIN = (1 << 0), - CD_FLAG_TXT = (1 << 1), - CD_FLAG_ISEDITABLE = (1 << 2), - CD_FLAG_ISNOTEDITABLE = (1 << 3), - /* Show this element in "short" info (abrt-cli -l) */ - CD_FLAG_LIST = (1 << 4), - CD_FLAG_UNIXTIME = (1 << 5), -}; - -struct problem_item { - char *content; - unsigned flags; - /* Used by UI for presenting "item allowed/not allowed" checkboxes: */ - int selected_by_user; /* 0 "don't know", -1 "no", 1 "yes" */ - int allowed_by_reporter; /* 0 "no", 1 "yes" */ - int default_by_reporter; /* 0 "no", 1 "yes" */ - int required_by_reporter; /* 0 "no", 1 "yes" */ -}; -typedef struct problem_item problem_item; - -char *format_problem_item(struct problem_item *item); - - -/* In-memory problem data structure and accessors */ - -typedef GHashTable problem_data_t; - -problem_data_t *new_problem_data(void); - -void add_basics_to_problem_data(problem_data_t *pd); - -static inline void free_problem_data(problem_data_t *problem_data) -{ - if (problem_data) - g_hash_table_destroy(problem_data); -} - -void add_to_problem_data_ext(problem_data_t *problem_data, - const char *name, - const char *content, - unsigned flags); -/* Uses CD_FLAG_TXT + CD_FLAG_ISNOTEDITABLE flags */ -void add_to_problem_data(problem_data_t *problem_data, - const char *name, - const char *content); - -static inline struct problem_item *get_problem_data_item_or_NULL(problem_data_t *problem_data, const char *key) -{ - return (struct problem_item *)g_hash_table_lookup(problem_data, key); -} -const char *get_problem_item_content_or_NULL(problem_data_t *problem_data, const char *key); -/* Aborts if key is not found: */ -const char *get_problem_item_content_or_die(problem_data_t *problem_data, const char *key); - - -/* Conversions between in-memory and on-disk formats */ - -void load_problem_data_from_dump_dir(problem_data_t *problem_data, struct dump_dir *dd, char **excluding); -problem_data_t *create_problem_data_from_dump_dir(struct dump_dir *dd); -/* Helper for typical operation in reporters: */ -problem_data_t *create_problem_data_for_reporting(const char *dump_dir_name); - -struct dump_dir *create_dump_dir_from_problem_data(problem_data_t *problem_data, const char *base_dir_name); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/include/report/report.h b/src/include/report/report.h deleted file mode 100644 index 269866b2..00000000 --- a/src/include/report/report.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 2011 Abrt team. - Copyright (C) 2011 RedHat inc. - - 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; either version 2 of the License, or - (at your option) any later version. - - 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#ifndef REPORT_H_ -#define REPORT_H_ - -#include "problem_data.h" - -enum { - LIBREPORT_NOWAIT = 0, - LIBREPORT_WAIT = (1 << 0), /* wait for report to finish and reload the problem data */ - LIBREPORT_ANALYZE = (1 << 1), /* run analyzers? */ - /* ("run reporters" is always on, has no flag (for now?)) */ - LIBREPORT_RELOAD_DATA = (1 << 3), /* reload problem data after run (needs WAIT) */ -}; - -int report_problem_in_dir(const char *dirname, int flags); - -/* Reports a problem stored in problem_data_t. - * It's first saved to /tmp and then processed as a dump dir. - */ -int report_problem_in_memory(problem_data_t *pd, int flags); - -/* Simple wrapper for trivial uses */ -int report_problem(problem_data_t *pd); - -#endif /* REPORT_H_ */ diff --git a/src/include/report/run_event.h b/src/include/report/run_event.h deleted file mode 100644 index 9726b643..00000000 --- a/src/include/report/run_event.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - Copyright (C) 2009 Abrt team. - Copyright (C) 2009 RedHat inc. - - 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; either version 2 of the License, or - (at your option) any later version. - - 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#ifndef RUN_EVENT_H_ -#define RUN_EVENT_H_ - -#include "problem_data.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct dump_dir; - -struct run_event_state { - int children_count; - - /* Used only for post-create dup detection. TODO: document its API */ - int (*post_run_callback)(const char *dump_dir_name, void *param); - void *post_run_param; - - /* Can take ownership of log_line, which is malloced. In this case, return NULL. - * Otherwise should return log_line (it will be freed by caller) - */ - char* (*logging_callback)(char *log_line, void *param); - void *logging_param; - - /* Internal data for async command execution */ - GList *rule_list; - pid_t command_pid; - int command_out_fd; -}; -struct run_event_state *new_run_event_state(void); -void free_run_event_state(struct run_event_state *state); - -/* Asynchronous command execution */ - -/* Returns 0 if no commands found for this dump_dir_name+event, else >0 */ -int prepare_commands(struct run_event_state *state, const char *dump_dir_name, const char *event); -/* Returns -1 is no more commands needs to be executed, - * else sets state->command_pid and state->command_out_fd and returns >=0 - */ -int spawn_next_command(struct run_event_state *state, const char *dump_dir_name, const char *event); -/* Cleans up internal state created in prepare_commands */ -void free_commands(struct run_event_state *state); - -/* Synchronous command execution */ - -/* Returns exit code of first failed action, or first nonzero return value - * of post_run_callback. If all actions are successful, returns 0. - */ -int run_event_on_dir_name(struct run_event_state *state, const char *dump_dir_name, const char *event); -int run_event_on_problem_data(struct run_event_state *state, problem_data_t *data, const char *event); - -/* Querying for possible events */ - -/* Scans event.conf for events starting with pfx which are applicable - * to dd, or (if dd is NULL), to dump_dir. - * Returns a malloced string with '\n'-terminated event names. - */ -char *list_possible_events(struct dump_dir *dd, const char *dump_dir_name, const char *pfx); - -#ifdef __cplusplus -} -#endif - -#endif -- cgit