Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-wsgi
[kai/samba.git] / source / torture / locktest.c
index fcb229df083db9992c260ec5ca46357926796e27..8959232edb6149d8c6f033dbeb0a0c3bb83c3853 100644 (file)
@@ -5,7 +5,7 @@
    
    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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "lib/cmdline/popt_common.h"
+#include "lib/events/events.h"
+#include "system/filesys.h"
+#include "system/time.h"
+#include "pstring.h"
+#include "auth/credentials/credentials.h"
+#include "auth/gensec/gensec.h"
+#include "libcli/libcli.h"
+#include "param/param.h"
+#include "dynconfig.h"
+#include "libcli/resolve/resolve.h"
 
-static fstring password[2];
-static fstring username[2];
-static int got_user;
-static int got_pass;
-static BOOL use_kerberos;
 static int numops = 1000;
-static BOOL showall;
-static BOOL analyze;
-static BOOL hide_unlock_fails;
-static BOOL use_oplocks;
-static unsigned lock_range = 100;
-static unsigned lock_base = 0;
-static unsigned min_length = 0;
-static BOOL exact_error_codes;
-static BOOL zero_zero;
+static int showall;
+static int analyze;
+static int hide_unlock_fails;
+static int use_oplocks;
+static uint_t lock_range = 100;
+static uint_t lock_base = 0;
+static uint_t min_length = 0;
+static int exact_error_codes;
+static int zero_zero;
 
 #define FILENAME "\\locktest.dat"
 
@@ -47,7 +52,7 @@ static BOOL zero_zero;
 #define NFILES 2
 #define LOCK_TIMEOUT 0
 
-#define NASTY_POSIX_LOCK_HACK 0
+static struct cli_credentials *servers[NSERVERS];
 
 enum lock_op {OP_LOCK, OP_UNLOCK, OP_REOPEN};
 
@@ -55,8 +60,9 @@ struct record {
        enum lock_op lock_op;
        enum brl_type lock_type;
        char conn, f;
-       SMB_BIG_UINT start, len;
+       uint64_t start, len;
        char needed;
+       uint16_t pid;
 };
 
 #define PRESETS 0
@@ -102,12 +108,19 @@ static struct record *recorded;
 /***************************************************** 
 return a connection to a server
 *******************************************************/
-static struct cli_state *connect_one(char *share, int snum)
+static struct smbcli_state *connect_one(struct event_context *ev,
+                                       struct loadparm_context *lp_ctx,
+                                       char *share, int snum, int conn)
 {
-       struct cli_state *c;
+       struct smbcli_state *c;
        fstring server, myname;
-       uint_t flags = 0;
        NTSTATUS status;
+       int retries = 10;
+       struct smbcli_options options;
+
+       lp_smbcli_options(lp_ctx, &options);
+
+       printf("connect_one(%s, %d, %d)\n", share, snum, conn);
 
        fstrcpy(server,share+2);
        share = strchr_m(server,'\\');
@@ -115,16 +128,47 @@ static struct cli_state *connect_one(char *share, int snum)
        *share = 0;
        share++;
 
-       slprintf(myname,sizeof(myname), "lock-%u-%u", getpid(), snum);
+       if (snum == 0) {
+               char **unc_list = NULL;
+               int num_unc_names;
+               const char *p;
+               p = lp_parm_string(lp_ctx, NULL, "torture", "unclist");
+               if (p) {
+                       char *h, *s;
+                       unc_list = file_lines_load(p, &num_unc_names, NULL);
+                       if (!unc_list || num_unc_names <= 0) {
+                               printf("Failed to load unc names list from '%s'\n", p);
+                               exit(1);
+                       }
 
-       if (use_kerberos)
-               flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
-       
-       status = cli_full_connection(&c, myname,
-                                    server, NULL,  
-                                    share, "?????", 
-                                    username[snum], lp_workgroup(), 
-                                    password[snum], flags, NULL);
+                       if (!smbcli_parse_unc(unc_list[conn % num_unc_names],
+                                             NULL, &h, &s)) {
+                               printf("Failed to parse UNC name %s\n",
+                                      unc_list[conn % num_unc_names]);
+                               exit(1);
+                       }
+                       fstrcpy(server, h);
+                       fstrcpy(share, s);
+               }
+       }
+
+
+       slprintf(myname,sizeof(myname), "lock-%u-%u", getpid(), snum);
+       cli_credentials_set_workstation(servers[snum], myname, CRED_SPECIFIED);
+
+       do {
+               printf("\\\\%s\\%s\n", server, share);
+               status = smbcli_full_connection(NULL, &c, 
+                                               server, 
+                                               lp_smb_ports(lp_ctx),
+                                               share, NULL,
+                                               servers[snum], 
+                                               lp_resolve_context(lp_ctx),
+                                               ev, &options);
+               if (!NT_STATUS_IS_OK(status)) {
+                       sleep(2);
+               }
+       } while (!NT_STATUS_IS_OK(status) && retries--);
 
        if (!NT_STATUS_IS_OK(status)) {
                return NULL;
@@ -134,7 +178,9 @@ static struct cli_state *connect_one(char *share, int snum)
 }
 
 
-static void reconnect(struct cli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NSERVERS][NCONNECTIONS][NFILES],
+static void reconnect(struct event_context *ev,
+                     struct loadparm_context *lp_ctx,
+                     struct smbcli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NSERVERS][NCONNECTIONS][NFILES],
                      char *share[NSERVERS])
 {
        int server, conn, f;
@@ -144,13 +190,14 @@ static void reconnect(struct cli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NS
                if (cli[server][conn]) {
                        for (f=0;f<NFILES;f++) {
                                if (fnum[server][conn][f] != -1) {
-                                       cli_close(cli[server][conn]->tree, fnum[server][conn][f]);
+                                       smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]);
                                        fnum[server][conn][f] = -1;
                                }
                        }
-                       cli_shutdown(cli[server][conn]);
+                       talloc_free(cli[server][conn]);
                }
