ctdb-scripts: Ignore shellcheck SC2181 warning (use of $?)
[metze/samba/wip.git] / source3 / libsmb / libsmb_context.c
index f09e9c6287f65b513316050bb043cc2222013084..ed6ca2b1b9fd0d7109120dd7cae3be2edae85cbd 100644 (file)
-/* 
+/*
    Unix SMB/Netbios implementation.
    SMB client library implementation
    Copyright (C) Andrew Tridgell 1998
    Copyright (C) Richard Sharpe 2000, 2002
    Copyright (C) John Terpstra 2000
-   Copyright (C) Tom Jansen (Ninja ISD) 2002 
+   Copyright (C) Tom Jansen (Ninja ISD) 2002
    Copyright (C) Derrell Lipman 2003-2008
    Copyright (C) Jeremy Allison 2007, 2008
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "libsmb/libsmb.h"
 #include "libsmbclient.h"
 #include "libsmb_internal.h"
+#include "secrets.h"
+#include "../libcli/smb/smbXcli_base.h"
 
+/*
+ * Is the logging working / configfile read ?
+ */
+static bool SMBC_initialized = false;
+static unsigned int initialized_ctx_count = 0;
+static void *initialized_ctx_count_mutex = NULL;
 
 /*
- * Is the logging working / configfile read ? 
+ * Do some module- and library-wide intializations
  */
-static bool SMBC_initialized;
-static unsigned int initialized_ctx_count;
+static void
+SMBC_module_init(void * punused)
+{
+    bool conf_loaded = False;
+    char *home = NULL;
+    TALLOC_CTX *frame = talloc_stackframe();
+
+    setup_logging("libsmbclient", DEBUG_STDOUT);
+
+    /* Here we would open the smb.conf file if needed ... */
+
+    home = getenv("HOME");
+    if (home) {
+        char *conf = NULL;
+        if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) {
+            if (lp_load_client(conf)) {
+                conf_loaded = True;
+            } else {
+                DEBUG(5, ("Could not load config file: %s\n",
+                          conf));
+            }
+            SAFE_FREE(conf);
+        }
+    }
+
+    if (!conf_loaded) {
+        /*
+         * Well, if that failed, try the get_dyn_CONFIGFILE
+         * Which points to the standard locn, and if that
+         * fails, silently ignore it and use the internal
+         * defaults ...
+         */
+
+        if (!lp_load_client(get_dyn_CONFIGFILE())) {
+            DEBUG(5, ("Could not load config file: %s\n",
+                      get_dyn_CONFIGFILE()));
+        } else if (home) {
+            char *conf;
+            /*
+             * We loaded the global config file.  Now lets
+             * load user-specific modifications to the
+             * global config.
+             */
+            if (asprintf(&conf,
+                         "%s/.smb/smb.conf.append",
+                         home) > 0) {
+                if (!lp_load_client_no_reinit(conf)) {
+                    DEBUG(10,
+                          ("Could not append config file: "
+                           "%s\n",
+                           conf));
+                }
+                SAFE_FREE(conf);
+            }
+        }
+    }
+
+    load_interfaces();  /* Load the list of interfaces ... */
+
+    reopen_logs();  /* Get logging working ... */
+
+    /*
+     * Block SIGPIPE (from lib/util_sock.c: write())
+     * It is not needed and should not stop execution
+     */
+    BlockSignals(True, SIGPIPE);
+
+    /* Create the mutex we'll use to protect initialized_ctx_count */
+    if (SMB_THREAD_CREATE_MUTEX("initialized_ctx_count_mutex",
+                                initialized_ctx_count_mutex) != 0) {
+        smb_panic("SMBC_module_init: "
+                  "failed to create 'initialized_ctx_count' mutex");
+    }
+
+
+    TALLOC_FREE(frame);
+}
+
+
+static void
+SMBC_module_terminate(void)
+{
+    TALLOC_CTX *frame = talloc_stackframe();
+    secrets_shutdown();
+    gfree_all();
+    SMBC_initialized = false;
+    TALLOC_FREE(frame);
+}
+
 
 /*
  * Get a new empty handle to fill in with your own info
@@ -40,53 +136,65 @@ SMBCCTX *
 smbc_new_context(void)
 {
         SMBCCTX *context;
-        
+       TALLOC_CTX *frame = talloc_stackframe();
+
+        /* The first call to this function should initialize the module */
+        SMB_THREAD_ONCE(&SMBC_initialized, SMBC_module_init, NULL);
+
         /*
          * All newly added context fields should be placed in
          * SMBC_internal_data, not directly in SMBCCTX.
          */
         context = SMB_MALLOC_P(SMBCCTX);
         if (!context) {
+               TALLOC_FREE(frame);
                 errno = ENOMEM;
                 return NULL;
         }
