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