-               cli[server][conn] = connect_one(share[server], server);
+               cli[server][conn] = connect_one(ev, lp_ctx, share[server], 
+                                               server, conn);
                if (!cli[server][conn]) {
                        DEBUG(0,("Failed to connect to %s\n", share[server]));
                        exit(1);
@@ -160,27 +207,53 @@ static void reconnect(struct cli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NS
 
 
 
-static BOOL test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS], 
+static bool test_one(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
                     int fnum[NSERVERS][NCONNECTIONS][NFILES],
                     struct record *rec)
 {
-       unsigned conn = rec->conn;
-       unsigned f = rec->f;
-       SMB_BIG_UINT start = rec->start;
-       SMB_BIG_UINT len = rec->len;
+       uint_t conn = rec->conn;
+       uint_t f = rec->f;
+       uint64_t start = rec->start;
+       uint64_t len = rec->len;
        enum brl_type op = rec->lock_type;
        int server;
-       BOOL ret[NSERVERS];
+       bool ret[NSERVERS];
        NTSTATUS status[NSERVERS];
 
        switch (rec->lock_op) {
        case OP_LOCK:
                /* set a lock */
                for (server=0;server<NSERVERS;server++) {
-                       ret[server] = cli_lock64(cli[server][conn]->tree, 
-                                                fnum[server][conn][f],
-                                                start, len, LOCK_TIMEOUT, op);
-                       status[server] = cli_nt_error(cli[server][conn]->tree);
+                       NTSTATUS res;
+                       struct smbcli_tree *tree=cli[server][conn]->tree;
+                       int fn=fnum[server][conn][f];
+
+                       if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
+                               res=smbcli_lock(tree, fn, start, len, LOCK_TIMEOUT, rec->lock_op);
+                       } else {
+                               union smb_lock parms;
+                               int ltype;
+                               struct smb_lock_entry lock[1];
+
+                               parms.lockx.level = RAW_LOCK_LOCKX;
+                               parms.lockx.in.file.fnum = fn;
+       
+                               ltype = (rec->lock_op == READ_LOCK? 1 : 0);
+                               ltype |= LOCKING_ANDX_LARGE_FILES;
+                               parms.lockx.in.mode = ltype;
+                               parms.lockx.in.timeout = LOCK_TIMEOUT;
+                               parms.lockx.in.ulock_cnt = 0;
+                               parms.lockx.in.lock_cnt = 1;
+                               lock[0].pid = rec->pid;
+                               lock[0].offset = start;
+                               lock[0].count = len;
+                               parms.lockx.in.locks = &lock[0];
+
+                               res = smb_raw_lock(tree, &parms);
+                       }
+
+                       ret[server] = NT_STATUS_IS_OK(res); 
+                       status[server] = smbcli_nt_error(cli[server][conn]->tree);
                        if (!exact_error_codes && 
                            NT_STATUS_EQUAL(status[server], 
                                            NT_STATUS_FILE_LOCK_CONFLICT)) {
@@ -194,16 +267,39 @@ static BOOL test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS],
                               op==READ_LOCK?"READ_LOCK":"WRITE_LOCK",
                               nt_errstr(status[0]), nt_errstr(status[1]));
                }
-               if (!NT_STATUS_EQUAL(status[0],status[1])) return False;
+               if (!NT_STATUS_EQUAL(status[0],status[1])) return false;
                break;
                
        case OP_UNLOCK:
                /* unset a lock */
                for (server=0;server<NSERVERS;server++) {
-                       ret[server] = cli_unlock64(cli[server][conn]->tree, 
-                                                  fnum[server][conn][f],
-                                                  start, len);
-                       status[server] = cli_nt_error(cli[server][conn]->tree);
+                       NTSTATUS res;
+                       struct smbcli_tree *tree=cli[server][conn]->tree;
+                       int fn=fnum[server][conn][f];
+
+
+                       if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
+                               res=smbcli_unlock(tree, fn, start, len);
+                       } else {
+                               union smb_lock parms;
+                               struct smb_lock_entry lock[1];
+
+                               parms.lockx.level = RAW_LOCK_LOCKX;
+                               parms.lockx.in.file.fnum = fn;
+                               parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
+                               parms.lockx.in.timeout = 0;
+                               parms.lockx.in.ulock_cnt = 1;
+                               parms.lockx.in.lock_cnt = 0;
+                               lock[0].pid = rec->pid;
+                               lock[0].count = len;
+                               lock[0].offset = start;
+                               parms.lockx.in.locks = &lock[0];
+
+                               res = smb_raw_lock(tree, &parms);
+                       }
+
+                       ret[server] = NT_STATUS_IS_OK(res);
+                       status[server] = smbcli_nt_error(cli[server][conn]->tree);
                }
                if (showall || 
                    (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1]))) {
@@ -213,22 +309,22 @@ static BOOL test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS],
                               nt_errstr(status[0]), nt_errstr(status[1]));
                }
                if (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1])) 