-        
+
         ZERO_STRUCTP(context);
-        
+
         context->internal = SMB_MALLOC_P(struct SMBC_internal_data);
         if (!context->internal) {
+               TALLOC_FREE(frame);
                 SAFE_FREE(context);
                 errno = ENOMEM;
                 return NULL;
         }
-        
+
         /* Initialize the context and establish reasonable defaults */
         ZERO_STRUCTP(context->internal);
-        
+
         smbc_setDebug(context, 0);
         smbc_setTimeout(context, 20000);
-        
+        smbc_setPort(context, 0);
+
         smbc_setOptionFullTimeNames(context, False);
         smbc_setOptionOpenShareMode(context, SMBC_SHAREMODE_DENY_NONE);
         smbc_setOptionSmbEncryptionLevel(context, SMBC_ENCRYPTLEVEL_NONE);
+        smbc_setOptionUseCCache(context, True);
         smbc_setOptionCaseSensitive(context, False);
         smbc_setOptionBrowseMaxLmbCount(context, 3);    /* # LMBs to query */
         smbc_setOptionUrlEncodeReaddirEntries(context, False);
         smbc_setOptionOneSharePerServer(context, False);
-        
+       if (getenv("LIBSMBCLIENT_NO_CCACHE") != NULL) {
+               smbc_setOptionUseCCache(context, false);
+       }
+
         smbc_setFunctionAuthData(context, SMBC_get_auth_data);
         smbc_setFunctionCheckServer(context, SMBC_check_server);
         smbc_setFunctionRemoveUnusedServer(context, SMBC_remove_unused_server);
-        
+
         smbc_setOptionUserData(context, NULL);
         smbc_setFunctionAddCachedServer(context, SMBC_add_cached_server);
         smbc_setFunctionGetCachedServer(context, SMBC_get_cached_server);
         smbc_setFunctionRemoveCachedServer(context, SMBC_remove_cached_server);
         smbc_setFunctionPurgeCachedServers(context, SMBC_purge_cached_servers);
-        
+
         smbc_setFunctionOpen(context, SMBC_open_ctx);
         smbc_setFunctionCreat(context, SMBC_creat_ctx);
         smbc_setFunctionRead(context, SMBC_read_ctx);
+        smbc_setFunctionSplice(context, SMBC_splice_ctx);
         smbc_setFunctionWrite(context, SMBC_write_ctx);
         smbc_setFunctionClose(context, SMBC_close_ctx);
         smbc_setFunctionUnlink(context, SMBC_unlink_ctx);
@@ -106,18 +214,20 @@ smbc_new_context(void)
         smbc_setFunctionTelldir(context, SMBC_telldir_ctx);
         smbc_setFunctionLseekdir(context, SMBC_lseekdir_ctx);
         smbc_setFunctionFstatdir(context, SMBC_fstatdir_ctx);
+        smbc_setFunctionNotify(context, SMBC_notify_ctx);
         smbc_setFunctionChmod(context, SMBC_chmod_ctx);
         smbc_setFunctionUtimes(context, SMBC_utimes_ctx);
         smbc_setFunctionSetxattr(context, SMBC_setxattr_ctx);
         smbc_setFunctionGetxattr(context, SMBC_getxattr_ctx);
         smbc_setFunctionRemovexattr(context, SMBC_removexattr_ctx);
         smbc_setFunctionListxattr(context, SMBC_listxattr_ctx);
