1 /* 2 * Copyright 2009-2017 Citrix Ltd and other contributors 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License as published 6 * by the Free Software Foundation; version 2.1 only. with the special 7 * exception on linking described in file LICENSE. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 */ 14 15 #ifndef XL_UTILS_H 16 #define XL_UTILS_H 17 18 #include <getopt.h> 19 20 /* For calls which return an errno on failure */ 21 #define CHK_ERRNOVAL( call ) ({ \ 22 int chk_errnoval = (call); \ 23 if (chk_errnoval < 0) \ 24 abort(); \ 25 else if (chk_errnoval > 0) { \ 26 fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n", \ 27 __FILE__,__LINE__, strerror(chk_errnoval), #call); \ 28 exit(EXIT_FAILURE); \ 29 } \ 30 }) 31 32 /* For calls which return -1 and set errno on failure */ 33 #define CHK_SYSCALL( call ) ({ \ 34 if ((call) == -1) { \ 35 fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n", \ 36 __FILE__,__LINE__, strerror(errno), #call); \ 37 exit(EXIT_FAILURE); \ 38 } \ 39 }) 40 41 #define MUST( call ) ({ \ 42 int must_rc = (call); \ 43 if (must_rc < 0) { \ 44 fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n", \ 45 __FILE__,__LINE__, must_rc, #call); \ 46 exit(EXIT_FAILURE); \ 47 } \ 48 }) 49 50 #define STR_HAS_PREFIX( a, b ) \ 51 ( strncmp(a, b, strlen(b)) == 0 ) 52 #define STR_SKIP_PREFIX( a, b ) \ 53 ( STR_HAS_PREFIX(a, b) ? ((a) += strlen(b), 1) : 0 ) 54 55 #define LOG(_f, _a...) dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a) 56 57 /* 58 * Wraps def_getopt into a convenient loop+switch to process all 59 * arguments. This macro is intended to be called from main_XXX(). 60 * 61 * SWITCH_FOREACH_OPT(int *opt, "OPTS", 62 * const struct option *longopts, 63 * const char *commandname, 64 * int num_opts_req) { ... 65 * 66 * opt: pointer to an int variable, holds the current option 67 * during processing. 68 * OPTS: short options, as per getopt_long(3)'s optstring argument. 69 * do not include "h"; will be provided automatically 70 * longopts: long options, as per getopt_long(3)'s longopts argument. 71 * May be null. 72 * commandname: name of this command, for usage string. 73 * num_required_opts: number of non-option command line parameters 74 * which are required. 75 * 76 * In addition the calling context is expected to contain variables 77 * "argc" and "argv" in the conventional C-style: 78 * main(int argc, char **argv) 79 * manner. 80 * 81 * Callers should treat SWITCH_FOREACH_OPT as they would a switch 82 * statement over the value of `opt`. Each option given in `opts` (or 83 * `lopts`) should be handled by a case statement as if it were inside 84 * a switch statement. 85 * 86 * In addition to the options provided in opts the macro will handle 87 * the "help" option and enforce a minimum number of non-option 88 * command line pearameters as follows: 89 * -- if the user passes a -h or --help option. help will be printed, 90 * and the macro will cause the process to exit with code 0. 91 * -- if the user does not provided `num_required_opts` non-option 92 * arguments, the macro will cause the process to exit with code 2. 93 * 94 * Example: 95 * 96 * int main_foo(int argc, char **argv) { 97 * int opt; 98 * 99 * SWITCH_FOREACH_OPT(opt, "blah", NULL, "foo", 0) { 100 * case 'b': 101 * ... handle b option... 102 * break; 103 * case 'l': 104 * ... handle l option ... 105 * break; 106 * case etc etc... 107 * } 108 * ... do something useful with the options ... 109 * } 110 */ 111 #define SWITCH_FOREACH_OPT(opt, opts, longopts, \ 112 commandname, num_required_opts) \ 113 while (((opt) = def_getopt(argc, argv, "h" opts, (longopts), \ 114 (commandname), (num_required_opts))) != -1) \ 115 switch (opt) 116 117 /* Must be last in list */ 118 #define COMMON_LONG_OPTS {"help", 0, 0, 'h'}, \ 119 {0, 0, 0, 0} 120 121 int def_getopt(int argc, char * const argv[], 122 const char *optstring, 123 const struct option *longopts, 124 const char* helpstr, int reqargs); 125 126 void dolog(const char *file, int line, const char *func, char *fmt, ...) 127 __attribute__((format(printf,4,5))); 128 129 void xvasprintf(char **strp, const char *fmt, va_list ap) 130 __attribute__((format(printf,2,0))); 131 132 void xasprintf(char **strp, const char *fmt, ...) 133 __attribute__((format(printf,2,3))); 134 135 void *xmalloc(size_t sz); 136 void *xcalloc(size_t n, size_t sz); 137 void *xrealloc(void *ptr, size_t sz); 138 char *xstrdup(const char *x); 139 void string_realloc_append(char **accumulate, const char *more); 140 141 void flush_stream(FILE *fh); 142 uint32_t find_domain(const char *p) __attribute__((warn_unused_result)); 143 144 void print_bitmap(uint8_t *map, int maplen, FILE *stream); 145 146 int do_daemonize(char *name, const char *pidfile); 147 #endif /* XL_UTILS_H */ 148 149 /* 150 * Local variables: 151 * mode: C 152 * c-basic-offset: 4 153 * indent-tabs-mode: nil 154 * End: 155 */ 156