-                       return False;
+                       return false;
                break;
 
        case OP_REOPEN:
                /* reopen the file */
                for (server=0;server<NSERVERS;server++) {
-                       cli_close(cli[server][conn]->tree, fnum[server][conn][f]);
+                       smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]);
                        fnum[server][conn][f] = -1;
                }
                for (server=0;server<NSERVERS;server++) {
-                       fnum[server][conn][f] = cli_open(cli[server][conn]->tree, FILENAME,
+                       fnum[server][conn][f] = smbcli_open(cli[server][conn]->tree, FILENAME,
                                                         O_RDWR|O_CREAT,
                                                         DENY_NONE);
                        if (fnum[server][conn][f] == -1) {
                                printf("failed to reopen on share%d\n", server);
-                               return False;
+                               return false;
                        }
                }
                if (showall) {
@@ -238,10 +334,10 @@ static BOOL test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS],
                break;
        }
 
-       return True;
+       return true;
 }
 
-static void close_files(struct cli_state *cli[NSERVERS][NCONNECTIONS], 
+static void close_files(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
                        int fnum[NSERVERS][NCONNECTIONS][NFILES])
 {
        int server, conn, f; 
@@ -250,16 +346,16 @@ static void close_files(struct cli_state *cli[NSERVERS][NCONNECTIONS],
        for (conn=0;conn<NCONNECTIONS;conn++)
        for (f=0;f<NFILES;f++) {
                if (fnum[server][conn][f] != -1) {
-                       cli_close(cli[server][conn]->tree, fnum[server][conn][f]);
+                       smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]);
                        fnum[server][conn][f] = -1;
                }
        }
        for (server=0;server<NSERVERS;server++) {
-               cli_unlink(cli[server][0]->tree, FILENAME);
+               smbcli_unlink(cli[server][0]->tree, FILENAME);
        }
 }
 
