| 1 | /* 
 | 
|---|
| 2 |    Unix SMB/CIFS implementation.
 | 
|---|
| 3 | 
 | 
|---|
| 4 |    Main SMB server 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 |    
 | 
|---|
| 11 |    This program is free software; you can redistribute it and/or modify
 | 
|---|
| 12 |    it under the terms of the GNU General Public License as published by
 | 
|---|
| 13 |    the Free Software Foundation; either version 3 of the License, or
 | 
|---|
| 14 |    (at your option) any later version.
 | 
|---|
| 15 |    
 | 
|---|
| 16 |    This program is distributed in the hope that it will be useful,
 | 
|---|
| 17 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 18 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 19 |    GNU General Public License for more details.
 | 
|---|
| 20 |    
 | 
|---|
| 21 |    You should have received a copy of the GNU General Public License
 | 
|---|
| 22 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
|---|
| 23 | */
 | 
|---|
| 24 | 
 | 
|---|
| 25 | #include "includes.h"
 | 
|---|
| 26 | #include "lib/events/events.h"
 | 
|---|
| 27 | #include "version.h"
 | 
|---|
| 28 | #include "lib/cmdline/popt_common.h"
 | 
|---|
| 29 | #include "system/dir.h"
 | 
|---|
| 30 | #include "system/filesys.h"
 | 
|---|
| 31 | #include "ntvfs/ntvfs.h"
 | 
|---|
| 32 | #include "ntptr/ntptr.h"
 | 
|---|
| 33 | #include "auth/gensec/gensec.h"
 | 
|---|
| 34 | #include "smbd/process_model.h"
 | 
|---|
| 35 | #include "param/secrets.h"
 | 
|---|
| 36 | #include "smbd/pidfile.h"
 | 
|---|
| 37 | #include "param/param.h"
 | 
|---|
| 38 | #include "dsdb/samdb/samdb.h"
 | 
|---|
| 39 | #include "auth/session.h"
 | 
|---|
| 40 | #include "lib/messaging/irpc.h"
 | 
|---|
| 41 | #include "librpc/gen_ndr/ndr_irpc.h"
 | 
|---|
| 42 | #include "cluster/cluster.h"
 | 
|---|
| 43 | 
 | 
|---|
| 44 | /*
 | 
|---|
| 45 |   recursively delete a directory tree
 | 
|---|
| 46 | */
 | 
|---|
| 47 | static void recursive_delete(const char *path)
 | 
|---|
| 48 | {
 | 
|---|
| 49 |         DIR *dir;
 | 
|---|
| 50 |         struct dirent *de;
 | 
|---|
| 51 | 
 | 
|---|
| 52 |         dir = opendir(path);
 | 
|---|
| 53 |         if (!dir) {
 | 
|---|
| 54 |                 return;
 | 
|---|
| 55 |         }
 | 
|---|
| 56 | 
 | 
|---|
| 57 |         for (de=readdir(dir);de;de=readdir(dir)) {
 | 
|---|
| 58 |                 char *fname;
 | 
|---|
| 59 |                 struct stat st;
 | 
|---|
| 60 | 
 | 
|---|
| 61 |                 if (ISDOT(de->d_name) || ISDOTDOT(de->d_name)) {
 | 
|---|
| 62 |                         continue;
 | 
|---|
| 63 |                 }
 | 
|---|
| 64 | 
 | 
|---|
| 65 |                 fname = talloc_asprintf(path, "%s/%s", path, de->d_name);
 | 
|---|
| 66 |                 if (stat(fname, &st) != 0) {
 | 
|---|
| 67 |                         continue;
 | 
|---|
| 68 |                 }
 | 
|---|
| 69 |                 if (S_ISDIR(st.st_mode)) {
 | 
|---|
| 70 |                         recursive_delete(fname);
 | 
|---|
| 71 |                         talloc_free(fname);
 | 
|---|
| 72 |                         continue;
 | 
|---|
| 73 |                 }
 | 
|---|
| 74 |                 if (unlink(fname) != 0) {
 | 
|---|
| 75 |                         DEBUG(0,("Unabled to delete '%s' - %s\n", 
 | 
|---|
| 76 |                                  fname, strerror(errno)));
 | 
|---|
| 77 |                         smb_panic("unable to cleanup tmp files");
 | 
|---|
| 78 |                 }
 | 
|---|
| 79 |                 talloc_free(fname);
 | 
|---|
| 80 |         }
 | 
|---|
| 81 |         closedir(dir);
 | 
|---|
| 82 | }
 | 
