rpc: Don't crash if npa_accept fails
[ambi/samba-autobuild/.git] / source3 / utils / testparm.c
1 /*
2    Unix SMB/CIFS implementation.
3    Test validity of smb.conf
4    Copyright (C) Karl Auer 1993, 1994-1998
5
6    Extensively modified by Andrew Tridgell, 1995
7    Converted to popt by Jelmer Vernooij (jelmer@nl.linux.org), 2002
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /*
24  * Testbed for loadparm.c/params.c
25  *
26  * This module simply loads a specified configuration file and
27  * if successful, dumps it's contents to stdout. Note that the
28  * operation is performed with DEBUGLEVEL at 3.
29  *
30  * Useful for a quick 'syntax check' of a configuration file.
31  *
32  */
33
34 #include "includes.h"
35 #include "system/filesys.h"
36 #include "popt_common.h"
37 #include "lib/param/loadparm.h"
38 #include "cmdline_contexts.h"
39
40 #include <regex.h>
41
42 /*******************************************************************
43  Check if a directory exists.
44 ********************************************************************/
45
46 static bool directory_exist_stat(const char *dname,SMB_STRUCT_STAT *st)
47 {
48         SMB_STRUCT_STAT st2;
49         bool ret;
50
51         if (!st)
52                 st = &st2;
53
54         if (sys_stat(dname, st, false) != 0)
55                 return(False);
56
57         ret = S_ISDIR(st->st_ex_mode);
58         if(!ret)
59                 errno = ENOTDIR;
60         return ret;
61 }
62
63 struct idmap_config {
64         const char *domain_name;
65         const char *backend;
66         uint32_t high;
67         uint32_t low;
68 };
69
70 struct idmap_domains {
71         struct idmap_config *c;
72         uint32_t count;
73         uint32_t size;
74 };
75
76 static bool lp_scan_idmap_found_domain(const char *string,
77                                        regmatch_t matches[],
78                                        void *private_data)
79 {
80         bool ok = false;
81
82         if (matches[1].rm_so == -1) {
83                 fprintf(stderr, "Found match, but no name - invalid idmap config");
84                 return false;
85         }
86         if (matches[1].rm_eo <= matches[1].rm_so) {
87                 fprintf(stderr, "Invalid match - invalid idmap config");
88                 return false;
89         }
90
91         {
92                 struct idmap_domains *d = private_data;
93                 struct idmap_config *c = &d->c[d->count];
94                 regoff_t len = matches[1].rm_eo - matches[1].rm_so;
95                 char domname[len + 1];
96
97                 if (d->count >= d->size) {
98                         return false;
99                 }
100
101                 memcpy(domname, string + matches[1].rm_so, len);
102                 domname[len] = '\0';
103
104                 c->domain_name = talloc_strdup_upper(d->c, domname);
105                 if (c->domain_name == NULL) {
106                         return false;
107                 }
108                 c->backend = talloc_strdup(d->c, lp_idmap_backend(domname));
109                 if (c->backend == NULL) {
110                         return false;
111                 }
112
113                 if (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) {
114                         ok = lp_idmap_range(domname, &c->low, &c->high);
115                         if (!ok) {
116                                 fprintf(stderr,
117                                         "ERROR: Invalid idmap range for domain "
118                                         "%s!\n\n",
119                                         c->domain_name);
120                                 return false;
121                         }
122                 }
123
124                 d->count++;
125         }
126
127         return false; /* Keep scanning */
128 }
129
130 static bool do_idmap_check(void)
131 {
132         struct idmap_domains *d;
133         uint32_t i;
134         bool ok = false;
135         int rc;
136
137         d = talloc_zero(talloc_tos(), struct idmap_domains);
138         if (d == NULL) {
139                 return false;
140         }
141         d->count = 0;
142         d->size = 32;
143
144         d->c = talloc_array(d, struct idmap_config, d->size);
145         if (d->c == NULL) {
146                 goto done;
147         }
148
149         rc = lp_wi_scan_global_parametrics("idmapconfig\\(.*\\):backend",
150                                            2,
151                                            lp_scan_idmap_found_domain,
152                                            d);
153         if (rc != 0) {
154                 fprintf(stderr,
155                         "FATAL: wi_scan_global_parametrics failed: %d",
156                         rc);
157         }
158
159         for (i = 0; i < d->count; i++) {
160                 struct idmap_config *c = &d->c[i];
161                 uint32_t j;
162
163                 for (j = 0; j < d->count && j != i; j++) {
164                         struct idmap_config *x = &d->c[j];
165
166                         if ((c->low >= x->low && c->low <= x->high) ||
167                             (c->high >= x->low && c->high <= x->high)) {
168                                 /* Allow overlapping ranges for idmap_ad */
169                                 ok = strequal(c->backend, x->backend);
170                                 if (ok) {
171                                         ok = strequal(c->backend, "ad");
172                                         if (ok) {
173                                                 fprintf(stderr,
174                                                         "NOTE: The idmap_ad "
175                                                         "range for the domain "
176                                                         "%s overlaps with the "
177                                                         "range of %s.\n\n",
178                                                         c->domain_name,
179                                                         x->domain_name);
180                                                 continue;
181                                         }
182                                 }
183
184                                 fprintf(stderr,
185                                         "ERROR: The idmap range for the domain "
186                                         "%s (%s) overlaps with the range of "
187                                         "%s (%s)!\n\n",
188                                         c->domain_name,
189                                         c->backend,
190                                         x->domain_name,
191                                         x->backend);
192                                 ok = false;
193                                 goto done;
194                         }
195                 }
196         }
197
198         ok = true;
199 done:
200         TALLOC_FREE(d);
201         return ok;
202 }
203
204 /***********************************************
205  Here we do a set of 'hard coded' checks for bad
206  configuration settings.
207 ************************************************/
208
209 static int do_global_checks(void)
210 {
211         int ret = 0;
212         SMB_STRUCT_STAT st;
213         const char *socket_options;
214
215         if (lp_security() >= SEC_DOMAIN && !lp_encrypt_passwords()) {
216                 fprintf(stderr, "ERROR: in 'security=domain' mode the "
217                                 "'encrypt passwords' parameter must always be "
218                                 "set to 'true'.\n\n");
219                 ret = 1;
220         }
221
222         if (lp_we_are_a_wins_server() && lp_wins_server_list()) {
223                 fprintf(stderr, "ERROR: both 'wins support = true' and "
224                                 "'wins server = <server list>' cannot be set in "
225                                 "the smb.conf file. nmbd will abort with this "
226                                 "setting.\n\n");
227                 ret = 1;
228         }
229
230         if (strequal(lp_workgroup(), lp_netbios_name())) {
231                 fprintf(stderr, "WARNING: 'workgroup' and 'netbios name' "
232                                 "must differ.\n\n");
233         }
234
235         if (lp_client_ipc_signing() == SMB_SIGNING_IF_REQUIRED
236          || lp_client_ipc_signing() == SMB_SIGNING_OFF) {
237                 fprintf(stderr, "WARNING: The 'client ipc signing' value "
238                         "%s SMB signing is not used when contacting a "
239                         "domain controller or other server. "
240                         "This setting is not recommended; please be "
241                         "aware of the security implications when using "
242                         "this configuration setting.\n\n",
243                         lp_client_ipc_signing() == SMB_SIGNING_OFF ?
244                         "ensures" : "may mean");
245         }
246
247         if (strlen(lp_netbios_name()) > 15) {
248                 fprintf(stderr, "WARNING: The 'netbios name' is too long "
249                                 "(max. 15 chars).\n\n");
250         }
251
252         if (!directory_exist_stat(lp_lock_directory(), &st)) {
253                 fprintf(stderr, "ERROR: lock directory %s does not exist\n\n",
254                        lp_lock_directory());
255                 ret = 1;
256         } else if ((st.st_ex_mode & 0777) != 0755) {
257                 fprintf(stderr, "WARNING: lock directory %s should have "
258                                 "permissions 0755 for browsing to work\n\n",
259                        lp_lock_directory());
260         }
261
262         if (!directory_exist_stat(lp_state_directory(), &st)) {
263                 fprintf(stderr, "ERROR: state directory %s does not exist\n\n",
264                        lp_state_directory());
265                 ret = 1;
266         } else if ((st.st_ex_mode & 0777) != 0755) {
267                 fprintf(stderr, "WARNING: state directory %s should have "
268                                 "permissions 0755 for browsing to work\n\n",
269                        lp_state_directory());
270         }
271
272         if (!directory_exist_stat(lp_cache_directory(), &st)) {
273                 fprintf(stderr, "ERROR: cache directory %s does not exist\n\n",
274                        lp_cache_directory());
275                 ret = 1;
276         } else if ((st.st_ex_mode & 0777) != 0755) {
277                 fprintf(stderr, "WARNING: cache directory %s should have "
278                                 "permissions 0755 for browsing to work\n\n",
279                        lp_cache_directory());
280         }
281
282         if (!directory_exist_stat(lp_pid_directory(), &st)) {
283                 fprintf(stderr, "ERROR: pid directory %s does not exist\n\n",
284                        lp_pid_directory());
285                 ret = 1;
286         }
287
288         if (lp_passdb_expand_explicit()) {
289                 fprintf(stderr, "WARNING: passdb expand explicit = yes is "
290                                 "deprecated\n\n");
291         }
292
293         /*
294          * Socket options.
295          */
296         socket_options = lp_socket_options();
297         if (socket_options != NULL &&
298             (strstr(socket_options, "SO_SNDBUF") ||
299              strstr(socket_options, "SO_RCVBUF") ||
300              strstr(socket_options, "SO_SNDLOWAT") ||
301              strstr(socket_options, "SO_RCVLOWAT")))
302         {
303                 fprintf(stderr,
304                         "WARNING: socket options = %s\n"
305                         "This warning is printed because you set one of the\n"
306                         "following options: SO_SNDBUF, SO_RCVBUF, SO_SNDLOWAT,\n"
307                         "SO_RCVLOWAT\n"
308                         "Modern server operating systems are tuned for\n"
309                         "high network performance in the majority of situations;\n"
310                         "when you set 'socket options' you are overriding those\n"
311                         "settings.\n"
312                         "Linux in particular has an auto-tuning mechanism for\n"
313                         "buffer sizes (SO_SNDBUF, SO_RCVBUF) that will be\n"
314                         "disabled if you specify a socket buffer size. This can\n"
315                         "potentially cripple your TCP/IP stack.\n\n"
316                         "Getting the 'socket options' correct can make a big\n"
317                         "difference to your performance, but getting them wrong\n"
318                         "can degrade it by just as much. As with any other low\n"
319                         "level setting, if you must make changes to it, make\n "
320                         "small changes and test the effect before making any\n"
321                         "large changes.\n\n",
322                         socket_options);
323         }
324
325         /*
326          * Password server sanity checks.
327          */
328
329         if((lp_security() >= SEC_DOMAIN) && !*lp_password_server()) {
330                 const char *sec_setting;
331                 if(lp_security() == SEC_DOMAIN)
332                         sec_setting = "domain";
333                 else if(lp_security() == SEC_ADS)
334                         sec_setting = "ads";
335                 else
336                         sec_setting = "";
337
338                 fprintf(stderr, "ERROR: The setting 'security=%s' requires the "
339                                 "'password server' parameter be set to the "
340                                 "default value * or a valid password server.\n\n",
341                                 sec_setting );
342                 ret = 1;
343         }
344
345         if((lp_security() >= SEC_DOMAIN) && (strcmp(lp_password_server(), "*") != 0)) {
346                 const char *sec_setting;
347                 if(lp_security() == SEC_DOMAIN)
348                         sec_setting = "domain";
349                 else if(lp_security() == SEC_ADS)
350                         sec_setting = "ads";
351                 else
352                         sec_setting = "";
353
354                 fprintf(stderr, "WARNING: The setting 'security=%s' should NOT "
355                                 "be combined with the 'password server' "
356                                 "parameter.\n"
357                                 "(by default Samba will discover the correct DC "
358                                 "to contact automatically).\n\n",
359                                 sec_setting );
360         }
361
362         /*
363          * Password chat sanity checks.
364          */
365
366         if(lp_security() == SEC_USER && lp_unix_password_sync()) {
367
368                 /*
369                  * Check that we have a valid lp_passwd_program() if not using pam.
370                  */
371
372 #ifdef WITH_PAM
373                 if (!lp_pam_password_change()) {
374 #endif
375
376                         if((lp_passwd_program(talloc_tos()) == NULL) ||
377                            (strlen(lp_passwd_program(talloc_tos())) == 0))
378                         {
379                                 fprintf(stderr,
380                                         "ERROR: the 'unix password sync' "
381                                         "parameter is set and there is no valid "
382                                         "'passwd program' parameter.\n\n");
383                                 ret = 1;
384                         } else {
385                                 const char *passwd_prog;
386                                 char *truncated_prog = NULL;
387                                 const char *p;
388
389                                 passwd_prog = lp_passwd_program(talloc_tos());
390                                 p = passwd_prog;
391                                 next_token_talloc(talloc_tos(),
392                                                 &p,
393                                                 &truncated_prog, NULL);
394                                 if (truncated_prog && access(truncated_prog, F_OK) == -1) {
395                                         fprintf(stderr,
396                                                 "ERROR: the 'unix password sync' "
397                                                 "parameter is set and the "
398                                                 "'passwd program' (%s) cannot be "
399                                                 "executed (error was %s).\n\n",
400                                                 truncated_prog,
401                                                 strerror(errno));
402                                         ret = 1;
403                                 }
404                         }
405
406 #ifdef WITH_PAM
407                 }
408 #endif
409
410                 if(lp_passwd_chat(talloc_tos()) == NULL) {
411                         fprintf(stderr,
412                                 "ERROR: the 'unix password sync' parameter is "
413                                 "set and there is no valid 'passwd chat' "
414                                 "parameter.\n\n");
415                         ret = 1;
416                 }
417
418                 if ((lp_passwd_program(talloc_tos()) != NULL) &&
419                     (strlen(lp_passwd_program(talloc_tos())) > 0))
420                 {
421                         /* check if there's a %u parameter present */
422                         if(strstr_m(lp_passwd_program(talloc_tos()), "%u") == NULL) {
423                                 fprintf(stderr,
424                                         "ERROR: the 'passwd program' (%s) "
425                                         "requires a '%%u' parameter.\n\n",
426                                         lp_passwd_program(talloc_tos()));
427                                 ret = 1;
428                         }
429                 }
430
431                 /*
432                  * Check that we have a valid script and that it hasn't
433                  * been written to expect the old password.
434                  */
435
436                 if(lp_encrypt_passwords()) {
437                         if(strstr_m( lp_passwd_chat(talloc_tos()), "%o")!=NULL) {
438                                 fprintf(stderr,
439                                         "ERROR: the 'passwd chat' script [%s] "
440                                         "expects to use the old plaintext "
441                                         "password via the %%o substitution. With "
442                                         "encrypted passwords this is not "
443                                         "possible.\n\n",
444                                         lp_passwd_chat(talloc_tos()) );
445                                 ret = 1;
446                         }
447                 }
448         }
449
450         if (strlen(lp_winbind_separator()) != 1) {
451                 fprintf(stderr, "ERROR: the 'winbind separator' parameter must "
452                                 "be a single character.\n\n");
453                 ret = 1;
454         }
455
456         if (*lp_winbind_separator() == '+') {
457                 fprintf(stderr, "'winbind separator = +' might cause problems "
458                                 "with group membership.\n\n");
459         }
460
461         if (lp_algorithmic_rid_base() < BASE_RID) {
462                 /* Try to prevent admin foot-shooting, we can't put algorithmic
463                    rids below 1000, that's the 'well known RIDs' on NT */
464                 fprintf(stderr, "'algorithmic rid base' must be equal to or "
465                                 "above %lu\n\n", BASE_RID);
466         }
467
468         if (lp_algorithmic_rid_base() & 1) {
469                 fprintf(stderr, "'algorithmic rid base' must be even.\n\n");
470         }
471
472         if (lp_server_role() != ROLE_STANDALONE) {
473                 const char *default_backends[] = {
474                         "tdb", "tdb2", "ldap", "autorid", "hash"
475                 };
476                 const char *idmap_backend;
477                 bool valid_backend = false;
478                 uint32_t i;
479                 bool ok;
480
481                 idmap_backend = lp_idmap_default_backend();
482
483                 for (i = 0; i < ARRAY_SIZE(default_backends); i++) {
484                         ok = strequal(idmap_backend, default_backends[i]);
485                         if (ok) {
486                                 valid_backend = true;
487                         }
488                 }
489
490                 if (!valid_backend) {
491                         ret = 1;
492                         fprintf(stderr, "ERROR: Do not use the '%s' backend "
493                                         "as the default idmap backend!\n\n",
494                                         idmap_backend);
495                 }
496
497                 ok = do_idmap_check();
498                 if (!ok) {
499                         ret = 1;
500                 }
501         }
502
503 #ifndef HAVE_DLOPEN
504         if (lp_preload_modules()) {
505                 fprintf(stderr, "WARNING: 'preload modules = ' set while loading "
506                                 "plugins not supported.\n\n");
507         }
508 #endif
509
510         if (!lp_passdb_backend()) {
511                 fprintf(stderr, "ERROR: passdb backend must have a value or be "
512                                 "left out\n\n");
513         }
514
515         if (lp_os_level() > 255) {
516                 fprintf(stderr, "WARNING: Maximum value for 'os level' is "
517                                 "255!\n\n");
518         }
519
520         if (strequal(lp_dos_charset(), "UTF8") || strequal(lp_dos_charset(), "UTF-8")) {
521                 fprintf(stderr, "ERROR: 'dos charset' must not be UTF8\n\n");
522                 ret = 1;
523         }
524
525         return ret;
526 }
527
528 /**
529  * per-share logic tests
530  */
531 static void do_per_share_checks(int s)
532 {
533         const char **deny_list = lp_hosts_deny(s);
534         const char **allow_list = lp_hosts_allow(s);
535         const char **vfs_objects = NULL;
536         int i;
537         static bool uses_fruit;
538         static bool doesnt_use_fruit;
539         static bool fruit_mix_warned;
540
541         if(deny_list) {
542                 for (i=0; deny_list[i]; i++) {
543                         char *hasstar = strchr_m(deny_list[i], '*');
544                         char *hasquery = strchr_m(deny_list[i], '?');
545                         if(hasstar || hasquery) {
546                                 fprintf(stderr,
547                                         "Invalid character %c in hosts deny list "
548                                         "(%s) for service %s.\n\n",
549                                         hasstar ? *hasstar : *hasquery,
550                                         deny_list[i],
551                                         lp_servicename(talloc_tos(), s));
552                         }
553                 }
554         }
555
556         if(allow_list) {
557                 for (i=0; allow_list[i]; i++) {
558                         char *hasstar = strchr_m(allow_list[i], '*');
559                         char *hasquery = strchr_m(allow_list[i], '?');
560                         if(hasstar || hasquery) {
561                                 fprintf(stderr,
562                                         "Invalid character %c in hosts allow "
563                                         "list (%s) for service %s.\n\n",
564                                         hasstar ? *hasstar : *hasquery,
565                                         allow_list[i],
566                                         lp_servicename(talloc_tos(), s));
567                         }
568                 }
569         }
570
571         if(lp_level2_oplocks(s) && !lp_oplocks(s)) {
572                 fprintf(stderr, "Invalid combination of parameters for service "
573                                 "%s. Level II oplocks can only be set if oplocks "
574                                 "are also set.\n\n",
575                                 lp_servicename(talloc_tos(), s));
576         }
577
578         if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
579             && !(lp_create_mask(s) & S_IXOTH))
580         {
581                 fprintf(stderr,
582                         "Invalid combination of parameters for service %s. Map "
583                         "hidden can only work if create mask includes octal "
584                         "01 (S_IXOTH).\n\n",
585                         lp_servicename(talloc_tos(), s));
586         }
587         if (!lp_store_dos_attributes(s) && lp_map_hidden(s)
588             && (lp_force_create_mode(s) & S_IXOTH))
589         {
590                 fprintf(stderr,
591                         "Invalid combination of parameters for service "
592                         "%s. Map hidden can only work if force create mode "
593                         "excludes octal 01 (S_IXOTH).\n\n",
594                         lp_servicename(talloc_tos(), s));
595         }
596         if (!lp_store_dos_attributes(s) && lp_map_system(s)
597             && !(lp_create_mask(s) & S_IXGRP))
598         {
599                 fprintf(stderr,
600                         "Invalid combination of parameters for service "
601                         "%s. Map system can only work if create mask includes "
602                         "octal 010 (S_IXGRP).\n\n",
603                         lp_servicename(talloc_tos(), s));
604         }
605         if (!lp_store_dos_attributes(s) && lp_map_system(s)
606             && (lp_force_create_mode(s) & S_IXGRP))
607         {
608                 fprintf(stderr,
609                         "Invalid combination of parameters for service "
610                         "%s. Map system can only work if force create mode "
611                         "excludes octal 010 (S_IXGRP).\n\n",
612                         lp_servicename(talloc_tos(), s));
613         }
614         if (lp_printing(s) == PRINT_CUPS && *(lp_print_command(talloc_tos(), s)) != '\0') {
615                 fprintf(stderr,
616                         "Warning: Service %s defines a print command, but "
617                         "parameter is ignored when using CUPS libraries.\n\n",
618                         lp_servicename(talloc_tos(), s));
619         }
620
621         vfs_objects = lp_vfs_objects(s);
622         if (vfs_objects && str_list_check(vfs_objects, "fruit")) {
623                 uses_fruit = true;
624         } else {
625                 doesnt_use_fruit = true;
626         }
627
628         if (uses_fruit && doesnt_use_fruit && !fruit_mix_warned) {
629                 fruit_mix_warned = true;
630                 fprintf(stderr,
631                         "WARNING: some services use vfs_fruit, others don't. Mounting them "
632                         "in conjunction on OS X clients results in undefined behaviour.\n\n");
633         }
634 }
635
636  int main(int argc, const char *argv[])
637 {
638         const char *config_file = get_dyn_CONFIGFILE();
639         int s;
640         static int silent_mode = False;
641         static int show_all_parameters = False;
642         int ret = 0;
643         poptContext pc;
644         static char *parameter_name = NULL;
645         static const char *section_name = NULL;
646         const char *cname;
647         const char *caddr;
648         static int show_defaults;
649         static int skip_logic_checks = 0;
650
651         struct poptOption long_options[] = {
652                 POPT_AUTOHELP
653                 {
654                         .longName   = "suppress-prompt",
655                         .shortName  = 's',
656                         .argInfo    = POPT_ARG_VAL,
657                         .arg        = &silent_mode,
658                         .val        = 1,
659                         .descrip    = "Suppress prompt for enter",
660                 },
661                 {
662                         .longName   = "verbose",
663                         .shortName  = 'v',
664                         .argInfo    = POPT_ARG_NONE,
665                         .arg        = &show_defaults,
666                         .val        = 1,
667                         .descrip    = "Show default options too",
668                 },
669                 {
670                         .longName   = "skip-logic-checks",
671                         .shortName  = 'l',
672                         .argInfo    = POPT_ARG_NONE,
673                         .arg        = &skip_logic_checks,
674                         .val        = 1,
675                         .descrip    = "Skip the global checks",
676                 },
677                 {
678                         .longName   = "show-all-parameters",
679                         .shortName  = '\0',
680                         .argInfo    = POPT_ARG_VAL,
681                         .arg        = &show_all_parameters,
682                         .val        = True,
683                         .descrip    = "Show the parameters, type, possible "
684                                       "values",
685                 },
686                 {
687                         .longName   = "parameter-name",
688                         .shortName  = '\0',
689                         .argInfo    = POPT_ARG_STRING,
690                         .arg        = &parameter_name,
691                         .val        = 0,
692                         .descrip    = "Limit testparm to a named parameter",
693                 },
694                 {
695                         .longName   = "section-name",
696                         .shortName  = '\0',
697                         .argInfo    = POPT_ARG_STRING,
698                         .arg        = &section_name,
699                         .val        = 0,
700                         .descrip    = "Limit testparm to a named section",
701                 },
702                 POPT_COMMON_VERSION
703                 POPT_COMMON_DEBUGLEVEL
704                 POPT_COMMON_OPTION
705                 POPT_TABLEEND
706         };
707
708         TALLOC_CTX *frame = talloc_stackframe();
709
710         smb_init_locale();
711         /*
712          * Set the default debug level to 1.
713          * Allow it to be overridden by the command line,
714          * not by smb.conf.
715          */
716         lp_set_cmdline("log level", "1");
717
718         pc = poptGetContext(NULL, argc, argv, long_options,
719                             POPT_CONTEXT_KEEP_FIRST);
720         poptSetOtherOptionHelp(pc, "[OPTION...] <config-file> [host-name] [host-ip]");
721
722         while(poptGetNextOpt(pc) != -1);
723
724         if (show_all_parameters) {
725                 show_parameter_list();
726                 exit(0);
727         }
728
729         setup_logging(poptGetArg(pc), DEBUG_STDERR);
730
731         if (poptPeekArg(pc))
732                 config_file = poptGetArg(pc);
733
734         cname = poptGetArg(pc);
735         caddr = poptGetArg(pc);
736
737         poptFreeContext(pc);
738
739         if ( cname && ! caddr ) {
740                 printf ( "ERROR: You must specify both a machine name and an IP address.\n" );
741                 ret = 1;
742                 goto done;
743         }
744
745         cmdline_messaging_context(config_file);
746
747         fprintf(stderr,"Load smb config files from %s\n",config_file);
748
749         if (!lp_load_with_registry_shares(config_file)) {
750                 fprintf(stderr,"Error loading services.\n");
751                 ret = 1;
752                 goto done;
753         }
754
755         fprintf(stderr,"Loaded services file OK.\n");
756
757         if (skip_logic_checks == 0) {
758                 ret = do_global_checks();
759         }
760
761         for (s=0;s<1000;s++) {
762                 if (VALID_SNUM(s) && (skip_logic_checks == 0)) {
763                         do_per_share_checks(s);
764                 }
765         }
766
767
768         if (!section_name && !parameter_name) {
769                 fprintf(stderr,
770                         "Server role: %s\n\n",
771                         server_role_str(lp_server_role()));
772         }
773
774         if (!cname) {
775                 if (!silent_mode) {
776                         fprintf(stderr,"Press enter to see a dump of your service definitions\n");
777                         fflush(stdout);
778                         getc(stdin);
779                 }
780                 if (parameter_name || section_name) {
781                         bool isGlobal = False;
782                         s = GLOBAL_SECTION_SNUM;
783
784                         if (!section_name) {
785                                 section_name = GLOBAL_NAME;
786                                 isGlobal = True;
787                         } else if ((isGlobal=!strwicmp(section_name, GLOBAL_NAME)) == 0 &&
788                                  (s=lp_servicenumber(section_name)) == -1) {
789                                         fprintf(stderr,"Unknown section %s\n",
790                                                 section_name);
791                                         ret = 1;
792                                         goto done;
793                         }
794                         if (parameter_name) {
795                                 if (!dump_a_parameter( s, parameter_name, stdout, isGlobal)) {
796                                         fprintf(stderr,"Parameter %s unknown for section %s\n",
797                                                 parameter_name, section_name);
798                                         ret = 1;
799                                         goto done;
800                                 }
801                         } else {
802                                 if (isGlobal == True)
803                                         lp_dump(stdout, show_defaults, 0);
804                                 else
805                                         lp_dump_one(stdout, show_defaults, s);
806                         }
807                         goto done;
808                 }
809
810                 lp_dump(stdout, show_defaults, lp_numservices());
811         }
812
813         if(cname && caddr){
814                 /* this is totally ugly, a real `quick' hack */
815                 for (s=0;s<1000;s++) {
816                         if (VALID_SNUM(s)) {
817                                 if (allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1), cname, caddr)
818                                     && allow_access(lp_hosts_deny(s), lp_hosts_allow(s), cname, caddr)) {
819                                         fprintf(stderr,"Allow connection from %s (%s) to %s\n",
820                                                    cname,caddr,lp_servicename(talloc_tos(), s));
821                                 } else {
822                                         fprintf(stderr,"Deny connection from %s (%s) to %s\n",
823                                                    cname,caddr,lp_servicename(talloc_tos(), s));
824                                 }
825                         }
826                 }
827         }
828
829 done:
830         gfree_loadparm();
831         TALLOC_FREE(frame);
832         return ret;
833 }
834