-        
+
         smbc_setFunctionOpenPrintJob(context, SMBC_open_print_job_ctx);
         smbc_setFunctionPrintFile(context, SMBC_print_file_ctx);
         smbc_setFunctionListPrintJobs(context, SMBC_list_print_jobs_ctx);
         smbc_setFunctionUnlinkPrintJob(context, SMBC_unlink_print_job_ctx);
-        
+
+       TALLOC_FREE(frame);
         return context;
 }
 
@@ -132,22 +242,26 @@ int
 smbc_free_context(SMBCCTX *context,
                   int shutdown_ctx)
 {
+       TALLOC_CTX *frame;
         if (!context) {
                 errno = EBADF;
                 return 1;
         }
-        
+
+       frame = talloc_stackframe();
+
         if (shutdown_ctx) {
                 SMBCFILE * f;
                 DEBUG(1,("Performing aggressive shutdown.\n"));
-                
+
                 f = context->internal->files;
                 while (f) {
+                       SMBCFILE *next = f->next;
                         smbc_getFunctionClose(context)(context, f);
-                        f = f->next;
+                       f = next;
                 }
                 context->internal->files = NULL;
-                
+
                 /* First try to remove the servers the nice way. */
                 if (smbc_getFunctionPurgeCachedServers(context)(context)) {
                         SMBCSRV * s;
@@ -156,8 +270,8 @@ smbc_free_context(SMBCCTX *context,
                                   "Nice way shutdown failed.\n"));
                         s = context->internal->servers;
                         while (s) {
-                                DEBUG(1, ("Forced shutdown: %p (fd=%d)\n",
-                                          s, s->cli->fd));
+                                DEBUG(1, ("Forced shutdown: %p (cli=%p)\n",
+                                          s, s->cli));
                                 cli_shutdown(s->cli);
                                 smbc_getFunctionRemoveCachedServer(context)(context,
                                                                          s);
@@ -175,32 +289,30 @@ smbc_free_context(SMBCCTX *context,
                         DEBUG(1, ("Could not purge all servers, "
                                   "free_context failed.\n"));
                         errno = EBUSY;
+                       TALLOC_FREE(frame);
                         return 1;
                 }
                 if (context->internal->servers) {
                         DEBUG(1, ("Active servers in context, "
                                   "free_context failed.\n"));
                         errno = EBUSY;
+                       TALLOC_FREE(frame);
                         return 1;
                 }
                 if (context->internal->files) {
                         DEBUG(1, ("Active files in context, "
                                   "free_context failed.\n"));
                         errno = EBUSY;
+                       TALLOC_FREE(frame);
                         return 1;
                 }
         }
-        
+
         /* Things we have to clean up */
-        free(smbc_getWorkgroup(context));
         smbc_setWorkgroup(context, NULL);
-
-        free(smbc_getNetbiosName(context));
         smbc_setNetbiosName(context, NULL);
-
-        free(smbc_getUser(context));
         smbc_setUser(context, NULL);
-        
+
         DEBUG(3, ("Context %p successfully freed\n", context));
 
        /* Free any DFS auth context. */
@@ -209,16 +321,25 @@ smbc_free_context(SMBCCTX *context,
        SAFE_FREE(context->internal);
         SAFE_FREE(context);
 
+        /* Protect access to the count of contexts in use */
+       if (SMB_THREAD_LOCK(initialized_ctx_count_mutex) != 0) {
+                smb_panic("error locking 'initialized_ctx_count'");
+       }
+
        if (initialized_ctx_count) {
                initialized_ctx_count--;
        }
 
-       if (initialized_ctx_count == 0 && SMBC_initialized) {
-               gencache_shutdown();
-               secrets_shutdown();
-               gfree_all();
-               SMBC_initialized = false;
+       if (initialized_ctx_count == 0) {
+            SMBC_module_terminate();
+       }
+
+        /* Unlock the mutex */
+       if (SMB_THREAD_UNLOCK(initialized_ctx_count_mutex) != 0) {
+                smb_panic("error unlocking 'initialized_ctx_count'");
        }
+
+       TALLOC_FREE(frame);
         return 0;
 }
 
@@ -240,30 +361,32 @@ smbc_option_set(SMBCCTX *context,
                 void *v;
                 const char *s;
         } option_value;
-        
+
+       TALLOC_CTX *frame = talloc_stackframe();
+
         va_start(ap, option_name);
-        
+
         if (strcmp(option_name, "debug_to_stderr") == 0) {
                 option_value.b = (bool) va_arg(ap, int);
                 smbc_setOptionDebugToStderr(context, option_value.b);
-                
+
         } else if (strcmp(option_name, "full_time_names") == 0) {
                 option_value.b = (bool) va_arg(ap, int);
                 smbc_setOptionFullTimeNames(context, option_value.b);
-                
+
         } else if (strcmp(option_name, "open_share_mode") == 0) {
                 option_value.i = va_arg(ap, int);
                 smbc_setOptionOpenShareMode(context, option_value.i);
-                
+
         } else if (strcmp(option_name, "auth_function") == 0) {
                 option_value.auth_fn =
                         va_arg(ap, smbc_get_auth_data_with_context_fn);
                 smbc_setFunctionAuthDataWithContext(context, option_value.auth_fn);
-                
+
         } else if (strcmp(option_name, "user_data") == 0) {
                 option_value.v = va_arg(ap, void *);
                 smbc_setOptionUserData(context, option_value.v);
-                
+
         } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
                 option_value.s = va_arg(ap, const char *);
                 if (strcmp(option_value.s, "none") == 0) {
@@ -276,33 +399,38 @@ smbc_option_set(SMBCCTX *context,
                         smbc_setOptionSmbEncryptionLevel(context,
                                                          SMBC_ENCRYPTLEVEL_REQUIRE);
                 }
-                
+
         } else if (strcmp(option_name, "browse_max_lmb_count") == 0) {
                 option_value.i = va_arg(ap, int);
                 smbc_setOptionBrowseMaxLmbCount(context, option_value.i);
-                
+
         } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) {
                 option_value.b = (bool) va_arg(ap, int);
                 smbc_setOptionUrlEncodeReaddirEntries(context, option_value.b);
-                
+
         } else if (strcmp(option_name, "one_share_per_server") == 0) {
                 option_value.b = (bool) va_arg(ap, int);
                 smbc_setOptionOneSharePerServer(context, option_value.b);
-                
+
         } else if (strcmp(option_name, "use_kerberos") == 0) {
                 option_value.b = (bool) va_arg(ap, int);
                 smbc_setOptionUseKerberos(context, option_value.b);
-                
+
         } else if (strcmp(option_name, "fallback_after_kerberos") == 0) {
                 option_value.b = (bool) va_arg(ap, int);
                 smbc_setOptionFallbackAfterKerberos(context, option_value.b);
-                
+
+        } else if (strcmp(option_name, "use_ccache") == 0) {
+                option_value.b = (bool) va_arg(ap, int);
+                smbc_setOptionUseCCache(context, option_value.b);
+
         } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) {
                 option_value.b = (bool) va_arg(ap, int);
                 smbc_setOptionNoAutoAnonymousLogin(context, option_value.b);
         }
-        
+
         va_end(ap);
+       TALLOC_FREE(frame);
 }
 
 