|---|
| 83 | 
 | 
|---|
| 84 | /*
 | 
|---|
| 85 |   cleanup temporary files. This is the new alternative to
 | 
|---|
| 86 |   TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not
 | 
|---|
| 87 |   efficient on unix systems due to the lack of scaling of the byte
 | 
|---|
| 88 |   range locking system. So instead of putting the burden on tdb to
 | 
|---|
| 89 |   cleanup tmp files, this function deletes them. 
 | 
|---|
| 90 | */
 | 
|---|
| 91 | static void cleanup_tmp_files(struct loadparm_context *lp_ctx)
 | 
|---|
| 92 | {
 | 
|---|
| 93 |         char *path;
 | 
|---|
| 94 |         TALLOC_CTX *mem_ctx = talloc_new(NULL);
 | 
|---|
| 95 | 
 | 
|---|
| 96 |         path = smbd_tmp_path(mem_ctx, lp_ctx, NULL);
 | 
|---|
| 97 | 
 | 
|---|
| 98 |         recursive_delete(path);
 | 
|---|
| 99 |         talloc_free(mem_ctx);
 | 
|---|
| 100 | }
 | 
|---|
| 101 | 
 | 
|---|
| 102 | static void sig_hup(int sig)
 | 
|---|
| 103 | {
 | 
|---|
| 104 |         debug_schedule_reopen_logs();
 | 
|---|
| 105 | }
 | 
|---|
| 106 | 
 | 
|---|
| 107 | static void sig_term(int sig)
 | 
|---|
| 108 | {
 | 
|---|
| 109 | #if HAVE_GETPGRP
 | 
|---|
| 110 |         static int done_sigterm;
 | 
|---|
| 111 |         if (done_sigterm == 0 && getpgrp() == getpid()) {
 | 
|---|
| 112 |                 DEBUG(0,("SIGTERM: killing children\n"));
 | 
|---|
| 113 |                 done_sigterm = 1;
 | 
|---|
| 114 |                 kill(-getpgrp(), SIGTERM);
 | 
|---|
| 115 |         }
 | 
|---|
| 116 | #endif
 | 
|---|
| 117 |         DEBUG(0,("Exiting pid %d on SIGTERM\n", (int)getpid()));
 | 
|---|
| 118 |         exit(0);
 | 
|---|
| 119 | }
 | 
|---|
| 120 | 
 | 
|---|
| 121 | /*
 | 
|---|
| 122 |   setup signal masks
 | 
|---|
| 123 | */
 | 
|---|
| 124 | static void setup_signals(void)
 | 
|---|
| 125 | {
 | 
|---|
| 126 |         /* we are never interested in SIGPIPE */
 | 
|---|
| 127 |         BlockSignals(true,SIGPIPE);
 | 
|---|
| 128 | 
 | 
|---|
| 129 | #if defined(SIGFPE)
 | 
|---|
| 130 |         /* we are never interested in SIGFPE */
 | 
|---|
| 131 |         BlockSignals(true,SIGFPE);
 | 
|---|
| 132 | #endif
 | 
|---|
| 133 | 
 | 
|---|
| 134 |         /* We are no longer interested in USR1 */
 | 
|---|
| 135 |         BlockSignals(true, SIGUSR1);
 | 
|---|
| 136 | 
 | 
|---|
| 137 | #if defined(SIGUSR2)
 | 
|---|
| 138 |         /* We are no longer interested in USR2 */
 | 
|---|
| 139 |         BlockSignals(true,SIGUSR2);
 | 
|---|
| 140 | #endif
 | 
|---|
| 141 | 
 | 
|---|
| 142 |         /* POSIX demands that signals are inherited. If the invoking process has
 | 
|---|
| 143 |          * these signals masked, we will have problems, as we won't recieve them. */
 | 
|---|
| 144 |         BlockSignals(false, SIGHUP);
 | 
|---|
| 145 |         BlockSignals(false, SIGTERM);
 | 
|---|
| 146 | 
 | 
|---|
| 147 |         CatchSignal(SIGHUP, sig_hup);
 | 
|---|
| 148 |         CatchSignal(SIGTERM, sig_term);
 | 
|---|
| 149 | }
 | 
