"Fossies" - the Fresh Open Source Software Archive 
Member "smbnetfs-0.6.3/src/process.c" (10 Jan 2015, 8629 Bytes) of package /linux/misc/smbnetfs-0.6.3.tar.bz2:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "process.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
0.5.3b_vs_0.6.0.
1 #include "config.h"
2 #include <errno.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/wait.h>
8 #include <sys/socket.h>
9 #include <signal.h>
10 #include <pthread.h>
11 #include <langinfo.h>
12
13 #include "common.h"
14 #include "list.h"
15 #include "smb_conn_proto.h"
16 #include "process.h"
17
18 #define CHARSET_LEN 64
19
20 struct process_rec{
21 LIST entries;
22 int child_fd;
23 pid_t child_pid;
24 };
25
26 static char process_system_charset[CHARSET_LEN] = "UTF-8";
27 static char process_server_local_charset[CHARSET_LEN] = "UTF-8";
28 static char process_server_samba_charset[CHARSET_LEN] = "UTF-8";
29 static int process_server_listen_timeout = 300;
30 static int process_server_smb_timeout = 20000;
31 static int process_server_smb_debug_level = 0;
32 static int process_start_enabled = 1;
33
34 static LIST process_list = STATIC_LIST_INITIALIZER(process_list);
35 static pthread_mutex_t m_process = PTHREAD_MUTEX_INITIALIZER;
36
37
38 int process_init(void){
39 static int initialized = 0;
40
41 char *charset;
42
43 if (! initialized){
44 if ((charset = nl_langinfo(CODESET)) == NULL){
45 DPRINTF(0, "Can't find system charset, use utf-8 instead. Check your locale.\n");
46 charset = "UTF-8";
47 }else{
48 initialized = 1;
49 }
50 strncpy(process_system_charset, charset, CHARSET_LEN);
51 process_system_charset[CHARSET_LEN - 1] = '\0';
52 DPRINTF(5, "system_charset=%s\n", process_system_charset);
53 }
54 pthread_mutex_lock(&m_process);
55 strncpy(process_server_local_charset, process_system_charset, CHARSET_LEN);
56 process_server_local_charset[CHARSET_LEN - 1] = '\0';
57 strncpy(process_server_samba_charset, "UTF-8", CHARSET_LEN);
58 process_server_samba_charset[CHARSET_LEN - 1] = '\0';
59 pthread_mutex_unlock(&m_process);
60 return initialized;
61 }
62
63 void process_disable_new_smb_conn_starting(void){
64 DPRINTF(7, "disable new process starting at %u\n", (unsigned int) time(NULL));
65 pthread_mutex_lock(&m_process);
66 process_start_enabled = 0;
67 pthread_mutex_unlock(&m_process);
68 }
69
70 int process_set_server_listen_timeout(int timeout){
71 if (timeout < 30) return 0;
72 DPRINTF(7, "timeout=%d\n", timeout);
73 pthread_mutex_lock(&m_process);
74 process_server_listen_timeout = timeout;
75 pthread_mutex_unlock(&m_process);
76 return 1;
77 }
78
79 int process_set_server_smb_timeout(int timeout){
80 if (timeout < 1000) return 0;
81 DPRINTF(7, "smb_timeout=%d\n", timeout);
82 pthread_mutex_lock(&m_process);
83 process_server_smb_timeout = timeout;
84 pthread_mutex_unlock(&m_process);
85 return 1;
86 }
87
88 int process_set_server_smb_debug_level(int level){
89 if ((level < 0) || (level > 10)) return 0;
90 DPRINTF(7, "level=%d\n", level);
91 pthread_mutex_lock(&m_process);
92 process_server_smb_debug_level = level;
93 pthread_mutex_unlock(&m_process);
94 return 1;
95 }
96
97 int process_set_server_local_charset(const char *charset){
98 if ((charset == NULL) || (*charset == '\0'))
99 charset = process_system_charset;
100
101 DPRINTF(7, "local_charset=%s\n", charset);
102 pthread_mutex_lock(&m_process);
103 strncpy(process_server_local_charset, charset, CHARSET_LEN);
104 process_server_local_charset[CHARSET_LEN - 1] = '\0';
105 pthread_mutex_unlock(&m_process);
106 return 1;
107 }
108
109 int process_set_server_samba_charset(const char *charset){
110 if ((charset == NULL) || (*charset == '\0')) charset = "UTF-8";
111
112 DPRINTF(7, "samba_charset=%s\n", charset);
113 pthread_mutex_lock(&m_process);
114 strncpy(process_server_samba_charset, charset, CHARSET_LEN);
115 process_server_samba_charset[CHARSET_LEN - 1] = '\0';
116 pthread_mutex_unlock(&m_process);
117 return 1;
118 }
119
120 int process_start_new_smb_conn(char *shmem_ptr, size_t shmem_size){
121 int error;
122 int debug_level;
123 int pair[2];
124 pid_t pid;
125 struct process_rec *rec;
126
127 if ((shmem_ptr == NULL) || (shmem_size < (size_t) getpagesize())){
128 errno = EINVAL;
129 return -1;
130 }
131
132 error = 0;
133 pid = (pid_t) (-1);
134 pthread_mutex_lock(&m_process);
135 if (process_start_enabled != 1){
136 error = EPERM;
137 pair[0] = -1;
138 goto error;
139 }
140 if ((rec = malloc(sizeof(struct process_rec))) == NULL){
141 error = errno;
142 pair[0] = -1;
143 DPRINTF(6, "starting new child failed on malloc(): errno=%d, %s\n",
144 errno, strerror(errno));
145 goto error;
146 }
147 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0){
148 DPRINTF(6, "using SOCK_DGRAM instead of SOCK_SEQPACKET\n");
149 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0){
150 error = errno;
151 free(rec);
152 pair[0] = -1;
153 DPRINTF(6, "starting new child failed on socketpair(): errno=%d, %s\n",
154 errno, strerror(errno));
155 goto error;
156 }
157 }
158
159 memset(rec, 0, sizeof(struct process_rec));
160 debug_level = common_get_smbnetfs_debug_level();
161
162 if ((pid = fork()) == -1){
163 error = errno;
164 close(pair[0]);
165 close(pair[1]);
166 free(rec);
167 pair[0] = -1;
168 DPRINTF(6, "starting new child failed on fork(): errno=%d, %s\n",
169 errno, strerror(errno));
170 goto error;
171 }
172
173 if (pid == 0){
174 struct smb_conn_srv_ctx srv_ctx;
175
176 pthread_mutex_unlock(&m_process);
177 close(pair[0]);
178
179 /* We are after fork here, so we are in single thread situation. *
180 * This mean we may read any variable without acquiring locks. *
181 * Moreover, we can NOT use safely any mutex protected code, *
182 * as the mutexes after the fork() are in UNKNOWN state */
183 srv_ctx.conn_fd = pair[1];
184 srv_ctx.shmem_ptr = shmem_ptr;
185 srv_ctx.shmem_size = shmem_size;
186 srv_ctx.timeout = process_server_listen_timeout;
187 srv_ctx.smb_timeout = process_server_smb_timeout;
188 srv_ctx.debug_level = debug_level;
189 srv_ctx.smb_debug_level = process_server_smb_debug_level;
190 srv_ctx.samba_charset = process_server_samba_charset;
191 srv_ctx.local_charset = process_server_local_charset;
192 smb_conn_srv_listen(&srv_ctx);
193 exit(EXIT_SUCCESS);
194 }
195
196 close(pair[1]);
197 rec->child_pid = pid;
198 rec->child_fd = pair[0];
199 add_to_list(&process_list, &rec->entries);
200 DPRINTF(6, "starting new child with pid=%d, fd=%d\n", (int) pid, pair[0]);
201
202 error:
203 pthread_mutex_unlock(&m_process);
204 errno = error;
205 return pair[0];
206 }
207
208 int process_is_smb_conn_alive(int fd){
209 int result;
210 LIST *elem;
211 struct process_rec *rec;
212
213 result = 0;
214 pthread_mutex_lock(&m_process);
215 elem = first_list_elem(&process_list);
216 while(is_valid_list_elem(&process_list, elem)){
217 rec = list_entry(elem, struct process_rec, entries);
218 elem = elem->next;
219
220 if ((rec->child_fd == fd) &&
221 (rec->child_pid != (pid_t) (-1))){
222 result = 1;
223 break;
224 }
225 }
226 pthread_mutex_unlock(&m_process);
227 return result;
228 }
229
230 void process_kill_all(void){
231 LIST *elem;
232 struct process_rec *rec;
233
234 pthread_mutex_lock(&m_process);
235 elem = first_list_elem(&process_list);
236 while(is_valid_list_elem(&process_list, elem)){
237 rec = list_entry(elem, struct process_rec, entries);
238 elem = elem->next;
239
240 if (rec->child_pid != (pid_t) (-1)){
241 DPRINTF(6, "kill child with pid=%d, fd=%d\n",
242 (int) rec->child_pid, rec->child_fd);
243 kill(rec->child_pid, SIGKILL);
244 }
245 }
246 pthread_mutex_unlock(&m_process);
247 }
248
249 void process_kill_by_smb_conn_fd(int fd){
250 LIST *elem;
251 struct process_rec *rec;
252
253 pthread_mutex_lock(&m_process);
254 elem = first_list_elem(&process_list);
255 while(is_valid_list_elem(&process_list, elem)){
256 rec = list_entry(elem, struct process_rec, entries);
257 elem = elem->next;
258
259 if (rec->child_fd == fd){
260 DPRINTF(6, "closing child connection with pid=%d, fd=%d\n",
261 (int) rec->child_pid, rec->child_fd);
262 close(rec->child_fd);
263 rec->child_fd = -1;
264 if (rec->child_pid == (pid_t) (-1)){
265 DPRINTF(6, "cleanup child record with fd=%d\n", fd);
266 remove_from_list(&process_list, &rec->entries);
267 free(rec);
268 }else
269 kill(rec->child_pid, SIGKILL);
270 break;
271 }
272 }
273 pthread_mutex_unlock(&m_process);
274 }
275
276 void process_cleanup_from_zombies(void){
277 pid_t pid;
278 LIST *elem;
279 struct process_rec *rec;
280
281 pthread_mutex_lock(&m_process);
282 while(1){
283 pid = waitpid((pid_t) (-1), NULL, WNOHANG);
284 if (pid <= 0) break;
285
286 elem = first_list_elem(&process_list);
287 while(is_valid_list_elem(&process_list, elem)){
288 rec = list_entry(elem, struct process_rec, entries);
289 elem = elem->next;
290
291 if (rec->child_pid == pid){
292 DPRINTF(6, "R.I.P. child with pid=%d, fd=%d\n",
293 (int) rec->child_pid, rec->child_fd);
294 rec->child_pid = (pid_t) (-1);
295 if (rec->child_fd == -1){
296 DPRINTF(6, "cleanup child record with pid=%d\n", (int) pid);
297 remove_from_list(&process_list, &rec->entries);
298 free(rec);
299 }
300 break;
301 }
302 }
303 }
304 pthread_mutex_unlock(&m_process);
305 }