1 /* beanstalk - fast, general-purpose work queue */
3 /* Copyright (C) 2007 Keith Rarick and Philotic Inc.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "sd-daemon.h"
30 static char *user
= NULL
;
31 static int detach
= 0;
32 static char *port
= "11300";
33 static char *host_addr
;
36 nullfd(int fd
, int flags
)
41 r
= open("/dev/null", flags
);
42 if (r
!= fd
) twarn("open(\"/dev/null\")"), exit(1);
61 if (r
) return twarn("chdir");
73 su(const char *user
) {
78 pwent
= getpwnam(user
);
79 if (errno
) twarn("getpwnam(\"%s\")", user
), exit(32);
80 if (!pwent
) twarnx("getpwnam(\"%s\"): no such user", user
), exit(33);
82 r
= setgid(pwent
->pw_gid
);
83 if (r
== -1) twarn("setgid(%d \"%s\")", pwent
->pw_gid
, user
), exit(34);
85 r
= setuid(pwent
->pw_uid
);
86 if (r
== -1) twarn("setuid(%d \"%s\")", pwent
->pw_uid
, user
), exit(34);
103 sa
.sa_handler
= SIG_IGN
;
105 r
= sigemptyset(&sa
.sa_mask
);
106 if (r
== -1) twarn("sigemptyset()"), exit(111);
108 r
= sigaction(SIGPIPE
, &sa
, 0);
109 if (r
== -1) twarn("sigaction(SIGPIPE)"), exit(111);
111 sa
.sa_handler
= enter_drain_mode
;
112 r
= sigaction(SIGUSR1
, &sa
, 0);
113 if (r
== -1) twarn("sigaction(SIGUSR1)"), exit(111);
115 sa
.sa_handler
= exit_cleanly
;
116 r
= sigaction(SIGINT
, &sa
, 0);
117 if (r
== -1) twarn("sigaction(SIGINT)"), exit(111);
119 sa
.sa_handler
= exit_cleanly
;
120 r
= sigaction(SIGTERM
, &sa
, 0);
121 if (r
== -1) twarn("sigaction(SIGTERM)"), exit(111);
125 usage(char *msg
, char *arg
)
127 if (arg
) warnx("%s: %s", msg
, arg
);
128 fprintf(stderr
, "Use: %s [OPTIONS]\n"
132 " -b DIR binlog directory (must be absolute path if used with -d)\n"
133 " -f MS fsync at most once every MS milliseconds"
134 " (use -f 0 for \"always fsync\")\n"
135 " -F never fsync (default)\n"
136 " -l ADDR listen on address (default is 0.0.0.0)\n"
137 " -p PORT listen on port (default is 11300)\n"
138 " -u USER become user and group\n"
139 " -z BYTES set the maximum job size in bytes (default is %d)\n"
140 " -s BYTES set the size of each binlog file (default is %d)\n"
141 " (will be rounded up to a multiple of 512 bytes)\n"
142 " -v show version information\n"
143 " -h show this help\n",
144 progname
, JOB_DATA_SIZE_LIMIT_DEFAULT
, BINLOG_SIZE_LIMIT_DEFAULT
);
149 parse_size_t(char *str
)
154 r
= sscanf(str
, "%zu%c", &size
, &x
);
155 if (1 != r
) usage("invalid size", str
);
160 require_arg(char *opt
, char *arg
)
162 if (!arg
) usage("option requires an argument", opt
);
167 warn_systemd_ignored_option(char *opt
, char *arg
)
169 if (sd_listen_fds(0) > 0) {
170 warnx("inherited listen fd; ignoring option: %s %s", opt
, arg
);
175 opts(int argc
, char **argv
)
179 for (i
= 1; i
< argc
; ++i
) {
180 if (argv
[i
][0] != '-') usage("unknown option", argv
[i
]);
181 if (argv
[i
][1] == 0 || argv
[i
][2] != 0) usage("unknown option",argv
[i
]);
182 switch (argv
[i
][1]) {
187 port
= require_arg("-p", argv
[++i
]);
188 warn_systemd_ignored_option("-p", argv
[i
]);
191 host_addr
= require_arg("-l", argv
[++i
]);
192 warn_systemd_ignored_option("-l", argv
[i
]);
195 job_data_size_limit
= parse_size_t(require_arg("-z",
199 binlog_size_limit
= parse_size_t(require_arg("-s", argv
[++i
]));
202 fsync_throttle_ms
= parse_size_t(require_arg("-f", argv
[++i
]));
209 user
= require_arg("-u", argv
[++i
]);
212 binlog_dir
= require_arg("-b", argv
[++i
]);
217 printf("beanstalkd %s\n", version
);
220 usage("unknown option", argv
[i
]);
226 main(int argc
, char **argv
)
230 struct job binlog_jobs
= {};
235 if (detach
&& binlog_dir
) {
236 if (binlog_dir
[0] != '/') {
237 warnx("The -b option requires an absolute path when used with -d.");
238 usage("Path is not absolute", binlog_dir
);
242 r
= make_server_socket(host_addr
, port
);
243 if (r
== -1) twarnx("make_server_socket()"), exit(111);
248 /* We want to make sure that only one beanstalkd tries to use the binlog
249 * directory at a time. So acquire a lock now and never release it. */
252 if (!r
) twarnx("failed to lock binlog dir %s", binlog_dir
), exit(10);
259 binlog_jobs
.prev
= binlog_jobs
.next
= &binlog_jobs
;
260 binlog_init(&binlog_jobs
);
261 prot_replay_binlog(&binlog_jobs
);