|---|
| 150 | 
 | 
|---|
| 151 | /*
 | 
|---|
| 152 |   handle io on stdin
 | 
|---|
| 153 | */
 | 
|---|
| 154 | static void server_stdin_handler(struct tevent_context *event_ctx, struct tevent_fd *fde, 
 | 
|---|
| 155 |                                  uint16_t flags, void *private_data)
 | 
|---|
| 156 | {
 | 
|---|
| 157 |         const char *binary_name = (const char *)private_data;
 | 
|---|
| 158 |         uint8_t c;
 | 
|---|
| 159 |         if (read(0, &c, 1) == 0) {
 | 
|---|
| 160 |                 DEBUG(0,("%s: EOF on stdin - terminating\n", binary_name));
 | 
|---|
| 161 | #if HAVE_GETPGRP
 | 
|---|
| 162 |                 if (getpgrp() == getpid()) {
 | 
|---|
| 163 |                         DEBUG(0,("Sending SIGTERM from pid %d\n", (int)getpid()));
 | 
|---|
| 164 |                         kill(-getpgrp(), SIGTERM);
 | 
|---|
| 165 |                 }
 | 
|---|
| 166 | #endif
 | 
|---|
| 167 |                 exit(0);
 | 
|---|
| 168 |         }
 | 
|---|
| 169 | }
 | 
|---|
| 170 | 
 | 
|---|
| 171 | /*
 | 
|---|
| 172 |   die if the user selected maximum runtime is exceeded
 | 
|---|
| 173 | */
 | 
|---|
| 174 | _NORETURN_ static void max_runtime_handler(struct tevent_context *ev, 
 | 
|---|
| 175 |                                            struct tevent_timer *te, 
 | 
|---|
| 176 |                                            struct timeval t, void *private_data)
 | 
|---|
| 177 | {
 | 
|---|
| 178 |         const char *binary_name = (const char *)private_data;
 | 
|---|
| 179 |         DEBUG(0,("%s: maximum runtime exceeded - terminating\n", binary_name));
 | 
|---|
| 180 |         exit(0);
 | 
|---|
| 181 | }
 | 
|---|
| 182 | 
 | 
|---|
| 183 | /*
 | 
|---|
| 184 |   pre-open the sam ldb to ensure the schema has been loaded. This
 | 
|---|
| 185 |   saves a lot of time in child processes  
 | 
|---|
| 186 |  */
 | 
|---|
| 187 | static void prime_samdb_schema(struct tevent_context *event_ctx)
 | 
|---|
| 188 | {
 | 
|---|
| 189 |         TALLOC_CTX *samdb_context;
 | 
|---|
| 190 |         samdb_context = talloc_new(event_ctx);
 | 
|---|
| 191 |         samdb_connect(samdb_context, event_ctx, cmdline_lp_ctx, system_session(samdb_context, cmdline_lp_ctx));
 | 
|---|
| 192 |         talloc_free(samdb_context);
 | 
|---|
| 193 | }
 | 
|---|
| 194 | 
 | 
|---|
| 195 | 
 | 
|---|
| 196 | /*
 | 
|---|
| 197 |   called when a fatal condition occurs in a child task
 | 
|---|
| 198 |  */
 | 
