33 #ifdef HAVE_SYS_WAIT_H
34 # include <sys/wait.h>
36 #ifdef HAVE_SYS_SOCKET_H
37 # include <sys/socket.h>
39 #ifdef HAVE_NETINET_IN_H
40 # include <netinet/in.h>
43 #ifdef HAVE_SYS_RESOURCE_H
44 # include <sys/resource.h>
47 #ifdef HAVE_SYS_SYSCTL_H
48 # include <sys/sysctl.h>
51 #ifndef USE_MSG_NOSIGNAL
55 # define MSG_NOSIGNAL 0
59 # define STDIN_FILENO 0
62 # define STDOUT_FILENO 1
65 # define STDERR_FILENO 2
68 #define DEFAULT_PORT 10041
69 #define DEFAULT_DEST "localhost"
70 #define DEFAULT_MAX_NFTHREADS 8
71 #define MAX_CON 0x10000
73 #define RLIMIT_NOFILE_MINIMUM 4096
79 static int number_of_lines = 0;
83 static int (*do_client)(
int argc,
char **argv);
84 static int (*do_server)(
char *path);
85 static const char *pid_file_path = NULL;
86 static const char *input_path = NULL;
87 static FILE *output = NULL;
89 static int ready_notify_pipe[2];
95 static int64_t default_match_escalation_threshold;
99 grn_rc_to_exit_code(
grn_rc rc)
108 #ifdef GRN_WITH_LIBEDIT
110 #include <histedit.h>
111 static EditLine *line_editor = NULL;
112 static HistoryW *line_editor_history = NULL;
113 static HistEventW line_editor_history_event;
114 static char line_editor_history_path[
PATH_MAX] =
"";
116 static const wchar_t *
121 static const wchar_t *
const line_editor_editor = L
"emacs";
124 line_editor_init(
int argc
__attribute__((unused)),
char *argv[])
126 const char *
const HOME_PATH = getenv(
"HOME");
127 const char *
const HISTORY_PATH =
"/.groonga-history";
129 setlocale(LC_ALL,
"");
131 if (strlen(HOME_PATH) + strlen(HISTORY_PATH) <
PATH_MAX) {
132 strcpy(line_editor_history_path, HOME_PATH);
133 strcat(line_editor_history_path, HISTORY_PATH);
135 line_editor_history_path[0] =
'\0';
138 line_editor_history = history_winit();
139 history_w(line_editor_history, &line_editor_history_event, H_SETSIZE, 200);
140 if (line_editor_history_path[0]) {
141 history_w(line_editor_history, &line_editor_history_event,
142 H_LOAD, line_editor_history_path);
145 line_editor = el_init(argv[0], stdin, stdout, stderr);
146 el_wset(line_editor, EL_PROMPT, &line_editor_prompt);
147 el_wset(line_editor, EL_EDITOR, line_editor_editor);
148 el_wset(line_editor, EL_HIST, history_w, line_editor_history);
149 el_source(line_editor, NULL);
153 line_editor_fin(
void)
157 if (line_editor_history) {
158 if (line_editor_history_path[0]) {
159 history_w(line_editor_history, &line_editor_history_event,
160 H_SAVE, line_editor_history_path);
162 history_wend(line_editor_history);
173 line = el_wgets(line_editor, &nchar);
176 char multibyte_buf[MB_CUR_MAX];
177 size_t multibyte_len;
179 history_w(line_editor_history, &line_editor_history_event, H_ENTER, line);
180 memset(&ps, 0,
sizeof(ps));
181 wcrtomb(NULL, L
'\0', &ps);
182 for (i = 0; i < nchar; i++) {
183 multibyte_len = wcrtomb(multibyte_buf, line[i], &ps);
184 if (multibyte_len == (
size_t)-1) {
186 "[prompt][libedit] failed to read input: %s", strerror(errno));
202 static int the_first_read =
GRN_TRUE;
205 #ifdef GRN_WITH_LIBEDIT
206 rc = line_editor_fgets(ctx, buf);
208 fprintf(stderr,
"> ");
218 const char bom[] = {0xef, 0xbb, 0xbf};
249 while (need_next_line) {
250 rc = read_next_line(ctx, buf);
276 s_output(
grn_ctx *ctx,
int flags,
void *arg)
282 FILE * stream = (FILE *) arg;
286 output_envelope(ctx, ctx->
rc, &head, buf, &foot);
302 do_alone(
int argc,
char **argv)
304 int exit_code = EXIT_FAILURE;
309 if (argc > 0 && argv) { path = *argv++; argc--; }
324 exit_code = grn_rc_to_exit_code(ctx->
rc);
329 exit_code = grn_rc_to_exit_code(rc);
334 fprintf(stderr,
"db open failed (%s): %s\n", path, ctx->
errbuf);
345 unsigned int str_len;
354 if (str_len || ctx->
rc) {
362 ERR(ctx->
rc,
"%.*s", str_len, str);
364 output_envelope(ctx, ctx->
rc, &head, &body, &foot);
379 g_client(
int argc,
char **argv)
381 int exit_code = EXIT_FAILURE;
384 if (argc > 0 && argv) { hostname = *argv++; argc--; }
392 exit_code = grn_rc_to_exit_code(ctx->
rc);
394 if (c_output(ctx)) {
goto exit; }
401 exit_code = grn_rc_to_exit_code(rc);
402 if (c_output(ctx)) {
goto exit; }
405 fprintf(stderr,
"grn_ctx_connect failed (%s:%d)\n", hostname, port);
419 static grn_mutex q_mutex;
421 static uint32_t nthreads = 0, nfthreads = 0, max_nfthreads;
424 reset_ready_notify_pipe(
void)
431 close_ready_notify_pipe(
void)
439 reset_ready_notify_pipe();
443 send_ready_notify(
void)
446 const char *ready_notify_message =
"ready";
448 ready_notify_message,
449 strlen(ready_notify_message));
451 close_ready_notify_pipe();
457 int exit_code = EXIT_SUCCESS;
461 if (pipe(ready_notify_pipe) == -1) {
462 reset_ready_notify_pipe();
477 FD_SET(ready_notify_pipe[
PIPE_READ], &read_fds);
478 max_fd = ready_notify_pipe[
PIPE_READ] + 1;
479 select(max_fd, &read_fds, NULL, NULL, NULL);
481 close_ready_notify_pipe();
487 FILE *pid_file = NULL;
489 pid_file = fopen(pid_file_path,
"w");
493 fprintf(stderr,
"%d\n", pid);
495 fprintf(pid_file,
"%d\n", pid);
505 close_ready_notify_pipe();
509 int null_fd =
GRN_OPEN(
"/dev/null", O_RDWR, 0);
526 unlink(pid_file_path);
554 if (nthreads == nfthreads) {
break; }
555 MUTEX_UNLOCK(q_mutex);
585 int exit_code = EXIT_SUCCESS;
587 if (!(he = gethostbyname(hostname))) {
589 SERR(
"gethostbyname");
593 if (!
grn_com_sopen(ctx, ev, bind_address, port, handler, he)) {
595 run_server_loop(ctx, ev);
596 exit_code = EXIT_SUCCESS;
599 fprintf(stderr,
"grn_com_sopen failed (%s:%d): %s\n",
600 bind_address, port, ctx->
errbuf);
608 start_service(
grn_ctx *ctx,
const char *db_path,
611 int exit_code = EXIT_SUCCESS;
614 if (is_daemon_mode) {
615 exit_code = daemonize();
616 if (exit_code != EXIT_SUCCESS) {
625 exit_code = run_server(ctx, db, &ev, dispatcher, handler);
628 fprintf(stderr,
"db open failed (%s)\n", db_path);
629 exit_code = EXIT_FAILURE;
634 fprintf(stderr,
"grn_com_event_init failed\n");
635 exit_code = EXIT_FAILURE;
639 if (is_daemon_mode) {
651 h_output(
grn_ctx *ctx,
int flags,
void *arg)
657 if (!(flags & GRN_CTX_TAIL)) {
return; }
661 output_envelope(ctx, expr_rc, &head, outbuf, &foot);
673 GRN_TEXT_SETS(ctx, &header,
"HTTP/1.1 500 Internal Server Error\r\n");
695 if (WSASend(fd, wsabufs, 4, &ret, 0, NULL, NULL) == SOCKET_ERROR) {
699 struct iovec msg_iov[4];
703 msg.msg_iov = msg_iov;
705 msg.msg_control = NULL;
706 msg.msg_controllen = 0;
725 (
long long int)ret, (
long long int)len);
740 switch (header->
qtype) {
753 if (e <= pathe + 6) {
761 if (!memcmp(pathe + 1,
"HTTP/1", 6)) {
822 static grn_critical_section cache_lock;
823 static grn_obj *cache_table = NULL;
824 static grn_obj *cache_value = NULL;
825 static grn_obj *cache_flags = NULL;
826 static grn_obj *cache_expire = NULL;
827 static grn_obj *cache_cas = NULL;
829 #define CTX_GET(name) (grn_ctx_get(ctx, (name), strlen(name)))
834 if (cache_cas) {
return cache_cas; }
835 CRITICAL_SECTION_ENTER(cache_lock);
837 if ((cache_table =
CTX_GET(
"Memcache"))) {
838 cache_value =
CTX_GET(
"Memcache.value");
839 cache_flags =
CTX_GET(
"Memcache.flags");
840 cache_expire =
CTX_GET(
"Memcache.expire");
841 cache_cas =
CTX_GET(
"Memcache.cas");
849 shorttext_type, NULL))) {
862 CRITICAL_SECTION_LEAVE(cache_lock);
866 #define RELATIVE_TIME_THRESH 1000000000
868 #define MBRES(ctx,re,status,key_len,extra_len,flags) do {\
869 grn_msg_set_property((ctx), (re), (status), (key_len), (extra_len));\
870 grn_msg_send((ctx), (re), (flags));\
873 #define GRN_MSG_MBRES(block) do {\
875 grn_obj *re = grn_msg_open_for_reply(ctx, (grn_obj *)msg, &edge->send_old);\
876 ((grn_msg *)re)->header.qtype = header->qtype;\
884 static uint64_t cas_id = 0;
897 switch (header->
qtype) {
904 uint16_t keylen = ntohs(header->
keylen);
923 if (expire && expire < tv.
tv_sec) {
953 uint32_t size = ntohl(header->
size);
954 uint16_t keylen = ntohs(header->
keylen);
955 uint8_t extralen = header->
level;
957 uint32_t flags = *((uint32_t *)body);
958 uint32_t expire = ntohl(*((uint32_t *)(body + 4)));
959 uint32_t valuelen = size - keylen - extralen;
960 char *key = body + 8;
961 char *value = key + keylen;
1000 uint64_t cas_id = get_mbreq_cas_id();
1006 ((
grn_msg *)re)->header.cas = cas_id;
1022 if (oexpire && oexpire < tv.
tv_sec) {
1067 uint64_t cas_id = get_mbreq_cas_id();
1072 ((
grn_msg *)re)->header.cas = cas_id;
1088 uint16_t keylen = ntohs(header->
keylen);
1114 uint64_t delta, init;
1115 uint16_t keylen = ntohs(header->
keylen);
1117 char *key = body + 20;
1118 uint32_t expire = ntohl(*((uint32_t *)(body + 16)));
1123 if (expire == 0xffffffff) {
1149 if (oexpire && oexpire < tv.
tv_sec) {
1150 if (expire == 0xffffffffU) {
1195 uint8_t extralen = header->
level;
1199 expire = ntohl(*((uint32_t *)(body)));
1242 uint16_t keylen = ntohs(header->
keylen);
1258 if (expire && expire < tv.
tv_sec) {
1286 uint32_t size = ntohl(header->
size);
1287 uint16_t keylen = ntohs(header->
keylen);
1289 char *value = key + keylen;
1290 uint32_t valuelen = size - keylen;
1312 pid_t pid = getpid();
1344 check_rlimit_nofile(
grn_ctx *ctx)
1347 struct rlimit limit;
1350 getrlimit(RLIMIT_NOFILE, &limit);
1354 setrlimit(RLIMIT_NOFILE, &limit);
1357 getrlimit(RLIMIT_NOFILE, &limit);
1361 (
long long int)limit.rlim_cur, (
long long int)limit.rlim_max);
1374 MUTEX_LOCK(q_mutex);
1386 MUTEX_UNLOCK(q_mutex);
1388 do_htreq(ctx, (
grn_msg *)msg);
1389 MUTEX_LOCK(q_mutex);
1393 MUTEX_UNLOCK(q_mutex);
1412 MUTEX_LOCK(q_mutex);
1414 if (!nfthreads && nthreads < max_nfthreads) {
1417 if (THREAD_CREATE(thread, h_worker, arg)) {
SERR(
"pthread_create"); }
1420 MUTEX_UNLOCK(q_mutex);
1425 h_server(
char *path)
1427 int exit_code = EXIT_FAILURE;
1430 MUTEX_INIT(q_mutex);
1432 CRITICAL_SECTION_INIT(cache_lock);
1435 check_rlimit_nofile(ctx);
1436 exit_code = start_service(ctx, path, NULL, h_handler);
1445 MUTEX_LOCK(q_mutex);
1464 MUTEX_UNLOCK(q_mutex);
1470 switch (header->
proto) {
1472 do_mbreq(ctx, edge);
1487 MUTEX_LOCK(q_mutex);
1500 MUTEX_UNLOCK(q_mutex);
1508 MUTEX_LOCK(q_mutex);
1512 if (!nfthreads && nthreads < max_nfthreads) {
1515 if (THREAD_CREATE(thread, g_worker, NULL)) {
SERR(
"pthread_create"); }
1519 MUTEX_UNLOCK(q_mutex);
1523 g_output(
grn_ctx *ctx,
int flags,
void *arg)
1535 (flags &
GRN_CTX_MORE) ? GRN_CTX_MORE : GRN_CTX_TAIL)) {
1548 if ((edge = com->
opaque)) {
1549 MUTEX_LOCK(q_mutex);
1554 MUTEX_UNLOCK(q_mutex);
1580 g_dispatcher(ctx, edge);
1586 g_server(
char *path)
1588 int exit_code = EXIT_FAILURE;
1591 MUTEX_INIT(q_mutex);
1593 CRITICAL_SECTION_INIT(cache_lock);
1596 check_rlimit_nofile(ctx);
1597 exit_code = start_service(ctx, path, g_dispatcher, g_handler);
1613 #define MODE_MASK 0x007f
1614 #define MODE_USE_QL 0x0080
1615 #define MODE_NEW_DB 0x0100
1618 get_core_number(
void)
1622 GetSystemInfo(&sinfo);
1623 return sinfo.dwNumberOfProcessors;
1625 # ifdef _SC_NPROCESSORS_CONF
1626 return sysconf(_SC_NPROCESSORS_CONF);
1629 size_t length =
sizeof(n_processors);
1630 int mib[] = {CTL_HW, HW_NCPU};
1631 if (sysctl(mib,
sizeof(mib) /
sizeof(mib[0]),
1632 &n_processors, &length, NULL, 0) == 0 &&
1633 length ==
sizeof(n_processors) &&
1635 return n_processors;
1656 #define CONFIG_FILE_BUF_SIZE 4096
1657 #define CONFIG_FILE_MAX_NAME_LENGTH 128
1658 #define CONFIG_FILE_MAX_VALUE_LENGTH 2048
1679 config_file_clear(
void) {
1680 while (config_file_entry_head) {
1682 free(config_file_entry_head);
1683 config_file_entry_head =
next;
1689 int *flags,
const char *name,
size_t name_length,
1690 const char *value,
size_t value_length)
1696 name_buf[0] = name_buf[1] =
'-';
1697 strcpy(name_buf + 2, name);
1703 fprintf(stderr,
"memory allocation failed: %u bytes\n",
1704 (
unsigned int)entry_size);
1707 strcpy((
char *)(entry + 1), value);
1708 entry->
next = config_file_entry_head;
1709 if (!config_file_entry_head) {
1710 if (atexit(config_file_clear)) {
1715 config_file_entry_head = entry;
1718 args[0] = (
char *)path;
1720 args[2] = entry ? (
char *)(entry + 1) : NULL;
1728 int *flags,
char *buf) {
1729 char *ptr, *name, *value;
1730 size_t name_length, value_length;
1732 while (isspace(*buf)) {
1737 while (*ptr && *ptr !=
'#' && *ptr !=
';') {
1743 }
while (ptr >= buf && isspace(*ptr));
1750 while (*ptr && !isspace(*ptr) && *ptr !=
'=') {
1753 while (isspace(*ptr)) {
1757 name_length = strlen(name);
1758 if (name_length == 0) {
1761 fprintf(stderr,
"too long name in config file: %u bytes\n",
1762 (
unsigned int)name_length);
1768 while (isspace(*ptr)) {
1773 fprintf(stderr,
"invalid name in config file\n");
1779 value_length = value ? strlen(value) : 0;
1781 fprintf(stderr,
"too long value in config file: %u bytes\n",
1782 (
unsigned int)value_length);
1786 return config_file_register(path, opts, flags,
1787 name, name_length, value, value_length);
1796 FILE *
const file = fopen(path,
"rb");
1802 int c = fgetc(file);
1803 if (c ==
'\r' || c ==
'\n' || c == EOF) {
1804 if (length <
sizeof(buf) - 1) {
1806 status = config_file_parse(path, opts, flags, buf);
1812 }
else if (c ==
'\0') {
1813 fprintf(stderr,
"prohibited '\\0' in config file: %s\n", path);
1817 if (length <
sizeof(buf) - 1) {
1818 buf[length] = (char)c;
1837 static const char *
const default_protocol =
"gqtp";
1838 static const char *default_hostname =
"localhost";
1839 static const char *
const default_dest =
"localhost";
1840 static const char *default_log_path =
"";
1841 static const char *default_query_log_path =
"";
1842 static const char *default_config_path =
"";
1843 static const char *default_document_root =
"";
1846 static int64_t default_default_match_escalation_threshold = 0;
1847 static const char *
const default_bind_address =
"0.0.0.0";
1850 init_default_hostname(
void)
1853 struct addrinfo hints, *result;
1859 memset(&hints, 0,
sizeof(hints));
1860 hints.ai_family = AF_UNSPEC;
1861 hints.ai_socktype = SOCK_STREAM;
1862 hints.ai_addr = NULL;
1863 hints.ai_canonname = NULL;
1864 hints.ai_next = NULL;
1865 if (getaddrinfo(hostname, NULL, &hints, &result) != 0)
1867 freeaddrinfo(result);
1869 default_hostname = hostname;
1873 init_default_settings(
void)
1880 const uint32_t num_cores = get_core_number();
1881 if (num_cores != 0) {
1882 default_max_num_threads = num_cores;
1886 init_default_hostname();
1891 default_config_path = getenv(
"GRN_CONFIG_PATH");
1892 if (!default_config_path) {
1894 if (!default_config_path) {
1895 default_config_path =
"";
1901 static char win32_default_document_root[
PATH_MAX];
1903 strlen(GRN_DEFAULT_RELATIVE_DOCUMENT_ROOT) + 1;
1904 if (document_root_length >=
PATH_MAX) {
1905 fprintf(stderr,
"can't use default root: too long path\n");
1908 strcat(win32_default_document_root,
"/");
1909 strcat(win32_default_document_root, GRN_DEFAULT_RELATIVE_DOCUMENT_ROOT);
1910 default_document_root = win32_default_document_root;
1914 default_document_root = GRN_DEFAULT_DOCUMENT_ROOT;
1918 default_default_match_escalation_threshold =
1932 fprintf(out,
"%s=%s\n", o->
longopt, *o->
arg);
1937 if (flags & o->
flag) {
1942 if (!(flags & o->
flag)) {
1947 if (flags == o->
flag) {
1950 fprintf(out,
"%s\n", o->
longopt);
1974 printf(
",match-escalation-threshold=%" GRN_FMT_LLD,
1980 #ifdef GRN_WITH_MECAB
1983 #ifdef GRN_WITH_MESSAGE_PACK
2003 #ifdef CONFIGURE_OPTIONS
2010 show_usage(FILE *output)
2015 "Usage: groonga [options...] [dest]\n"
2017 "Mode options: (default: standalone)\n"
2018 " By default, groonga runs in standalone mode.\n"
2019 " -c: run in client mode\n"
2020 " -s: run in server mode\n"
2021 " -d: run in daemon mode\n"
2023 "Database creation options:\n"
2024 " -n: create new database (except client mode)\n"
2025 " -e, --encoding <encoding>:\n"
2026 " specify encoding for new database\n"
2027 " [none|euc|utf8|sjis|latin1|koi8r] (default: %s)\n"
2029 "Standalone/client options:\n"
2030 " --file <path>: read commands from specified file\n"
2031 " --input-fd <FD>: read commands from specified file descriptor\n"
2032 " --file has a prioriry over --input-fd\n"
2033 " --output-fd <FD>: output response to specifid file descriptor\n"
2034 " -p, --port <port number>: specify server port number (client mode only)\n"
2037 "Server/daemon options:\n"
2038 " --bind-address <ip/hostname>:\n"
2039 " specify server address to bind\n"
2041 " -p, --port <port number>: specify server port number (default: %d)\n"
2042 " -i, --server-id <ip/hostname>:\n"
2043 " specify server ID address (default: %s)\n"
2044 " --protocol <protocol>: specify server protocol to listen\n"
2045 " [gqtp|http|memcached] (default: %s)\n"
2046 " --document-root <path>: specify document root path (http only)\n"
2048 " --cache-limit <limit>: specify max number of cache data (default: %u)\n"
2049 " -t, --max-threads <max threads>:\n"
2050 " specify max number of threads (default: %u)\n"
2051 " --pid-path <path>: specify file to write process ID to\n"
2052 " (daemon mode only)\n"
2054 "Logging options:\n"
2055 " -l, --log-level <log level>:\n"
2056 " specify log level (default: %d)\n"
2057 " --log-path <path>: specify log path\n"
2059 " --query-log-path <path>:\n"
2060 " specify query log path\n"
2064 " --working-directory <path>:\n"
2065 " specify working directory path\n"
2067 " --config-path <path>:\n"
2068 " specify config file path\n"
2070 " --default-command-version <version>:\n"
2071 " specify default command version (default: %d)\n"
2072 " --default-match-escalation-threshold <threshold>:\n"
2073 " specify default match escalation threshold"
2076 " --show-config: show config\n"
2077 " -h, --help: show usage\n"
2078 " --version: show groonga version\n"
2081 " <db pathname> [<commands>]: in standalone mode\n"
2082 " <db pathname>: in server/daemon mode\n"
2083 " <dest hostname> [<commands>]: in client mode (default: %s)\n",
2085 default_port, default_bind_address,
2086 default_port, default_hostname, default_protocol,
2087 default_document_root, default_cache_limit, default_max_num_threads,
2088 default_log_level, default_log_path, default_query_log_path,
2089 default_config_path, default_default_command_version,
2090 (
long long int)default_default_match_escalation_threshold,
2097 const char *port_arg = NULL, *encoding_arg = NULL,
2098 *max_num_threads_arg = NULL, *log_level_arg = NULL,
2099 *bind_address_arg = NULL, *hostname_arg = NULL, *protocol_arg = NULL,
2100 *log_path_arg = NULL, *query_log_path_arg = NULL,
2101 *cache_limit_arg = NULL, *document_root_arg = NULL,
2102 *default_command_version_arg = NULL,
2103 *default_match_escalation_threshold_arg = NULL,
2104 *input_fd_arg = NULL, *output_fd_arg = NULL,
2105 *working_directory_arg = NULL;
2106 const char *config_path = NULL;
2107 int exit_code = EXIT_SUCCESS;
2109 uint32_t cache_limit = 0;
2133 {
'\0',
"default-match-escalation-threshold", NULL, 0,
GETOPT_OP_NONE},
2138 {
'\0', NULL, NULL, 0, 0}
2140 opts[0].
arg = &port_arg;
2141 opts[1].
arg = &encoding_arg;
2142 opts[2].
arg = &max_num_threads_arg;
2143 opts[7].
arg = &log_level_arg;
2144 opts[8].
arg = &hostname_arg;
2145 opts[11].
arg = &protocol_arg;
2146 opts[13].
arg = &log_path_arg;
2147 opts[14].
arg = &query_log_path_arg;
2148 opts[15].
arg = &pid_file_path;
2149 opts[16].
arg = &config_path;
2150 opts[18].
arg = &cache_limit_arg;
2151 opts[19].
arg = &input_path;
2152 opts[20].
arg = &document_root_arg;
2153 opts[21].
arg = &default_command_version_arg;
2154 opts[22].
arg = &default_match_escalation_threshold_arg;
2155 opts[23].
arg = &bind_address_arg;
2156 opts[24].
arg = &input_fd_arg;
2157 opts[25].
arg = &output_fd_arg;
2158 opts[26].
arg = &working_directory_arg;
2160 reset_ready_notify_pipe();
2162 init_default_settings();
2168 return EXIT_FAILURE;
2174 fprintf(stderr,
"%s: can't open config file: %s (%s)\n",
2175 argv[0], config_path, strerror(errno));
2176 return EXIT_FAILURE;
2178 fprintf(stderr,
"%s: failed to parse config file: %s (%s)\n",
2179 argv[0], config_path,
2181 return EXIT_FAILURE;
2183 }
else if (*default_config_path) {
2185 config_file_load(default_config_path, opts, &mode);
2187 fprintf(stderr,
"%s: failed to parse config file: %s (%s)\n",
2188 argv[0], default_config_path,
2190 return EXIT_FAILURE;
2194 if (working_directory_arg) {
2195 if (chdir(working_directory_arg) == -1) {
2196 fprintf(stderr,
"%s: failed to change directory: %s: %s\n",
2197 argv[0], working_directory_arg, strerror(errno));
2198 return EXIT_FAILURE;
2211 return EXIT_SUCCESS;
2214 return EXIT_SUCCESS;
2216 show_config(output, opts, mode & ~MODE_MASK);
2217 return EXIT_SUCCESS;
2220 return EXIT_FAILURE;
2224 const char *
const end = port_arg + strlen(port_arg);
2225 const char *rest = NULL;
2226 const int value =
grn_atoi(port_arg, end, &rest);
2227 if (rest != end || value <= 0 || value > 65535) {
2228 fprintf(stderr,
"invalid port number: <%s>\n", port_arg);
2229 return EXIT_FAILURE;
2233 port = default_port;
2237 switch (*encoding_arg) {
2275 switch (*protocol_arg) {
2278 do_client = g_client;
2279 do_server = g_server;
2283 do_client = g_client;
2284 do_server = h_server;
2288 do_client = g_client;
2289 do_server = g_server;
2292 do_client = g_client;
2293 do_server = g_server;
2297 do_client = g_client;
2298 do_server = g_server;
2305 if (query_log_path_arg) {
2309 if (log_level_arg) {
2310 const char *
const end = log_level_arg + strlen(log_level_arg);
2311 const char *rest = NULL;
2312 const int value =
grn_atoi(log_level_arg, end, &rest);
2313 if (end != rest || value < 0 || value > 9) {
2314 fprintf(stderr,
"invalid log level: <%s>\n", log_level_arg);
2315 return EXIT_FAILURE;
2319 log_level = default_log_level;
2323 if (max_num_threads_arg) {
2324 const char *
const end = max_num_threads_arg + strlen(max_num_threads_arg);
2325 const char *rest = NULL;
2326 const uint32_t value =
grn_atoui(max_num_threads_arg, end, &rest);
2327 if (end != rest || value < 1 || value > 100) {
2328 fprintf(stderr,
"invalid max number of threads: <%s>\n",
2329 max_num_threads_arg);
2330 return EXIT_FAILURE;
2332 max_nfthreads = value;
2334 max_nfthreads = default_max_num_threads;
2338 if (!freopen(input_path,
"r", stdin)) {
2339 fprintf(stderr,
"can't open input file: %s (%s)\n",
2340 input_path, strerror(errno));
2341 return EXIT_FAILURE;
2346 const char *
const end = input_fd_arg + strlen(input_fd_arg);
2347 const char *rest = NULL;
2348 const int input_fd =
grn_atoi(input_fd_arg, end, &rest);
2349 if (rest != end || input_fd == 0) {
2350 fprintf(stderr,
"invalid input FD: <%s>\n", input_fd_arg);
2351 return EXIT_FAILURE;
2354 fprintf(stderr,
"can't open input FD: %d (%s)\n",
2355 input_fd, strerror(errno));
2356 return EXIT_FAILURE;
2363 batchmode = !isatty(0);
2368 if (output_fd_arg) {
2369 const char *
const end = output_fd_arg + strlen(output_fd_arg);
2370 const char *rest = NULL;
2371 const int output_fd =
grn_atoi(output_fd_arg, end, &rest);
2372 if (rest != end || output_fd == 0) {
2373 fprintf(stderr,
"invalid output FD: <%s>\n", output_fd_arg);
2374 return EXIT_FAILURE;
2376 output = fdopen(output_fd,
"w");
2378 fprintf(stderr,
"can't open output FD: %d (%s)\n",
2379 output_fd, strerror(errno));
2380 return EXIT_FAILURE;
2385 if (bind_address_arg) {
2386 const size_t bind_address_length = strlen(bind_address_arg);
2388 fprintf(stderr,
"too long bind address: %s (%u bytes):"
2389 " must not be longer than %u bytes\n",
2390 bind_address_arg, (
unsigned int)bind_address_length,
HOST_NAME_MAX);
2391 return EXIT_FAILURE;
2393 strcpy(bind_address, bind_address_arg);
2395 strcpy(bind_address, default_bind_address);
2399 const size_t hostname_length = strlen(hostname_arg);
2401 fprintf(stderr,
"too long hostname: %s (%u bytes):"
2402 " must not be longer than %u bytes\n",
2403 hostname_arg, (
unsigned int)hostname_length,
HOST_NAME_MAX);
2404 return EXIT_FAILURE;
2406 strcpy(hostname, hostname_arg);
2408 strcpy(hostname, default_hostname);
2411 if (document_root_arg) {
2415 if (default_command_version_arg) {
2416 const char *
const end = default_command_version_arg
2417 + strlen(default_command_version_arg);
2418 const char *rest = NULL;
2419 const int value =
grn_atoi(default_command_version_arg, end, &rest);
2422 fprintf(stderr,
"invalid command version: <%s>\n",
2423 default_command_version_arg);
2424 return EXIT_FAILURE;
2434 fprintf(stderr,
"invalid command version: <%s>\n",
2435 default_command_version_arg);
2436 return EXIT_FAILURE;
2439 default_command_version = default_default_command_version;
2442 if (default_match_escalation_threshold_arg) {
2443 const char *
const end = default_match_escalation_threshold_arg
2444 + strlen(default_match_escalation_threshold_arg);
2445 const char *rest = NULL;
2446 const int64_t value =
grn_atoll(default_match_escalation_threshold_arg, end, &rest);
2448 fprintf(stderr,
"invalid match escalation threshold: <%s>\n",
2449 default_match_escalation_threshold_arg);
2450 return EXIT_FAILURE;
2452 default_match_escalation_threshold = value;
2454 default_match_escalation_threshold = default_default_match_escalation_threshold;
2457 if (cache_limit_arg) {
2458 const char *
const end = cache_limit_arg + strlen(cache_limit_arg);
2459 const char *rest = NULL;
2460 const uint32_t value =
grn_atoui(cache_limit_arg, end, &rest);
2462 fprintf(stderr,
"invalid --cache-limit value: <%s>\n", cache_limit_arg);
2463 return EXIT_FAILURE;
2465 cache_limit = value;
2468 #ifdef GRN_WITH_LIBEDIT
2470 line_editor_init(argc, argv);
2473 if (
grn_init()) {
return EXIT_FAILURE; }
2477 if (default_command_version_arg) {
2481 if (default_match_escalation_threshold_arg) {
2489 if (cache_limit_arg) {
2497 switch (mode & MODE_MASK) {
2499 exit_code = do_alone(argc - i, argv + i);
2502 exit_code = do_client(argc - i, argv + i);
2508 exit_code = do_server(argc > i ? argv[i] : NULL);
2511 exit_code = EXIT_FAILURE;
2515 #ifdef GRN_WITH_LIBEDIT
2520 if (output != stdout) {