-static void open_files(struct cli_state *cli[NSERVERS][NCONNECTIONS], 
+static void open_files(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
                       int fnum[NSERVERS][NCONNECTIONS][NFILES])
 {
        int server, conn, f; 
@@ -267,7 +363,7 @@ static void open_files(struct cli_state *cli[NSERVERS][NCONNECTIONS],
        for (server=0;server<NSERVERS;server++)
        for (conn=0;conn<NCONNECTIONS;conn++)
        for (f=0;f<NFILES;f++) {
-               fnum[server][conn][f] = cli_open(cli[server][conn]->tree, FILENAME,
+               fnum[server][conn][f] = smbcli_open(cli[server][conn]->tree, FILENAME,
                                                 O_RDWR|O_CREAT,
                                                 DENY_NONE);
                if (fnum[server][conn][f] == -1) {
@@ -279,7 +375,7 @@ static void open_files(struct cli_state *cli[NSERVERS][NCONNECTIONS],
 }
 
 
-static int retest(struct cli_state *cli[NSERVERS][NCONNECTIONS], 
+static int retest(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], 
                   int fnum[NSERVERS][NCONNECTIONS][NFILES],
                   int n)
 {
@@ -303,16 +399,18 @@ static int retest(struct cli_state *cli[NSERVERS][NCONNECTIONS],
    we then do random locking ops in tamdem on the 4 fnums from each
    server and ensure that the results match
  */
-static void test_locks(char *share[NSERVERS])
+static int test_locks(struct event_context *ev,
+                     struct loadparm_context *lp_ctx,
+                     char *share[NSERVERS])
 {
-       struct cli_state *cli[NSERVERS][NCONNECTIONS];
+       struct smbcli_state *cli[NSERVERS][NCONNECTIONS];
        int fnum[NSERVERS][NCONNECTIONS][NFILES];
        int n, i, n1, skip, r1, r2; 
 
        ZERO_STRUCT(fnum);
        ZERO_STRUCT(cli);
 
-       recorded = (struct record *)malloc(sizeof(*recorded) * numops);
+       recorded = malloc_array_p(struct record, numops);
 
        for (n=0; n<numops; n++) {
 #if PRESETS
@@ -322,11 +420,15 @@ static void test_locks(char *share[NSERVERS])
 #endif
                        recorded[n].conn = random() % NCONNECTIONS;
                        recorded[n].f = random() % NFILES;
-                       recorded[n].start = lock_base + ((unsigned)random() % (lock_range-1));
+                       recorded[n].start = lock_base + ((uint_t)random() % (lock_range-1));
                        recorded[n].len =  min_length +
                                random() % (lock_range-(recorded[n].start-lock_base));
                        recorded[n].start *= RANGE_MULTIPLE;
                        recorded[n].len *= RANGE_MULTIPLE;
+                       recorded[n].pid = random()%3;
+                       if (recorded[n].pid == 2) {
+                               recorded[n].pid = 0xFFFF; /* see if its magic */
+                       }
                        r1 = random() % 100;
                        r2 = random() % 100;
                        if (r1 < READ_PCT) {
@@ -341,7 +443,7 @@ static void test_locks(char *share[NSERVERS])
                        } else {
                                recorded[n].lock_op = OP_REOPEN;
                        }
-                       recorded[n].needed = True;
+                       recorded[n].needed = true;
                        if (!zero_zero && recorded[n].start==0 && recorded[n].len==0) {
                                recorded[n].len = 1;
                        }
@@ -350,11 +452,16 @@ static void test_locks(char *share[NSERVERS])
 #endif
        }
 
-       reconnect(cli, fnum, share);
+       reconnect(ev, lp_ctx, cli, fnum, share);
        open_files(cli, fnum);
        n = retest(cli, fnum, numops);
 
-       if (n == numops || !analyze) return;
+       if (n == numops || !analyze) {
+               if (n != numops) {
+                       return 1;
+               }
+               return 0;
+       }
        n++;
 
        skip = n/2;
@@ -363,14 +470,14 @@ static void test_locks(char *share[NSERVERS])
                n1 = n;
 
                close_files(cli, fnum);
-               reconnect(cli, fnum, share);
+               reconnect(ev, lp_ctx, cli, fnum, share);
                open_files(cli, fnum);
 
                for (i=0;i<n-skip;i+=skip) {
                        int m, j;
                        printf("excluding %d-%d\n", i, i+skip-1);
                        for (j=i;j<i+skip;j++) {
-                               recorded[j].needed = False;
+                               recorded[j].needed = false;
                        }
 
                        close_files(cli, fnum);
@@ -379,7 +486,7 @@ static void test_locks(char *share[NSERVERS])
                        m = retest(cli, fnum, n);
                        if (m == n) {
                                for (j=i;j<i+skip;j++) {
-                                       recorded[j].needed = True;
+                                       recorded[j].needed = true;
                                }
                        } else {
                                if (i+(skip-1) < m) {
@@ -401,9 +508,9 @@ static void test_locks(char *share[NSERVERS])
        }
 
        close_files(cli, fnum);
-       reconnect(cli, fnum, share);
+       reconnect(ev, lp_ctx, cli, fnum, share);
        open_files(cli, fnum);
-       showall = True;
+       showall = true;
        n1 = retest(cli, fnum, n);
        if (n1 != n-1) {
                printf("ERROR - inconsistent result (%u %u)\n", n1, n);
@@ -420,30 +527,16 @@ static void test_locks(char *share[NSERVERS])
                       (double)recorded[i].len,
                       recorded[i].needed);
        }       
+
+       return 1;
 }
 
 
 
-static void usage(void)
+static void usage(poptContext pc)
 {
-       printf(
-"Usage:\n\
-  locktest //server1/share1 //server2/share2 [options..]\n\
-  options:\n\
-        -U user%%pass        (may be specified twice)\n\
-        -k               use kerberos\n\
-        -s seed\n\
-        -o numops\n\
-        -u          hide unlock fails\n\
-        -a          (show all ops)\n\
-        -A          analyse for minimal ops\n\
-        -O          use oplocks\n\
-        -E          enable exact error code checking\n\
-        -Z          enable the zero/zero lock\n\
-        -R range    set lock range\n\
-        -B base     set lock base\n\
-        -M min      set min lock length\n\
-");
+       printf("Usage:\n\tlocktest //server1/share1 //server2/share2 [options..]\n");
+       poptPrintUsage(pc, stdout, 0);
 }
 
 /****************************************************************************
@@ -453,114 +546,105 @@ static void usage(void)
 {
        char *share[NSERVERS];
        int opt;
-       char *p;
        int seed, server;
+       int username_count=0;
+       struct event_context *ev;
+       struct loadparm_context *lp_ctx;
+       poptContext pc;
+       int argc_new, i;
+       char **argv_new;
+       enum {OPT_UNCLIST=1000};
+       struct poptOption long_options[] = {
+               POPT_AUTOHELP
+               {"seed",          0, POPT_ARG_INT,  &seed,      0,      "Seed to use for randomizer",   NULL},
+               {"num-ops",       0, POPT_ARG_INT,  &numops,    0,      "num ops",      NULL},
+               {"lockrange",     0, POPT_ARG_INT,  &lock_range,0,      "locking range", NULL},
+               {"lockbase",      0, POPT_ARG_INT,  &lock_base, 0,      "locking base", NULL},
+               {"minlength",     0, POPT_ARG_INT,  &min_length,0,      "min lock length", NULL},
+               {"hidefails",     0, POPT_ARG_NONE, &hide_unlock_fails,0,"hide unlock fails", NULL},
+               {"oplocks",       0, POPT_ARG_NONE, &use_oplocks,0,      "use oplocks", NULL},
+               {"showall",       0, POPT_ARG_NONE, &showall,    0,      "display all operations", NULL},
+               {"analyse",       0, POPT_ARG_NONE, &analyze,    0,      "do backtrack analysis", NULL},
+               {"zerozero",      0, POPT_ARG_NONE, &zero_zero,    0,      "do zero/zero lock", NULL},
+               {"exacterrors",   0, POPT_ARG_NONE, &exact_error_codes,0,"use exact error codes", NULL},
+               {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
+               { "user", 'U',       POPT_ARG_STRING, NULL, 'U', "Set the network username", "[DOMAIN/]USERNAME[%PASSWORD]" },
+               POPT_COMMON_SAMBA
+               POPT_COMMON_CONNECTION
+               POPT_COMMON_CREDENTIALS
+               POPT_COMMON_VERSION
+               { NULL }
+       };
 
        setlinebuf(stdout);
+       seed = time(NULL);
 
-       setup_logging("locktest", DEBUG_STDOUT);
-
-       if (argc < 3 || argv[1][0] == '-') {
-               usage();
-               exit(1);
-       }
-
-       setup_logging(argv[0], DEBUG_STDOUT);
-
-       for (server=0;server<NSERVERS;server++) {
-               share[server] = argv[1+server];
-               all_string_sub(share[server],"/","\\",0);
-       }
-
-       argc -= NSERVERS;
-       argv += NSERVERS;
+       pc = poptGetContext("locktest", argc, (const char **) argv, long_options, 
+                           POPT_CONTEXT_KEEP_FIRST);
 
-       lp_load(dyn_CONFIGFILE,True,False,False);
-       load_interfaces();
+       poptSetOtherOptionHelp(pc, "<unc1> <unc2>");
 
-       if (getenv("USER")) {
-               fstrcpy(username[0],getenv("USER"));
-               fstrcpy(username[1],getenv("USER"));
-       }
-
-       seed = time(NULL);
+       lp_ctx = cmdline_lp_ctx;
+       servers[0] = cli_credentials_init(talloc_autofree_context());
+       servers[1] = cli_credentials_init(talloc_autofree_context());
+       cli_credentials_guess(servers[0], lp_ctx);
+       cli_credentials_guess(servers[1], lp_ctx);
 
-       while ((opt = getopt(argc, argv, "U:s:ho:aAW:OkR:B:M:EZ")) != EOF) {
+       while((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
-               case 'k':
-#ifdef HAVE_KRB5
-                       use_kerberos = True;
-#else
-                       d_printf("No kerberos support compiled in\n");
-                       exit(1);
-#endif
+               case OPT_UNCLIST:
+                       lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
                        break;
                case 'U':
-                       got_user = 1;
-                       if (got_pass == 2) {
-                               d_printf("Max of 2 usernames\n");
+                       if (username_count == 2) {
+                               usage(pc);
                                exit(1);
                        }
-                       fstrcpy(username[got_pass],optarg);
-                       p = strchr_m(username[got_pass],'%');
-                       if (p) {
-                               *p = 0;
-                               fstrcpy(password[got_pass], p+1);
-                               got_pass++;
-                       }
-                       break;
-               case 'R':
-                       lock_range = strtol(optarg, NULL, 0);
-                       break;
-               case 'B':
-                       lock_base = strtol(optarg, NULL, 0);
+                       cli_credentials_parse_string(servers[username_count], poptGetOptArg(pc), CRED_SPECIFIED);
+                       username_count++;
                        break;
-               case 'M':
-                       min_length = strtol(optarg, NULL, 0);
-                       break;
-               case 's':
-                       seed = atoi(optarg);
-                       break;
-               case 'u':
-                       hide_unlock_fails = True;
-                       break;
-               case 'o':
-                       numops = atoi(optarg);
-                       break;
-               case 'O':
-                       use_oplocks = True;
-                       break;
-               case 'a':
-                       showall = True;
-                       break;
-               case 'A':
-                       analyze = True;
-                       break;
-               case 'Z':
-                       zero_zero = True;
-                       break;
-               case 'E':
-                       exact_error_codes = True;
+               }
+       }
+
+       argv_new = discard_const_p(char *, poptGetArgs(pc));
+       argc_new = argc;
+       for (i=0; i<argc; i++) {
+               if (argv_new[i] == NULL) {
+                       argc_new = i;
                        break;
-               case 'h':
-                       usage();
-                       exit(1);
-               default:
-                       printf("Unknown option %c (%d)\n", (char)opt, opt);
-                       exit(1);
                }
        }
 
-       if(use_kerberos && !got_user) got_pass = True;
+       if (!(argc_new >= 3)) {
+               usage(pc);
+               exit(1);
+       }
 
-       argc -= optind;
-       argv += optind;
+       setup_logging("locktest", DEBUG_STDOUT);
+
+       for (server=0;server<NSERVERS;server++) {
+               share[server] = argv_new[1+server];
+               all_string_sub(share[server],"/","\\",0);
+       }
+
+       lp_ctx = cmdline_lp_ctx;
+
+       if (username_count == 0) {
+               usage(pc);
+               return -1;
+       }
+       if (username_count == 1) {
+               servers[1] = servers[0];
+       }
+
+       ev = event_context_init(talloc_autofree_context());
+
+       gensec_init(lp_ctx);
 
        DEBUG(0,("seed=%u base=%d range=%d min_length=%d\n", 
                 seed, lock_base, lock_range, min_length));
        srandom(seed);
 
-       test_locks(share);
-
-       return(0);
+       return test_locks(ev, lp_ctx, share);
 }
+