|---|
| 199 | static NTSTATUS samba_terminate(struct irpc_message *msg, 
 | 
|---|
| 200 |                                 struct samba_terminate *r)
 | 
|---|
| 201 | {
 | 
|---|
| 202 |         DEBUG(0,("samba_terminate: %s\n", r->in.reason));
 | 
|---|
| 203 |         exit(1);
 | 
|---|
| 204 | }
 | 
|---|
| 205 | 
 | 
|---|
| 206 | /*
 | 
|---|
| 207 |   setup messaging for the top level samba (parent) task
 | 
|---|
| 208 |  */
 | 
|---|
| 209 | static NTSTATUS setup_parent_messaging(struct tevent_context *event_ctx, 
 | 
|---|
| 210 |                                        struct loadparm_context *lp_ctx)
 | 
|---|
| 211 | {
 | 
|---|
| 212 |         struct messaging_context *msg;
 | 
|---|
| 213 |         NTSTATUS status;
 | 
|---|
| 214 | 
 | 
|---|
| 215 |         msg = messaging_init(talloc_autofree_context(), 
 | 
|---|
| 216 |                              lp_messaging_path(event_ctx, lp_ctx),
 | 
|---|
| 217 |                              cluster_id(0, SAMBA_PARENT_TASKID),
 | 
|---|
| 218 |                              lp_iconv_convenience(lp_ctx),
 | 
|---|
| 219 |                              event_ctx);
 | 
|---|
| 220 |         NT_STATUS_HAVE_NO_MEMORY(msg);
 | 
|---|
| 221 | 
 | 
|---|
| 222 |         irpc_add_name(msg, "samba");
 | 
|---|
| 223 | 
 | 
|---|
| 224 |         status = IRPC_REGISTER(msg, irpc, SAMBA_TERMINATE,
 | 
|---|
| 225 |                                samba_terminate, NULL);
 | 
|---|
| 226 | 
 | 
|---|
| 227 |         return status;
 | 
|---|
| 228 | }
 | 
|---|
| 229 | 
 | 
|---|
| 230 | 
 | 
|---|
| 231 | 
 | 
|---|
| 232 | /*
 | 
|---|
| 233 |  main server.
 | 
|---|
| 234 | */
 | 
|---|
| 235 | static int binary_smbd_main(const char *binary_name, int argc, const char *argv[])
 | 
