added some QPATHINFO and QFILEINFO tests into smbtorture.
[nivanova/samba-autobuild/.git] / source3 / utils / torture.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB torture tester
5    Copyright (C) Andrew Tridgell 1997
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifdef SYSLOG
23 #undef SYSLOG
24 #endif
25
26 #include "includes.h"
27
28 static fstring host, workgroup, share, password, username, myname;
29 static int max_protocol = PROTOCOL_NT1;
30 static char *sockops="";
31
32
33 static struct timeval tp1,tp2;
34
35 static void start_timer()
36 {
37         gettimeofday(&tp1,NULL);
38 }
39
40 static double end_timer()
41 {
42         gettimeofday(&tp2,NULL);
43         return((tp2.tv_sec - tp1.tv_sec) + 
44                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
45 }
46
47
48 static BOOL open_connection(struct cli_state *c)
49 {
50         if (!cli_initialise(c) || !cli_connect(c, host, NULL)) {
51                 printf("Failed to connect with %s\n", host);
52                 return False;
53         }
54
55         if (!cli_session_request(c, host, 0x20, myname)) {
56                 printf("%s rejected the session\n",host);
57                 cli_shutdown(c);
58                 return False;
59         }
60
61         c->protocol = max_protocol;
62
63         if (!cli_negprot(c)) {
64                 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
65                 cli_shutdown(c);
66                 return False;
67         }
68
69         if (!cli_session_setup(c, username, password, strlen(password),
70                                "", 0, workgroup)) {
71                 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
72                 cli_shutdown(c);
73                 return False;
74         }
75
76         if (!cli_send_tconX(c, share, "A:", password, strlen(password)+1)) {
77                 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
78                 cli_shutdown(c);
79                 return False;
80         }
81
82         return True;
83 }
84
85
86
87 static void close_connection(struct cli_state *c)
88 {
89         if (!cli_tdis(c)) {
90                 printf("tdis failed (%s)\n", cli_errstr(c));
91         }
92
93         cli_shutdown(c);
94 }
95
96
97 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
98 {
99         while (!cli_lock(c, fnum, offset, len, -1)) {
100                 int eclass, num;
101                 cli_error(c, &eclass, &num);
102                 if (eclass != ERRDOS || num != ERRlock) {
103                         printf("lock failed (%s)\n", 
104                                cli_errstr(c));
105                         return False;
106                 }
107         }
108         return True;
109 }
110
111
112 static BOOL rw_torture(struct cli_state *c, int numops)
113 {
114         char *lockfname = "\\torture.lck";
115         fstring fname;
116         int fnum;
117         int fnum2;
118         int pid2, pid = getpid();
119         int i;
120
121         fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
122                          DENY_NONE);
123         if (fnum2 == -1)
124                 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
125         if (fnum2 == -1) {
126                 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
127                 return False;
128         }
129
130
131         for (i=0;i<numops;i++) {
132                 unsigned n = (unsigned)random()%10;
133                 if (i % 10 == 0) {
134                         printf("%d\r", i); fflush(stdout);
135                 }
136                 sprintf(fname,"\\torture.%u", n);
137
138                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
139                         return False;
140                 }
141
142                 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
143                 if (fnum == -1) {
144                         printf("open failed (%s)\n", cli_errstr(c));
145                         break;
146                 }
147
148                 if (cli_write(c, fnum, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
149                         printf("write failed (%s)\n", cli_errstr(c));
150                 }
151
152                 pid2 = 0;
153
154                 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
155                         printf("read failed (%s)\n", cli_errstr(c));
156                 }
157
158                 if (pid2 != pid) {
159                         printf("data corruption!\n");
160                 }
161
162                 if (!cli_close(c, fnum)) {
163                         printf("close failed (%s)\n", cli_errstr(c));
164                 }
165
166                 if (!cli_unlink(c, fname)) {
167                         printf("unlink failed (%s)\n", cli_errstr(c));
168                 }
169
170                 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int), -1)) {
171                         printf("unlock failed (%s)\n", cli_errstr(c));
172                 }
173         }
174
175         printf("%d\n", i);
176
177         return True;
178 }
179
180 static void usage(void)
181 {
182         printf("Usage: smbtorture \\\\server\\share <options>\n");
183
184         printf("\t-U user%%pass\n");
185         printf("\t-N numprocs\n");
186         printf("\t-n my_netbios_name\n");
187         printf("\t-W workgroup\n");
188         printf("\t-o num_operations\n");
189         printf("\t-O socket_options\n");
190         printf("\t-m maximum protocol\n");
191         printf("\n");
192
193         exit(1);
194 }
195
196
197
198 static void run_torture(int numops)
199 {
200         static struct cli_state cli;
201
202         if (open_connection(&cli)) {
203                 cli_sockopt(&cli, sockops);
204
205                 printf("pid %d OK\n", getpid());
206
207                 rw_torture(&cli, numops);
208
209                 close_connection(&cli);
210         }
211 }
212
213 /*
214   This test checks for two things:
215
216   1) correct support for retaining locks over a close (ie. the server
217      must not use posix semantics)
218   2) support for lock timeouts
219  */
220 static void run_locktest1(void)
221 {
222         static struct cli_state cli1, cli2;
223         char *fname = "\\locktest.lck";
224         int fnum1, fnum2, fnum3;
225         time_t t1, t2;
226
227         if (!open_connection(&cli1) || !open_connection(&cli2)) {
228                 return;
229         }
230         cli_sockopt(&cli1, sockops);
231         cli_sockopt(&cli2, sockops);
232
233         printf("starting locktest1\n");
234
235         cli_unlink(&cli1, fname);
236
237         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
238         if (fnum1 == -1) {
239                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
240                 return;
241         }
242         fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
243         if (fnum2 == -1) {
244                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
245                 return;
246         }
247         fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
248         if (fnum3 == -1) {
249                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
250                 return;
251         }
252
253         if (!cli_lock(&cli1, fnum1, 0, 4, 0)) {
254                 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
255                 return;
256         }
257
258
259         if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
260                 printf("lock2 succeeded! This is a locking bug\n");
261                 return;
262         } else {
263                 int eclass, num;
264                 cli_error(&cli2, &eclass, &num);
265                 if (eclass != ERRDOS || num != ERRlock) {
266                         printf("error should have been ERRDOS/ERRlock (%s)\n", 
267                                cli_errstr(&cli2));
268                         return;
269                 }
270         }
271
272
273         printf("Testing lock timeouts\n");
274         t1 = time(NULL);
275         if (cli_lock(&cli2, fnum3, 0, 4, 10*1000)) {
276                 printf("lock3 succeeded! This is a locking bug\n");
277                 return;
278         } else {
279                 int eclass, num;
280                 cli_error(&cli2, &eclass, &num);
281                 if (eclass != ERRDOS || num != ERRlock) {
282                         printf("error should have been ERRDOS/ERRlock (%s)\n", 
283                                cli_errstr(&cli2));
284                         return;
285                 }
286         }
287         t2 = time(NULL);
288
289         if (t2 - t1 < 5) {
290                 printf("error: This server appears not to support timed lock requests\n");
291         }
292
293         if (!cli_close(&cli1, fnum2)) {
294                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
295                 return;
296         }
297
298         if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
299                 printf("lock4 succeeded! This is a locking bug\n");
300                 return;
301         } else {
302                 int eclass, num;
303                 cli_error(&cli2, &eclass, &num);
304                 if (eclass != ERRDOS || num != ERRlock) {
305                         printf("error should have been ERRDOS/ERRlock (%s)\n", 
306                                cli_errstr(&cli2));
307                         return;
308                 }
309         }
310
311         if (!cli_close(&cli1, fnum1)) {
312                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
313                 return;
314         }
315
316         if (!cli_close(&cli2, fnum3)) {
317                 printf("close3 failed (%s)\n", cli_errstr(&cli2));
318                 return;
319         }
320
321         if (!cli_unlink(&cli1, fname)) {
322                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
323                 return;
324         }
325
326
327         close_connection(&cli1);
328         close_connection(&cli2);
329
330         printf("Passed locktest1\n");
331 }
332
333
334 /*
335   This test checks that 
336
337   1) the server supports multiple locking contexts on the one SMB
338   connection, distinguished by PID.  
339
340   2) the server correctly fails overlapping locks made by the same PID (this
341      goes against POSIX behaviour, which is why it is tricky to implement)
342
343   3) the server denies unlock requests by an incorrect client PID
344 */
345 static void run_locktest2(void)
346 {
347         static struct cli_state cli;
348         char *fname = "\\locktest.lck";
349         int fnum1, fnum2, fnum3;
350
351         if (!open_connection(&cli)) {
352                 return;
353         }
354
355         cli_sockopt(&cli, sockops);
356
357         printf("starting locktest2\n");
358
359         cli_unlink(&cli, fname);
360
361         cli_setpid(&cli, 1);
362
363         fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
364         if (fnum1 == -1) {
365                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
366                 return;
367         }
368
369         fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
370         if (fnum2 == -1) {
371                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
372                 return;
373         }
374
375         cli_setpid(&cli, 2);
376
377         fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
378         if (fnum3 == -1) {
379                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
380                 return;
381         }
382
383         cli_setpid(&cli, 1);
384
385         if (!cli_lock(&cli, fnum1, 0, 4, 0)) {
386                 printf("lock1 failed (%s)\n", cli_errstr(&cli));
387                 return;
388         }
389
390         if (cli_lock(&cli, fnum2, 0, 4, 0)) {
391                 printf("lock2 succeeded! This is a locking bug\n");
392         } else {
393                 int eclass, num;
394                 cli_error(&cli, &eclass, &num);
395                 if (eclass != ERRDOS || num != ERRlock) {
396                         printf("error should have been ERRDOS/ERRlock (%s)\n", 
397                                cli_errstr(&cli));
398                         return;
399                 }
400         }
401
402         cli_setpid(&cli, 2);
403
404         if (cli_unlock(&cli, fnum1, 0, 4, 0)) {
405                 printf("unlock1 succeeded! This is a locking bug\n");
406         }
407
408         if (cli_lock(&cli, fnum3, 0, 4, 0)) {
409                 printf("lock3 succeeded! This is a locking bug\n");
410         } else {
411                 int eclass, num;
412                 cli_error(&cli, &eclass, &num);
413                 if (eclass != ERRDOS || num != ERRlock) {
414                         printf("error should have been ERRDOS/ERRlock (%s)\n", 
415                                cli_errstr(&cli));
416                         return;
417                 }
418         }
419
420         cli_setpid(&cli, 1);
421
422         if (!cli_close(&cli, fnum1)) {
423                 printf("close1 failed (%s)\n", cli_errstr(&cli));
424                 return;
425         }
426
427         if (!cli_close(&cli, fnum2)) {
428                 printf("close2 failed (%s)\n", cli_errstr(&cli));
429                 return;
430         }
431
432         if (!cli_close(&cli, fnum3)) {
433                 printf("close3 failed (%s)\n", cli_errstr(&cli));
434                 return;
435         }
436
437         close_connection(&cli);
438
439         printf("locktest2 finished\n");
440 }
441
442
443 /*
444   This test checks that 
445
446   1) the server supports the full offset range in lock requests
447 */
448 static void run_locktest3(int numops)
449 {
450         static struct cli_state cli1, cli2;
451         char *fname = "\\locktest.lck";
452         int fnum1, fnum2, i;
453         uint32 offset;
454
455 #define NEXT_OFFSET offset += (~(uint32)0) / numops
456
457         if (!open_connection(&cli1) || !open_connection(&cli2)) {
458                 return;
459         }
460         cli_sockopt(&cli1, sockops);
461         cli_sockopt(&cli2, sockops);
462
463         printf("starting locktest3\n");
464
465         cli_unlink(&cli1, fname);
466
467         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
468         if (fnum1 == -1) {
469                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
470                 return;
471         }
472         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
473         if (fnum2 == -1) {
474                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
475                 return;
476         }
477
478         for (offset=i=0;i<numops;i++) {
479                 NEXT_OFFSET;
480                 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
481                         printf("lock1 %d failed (%s)\n", 
482                                i,
483                                cli_errstr(&cli1));
484                         return;
485                 }
486
487                 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
488                         printf("lock2 %d failed (%s)\n", 
489                                i,
490                                cli_errstr(&cli1));
491                         return;
492                 }
493         }
494
495         for (offset=i=0;i<numops;i++) {
496                 NEXT_OFFSET;
497
498                 if (cli_lock(&cli1, fnum1, offset-2, 1, 0)) {
499                         printf("error: lock1 %d succeeded!\n", i);
500                         return;
501                 }
502
503                 if (cli_lock(&cli2, fnum2, offset-1, 1, 0)) {
504                         printf("error: lock2 %d succeeded!\n", i);
505                         return;
506                 }
507
508                 if (cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
509                         printf("error: lock3 %d succeeded!\n", i);
510                         return;
511                 }
512
513                 if (cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
514                         printf("error: lock4 %d succeeded!\n", i);
515                         return;
516                 }
517         }
518
519         for (offset=i=0;i<numops;i++) {
520                 NEXT_OFFSET;
521
522                 if (!cli_unlock(&cli1, fnum1, offset-1, 1, 0)) {
523                         printf("unlock1 %d failed (%s)\n", 
524                                i,
525                                cli_errstr(&cli1));
526                         return;
527                 }
528
529                 if (!cli_unlock(&cli2, fnum2, offset-2, 1, 0)) {
530                         printf("unlock2 %d failed (%s)\n", 
531                                i,
532                                cli_errstr(&cli1));
533                         return;
534                 }
535         }
536
537         if (!cli_close(&cli1, fnum1)) {
538                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
539         }
540
541         if (!cli_close(&cli2, fnum2)) {
542                 printf("close2 failed (%s)\n", cli_errstr(&cli2));
543         }
544
545         if (!cli_unlink(&cli1, fname)) {
546                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
547                 return;
548         }
549
550         close_connection(&cli1);
551         close_connection(&cli2);
552
553         printf("finished locktest3\n");
554 }
555
556
557 /*
558   This test checks that 
559
560   1) the server does not allow an unlink on a file that is open
561 */
562 static void run_unlinktest(void)
563 {
564         static struct cli_state cli;
565         char *fname = "\\unlink.tst";
566         int fnum;
567
568         if (!open_connection(&cli)) {
569                 return;
570         }
571
572         cli_sockopt(&cli, sockops);
573
574         printf("starting unlink test\n");
575
576         cli_unlink(&cli, fname);
577
578         cli_setpid(&cli, 1);
579
580         fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
581         if (fnum == -1) {
582                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
583                 return;
584         }
585
586         if (cli_unlink(&cli, fname)) {
587                 printf("error: server allowed unlink on an open file\n");
588         }
589
590         close_connection(&cli);
591
592         printf("unlink test finished\n");
593 }
594
595
596
597 static void browse_callback(char *sname, uint32 stype, char *comment)
598 {
599         printf("\t%20.20s %08x %s\n", sname, stype, comment);
600 }
601
602
603 /*
604   This test checks the browse list code
605
606 */
607 static void run_browsetest(void)
608 {
609         static struct cli_state cli;
610
611         printf("staring browse test\n");
612
613         if (!open_connection(&cli)) {
614                 return;
615         }
616
617         printf("domain list:\n");
618         cli_NetServerEnum(&cli, workgroup, 
619                           SV_TYPE_DOMAIN_ENUM,
620                           browse_callback);
621
622         printf("machine list:\n");
623         cli_NetServerEnum(&cli, workgroup, 
624                           SV_TYPE_ALL,
625                           browse_callback);
626
627         close_connection(&cli);
628
629         printf("browse test finished\n");
630 }
631
632
633 /*
634   This checks how the getatr calls works
635 */
636 static void run_attrtest(void)
637 {
638         static struct cli_state cli;
639         int fnum;
640         time_t t, t2;
641         char *fname = "\\attrib.tst";
642
643         printf("staring attrib test\n");
644
645         if (!open_connection(&cli)) {
646                 return;
647         }
648
649         cli_unlink(&cli, fname);
650         fnum = cli_open(&cli, fname, 
651                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
652         cli_close(&cli, fnum);
653         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
654                 printf("getatr failed (%s)\n", cli_errstr(&cli));
655         }
656
657         if (abs(t - time(NULL)) > 2) {
658                 printf("ERROR: SMBgetatr bug. time is %s",
659                        ctime(&t));
660                 t = time(NULL);
661         }
662
663         t2 = t-60*60*24; /* 1 day ago */
664
665         if (!cli_setatr(&cli, fname, 0, t2)) {
666                 printf("setatr failed (%s)\n", cli_errstr(&cli));
667         }
668
669         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
670                 printf("getatr failed (%s)\n", cli_errstr(&cli));
671         }
672
673         if (t != t2) {
674                 printf("ERROR: getatr/setatr bug. times are\n%s",
675                        ctime(&t));
676                 printf("%s", ctime(&t2));
677         }
678
679         close_connection(&cli);
680
681         printf("attrib test finished\n");
682 }
683
684
685 /*
686   This checks a couple of trans2 calls
687 */
688 static void run_trans2test(void)
689 {
690         static struct cli_state cli;
691         int fnum;
692         uint32 size;
693         time_t c_time, a_time, m_time;
694         char *fname = "\\trans2.tst";
695
696         printf("staring trans2 test\n");
697
698         if (!open_connection(&cli)) {
699                 return;
700         }
701
702         cli_unlink(&cli, fname);
703         fnum = cli_open(&cli, fname, 
704                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
705         if (!cli_qfileinfo(&cli, fnum, &c_time, &a_time, &m_time, &size)) {
706                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
707         }
708         cli_close(&cli, fnum);
709
710         sleep(2);
711
712         cli_unlink(&cli, fname);
713         fnum = cli_open(&cli, fname, 
714                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
715         cli_close(&cli, fnum);
716
717         if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size)) {
718                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
719         } else {
720                 if (c_time != m_time) {
721                         printf("create time=%s", ctime(&c_time));
722                         printf("modify time=%s", ctime(&m_time));
723                         printf("This system appears to have sticky create times\n");
724                 }
725                 if (a_time % (60*60) == 0) {
726                         printf("access time=%s", ctime(&a_time));
727                         printf("This system appears to set a midnight access time\n");
728                 }
729
730                 if (abs(m_time - time(NULL)) > 60) {
731                         printf("ERROR: totally incorrect times - maybe word reversed?\n");
732                 }
733         }
734
735         cli_unlink(&cli, fname);
736
737         close_connection(&cli);
738
739         printf("trans2 test finished\n");
740 }
741
742
743 static void create_procs(int nprocs, int numops)
744 {
745         int i, status;
746
747         for (i=0;i<nprocs;i++) {
748                 if (fork() == 0) {
749                         int mypid = getpid();
750                         srandom(mypid ^ time(NULL));
751                         run_torture(numops);
752                         _exit(0);
753                 }
754         }
755
756         for (i=0;i<nprocs;i++)
757                 waitpid(0, &status, 0);
758 }
759
760
761
762 /****************************************************************************
763   main program
764 ****************************************************************************/
765  int main(int argc,char *argv[])
766 {
767         int nprocs=1, numops=100;
768         int opt;
769         char *p;
770         int gotpass = 0;
771         extern char *optarg;
772         extern int optind;
773         extern FILE *dbf;
774
775         dbf = stdout;
776
777         charset_initialise();
778
779         if (argc < 2) {
780                 usage();
781         }
782
783         if (strncmp(argv[1], "\\\\", 2)) {
784                 usage();
785         }
786
787         fstrcpy(host, &argv[1][2]);
788         p = strchr(&host[2],'\\');
789         if (!p) {
790                 usage();
791         }
792         *p = 0;
793         fstrcpy(share, p+1);
794
795         get_myname(myname,NULL);
796
797         if (*username == 0 && getenv("LOGNAME")) {
798           strcpy(username,getenv("LOGNAME"));
799         }
800
801         argc--;
802         argv++;
803
804
805         while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
806                 switch (opt) {
807                 case 'W':
808                         fstrcpy(workgroup,optarg);
809                         break;
810                 case 'm':
811                         max_protocol = interpret_protocol(optarg, max_protocol);
812                         break;
813                 case 'N':
814                         nprocs = atoi(optarg);
815                         break;
816                 case 'o':
817                         numops = atoi(optarg);
818                         break;
819                 case 'O':
820                         sockops = optarg;
821                         break;
822                 case 'n':
823                         fstrcpy(myname, optarg);
824                         break;
825                 case 'U':
826                         strcpy(username,optarg);
827                         p = strchr(username,'%');
828                         if (p) {
829                                 *p = 0;
830                                 strcpy(password, p+1);
831                                 gotpass = 1;
832                         }
833                         break;
834                 default:
835                         printf("Unknown option %c (%d)\n", (char)opt, opt);
836                         usage();
837                 }
838         }
839
840
841         while (!gotpass) {
842                 p = getpass("Password:");
843                 if (p) {
844                         strcpy(password, p);
845                         gotpass = 1;
846                 }
847         }
848
849         printf("host=%s share=%s user=%s myname=%s\n", 
850                host, share, username, myname);
851
852         start_timer();
853         create_procs(nprocs, numops);
854         printf("rw_torture: %g secs\n", end_timer());
855
856         run_locktest1();
857         run_locktest2();
858         run_locktest3(numops);
859         run_unlinktest();
860         run_browsetest();
861         run_attrtest();
862         run_trans2test();
863
864         return(0);
865 }
866
867