4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2016 by Delphix. All rights reserved.
27 * Simple doors name server cache daemon
40 #include <sys/resource.h>
43 #include "nscd_selfcred.h"
44 #include "nscd_frontend.h"
45 #include "nscd_common.h"
46 #include "nscd_admin.h"
47 #include "nscd_door.h"
48 #include "nscd_switch.h"
55 #define NSCDOPT "S:Kf:c:ge:p:n:i:l:d:s:h:o:GFR"
57 /* assume this is a single nscd or, if multiple, the main nscd */
58 int _whoami
= NSCD_MAIN
;
61 static char *cfgfile
= NULL
;
63 extern nsc_ctx_t
*cache_ctx_p
[];
65 static void usage(char *);
66 static void detachfromtty(void);
68 static char debug_level
[32] = { 0 };
69 static char logfile
[128] = { 0 };
70 static int will_become_server
;
75 while (*s
&& *s
!= ',')
77 return ((*s
== ',') ? (s
+ 1) : NULL
);
81 * declaring this causes the files backend to use hashing
82 * this is of course an utter hack, but provides a nice
83 * quiet back door to enable this feature for only the nscd.
86 __nss_use_files_hash(void)
90 static int saved_argc
= 0;
91 static char **saved_argv
= NULL
;
92 static char saved_execname
[MAXPATHLEN
];
97 const char *name
= getexecname();
99 saved_execname
[0] = 0;
101 if (name
[0] != '/') { /* started w/ relative path */
102 (void) getcwd(saved_execname
, MAXPATHLEN
);
103 (void) strlcat(saved_execname
, "/", MAXPATHLEN
);
105 (void) strlcat(saved_execname
, name
, MAXPATHLEN
);
109 main(int argc
, char ** argv
)
118 char *ret_textdomain
;
122 ret_locale
= setlocale(LC_ALL
, "");
123 if (ret_locale
== NULL
)
124 (void) fprintf(stderr
, gettext("Unable to set locale\n"));
126 ret_textdomain
= textdomain(TEXT_DOMAIN
);
127 if (ret_textdomain
== NULL
)
128 (void) fprintf(stderr
, gettext("Unable to set textdomain\n"));
131 * Special case non-root user here - he can just print stats
135 (strcmp(argv
[1], "-g") && strcmp(argv
[1], "-G"))) {
136 (void) fprintf(stderr
,
137 gettext("Must be root to use any option other than -g\n\n"));
141 if (_nscd_doorcall(NSCD_PING
) != NSS_SUCCESS
) {
142 (void) fprintf(stderr
,
143 gettext("%s doesn't appear to be running.\n"),
147 if (_nscd_client_getadmin(argv
[1][1]) != 0) {
148 (void) fprintf(stderr
,
149 gettext("unable to get configuration and statistics data\n"));
153 _nscd_client_showstats();
158 * Determine if there is already a daemon (main nscd) running.
159 * If not, will start it. Forker NSCD will always become a
162 will_become_server
= (_nscd_doorcall(NSCD_PING
) != NSS_SUCCESS
);
163 if (argc
>= 2 && strcmp(argv
[1], "-F") == 0) {
164 will_become_server
= 1;
165 _whoami
= NSCD_FORKER
;
168 * allow time for the main nscd to get ready
169 * to receive the IMHERE door request this
170 * process will send later
172 (void) usleep(100000);
176 * first get the config file path. Also detect
177 * invalid option as soon as possible.
179 while ((opt
= getopt(argc
, argv
, NSCDOPT
)) != EOF
) {
183 if ((cfgfile
= strdup(optarg
)) == NULL
)
187 if (will_become_server
) {
188 (void) fprintf(stderr
,
189 gettext("nscd not running, no statistics to show\n\n"));
194 if (will_become_server
) {
195 (void) fprintf(stderr
,
196 gettext("nscd not running, no cache to invalidate\n\n"));
211 * perform more initialization and load configuration
212 * if to become server
214 if (will_become_server
) {
216 /* initialize switch engine and config/stats management */
217 if ((rc
= _nscd_init(cfgfile
)) != NSCD_SUCCESS
) {
218 (void) fprintf(stderr
,
219 gettext("initialization of switch failed (rc = %d)\n"), rc
);
222 _nscd_get_log_info(debug_level
, sizeof (debug_level
),
223 logfile
, sizeof (logfile
));
226 * initialize cache store
228 if ((rc
= init_cache(0)) != NSCD_SUCCESS
) {
229 (void) fprintf(stderr
,
230 gettext("initialization of cache store failed (rc = %d)\n"), rc
);
236 * process usual options
238 optind
= 1; /* this is a rescan */
240 while ((opt
= getopt(argc
, argv
, NSCDOPT
)) != EOF
) {
244 case 'K': /* undocumented feature */
245 (void) _nscd_doorcall(NSCD_KILLSERVER
);
256 if (_nscd_add_admin_mod(optarg
, 'p',
258 msg
, sizeof (msg
)) == -1)
264 if (_nscd_add_admin_mod(optarg
, 'n',
266 msg
, sizeof (msg
)) == -1)
272 if (_nscd_add_admin_mod(optarg
, 'c',
274 msg
, sizeof (msg
)) == -1)
280 if (_nscd_add_admin_mod(optarg
, 'i', NULL
,
281 msg
, sizeof (msg
)) == -1)
287 (void) strlcpy(logfile
, optarg
, sizeof (logfile
));
292 (void) strlcpy(debug_level
, optarg
,
293 sizeof (debug_level
));
297 /* silently ignore secure-mode */
301 /* silently ignore suggested-size */
305 /* silently ignore old-data-ok */
310 if (_nscd_add_admin_mod(optarg
, 'h',
312 msg
, sizeof (msg
)) == -1)
318 if (_nscd_add_admin_mod(optarg
, 'e',
320 msg
, sizeof (msg
)) == -1)
325 _whoami
= NSCD_FORKER
;
337 (void) fprintf(stderr
, "\n%s: %s\n\n", argv
[0], msg
);
342 * if main nscd already running and not forker nscd,
343 * can only do admin work
345 if (_whoami
== NSCD_MAIN
) {
346 if (!will_become_server
) {
348 if (_nscd_client_getadmin('g')) {
349 (void) fprintf(stderr
,
350 gettext("Cannot contact nscd properly(?)\n"));
353 _nscd_client_showstats();
357 if (_nscd_client_setadmin() < 0) {
358 (void) fprintf(stderr
,
359 gettext("Error during admin call\n"));
363 if (!showstats
&& !doset
) {
364 (void) fprintf(stderr
,
365 gettext("%s already running.... no administration option specified\n"),
373 * daemon from here on
376 if (_whoami
== NSCD_MAIN
) {
378 /* save enough info in case need to restart or fork */
384 * if a log file is not specified, set it to
385 * "stderr" or "/dev/null" based on debug level
387 if (*logfile
== '\0') {
388 if (*debug_level
!= '\0')
389 /* we're debugging... */
390 (void) strcpy(logfile
, "stderr");
392 (void) strcpy(logfile
, "/dev/null");
394 (void) _nscd_add_admin_mod(NULL
, 'l', logfile
,
396 (void) _nscd_add_admin_mod(NULL
, 'd', debug_level
,
399 /* activate command options */
400 if (_nscd_server_setadmin(NULL
) != NSCD_SUCCESS
) {
401 (void) fprintf(stderr
,
402 gettext("unable to set command line options\n"));
406 if (*debug_level
!= '\0') {
407 /* we're debugging, no forking of nscd */
410 * forker nscd will be started if self credential
413 _nscd_start_forker(saved_execname
, saved_argc
,
417 * daemonize the nscd (forker nscd will also
418 * be started if self credential is configured)
422 } else { /* NSCD_FORKER */
424 * To avoid PUN (Per User Nscd) processes from becoming
425 * zombies after they exit, the forking nscd should
426 * ignore the SIGCLD signal so that it does not
427 * need to wait for every child PUN to exit.
429 (void) signal(SIGCLD
, SIG_IGN
);
430 (void) open("/dev/null", O_RDWR
, 0);
436 /* set NOFILE to unlimited */
437 rl
.rlim_cur
= rl
.rlim_max
= RLIM_INFINITY
;
438 if (setrlimit(RLIMIT_NOFILE
, &rl
) < 0) {
439 _NSCD_LOG(NSCD_LOG_FRONT_END
, NSCD_LOG_LEVEL_ERROR
)
440 (me
, "Cannot set open file limit: %s\n", strerror(errno
));
444 /* set up door and establish our own server thread pool */
445 if ((_doorfd
= _nscd_setup_server(saved_execname
, saved_argv
)) == -1) {
446 _NSCD_LOG(NSCD_LOG_FRONT_END
, NSCD_LOG_LEVEL_ERROR
)
447 (me
, "unable to set up door\n");
451 /* inform the main nscd that this forker is ready */
452 if (_whoami
== NSCD_FORKER
) {
455 for (ret
= NSS_ALTRETRY
; ret
== NSS_ALTRETRY
; )
456 ret
= _nscd_doorcall_sendfd(_doorfd
,
457 NSCD_IMHERE
| (NSCD_FORKER
& NSCD_WHOAMI
),
463 (void) _nscd_doorcall(NSCD_REFRESH
);
467 /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
473 (void) fprintf(stderr
,
474 "Usage: %s [-d debug_level] [-l logfilename]\n", s
);
475 (void) fprintf(stderr
,
476 " [-p cachename,positive_time_to_live]\n");
477 (void) fprintf(stderr
,
478 " [-n cachename,negative_time_to_live]\n");
479 (void) fprintf(stderr
,
480 " [-i cachename]\n");
481 (void) fprintf(stderr
,
482 " [-h cachename,keep_hot_count]\n");
483 (void) fprintf(stderr
,
484 " [-e cachename,\"yes\"|\"no\"] [-g] " \
485 "[-c cachename,\"yes\"|\"no\"]\n");
486 (void) fprintf(stderr
,
487 " [-f configfilename] \n");
488 (void) fprintf(stderr
,
489 "\n Supported caches:\n");
490 (void) fprintf(stderr
,
491 " auth_attr, bootparams, ethers\n");
492 (void) fprintf(stderr
,
493 " exec_attr, group, hosts, ipnodes, netmasks\n");
494 (void) fprintf(stderr
,
495 " networks, passwd, printers, prof_attr, project\n");
496 (void) fprintf(stderr
,
497 " protocols, rpc, services\n");
498 (void) fprintf(stderr
,
510 char *me
= "detachfromtty";
514 for (i
= 0; i
< _logfd
; i
++)
516 closefrom(_logfd
+ 1);
525 _NSCD_LOG(NSCD_LOG_FRONT_END
, NSCD_LOG_LEVEL_ERROR
)
526 (me
, "unable to fork: pid = %d, %s\n",
527 getpid(), strerror(errno
));
532 /* start the forker nscd if so configured */
533 _nscd_start_forker(saved_execname
, saved_argc
, saved_argv
);
540 (void) open("/dev/null", O_RDWR
, 0);
546 * start monitoring the states of the name service clients
548 rc
= _nscd_init_smf_monitor();
549 if (rc
!= NSCD_SUCCESS
) {
550 _NSCD_LOG(NSCD_LOG_FRONT_END
, NSCD_LOG_LEVEL_ERROR
)
551 (me
, "unable to start the SMF monitor (rc = %d)\n", rc
);