add changelog for 1.13
[beanstalkd.git] / util.c
blob2baf1a40ee553d1c0f5c71adb5e14331ee6edf5f
1 #include "dat.h"
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdarg.h>
9 #ifdef HAVE_LIBSYSTEMD
10 #include <systemd/sd-daemon.h>
11 #endif
13 const char *progname;
15 static void
16 vwarnx(const char *err, const char *fmt, va_list args)
17 __attribute__((format(printf, 2, 0)));
19 static void
20 vwarnx(const char *err, const char *fmt, va_list args)
22 fprintf(stderr, "%s: ", progname);
23 if (fmt) {
24 vfprintf(stderr, fmt, args);
25 if (err) fprintf(stderr, ": %s", err);
27 fputc('\n', stderr);
30 void
31 warn(const char *fmt, ...)
33 char *err = strerror(errno); /* must be done first thing */
34 va_list args;
36 va_start(args, fmt);
37 vwarnx(err, fmt, args);
38 va_end(args);
41 void
42 warnx(const char *fmt, ...)
44 va_list args;
45 va_start(args, fmt);
46 vwarnx(NULL, fmt, args);
47 va_end(args);
51 char*
52 fmtalloc(char *fmt, ...)
54 int n;
55 char *buf;
56 va_list ap;
58 // find out how much space is needed
59 va_start(ap, fmt);
60 n = vsnprintf(0, 0, fmt, ap) + 1; // include space for trailing NUL
61 va_end(ap);
63 buf = malloc(n);
64 if (buf) {
65 va_start(ap, fmt);
66 vsnprintf(buf, n, fmt, ap);
67 va_end(ap);
69 return buf;
73 // Zalloc allocates n bytes of zeroed memory and
74 // returns a pointer to it.
75 // If insufficient memory is available, zalloc returns 0.
76 void*
77 zalloc(int n)
79 void *p;
81 p = malloc(n);
82 if (p) {
83 memset(p, 0, n);
85 return p;
89 static void
90 warn_systemd_ignored_option(char *opt, char *arg)
92 #ifdef HAVE_LIBSYSTEMD
93 if (sd_listen_fds(0) > 0) {
94 warnx("inherited listen fd; ignoring option: %s %s", opt, arg);
96 #endif
100 static void usage(int code) __attribute__ ((noreturn));
101 static void
102 usage(int code)
104 fprintf(stderr, "Use: %s [OPTIONS]\n"
105 "\n"
106 "Options:\n"
107 " -b DIR write-ahead log directory\n"
108 " -f MS fsync at most once every MS milliseconds (default is %dms);\n"
109 " use -f0 for \"always fsync\"\n"
110 " -F never fsync\n"
111 " -l ADDR listen on address (default is 0.0.0.0)\n"
112 " -p PORT listen on port (default is " Portdef ")\n"
113 " -u USER become user and group\n"
114 " -z BYTES set the maximum job size in bytes (default is %d);\n"
115 " max allowed is %d bytes\n"
116 " -s BYTES set the size of each write-ahead log file (default is %d);\n"
117 " will be rounded up to a multiple of 4096 bytes\n"
118 " -v show version information\n"
119 " -V increase verbosity\n"
120 " -h show this help\n",
121 progname,
122 DEFAULT_FSYNC_MS,
123 JOB_DATA_SIZE_LIMIT_DEFAULT,
124 JOB_DATA_SIZE_LIMIT_MAX,
125 Filesizedef);
126 exit(code);
130 static char *flagusage(char *flag) __attribute__ ((noreturn));
131 static char *
132 flagusage(char *flag)
134 warnx("flag requires an argument: %s", flag);
135 usage(5);
139 static size_t
140 parse_size_t(char *str)
142 char r, x;
143 size_t size;
145 r = sscanf(str, "%zu%c", &size, &x);
146 if (1 != r) {
147 warnx("invalid size: %s", str);
148 usage(5);
150 return size;
154 void
155 optparse(Server *s, char **argv)
157 int64 ms;
158 char *arg, *tmp;
159 # define EARGF(x) (*arg ? (tmp=arg,arg="",tmp) : *argv ? *argv++ : (x))
161 while ((arg = *argv++) && *arg++ == '-' && *arg) {
162 char c;
163 while ((c = *arg++)) {
164 switch (c) {
165 case 'p':
166 s->port = EARGF(flagusage("-p"));
167 warn_systemd_ignored_option("-p", s->port);
168 break;
169 case 'l':
170 s->addr = EARGF(flagusage("-l"));
171 warn_systemd_ignored_option("-l", s->addr);
172 break;
173 case 'z':
174 job_data_size_limit = parse_size_t(EARGF(flagusage("-z")));
175 if (job_data_size_limit > JOB_DATA_SIZE_LIMIT_MAX) {
176 warnx("maximum job size was set to %d", JOB_DATA_SIZE_LIMIT_MAX);
177 job_data_size_limit = JOB_DATA_SIZE_LIMIT_MAX;
179 break;
180 case 's':
181 s->wal.filesize = parse_size_t(EARGF(flagusage("-s")));
182 break;
183 case 'c':
184 warnx("-c flag was removed. binlog is always compacted.");
185 break;
186 case 'n':
187 warnx("-n flag was removed. binlog is always compacted.");
188 break;
189 case 'f':
190 ms = (int64)parse_size_t(EARGF(flagusage("-f")));
191 s->wal.syncrate = ms * 1000000;
192 s->wal.wantsync = 1;
193 break;
194 case 'F':
195 s->wal.wantsync = 0;
196 break;
197 case 'u':
198 s->user = EARGF(flagusage("-u"));
199 break;
200 case 'b':
201 s->wal.dir = EARGF(flagusage("-b"));
202 s->wal.use = 1;
203 break;
204 case 'h':
205 usage(0);
206 case 'v':
207 printf("beanstalkd %s\n", version);
208 exit(0);
209 case 'V':
210 verbose++;
211 break;
212 default:
213 warnx("unknown flag: %s", arg-2);
214 usage(5);
218 if (arg) {
219 warnx("unknown argument: %s", arg-1);
220 usage(5);