@@ -320,45 +448,45 @@ smbc_option_get(SMBCCTX *context,
 #else
                 return (void *) smbc_getOptionDebugToStderr(context);
 #endif
-                
+
         } else if (strcmp(option_name, "full_time_names") == 0) {
 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
                 return (void *) (intptr_t) smbc_getOptionFullTimeNames(context);
 #else
                 return (void *) smbc_getOptionFullTimeNames(context);
 #endif
-                
+
         } else if (strcmp(option_name, "open_share_mode") == 0) {
 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
                 return (void *) (intptr_t) smbc_getOptionOpenShareMode(context);
 #else
                 return (void *) smbc_getOptionOpenShareMode(context);
 #endif
-                
+
         } else if (strcmp(option_name, "auth_function") == 0) {
                 return (void *) smbc_getFunctionAuthDataWithContext(context);
-                
+
         } else if (strcmp(option_name, "user_data") == 0) {
                 return smbc_getOptionUserData(context);
-                
+
         } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
                 switch(smbc_getOptionSmbEncryptionLevel(context))
                 {
                 case 0:
-                        return (void *) "none";
+                        return discard_const_p(void, "none");
                 case 1:
-                        return (void *) "request";
+                        return discard_const_p(void, "request");
                 case 2:
-                        return (void *) "require";
+                        return discard_const_p(void, "require");
                 }