|---|
| 236 | {
 | 
|---|
| 237 |         bool opt_daemon = false;
 | 
|---|
| 238 |         bool opt_interactive = false;
 | 
|---|
| 239 |         int opt;
 | 
|---|
| 240 |         poptContext pc;
 | 
|---|
| 241 |         extern NTSTATUS server_service_wrepl_init(void);
 | 
|---|
| 242 |         extern NTSTATUS server_service_kdc_init(void);
 | 
|---|
| 243 |         extern NTSTATUS server_service_ldap_init(void);
 | 
|---|
| 244 |         extern NTSTATUS server_service_web_init(void);
 | 
|---|
| 245 |         extern NTSTATUS server_service_ldap_init(void);
 | 
|---|
| 246 |         extern NTSTATUS server_service_winbind_init(void);
 | 
|---|
| 247 |         extern NTSTATUS server_service_nbtd_init(void);
 | 
|---|
| 248 |         extern NTSTATUS server_service_auth_init(void);
 | 
|---|
| 249 |         extern NTSTATUS server_service_cldapd_init(void);
 | 
|---|
| 250 |         extern NTSTATUS server_service_smb_init(void);
 | 
|---|
| 251 |         extern NTSTATUS server_service_drepl_init(void);
 | 
|---|
| 252 |         extern NTSTATUS server_service_kcc_init(void);
 | 
|---|
| 253 |         extern NTSTATUS server_service_rpc_init(void);
 | 
|---|
| 254 |         extern NTSTATUS server_service_ntp_signd_init(void);
 | 
|---|
| 255 |         extern NTSTATUS server_service_samba3_smb_init(void);
 | 
|---|
| 256 |         init_module_fn static_init[] = { STATIC_service_MODULES };
 | 
|---|
| 257 |         init_module_fn *shared_init;
 | 
|---|
| 258 |         struct tevent_context *event_ctx;
 | 
|---|
| 259 |         uint16_t stdin_event_flags;
 | 
|---|
| 260 |         NTSTATUS status;
 | 
|---|
| 261 |         const char *model = "standard";
 | 
|---|
| 262 |         int max_runtime = 0;
 | 
|---|
| 263 |         enum {
 | 
|---|
| 264 |                 OPT_DAEMON = 1000,
 | 
|---|
| 265 |                 OPT_INTERACTIVE,
 | 
|---|
| 266 |                 OPT_PROCESS_MODEL
 | 
|---|
| 267 |         };
 | 
|---|
| 268 |         struct poptOption long_options[] = {
 | 
|---|
| 269 |                 POPT_AUTOHELP
 | 
|---|
| 270 |                 {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON,
 | 
|---|
| 271 |                  "Become a daemon (default)", NULL },
 | 
|---|
| 272 |                 {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE,
 | 
|---|
| 273 |                  "Run interactive (not a daemon)", NULL},
 | 
|---|
| 274 |                 {"model", 'M', POPT_ARG_STRING, NULL, OPT_PROCESS_MODEL, 
 | 
|---|
| 275 |                  "Select process model", "MODEL"},
 | 
|---|
| 276 |                 {"maximum-runtime",0, POPT_ARG_INT, &max_runtime, 0, 
 | 
|---|
| 277 |                  "set maximum runtime of the server process, till autotermination", "seconds"},
 | 
|---|
| 278 |                 POPT_COMMON_SAMBA
 | 
|---|
| 279 |                 POPT_COMMON_VERSION
 | 
|---|
| 280 |                 { NULL }
 | 
|---|
| 281 |         };
 | 
|---|
| 282 | 
 | 
|---|
| 283 |         pc = poptGetContext(binary_name, argc, argv, long_options, 0);
 | 
|---|
| 284 |         while((opt = poptGetNextOpt(pc)) != -1) {
 | 
|---|
| 285 |                 switch(opt) {
 | 
|---|
| 286 |                 case OPT_DAEMON:
 | 
|---|
| 287 |                         opt_daemon = true;
 | 
|---|
| 288 |                         break;
 | 
|---|
| 289 |                 case OPT_INTERACTIVE:
 | 
|---|
| 290 |                         opt_interactive = true;
 | 
|---|
| 291 |                         break;
 | 
|---|
| 292 |                 case OPT_PROCESS_MODEL:
 | 
|---|
| 293 |                         model = poptGetOptArg(pc);
 | 
|---|
| 294 |                         break;
 | 
|---|
| 295 |                 default:
 | 
|---|
| 296 |                         fprintf(stderr, "\nInvalid option %s: %s\n\n",
 | 
|---|
| 297 |                                   poptBadOption(pc, 0), poptStrerror(opt));
 | 
|---|
| 298 |                         poptPrintUsage(pc, stderr, 0);
 | 
|---|
| 299 |                         exit(1);
 | 
|---|
| 300 |                 }
 | 
|---|
| 301 |         }
 | 
|---|
| 302 | 
 | 
|---|
| 303 |         if (opt_daemon && opt_interactive) {
 | 
|---|
| 304 |                 fprintf(stderr,"\nERROR: "
 | 
|---|
| 305 |                           "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
 | 
|---|
| 306 |                 poptPrintUsage(pc, stderr, 0);
 | 
|---|
| 307 |                 exit(1);
 | 
|---|
| 308 |         } else if (!opt_interactive) {
 | 
|---|
| 309 |                 /* default is --daemon */
 | 
|---|
| 310 |                 opt_daemon = true;
 | 
|---|
| 311 |         }
 | 
|---|
| 312 | 
 | 
|---|
| 313 |         poptFreeContext(pc);
 | 
|---|
| 314 | 
 | 
|---|
| 315 |         setup_logging(binary_name, opt_interactive?DEBUG_STDOUT:DEBUG_FILE);
 | 
|---|
| 316 |         setup_signals();
 | 
|---|
| 317 | 
 | 
|---|
| 318 |         /* we want total control over the permissions on created files,
 | 
|---|
| 319 |            so set our umask to 0 */
 | 
|---|
| 320 |         umask(0);
 | 
|---|
| 321 | 
 | 
|---|
| 322 |         DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING));
 | 
