Mercurial > dovecot > core-2.2
annotate src/master/dict-process.c @ 3885:b624b687fe13 HEAD
Create dict-server socket to base_dir.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 15 Jan 2006 12:07:32 +0200 |
parents | 928229f8b3e6 |
children | 1e37fad03602 |
rev | line source |
---|---|
3855 | 1 /* Copyright (C) 2006 Timo Sirainen */ |
2 | |
3 #include "common.h" | |
4 #include "ioloop.h" | |
5 #include "network.h" | |
6 #include "fd-close-on-exec.h" | |
7 #include "env-util.h" | |
8 #include "log.h" | |
9 #include "dict-process.h" | |
10 | |
11 #include <syslog.h> | |
12 #include <unistd.h> | |
13 #include <sys/stat.h> | |
14 | |
3885
b624b687fe13
Create dict-server socket to base_dir.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
15 #define DICT_SERVER_SOCKET_NAME "dict-server" |
3855 | 16 |
17 struct dict_process { | |
3885
b624b687fe13
Create dict-server socket to base_dir.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
18 char *path; |
3855 | 19 int fd; |
20 struct io *io; | |
21 }; | |
22 | |
23 static struct dict_process *process; | |
24 | |
25 static void dict_process_unlisten(struct dict_process *process); | |
26 | |
27 static int dict_process_start(struct dict_process *process) | |
28 { | |
29 struct log_io *log; | |
30 const char *executable; | |
31 int i, log_fd; | |
32 pid_t pid; | |
33 | |
34 log_fd = log_create_pipe(&log, 0); | |
35 if (log_fd < 0) | |
36 pid = -1; | |
37 else { | |
38 pid = fork(); | |
39 if (pid < 0) | |
40 i_error("fork() failed: %m"); | |
41 } | |
42 | |
43 if (pid < 0) { | |
44 (void)close(log_fd); | |
45 return -1; | |
46 } | |
47 | |
48 if (pid != 0) { | |
49 /* master */ | |
50 PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_DICT); | |
51 log_set_prefix(log, "dict: "); | |
52 (void)close(log_fd); | |
53 | |
54 dict_process_unlisten(process); | |
55 return 0; | |
56 } | |
57 log_set_prefix(log, "master-dict: "); | |
58 | |
59 /* set stdin and stdout to /dev/null, so anything written into it | |
60 gets ignored. */ | |
61 if (dup2(null_fd, 0) < 0) | |
62 i_fatal("dup2(stdin) failed: %m"); | |
63 if (dup2(null_fd, 1) < 0) | |
64 i_fatal("dup2(stdout) failed: %m"); | |
65 | |
66 /* stderr = log, 3 = listener */ | |
67 if (dup2(log_fd, 2) < 0) | |
68 i_fatal("dup2(stderr) failed: %m"); | |
69 if (dup2(process->fd, 3) < 0) | |
70 i_fatal("dup2(3) failed: %m"); | |
71 | |
72 for (i = 0; i <= 3; i++) | |
73 fd_close_on_exec(i, FALSE); | |
74 | |
75 child_process_init_env(); | |
76 env_put(t_strconcat("DICT_LISTEN_FROM_FD=", process->path, NULL)); | |
77 | |
78 /* make sure we don't leak syslog fd, but do it last so that | |
79 any errors above will be logged */ | |
80 closelog(); | |
81 | |
82 executable = PKG_LIBEXECDIR"/dict"; | |
83 client_process_exec(executable, ""); | |
84 i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable); | |
85 return -1; | |
86 } | |
87 | |
88 static void dict_process_listen_input(void *context) | |
89 { | |
90 struct dict_process *process = context; | |
91 | |
92 dict_process_start(process); | |
93 } | |
94 | |
95 static int dict_process_listen(struct dict_process *process) | |
96 { | |
97 mode_t old_umask; | |
98 int fd, i = 0; | |
99 | |
100 for (;;) { | |
101 old_umask = umask(0); | |
102 process->fd = net_listen_unix(process->path, 64); | |
103 umask(old_umask); | |
104 | |
105 if (process->fd != -1) | |
106 break; | |
107 | |
108 if (errno != EADDRINUSE || ++i == 2) { | |
109 i_error("net_listen_unix(%s) failed: %m", | |
110 process->path); | |
111 return -1; | |
112 } | |
113 | |
114 /* see if it really exists */ | |
115 fd = net_connect_unix(process->path); | |
116 if (fd != -1 || errno != ECONNREFUSED) { | |
117 if (fd != -1) (void)close(fd); | |
118 i_error("Socket already exists: %s", process->path); | |
119 return -1; | |
120 } | |
121 | |
122 /* delete and try again */ | |
123 if (unlink(process->path) < 0 && errno != ENOENT) { | |
124 i_error("unlink(%s) failed: %m", process->path); | |
125 return -1; | |
126 } | |
127 } | |
128 | |
129 fd_close_on_exec(process->fd, TRUE); | |
130 process->io = io_add(process->fd, IO_READ, | |
131 dict_process_listen_input, process); | |
132 | |
133 return process->fd != -1 ? 0 : -1; | |
134 } | |
135 | |
136 static void dict_process_unlisten(struct dict_process *process) | |
137 { | |
138 if (process->fd == -1) | |
139 return; | |
140 | |
141 if (close(process->fd) < 0) | |
142 i_error("close(dict) failed: %m"); | |
143 process->fd = -1; | |
144 | |
3879
928229f8b3e6
deinit, unref, destroy, close, free, etc. functions now take a pointer to
Timo Sirainen <tss@iki.fi>
parents:
3869
diff
changeset
|
145 io_remove(&process->io); |
3855 | 146 } |
147 | |
148 void dict_process_init(void) | |
149 { | |
150 process = i_new(struct dict_process, 1); | |
151 process->fd = -1; | |
3885
b624b687fe13
Create dict-server socket to base_dir.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
152 process->path = i_strconcat(settings_root->defaults->base_dir, |
b624b687fe13
Create dict-server socket to base_dir.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
153 DICT_SERVER_SOCKET_NAME, NULL); |
3855 | 154 (void)dict_process_listen(process); |
155 } | |
156 | |
157 void dict_process_deinit(void) | |
158 { | |
159 dict_process_unlisten(process); | |
3885
b624b687fe13
Create dict-server socket to base_dir.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
160 i_free(process->path); |
3855 | 161 i_free(process); |
162 } | |
163 | |
164 void dict_process_restart(void) | |
165 { | |
166 dict_process_deinit(); | |
167 dict_process_init(); | |
168 } |