-                
+
         } else if (strcmp(option_name, "smb_encrypt_on") == 0) {
                 SMBCSRV *s;
                 unsigned int num_servers = 0;
-                
+
                 for (s = context->internal->servers; s; s = s->next) {
                         num_servers++;
-                        if (s->cli->trans_enc_state == NULL) {
+                        if (!smb1cli_conn_encryption_on(s->cli->conn)) {
                                 return (void *)false;
                         }
                 }
@@ -367,42 +495,49 @@ smbc_option_get(SMBCCTX *context,
 #else
                 return (void *) (bool) (num_servers > 0);
 #endif
-                
+
         } else if (strcmp(option_name, "browse_max_lmb_count") == 0) {
 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
                 return (void *) (intptr_t) smbc_getOptionBrowseMaxLmbCount(context);
 #else
                 return (void *) smbc_getOptionBrowseMaxLmbCount(context);
 #endif
-                
+
         } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) {
 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
                 return (void *)(intptr_t) smbc_getOptionUrlEncodeReaddirEntries(context);
 #else
                 return (void *) (bool) smbc_getOptionUrlEncodeReaddirEntries(context);
 #endif
-                
+
         } else if (strcmp(option_name, "one_share_per_server") == 0) {
 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
                 return (void *) (intptr_t) smbc_getOptionOneSharePerServer(context);
 #else
                 return (void *) (bool) smbc_getOptionOneSharePerServer(context);
 #endif
-                
+
         } else if (strcmp(option_name, "use_kerberos") == 0) {
 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
                 return (void *) (intptr_t) smbc_getOptionUseKerberos(context);
 #else
                 return (void *) (bool) smbc_getOptionUseKerberos(context);
 #endif
-                
+
         } else if (strcmp(option_name, "fallback_after_kerberos") == 0) {
 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
                 return (void *)(intptr_t) smbc_getOptionFallbackAfterKerberos(context);
 #else
                 return (void *) (bool) smbc_getOptionFallbackAfterKerberos(context);
 #endif
-                
+
+        } else if (strcmp(option_name, "use_ccache") == 0) {
+#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
+                return (void *) (intptr_t) smbc_getOptionUseCCache(context);
+#else
+                return (void *) (bool) smbc_getOptionUseCCache(context);
+#endif
+
         } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) {
 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
                 return (void *) (intptr_t) smbc_getOptionNoAutoAnonymousLogin(context);
@@ -410,7 +545,7 @@ smbc_option_get(SMBCCTX *context,
                 return (void *) (bool) smbc_getOptionNoAutoAnonymousLogin(context);
 #endif
         }
-        
+
         return NULL;
 }
 