|---|
| 323 |         DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2009\n"));
 | 
|---|
| 324 | 
 | 
|---|
| 325 |         if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) {
 | 
|---|
| 326 |                 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
 | 
|---|
| 327 |                 DEBUGADD(0,("sizeof(uint16_t) = %u, sizeof(uint32_t) %u, sizeof(uint64_t) = %u\n",
 | 
|---|
| 328 |                             (unsigned int)sizeof(uint16_t), (unsigned int)sizeof(uint32_t), (unsigned int)sizeof(uint64_t)));
 | 
|---|
| 329 |                 exit(1);
 | 
|---|
| 330 |         }
 | 
|---|
| 331 | 
 | 
|---|
| 332 |         if (opt_daemon) {
 | 
|---|
| 333 |                 DEBUG(3,("Becoming a daemon.\n"));
 | 
|---|
| 334 |                 become_daemon(true, false);
 | 
|---|
| 335 |         }
 | 
|---|
| 336 | 
 | 
|---|
| 337 |         cleanup_tmp_files(cmdline_lp_ctx);
 | 
|---|
| 338 | 
 | 
|---|
| 339 |         if (!directory_exist(lp_lockdir(cmdline_lp_ctx))) {
 | 
|---|
| 340 |                 mkdir(lp_lockdir(cmdline_lp_ctx), 0755);
 | 
|---|
| 341 |         }
 | 
|---|
| 342 | 
 | 
|---|
| 343 |         pidfile_create(lp_piddir(cmdline_lp_ctx), binary_name);
 | 
|---|
| 344 | 
 | 
|---|
| 345 |         /* Do *not* remove this, until you have removed
 | 
|---|
| 346 |          * passdb/secrets.c, and proved that Samba still builds... */
 | 
|---|
| 347 |         /* Setup the SECRETS subsystem */
 | 
|---|
| 348 |         if (secrets_init(talloc_autofree_context(), cmdline_lp_ctx) == NULL) {
 | 
|---|
| 349 |                 exit(1);
 | 
|---|
| 350 |         }
 | 
|---|
| 351 | 
 | 
|---|
| 352 |         gensec_init(cmdline_lp_ctx); /* FIXME: */
 | 
|---|
| 353 | 
 | 
|---|
| 354 |         ntptr_init(cmdline_lp_ctx);     /* FIXME: maybe run this in the initialization function 
 | 
|---|
| 355 |                                                 of the spoolss RPC server instead? */
 | 
|---|
| 356 | 
 | 
|---|
| 357 |         ntvfs_init(cmdline_lp_ctx);     /* FIXME: maybe run this in the initialization functions 
 | 
|---|
| 358 |                                                 of the SMB[,2] server instead? */
 | 
|---|
| 359 | 
 | 
|---|
| 360 |         process_model_init(cmdline_lp_ctx); 
 | 
|---|
| 361 | 
 | 
|---|
| 362 |         shared_init = load_samba_modules(NULL, cmdline_lp_ctx, "service");
 | 
|---|
| 363 | 
 | 
|---|
| 364 |         run_init_functions(static_init);
 | 
|---|
| 365 |         run_init_functions(shared_init);
 | 
|---|
| 366 | 
 | 
|---|
| 367 |         talloc_free(shared_init);
 | 
|---|
| 368 |         
 | 
|---|
| 369 |         /* the event context is the top level structure in smbd. Everything else
 | 
|---|
| 370 |            should hang off that */
 | 
