Line data Source code
1 : /*
2 : SSSD
3 :
4 : Servers setup routines
5 :
6 : Copyright (C) Andrew Tridgell 1992-2005
7 : Copyright (C) Martin Pool 2002
8 : Copyright (C) Jelmer Vernooij 2002
9 : Copyright (C) James J Myers 2003 <myersjj@samba.org>
10 : Copyright (C) Simo Sorce 2008
11 :
12 : This program is free software; you can redistribute it and/or modify
13 : it under the terms of the GNU General Public License as published by
14 : the Free Software Foundation; either version 3 of the License, or
15 : (at your option) any later version.
16 :
17 : This program is distributed in the hope that it will be useful,
18 : but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : GNU General Public License for more details.
21 :
22 : You should have received a copy of the GNU General Public License
23 : along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : */
25 :
26 : #include <sys/types.h>
27 : #include <sys/wait.h>
28 : #include <sys/stat.h>
29 : #include <fcntl.h>
30 : #include <unistd.h>
31 : #include <ldb.h>
32 : #include "util/util.h"
33 : #include "confdb/confdb.h"
34 : #include "monitor/monitor_interfaces.h"
35 :
36 : #ifdef HAVE_PRCTL
37 : #include <sys/prctl.h>
38 : #endif
39 :
40 : /*******************************************************************
41 : Close the low 3 fd's and open dev/null in their place.
42 : ********************************************************************/
43 0 : static void close_low_fds(void)
44 : {
45 : #ifndef VALGRIND
46 : int fd;
47 : int i;
48 :
49 0 : close(0);
50 0 : close(1);
51 0 : close(2);
52 :
53 : /* try and use up these file descriptors, so silly
54 : library routines writing to stdout etc won't cause havoc */
55 0 : for (i = 0; i < 3; i++) {
56 0 : fd = open("/dev/null", O_RDWR, 0);
57 0 : if (fd < 0)
58 0 : fd = open("/dev/null", O_WRONLY, 0);
59 0 : if (fd < 0) {
60 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Can't open /dev/null\n");
61 0 : return;
62 : }
63 0 : if (fd != i) {
64 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Didn't get file descriptor %d\n",i);
65 0 : return;
66 : }
67 : }
68 : #endif
69 : }
70 :
71 0 : static void deamon_parent_sigterm(int sig)
72 : {
73 0 : _exit(0);
74 : }
75 :
76 : /**
77 : Become a daemon, discarding the controlling terminal.
78 : **/
79 :
80 0 : void become_daemon(bool Fork)
81 : {
82 : pid_t pid, cpid;
83 : int status;
84 : int ret, error;
85 :
86 0 : if (Fork) {
87 0 : pid = fork();
88 0 : if (pid != 0) {
89 : /* Terminate parent process on demand so we can hold systemd
90 : * or initd from starting next service until sssd in initialized.
91 : * We use signals directly here because we don't have a tevent
92 : * context yet. */
93 0 : CatchSignal(SIGTERM, deamon_parent_sigterm);
94 :
95 : /* or exit when sssd monitor is terminated */
96 : do {
97 0 : errno = 0;
98 0 : cpid = waitpid(pid, &status, 0);
99 0 : if (cpid == 1) {
100 : /* An error occurred while waiting */
101 0 : error = errno;
102 0 : if (error != EINTR) {
103 0 : DEBUG(SSSDBG_CRIT_FAILURE,
104 : "Error [%d][%s] while waiting for child\n",
105 : error, strerror(error));
106 : /* Forcibly kill this child */
107 0 : kill(pid, SIGKILL);
108 0 : ret = 1;
109 : }
110 : }
111 :
112 0 : error = 0;
113 : /* return error if we didn't exited normally */
114 0 : ret = 1;
115 :
116 0 : if (WIFEXITED(status)) {
117 : /* but return our exit code otherwise */
118 0 : ret = WEXITSTATUS(status);
119 : }
120 0 : } while (error == EINTR);
121 :
122 0 : _exit(ret);
123 : }
124 : }
125 :
126 : /* detach from the terminal */
127 0 : setsid();
128 :
129 : /* chdir to / to be sure we're not on a remote filesystem */
130 0 : errno = 0;
131 0 : if(chdir("/") == -1) {
132 0 : ret = errno;
133 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Cannot change directory (%d [%s])\n",
134 : ret, strerror(ret));
135 0 : return;
136 : }
137 :
138 : /* Close fd's 0,1,2. Needed if started by rsh */
139 0 : close_low_fds();
140 : }
141 :
142 0 : int pidfile(const char *path, const char *name)
143 : {
144 : char pid_str[32];
145 : pid_t pid;
146 : char *file;
147 : int fd;
148 : int ret, err;
149 : ssize_t len;
150 : size_t size;
151 : ssize_t written;
152 0 : ssize_t pidlen = sizeof(pid_str) - 1;
153 :
154 0 : file = talloc_asprintf(NULL, "%s/%s.pid", path, name);
155 0 : if (!file) {
156 0 : return ENOMEM;
157 : }
158 :
159 0 : fd = open(file, O_RDONLY, 0644);
160 0 : err = errno;
161 0 : if (fd != -1) {
162 0 : errno = 0;
163 0 : len = sss_atomic_read_s(fd, pid_str, pidlen);
164 0 : ret = errno;
165 0 : if (len == -1) {
166 0 : DEBUG(SSSDBG_CRIT_FAILURE,
167 : "read failed [%d][%s].\n", ret, strerror(ret));
168 0 : close(fd);
169 0 : talloc_free(file);
170 0 : return EINVAL;
171 : }
172 :
173 : /* Ensure NULL-termination */
174 0 : pid_str[len] = '\0';
175 :
176 : /* let's check the pid */
177 0 : pid = (pid_t)atoi(pid_str);
178 0 : if (pid != 0) {
179 0 : errno = 0;
180 0 : ret = kill(pid, 0);
181 : /* succeeded in signaling the process -> another sssd process */
182 0 : if (ret == 0) {
183 0 : close(fd);
184 0 : talloc_free(file);
185 0 : return EEXIST;
186 : }
187 0 : if (ret != 0 && errno != ESRCH) {
188 0 : err = errno;
189 0 : close(fd);
190 0 : talloc_free(file);
191 0 : return err;
192 : }
193 : }
194 :
195 : /* nothing in the file or no process */
196 0 : close(fd);
197 0 : ret = unlink(file);
198 : /* non-fatal failure */
199 0 : if (ret != EOK) {
200 0 : ret = errno;
201 0 : DEBUG(SSSDBG_MINOR_FAILURE,
202 : "Failed to remove file: %s - %d [%s]!\n",
203 : file, ret, sss_strerror(ret));
204 : }
205 : } else {
206 0 : if (err != ENOENT) {
207 0 : talloc_free(file);
208 0 : return err;
209 : }
210 : }
211 :
212 0 : fd = open(file, O_CREAT | O_WRONLY | O_EXCL, 0644);
213 0 : err = errno;
214 0 : if (fd == -1) {
215 0 : talloc_free(file);
216 0 : return err;
217 : }
218 0 : talloc_free(file);
219 :
220 0 : memset(pid_str, 0, sizeof(pid_str));
221 0 : snprintf(pid_str, sizeof(pid_str) -1, "%u\n", (unsigned int) getpid());
222 0 : size = strlen(pid_str);
223 :
224 0 : errno = 0;
225 0 : written = sss_atomic_write_s(fd, pid_str, size);
226 0 : if (written == -1) {
227 0 : err = errno;
228 0 : DEBUG(SSSDBG_CRIT_FAILURE,
229 : "write failed [%d][%s]\n", err, strerror(err));
230 0 : close(fd);
231 0 : return err;
232 : }
233 :
234 0 : if (written != size) {
235 0 : DEBUG(SSSDBG_CRIT_FAILURE,
236 : "Wrote %zd bytes expected %zu\n", written, size);
237 0 : close(fd);
238 0 : return EIO;
239 : }
240 :
241 0 : close(fd);
242 :
243 0 : return 0;
244 : }
245 :
246 0 : void orderly_shutdown(int status)
247 : {
248 : #if HAVE_GETPGRP
249 : static int sent_sigterm;
250 0 : if (sent_sigterm == 0 && getpgrp() == getpid()) {
251 0 : DEBUG(SSSDBG_FATAL_FAILURE, "SIGTERM: killing children\n");
252 0 : sent_sigterm = 1;
253 0 : kill(-getpgrp(), SIGTERM);
254 : }
255 : #endif
256 0 : if (status == 0) sss_log(SSS_LOG_INFO, "Shutting down");
257 0 : exit(status);
258 : }
259 :
260 0 : static void default_quit(struct tevent_context *ev,
261 : struct tevent_signal *se,
262 : int signum,
263 : int count,
264 : void *siginfo,
265 : void *private_data)
266 : {
267 0 : orderly_shutdown(0);
268 0 : }
269 :
270 : #ifndef HAVE_PRCTL
271 : static void sig_segv_abrt(int sig)
272 : {
273 : DEBUG(SSSDBG_FATAL_FAILURE,
274 : "Received signal %s, shutting down\n", strsignal(sig));
275 : orderly_shutdown(1);
276 : }
277 : #endif /* HAVE_PRCTL */
278 :
279 : /*
280 : setup signal masks
281 : */
282 0 : static void setup_signals(void)
283 : {
284 : /* we are never interested in SIGPIPE */
285 0 : BlockSignals(true, SIGPIPE);
286 :
287 : #if defined(SIGFPE)
288 : /* we are never interested in SIGFPE */
289 0 : BlockSignals(true, SIGFPE);
290 : #endif
291 :
292 : /* We are no longer interested in USR1 */
293 0 : BlockSignals(true, SIGUSR1);
294 :
295 : /* We are no longer interested in SIGINT except for monitor */
296 0 : BlockSignals(true, SIGINT);
297 :
298 : #if defined(SIGUSR2)
299 : /* We are no longer interested in USR2 */
300 0 : BlockSignals(true, SIGUSR2);
301 : #endif
302 :
303 : /* POSIX demands that signals are inherited. If the invoking process has
304 : * these signals masked, we will have problems, as we won't receive them. */
305 0 : BlockSignals(false, SIGHUP);
306 0 : BlockSignals(false, SIGTERM);
307 :
308 : #ifndef HAVE_PRCTL
309 : /* If prctl is not defined on the system, try to handle
310 : * some common termination signals gracefully */
311 : CatchSignal(SIGSEGV, sig_segv_abrt);
312 : CatchSignal(SIGABRT, sig_segv_abrt);
313 : #endif
314 :
315 0 : }
316 :
317 : /*
318 : handle io on stdin
319 : */
320 0 : static void server_stdin_handler(struct tevent_context *event_ctx,
321 : struct tevent_fd *fde,
322 : uint16_t flags, void *private)
323 : {
324 0 : const char *binary_name = (const char *)private;
325 : uint8_t c;
326 :
327 0 : errno = 0;
328 0 : if (sss_atomic_read_s(0, &c, 1) == 0) {
329 0 : DEBUG(SSSDBG_CRIT_FAILURE, "%s: EOF on stdin - terminating\n",
330 : binary_name);
331 : #if HAVE_GETPGRP
332 0 : if (getpgrp() == getpid()) {
333 0 : kill(-getpgrp(), SIGTERM);
334 : }
335 : #endif
336 0 : exit(0);
337 : }
338 0 : }
339 :
340 : /*
341 : main server helpers.
342 : */
343 :
344 0 : int die_if_parent_died(void)
345 : {
346 : #ifdef HAVE_PRCTL
347 : int ret;
348 :
349 0 : errno = 0;
350 0 : ret = prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
351 0 : if (ret != 0) {
352 0 : ret = errno;
353 0 : DEBUG(SSSDBG_OP_FAILURE, "prctl failed [%d]: %s\n",
354 : ret, strerror(ret));
355 0 : return ret;
356 : }
357 : #endif
358 0 : return EOK;
359 : }
360 :
361 : struct logrotate_ctx {
362 : struct confdb_ctx *confdb;
363 : const char *confdb_path;
364 : };
365 :
366 0 : static void te_server_hup(struct tevent_context *ev,
367 : struct tevent_signal *se,
368 : int signum,
369 : int count,
370 : void *siginfo,
371 : void *private_data)
372 : {
373 : errno_t ret;
374 0 : struct logrotate_ctx *lctx =
375 : talloc_get_type(private_data, struct logrotate_ctx);
376 :
377 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Received SIGHUP. Rotating logfiles.\n");
378 :
379 0 : ret = server_common_rotate_logs(lctx->confdb, lctx->confdb_path);
380 0 : if (ret != EOK) {
381 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Could not reopen log file [%s]\n",
382 : strerror(ret));
383 : }
384 0 : }
385 :
386 0 : errno_t server_common_rotate_logs(struct confdb_ctx *confdb,
387 : const char *conf_path)
388 : {
389 : errno_t ret;
390 0 : int old_debug_level = debug_level;
391 :
392 0 : ret = rotate_debug_files();
393 0 : if (ret) {
394 0 : sss_log(SSS_LOG_ALERT, "Could not rotate debug files! [%d][%s]\n",
395 : ret, strerror(ret));
396 0 : return ret;
397 : }
398 :
399 : /* Get new debug level from the confdb */
400 0 : ret = confdb_get_int(confdb, conf_path,
401 : CONFDB_SERVICE_DEBUG_LEVEL,
402 : old_debug_level,
403 : &debug_level);
404 0 : if (ret != EOK) {
405 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) [%s]\n",
406 : ret, strerror(ret));
407 : /* Try to proceed with the old value */
408 0 : debug_level = old_debug_level;
409 : }
410 :
411 0 : if (debug_level != old_debug_level) {
412 0 : DEBUG(SSSDBG_FATAL_FAILURE,
413 : "Debug level changed to %#.4x\n", debug_level);
414 0 : debug_level = debug_convert_old_level(debug_level);
415 : }
416 :
417 0 : return EOK;
418 : }
419 :
420 0 : static const char *get_db_path(void)
421 : {
422 : #ifdef UNIT_TESTING
423 : #ifdef TEST_DB_PATH
424 : return TEST_DB_PATH;
425 : #else
426 : #error "TEST_DB_PATH must be defined when unit testing server.c!"
427 : #endif /* TEST_DB_PATH */
428 : #else
429 0 : return DB_PATH;
430 : #endif /* UNIT_TESTING */
431 : }
432 :
433 0 : static const char *get_pid_path(void)
434 : {
435 : #ifdef UNIT_TESTING
436 : #ifdef TEST_PID_PATH
437 : return TEST_PID_PATH;
438 : #else
439 : #error "TEST_PID_PATH must be defined when unit testing server.c!"
440 : #endif /* TEST_PID_PATH */
441 : #else
442 0 : return PID_PATH;
443 : #endif
444 : }
445 :
446 0 : int server_setup(const char *name, int flags,
447 : uid_t uid, gid_t gid,
448 : const char *conf_entry,
449 : struct main_context **main_ctx)
450 : {
451 : struct tevent_context *event_ctx;
452 : struct main_context *ctx;
453 : uint16_t stdin_event_flags;
454 : char *conf_db;
455 0 : int ret = EOK;
456 : bool dt;
457 : bool dl;
458 : bool dm;
459 : struct tevent_signal *tes;
460 : struct logrotate_ctx *lctx;
461 : char *locale;
462 :
463 0 : ret = chown_debug_file(NULL, uid, gid);
464 0 : if (ret != EOK) {
465 0 : DEBUG(SSSDBG_MINOR_FAILURE,
466 : "Cannot chown the debug files, debugging might not work!\n");
467 : }
468 :
469 0 : ret = become_user(uid, gid);
470 0 : if (ret != EOK) {
471 0 : DEBUG(SSSDBG_FUNC_DATA,
472 : "Cannot become user [%"SPRIuid"][%"SPRIgid"].\n", uid, gid);
473 0 : return ret;
474 : }
475 :
476 0 : debug_prg_name = strdup(name);
477 0 : if (!debug_prg_name) {
478 0 : return ENOMEM;
479 : }
480 :
481 0 : setenv("_SSS_LOOPS", "NO", 0);
482 :
483 : /* To make sure the domain cannot be set from the environment, unset the
484 : * variable explicitly when setting up any server. Backends later set the
485 : * value after reading domain from the configuration */
486 0 : ret = unsetenv(SSS_DOM_ENV);
487 0 : if (ret != 0) {
488 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Unsetting "SSS_DOM_ENV" failed, journald "
489 : "logging mightnot work as expected\n");
490 : }
491 :
492 0 : setup_signals();
493 :
494 : /* we want default permissions on created files to be very strict */
495 0 : umask(SSS_DFL_UMASK);
496 :
497 0 : if (flags & FLAGS_DAEMON) {
498 0 : DEBUG(SSSDBG_IMPORTANT_INFO, "Becoming a daemon.\n");
499 0 : become_daemon(true);
500 : }
501 :
502 0 : if (flags & FLAGS_PID_FILE) {
503 0 : ret = pidfile(get_pid_path(), name);
504 0 : if (ret != EOK) {
505 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Error creating pidfile: %s/%s.pid! "
506 : "(%d [%s])\n", get_pid_path(), name, ret, strerror(ret));
507 0 : return ret;
508 : }
509 : }
510 :
511 : /* Set up locale */
512 0 : locale = setlocale(LC_ALL, "");
513 0 : if (locale == NULL) {
514 : /* Just print debug message and continue */
515 0 : DEBUG(SSSDBG_TRACE_FUNC, "Unable to set locale\n");
516 : }
517 :
518 0 : bindtextdomain(PACKAGE, LOCALEDIR);
519 0 : textdomain(PACKAGE);
520 :
521 : /* the event context is the top level structure.
522 : * Everything else should hang off that */
523 0 : event_ctx = tevent_context_init(talloc_autofree_context());
524 0 : if (event_ctx == NULL) {
525 0 : DEBUG(SSSDBG_FATAL_FAILURE,
526 : "The event context initialiaziton failed\n");
527 0 : return 1;
528 : }
529 :
530 : /* Set up an event handler for a SIGINT */
531 0 : tes = tevent_add_signal(event_ctx, event_ctx, SIGINT, 0,
532 : default_quit, NULL);
533 0 : if (tes == NULL) {
534 0 : return EIO;
535 : }
536 :
537 : /* Set up an event handler for a SIGTERM */
538 0 : tes = tevent_add_signal(event_ctx, event_ctx, SIGTERM, 0,
539 : default_quit, NULL);
540 0 : if (tes == NULL) {
541 0 : return EIO;
542 : }
543 :
544 0 : ctx = talloc(event_ctx, struct main_context);
545 0 : if (ctx == NULL) {
546 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory, aborting!\n");
547 0 : return ENOMEM;
548 : }
549 :
550 0 : ctx->parent_pid = getppid();
551 0 : ctx->event_ctx = event_ctx;
552 :
553 0 : conf_db = talloc_asprintf(ctx, "%s/%s",
554 : get_db_path(), CONFDB_FILE);
555 0 : if (conf_db == NULL) {
556 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory, aborting!\n");
557 0 : return ENOMEM;
558 : }
559 :
560 0 : ret = confdb_init(ctx, &ctx->confdb_ctx, conf_db);
561 0 : if (ret != EOK) {
562 0 : DEBUG(SSSDBG_FATAL_FAILURE, "The confdb initialization failed\n");
563 0 : return ret;
564 : }
565 :
566 0 : if (debug_level == SSSDBG_UNRESOLVED) {
567 : /* set debug level if any in conf_entry */
568 0 : ret = confdb_get_int(ctx->confdb_ctx, conf_entry,
569 : CONFDB_SERVICE_DEBUG_LEVEL,
570 : SSSDBG_UNRESOLVED,
571 : &debug_level);
572 0 : if (ret != EOK) {
573 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) "
574 : "[%s]\n", ret, strerror(ret));
575 0 : return ret;
576 : }
577 :
578 0 : if (debug_level == SSSDBG_UNRESOLVED) {
579 : /* Check for the `debug` alias */
580 0 : ret = confdb_get_int(ctx->confdb_ctx, conf_entry,
581 : CONFDB_SERVICE_DEBUG_LEVEL_ALIAS,
582 : SSSDBG_DEFAULT,
583 : &debug_level);
584 0 : if (ret != EOK) {
585 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) "
586 : "[%s]\n", ret, strerror(ret));
587 0 : return ret;
588 : }
589 : }
590 :
591 0 : debug_level = debug_convert_old_level(debug_level);
592 : }
593 :
594 : /* same for debug timestamps */
595 0 : if (debug_timestamps == SSSDBG_TIMESTAMP_UNRESOLVED) {
596 0 : ret = confdb_get_bool(ctx->confdb_ctx, conf_entry,
597 : CONFDB_SERVICE_DEBUG_TIMESTAMPS,
598 : SSSDBG_TIMESTAMP_DEFAULT,
599 : &dt);
600 0 : if (ret != EOK) {
601 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) "
602 : "[%s]\n", ret, strerror(ret));
603 0 : return ret;
604 : }
605 0 : if (dt) debug_timestamps = 1;
606 0 : else debug_timestamps = 0;
607 : }
608 :
609 : /* same for debug microseconds */
610 0 : if (debug_microseconds == SSSDBG_MICROSECONDS_UNRESOLVED) {
611 0 : ret = confdb_get_bool(ctx->confdb_ctx, conf_entry,
612 : CONFDB_SERVICE_DEBUG_MICROSECONDS,
613 : SSSDBG_MICROSECONDS_DEFAULT,
614 : &dm);
615 0 : if (ret != EOK) {
616 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) "
617 : "[%s]\n", ret, strerror(ret));
618 0 : return ret;
619 : }
620 0 : if (dm) debug_microseconds = 1;
621 0 : else debug_microseconds = 0;
622 : }
623 :
624 : /* same for debug to file */
625 0 : dl = (debug_to_file != 0);
626 0 : ret = confdb_get_bool(ctx->confdb_ctx, conf_entry,
627 : CONFDB_SERVICE_DEBUG_TO_FILES,
628 : dl, &dl);
629 0 : if (ret != EOK) {
630 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) [%s]\n",
631 : ret, strerror(ret));
632 0 : return ret;
633 : }
634 0 : if (dl) debug_to_file = 1;
635 :
636 : /* before opening the log file set up log rotation */
637 0 : lctx = talloc_zero(ctx, struct logrotate_ctx);
638 0 : if (!lctx) return ENOMEM;
639 :
640 0 : lctx->confdb = ctx->confdb_ctx;
641 0 : lctx->confdb_path = conf_entry;
642 :
643 0 : tes = tevent_add_signal(ctx->event_ctx, ctx, SIGHUP, 0,
644 : te_server_hup, lctx);
645 0 : if (tes == NULL) {
646 0 : return EIO;
647 : }
648 :
649 : /* open log file if told so */
650 0 : if (debug_to_file) {
651 0 : ret = open_debug_file();
652 0 : if (ret != EOK) {
653 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Error setting up logging (%d) "
654 : "[%s]\n", ret, strerror(ret));
655 0 : return ret;
656 : }
657 : }
658 :
659 0 : sss_log(SSS_LOG_INFO, "Starting up");
660 :
661 0 : DEBUG(SSSDBG_TRACE_FUNC, "CONFDB: %s\n", conf_db);
662 :
663 0 : if (flags & FLAGS_INTERACTIVE) {
664 : /* terminate when stdin goes away */
665 0 : stdin_event_flags = TEVENT_FD_READ;
666 : } else {
667 : /* stay alive forever */
668 0 : stdin_event_flags = 0;
669 : }
670 :
671 : /* catch EOF on stdin */
672 : #ifdef SIGTTIN
673 0 : signal(SIGTTIN, SIG_IGN);
674 : #endif
675 0 : tevent_add_fd(event_ctx, event_ctx, STDIN_FILENO, stdin_event_flags,
676 : server_stdin_handler, discard_const(name));
677 :
678 0 : *main_ctx = ctx;
679 0 : return EOK;
680 : }
681 :
682 0 : void server_loop(struct main_context *main_ctx)
683 : {
684 : /* wait for events - this is where the server sits for most of its
685 : life */
686 0 : tevent_loop_wait(main_ctx->event_ctx);
687 :
688 : /* as everything hangs off this event context, freeing it
689 : should initiate a clean shutdown of all services */
690 0 : talloc_free(main_ctx->event_ctx);
691 0 : }
|