@@ -426,116 +561,36 @@ SMBCCTX *
 smbc_init_context(SMBCCTX *context)
 {
         int pid;
-        char *user = NULL;
-        char *home = NULL;
-        
+        TALLOC_CTX *frame;
+
         if (!context) {
                 errno = EBADF;
                 return NULL;
         }
-        
+
         /* Do not initialise the same client twice */
         if (context->internal->initialized) {
                 return NULL;
         }
-        
+
+        frame = talloc_stackframe();
+
         if ((!smbc_getFunctionAuthData(context) &&
              !smbc_getFunctionAuthDataWithContext(context)) ||
             smbc_getDebug(context) < 0 ||
             smbc_getDebug(context) > 100) {
-                
+
+                TALLOC_FREE(frame);
                 errno = EINVAL;
                 return NULL;
-                
-        }
-        
-        if (!SMBC_initialized) {
-                /*
-                 * Do some library-wide intializations the first time we get
-                 * called
-                 */
-                bool conf_loaded = False;
-                TALLOC_CTX *frame = talloc_stackframe();
-                
-                load_case_tables();
-                
-                setup_logging("libsmbclient", True);
-                if (context->internal->debug_stderr) {
-                        dbf = x_stderr;
-                        x_setbuf(x_stderr, NULL);
-                }
-                
-                /* Here we would open the smb.conf file if needed ... */
-                
-                lp_set_in_client(True);
-                
-                home = getenv("HOME");
-                if (home) {
-                        char *conf = NULL;
-                        if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) {
-                                if (lp_load(conf, True, False, False, True)) {
-                                        conf_loaded = True;
-                                } else {
-                                        DEBUG(5, ("Could not load config file: %s\n",
-                                                  conf));
-                                }
-                                SAFE_FREE(conf);
-                        }
-                }
-                
-                if (!conf_loaded) {
-                        /*
-                         * Well, if that failed, try the get_dyn_CONFIGFILE
-                         * Which points to the standard locn, and if that
-                         * fails, silently ignore it and use the internal
-                         * defaults ...
-                         */
-                        
-                        if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) {
-                                DEBUG(5, ("Could not load config file: %s\n",
-                                          get_dyn_CONFIGFILE()));
-                        } else if (home) {
-                                char *conf;
-                                /*
-                                 * We loaded the global config file.  Now lets
-                                 * load user-specific modifications to the
-                                 * global config.
-                                 */
-                                if (asprintf(&conf,
-                                             "%s/.smb/smb.conf.append",
-                                             home) > 0) {
-                                        if (!lp_load(conf, True, False, False, False)) {
-                                                DEBUG(10,
-                                                      ("Could not append config file: "
-                                                       "%s\n",
-                                                       conf));
-                                        }
-                                        SAFE_FREE(conf);
-                                }
-                        }
-                }
-                
-                load_interfaces();  /* Load the list of interfaces ... */
-                
-                reopen_logs();  /* Get logging working ... */
-                
-                /*
-                 * Block SIGPIPE (from lib/util_sock.c: write())
-                 * It is not needed and should not stop execution
-                 */
-                BlockSignals(True, SIGPIPE);
-                
-                /* Done with one-time initialisation */
-                SMBC_initialized = true;
-                
-                TALLOC_FREE(frame);
+
         }
-        
+
         if (!smbc_getUser(context)) {
                 /*
                  * FIXME: Is this the best way to get the user info?
                  */
-                user = getenv("USER");
+               char *user = getenv("USER");
                 /* walk around as "guest" if no username can be found */
                 if (!user) {
                         user = SMB_STRDUP("guest");
@@ -544,13 +599,21 @@ smbc_init_context(SMBCCTX *context)
                 }
 
                 if (!user) {
+                        TALLOC_FREE(frame);
                         errno = ENOMEM;
                         return NULL;
                 }
 
                 smbc_setUser(context, user);
+               SAFE_FREE(user);
+
+               if (!smbc_getUser(context)) {
+                        TALLOC_FREE(frame);
+                        errno = ENOMEM;
+                        return NULL;
+                }
         }
-        
+
         if (!smbc_getNetbiosName(context)) {
                 /*
                  * We try to get our netbios name from the config. If that
@@ -558,16 +621,17 @@ smbc_init_context(SMBCCTX *context)
                  * our hostname etc
                  */
                 char *netbios_name;
-                if (global_myname()) {
-                        netbios_name = SMB_STRDUP(global_myname());
+                if (lp_netbios_name()) {
+                        netbios_name = SMB_STRDUP(lp_netbios_name());
                 } else {
                         /*
                          * Hmmm, I want to get hostname as well, but I am too
                          * lazy for the moment
                          */
-                        pid = sys_getpid();
+                        pid = getpid();
                         netbios_name = (char *)SMB_MALLOC(17);
                         if (!netbios_name) {
+                                TALLOC_FREE(frame);
                                 errno = ENOMEM;
                                 return NULL;
                         }
@@ -576,15 +640,23 @@ smbc_init_context(SMBCCTX *context)
                 }
 
                 if (!netbios_name) {
+                        TALLOC_FREE(frame);
                         errno = ENOMEM;
                         return NULL;
                 }
-                
+
                 smbc_setNetbiosName(context, netbios_name);
+               SAFE_FREE(netbios_name);
+
+                if (!smbc_getNetbiosName(context)) {
+                        TALLOC_FREE(frame);
+                        errno = ENOMEM;
+                        return NULL;
+                }
         }
-        
+
         DEBUG(1, ("Using netbios name %s.\n", smbc_getNetbiosName(context)));
-        
+
         if (!smbc_getWorkgroup(context)) {
                 char *workgroup;
 
@@ -597,26 +669,42 @@ smbc_init_context(SMBCCTX *context)
                 }
 
                 if (!workgroup) {
+                        TALLOC_FREE(frame);
                         errno = ENOMEM;
                         return NULL;
                 }
 
                 smbc_setWorkgroup(context, workgroup);
+               SAFE_FREE(workgroup);
+
+               if (!smbc_getWorkgroup(context)) {
+                        TALLOC_FREE(frame);
+                       errno = ENOMEM;
+                       return NULL;
+               }
         }