|---|
| 371 |         event_ctx = s4_event_context_init(talloc_autofree_context());
 | 
|---|
| 372 | 
 | 
|---|
| 373 |         if (event_ctx == NULL) {
 | 
|---|
| 374 |                 DEBUG(0,("Initializing event context failed\n"));
 | 
|---|
| 375 |                 return 1;
 | 
|---|
| 376 |         }
 | 
|---|
| 377 | 
 | 
|---|
| 378 |         if (opt_interactive) {
 | 
|---|
| 379 |                 /* terminate when stdin goes away */
 | 
|---|
| 380 |                 stdin_event_flags = TEVENT_FD_READ;
 | 
|---|
| 381 |         } else {
 | 
|---|
| 382 |                 /* stay alive forever */
 | 
|---|
| 383 |                 stdin_event_flags = 0;
 | 
|---|
| 384 |         }
 | 
|---|
| 385 | 
 | 
|---|
| 386 |         /* catch EOF on stdin */
 | 
|---|
| 387 | #ifdef SIGTTIN
 | 
|---|
| 388 |         signal(SIGTTIN, SIG_IGN);
 | 
|---|
| 389 | #endif
 | 
|---|
| 390 |         tevent_add_fd(event_ctx, event_ctx, 0, stdin_event_flags,
 | 
|---|
| 391 |                       server_stdin_handler,
 | 
|---|
| 392 |                       discard_const(binary_name));
 | 
|---|
| 393 | 
 | 
|---|
| 394 |         if (max_runtime) {
 | 
|---|
| 395 |                 tevent_add_timer(event_ctx, event_ctx,
 | 
|---|
| 396 |                                  timeval_current_ofs(max_runtime, 0),
 | 
|---|
| 397 |                                  max_runtime_handler,
 | 
|---|
| 398 |                                  discard_const(binary_name));
 | 
|---|
| 399 |         }
 | 
|---|
| 400 | 
 | 
|---|
| 401 |         prime_samdb_schema(event_ctx);
 | 
|---|
| 402 | 
 | 
|---|
| 403 |         status = setup_parent_messaging(event_ctx, cmdline_lp_ctx);
 | 
|---|
| 404 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 405 |                 DEBUG(0,("Failed to setup parent messaging - %s\n", nt_errstr(status)));
 | 
|---|
| 406 |                 return 1;
 | 
|---|
| 407 |         }
 | 
|---|
| 408 | 
 | 
|---|
| 409 |         DEBUG(0,("%s: using '%s' process model\n", binary_name, model));
 | 
|---|
| 410 | 
 | 
|---|
| 411 |         status = server_service_startup(event_ctx, cmdline_lp_ctx, model, 
 | 
|---|
| 412 |                                         lp_server_services(cmdline_lp_ctx));
 | 
|---|
| 413 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 414 |                 DEBUG(0,("Starting Services failed - %s\n", nt_errstr(status)));
 | 
|---|
| 415 |                 return 1;
 | 
|---|
| 416 |         }
 | 
|---|
| 417 | 
 | 
|---|
| 418 |         /* wait for events - this is where smbd sits for most of its
 | 
|---|
| 419 |            life */
 | 
|---|
| 420 |         tevent_loop_wait(event_ctx);
 | 
|---|
| 421 | 
 | 
|---|
| 422 |         /* as everything hangs off this event context, freeing it
 | 
|---|
| 423 |            should initiate a clean shutdown of all services */
 | 
|---|
| 424 |         talloc_free(event_ctx);
 | 
|---|
| 425 | 
 | 
|---|
| 426 |         return 0;
 | 
|---|
| 427 | }
 | 
|---|
| 428 | 
 | 
|---|
| 429 | int main(int argc, const char *argv[])
 | 
|---|
| 430 | {
 | 
|---|
| 431 |         return binary_smbd_main("samba", argc, argv);
 | 
|---|
| 432 | }
 | 
|---|