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 INVALID_DOMID ~0 56 57 #define LOG(_f, _a...) dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a) 58 59 /* 60 * Wraps def_getopt into a convenient loop+switch to process all 61 * arguments. This macro is intended to be called from main_XXX(). 62 * 63 * SWITCH_FOREACH_OPT(int *opt, "OPTS", 64 * const struct option *longopts, 65 * const char *commandname, 66 * int num_opts_req) { ... 67 * 68 * opt: pointer to an int variable, holds the current option 69 * during processing. 70 * OPTS: short options, as per getopt_long(3)'s optstring argument. 71 * do not include "h"; will be provided automatically 72 * longopts: long options, as per getopt_long(3)'s longopts argument. 73 * May be null. 74 * commandname: name of this command, for usage string. 75 * num_required_opts: number of non-option command line parameters 76 * which are required. 77 * 78 * In addition the calling context is expected to contain variables 79 * "argc" and "argv" in the conventional C-style: 80 * main(int argc, char **argv) 81 * manner. 82 * 83 * Callers should treat SWITCH_FOREACH_OPT as they would a switch 84 * statement over the value of `opt`. Each option given in `opts` (or 85 * `lopts`) should be handled by a case statement as if it were inside 86 * a switch statement. 87 * 88 * In addition to the options provided in opts the macro will handle 89 * the "help" option and enforce a minimum number of non-option 90 * command line pearameters as follows: 91 * -- if the user passes a -h or --help option. help will be printed, 92 * and the macro will cause the process to exit with code 0. 93 * -- if the user does not provided `num_required_opts` non-option 94 * arguments, the macro will cause the process to exit with code 2. 95 * 96 * Example: 97 * 98 * int main_foo(int argc, char **argv) { 99 * int opt; 100 * 101 * SWITCH_FOREACH_OPT(opt, "blah", NULL, "foo", 0) { 102 * case 'b': 103 * ... handle b option... 104 * break; 105 * case 'l': 106 * ... handle l option ... 107 * break; 108 * case etc etc... 109 * } 110 * ... do something useful with the options ... 111 * } 112 */ 113 #define SWITCH_FOREACH_OPT(opt, opts, longopts, \ 114 commandname, num_required_opts) \ 115 while (((opt) = def_getopt(argc, argv, "h" opts, (longopts), \ 116 (commandname), (num_required_opts))) != -1) \ 117 switch (opt) 118 119 /* Must be last in list */ 120 #define COMMON_LONG_OPTS {"help", 0, 0, 'h'}, \ 121 {0, 0, 0, 0} 122 123 int def_getopt(int argc, char * const argv[], 124 const char *optstring, 125 const struct option *longopts, 126 const char* helpstr, int reqargs); 127 128 void dolog(const char *file, int line, const char *func, char *fmt, ...) 129 __attribute__((format(printf,4,5))); 130 131 void xvasprintf(char **strp, const char *fmt, va_list ap) 132 __attribute__((format(printf,2,0))); 133 134 void xasprintf(char **strp, const char *fmt, ...) 135 __attribute__((format(printf,2,3))); 136 137 void *xmalloc(size_t sz); 138 void *xcalloc(size_t n, size_t sz); 139 void *xrealloc(void *ptr, size_t sz); 140 char *xstrdup(const char *x); 141 void string_realloc_append(char **accumulate, const char *more); 142 143 void flush_stream(FILE *fh); 144 uint32_t find_domain(const char *p) __attribute__((warn_unused_result)); 145 146 void print_bitmap(uint8_t *map, int maplen, FILE *stream); 147 148 int do_daemonize(char *name, const char *pidfile); 149 #endif /* XL_UTILS_H */ 150 151 /* 152 * Local variables: 153 * mode: C 154 * c-basic-offset: 4 155 * indent-tabs-mode: nil 156 * End: 157 */ 158