-        
+
         DEBUG(1, ("Using workgroup %s.\n", smbc_getWorkgroup(context)));
-        
+
         /* shortest timeout is 1 second */
         if (smbc_getTimeout(context) > 0 && smbc_getTimeout(context) < 1000)
                 smbc_setTimeout(context, 1000);
-        
-        /*
-         * FIXME: Should we check the function pointers here?
-         */
-        
+
         context->internal->initialized = True;
+
+        /* Protect access to the count of contexts in use */
+       if (SMB_THREAD_LOCK(initialized_ctx_count_mutex) != 0) {
+                smb_panic("error locking 'initialized_ctx_count'");
+       }
+
        initialized_ctx_count++;
 
+        /* Unlock the mutex */
+       if (SMB_THREAD_UNLOCK(initialized_ctx_count_mutex) != 0) {
+                smb_panic("error unlocking 'initialized_ctx_count'");
+       }
+
+        TALLOC_FREE(frame);
         return context;
 }
 
@@ -651,23 +739,33 @@ void smbc_set_credentials_with_fallback(SMBCCTX *context,
 {
        smbc_bool use_kerberos = false;
        const char *signing_state = "off";
-       struct user_auth_info *auth_info = user_auth_info_init(NULL);
+       struct user_auth_info *auth_info = NULL;
+       TALLOC_CTX *frame;
+
+       if (! context) {
 
-       if (auth_info) {
+               return;
        }
 
-       if (! context ||
-           ! workgroup || ! *workgroup ||
-           ! user || ! *user ||
-           ! password || ! *password) {
+       frame = talloc_stackframe();
 
-               return;
+       if (! workgroup || ! *workgroup) {
+               workgroup = smbc_getWorkgroup(context);
+       }
+
+       if (! user) {
+               user = smbc_getUser(context);
+       }
+
+       if (! password) {
+               password = "";
        }
 
        auth_info = user_auth_info_init(NULL);
 
-       if (auth_info) {
+       if (auth_info) {
                DEBUG(0, ("smbc_set_credentials_with_fallback: allocation fail\n"));
+               TALLOC_FREE(frame);
                return;
        }
 
@@ -675,23 +773,26 @@ void smbc_set_credentials_with_fallback(SMBCCTX *context,
                use_kerberos = True;
        }
 
-       if (lp_client_signing()) {
-               signing_state = "on";
+       if (lp_client_signing() != SMB_SIGNING_OFF) {
+               signing_state = "if_required";
        }
 
-       if (lp_client_signing() == Required) {
-               signing_state = "force";
+       if (lp_client_signing() == SMB_SIGNING_REQUIRED) {
+               signing_state = "required";
        }
 
         set_cmdline_auth_info_username(auth_info, user);
+        set_cmdline_auth_info_domain(auth_info, workgroup);
         set_cmdline_auth_info_password(auth_info, password);
         set_cmdline_auth_info_use_kerberos(auth_info, use_kerberos);
         set_cmdline_auth_info_signing_state(auth_info, signing_state);
        set_cmdline_auth_info_fallback_after_kerberos(auth_info,
                smbc_getOptionFallbackAfterKerberos(context));
-        set_global_myworkgroup(workgroup);
+       set_cmdline_auth_info_use_ccache(
+               auth_info, smbc_getOptionUseCCache(context));
 
        TALLOC_FREE(context->internal->auth_info);
 
         context->internal->auth_info = auth_info;
+       TALLOC_FREE(frame);
 }