added a DENY test that tests deny mode handling. It produces a matrix
[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-1998
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 #define NO_SYSLOG
23
24 #include "includes.h"
25
26 static fstring host, workgroup, share, password, username, myname;
27 static int max_protocol = PROTOCOL_NT1;
28 static char *sockops="TCP_NODELAY";
29 static int nprocs=1, numops=100;
30 static struct cli_state current_cli;
31
32 static double create_procs(void (*fn)(int));
33
34
35 static struct timeval tp1,tp2;
36
37 static void start_timer(void)
38 {
39         gettimeofday(&tp1,NULL);
40 }
41
42 static double end_timer(void)
43 {
44         gettimeofday(&tp2,NULL);
45         return((tp2.tv_sec - tp1.tv_sec) + 
46                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
47 }
48
49
50 /* return a pointer to a anonymous shared memory segment of size "size"
51    which will persist across fork() but will disappear when all processes
52    exit 
53
54    The memory is not zeroed 
55
56    This function uses system5 shared memory. It takes advantage of a property
57    that the memory is not destroyed if it is attached when the id is removed
58    */
59 static void *shm_setup(int size)
60 {
61         int shmid;
62         void *ret;
63
64         shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
65         if (shmid == -1) {
66                 printf("can't get shared memory\n");
67                 exit(1);
68         }
69         ret = (void *)shmat(shmid, 0, 0);
70         if (!ret || ret == (void *)-1) {
71                 printf("can't attach to shared memory\n");
72                 return NULL;
73         }
74         /* the following releases the ipc, but note that this process
75            and all its children will still have access to the memory, its
76            just that the shmid is no longer valid for other shm calls. This
77            means we don't leave behind lots of shm segments after we exit 
78
79            See Stevens "advanced programming in unix env" for details
80            */
81         shmctl(shmid, IPC_RMID, 0);
82         
83         return ret;
84 }
85
86
87 static BOOL open_connection(struct cli_state *c)
88 {
89         struct nmb_name called, calling;
90         struct in_addr ip;
91         extern struct in_addr ipzero;
92
93         ZERO_STRUCTP(c);
94
95         make_nmb_name(&calling, myname, 0x0);
96         make_nmb_name(&called , host, 0x20);
97
98         ip = ipzero;
99
100         if (!cli_initialise(c) || !cli_connect(c, host, &ip)) {
101                 printf("Failed to connect with %s\n", host);
102                 return False;
103         }
104
105         c->timeout = 120000; /* set a really long timeout (2 minutes) */
106
107         if (!cli_session_request(c, &calling, &called)) {
108                 printf("%s rejected the session\n",host);
109                 cli_shutdown(c);
110                 return False;
111         }
112
113         if (!cli_negprot(c)) {
114                 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
115                 cli_shutdown(c);
116                 return False;
117         }
118
119         if (!cli_session_setup(c, username, 
120                                password, strlen(password),
121                                password, strlen(password),
122                                workgroup)) {
123                 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
124                 cli_shutdown(c);
125                 return False;
126         }
127
128         if (!cli_send_tconX(c, share, "?????",
129                             password, strlen(password)+1)) {
130                 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
131                 cli_shutdown(c);
132                 return False;
133         }
134
135         return True;
136 }
137
138
139
140 static void close_connection(struct cli_state *c)
141 {
142         if (!cli_tdis(c)) {
143                 printf("tdis failed (%s)\n", cli_errstr(c));
144         }
145
146         cli_shutdown(c);
147 }
148
149
150 /* check if the server produced the expected error code */
151 static BOOL check_error(struct cli_state *c, 
152                         uint8 eclass, uint32 ecode, uint32 nterr)
153 {
154         uint8 class;
155         uint32 num;
156         (void)cli_error(c, &class, &num, NULL);
157         if ((eclass != class || ecode != num) &&
158             num != (nterr&0xFFFFFF)) {
159                 printf("unexpected error code class=%d code=%d\n", 
160                          (int)class, (int)num);
161                 printf(" expected %d/%d %d\n", 
162                        (int)eclass, (int)ecode, (int)nterr);
163                 return False;
164         }
165         return True;
166 }
167
168
169 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
170 {
171         while (!cli_lock(c, fnum, offset, len, -1)) {
172                 if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
173         }
174         return True;
175 }
176
177
178 static BOOL rw_torture(struct cli_state *c)
179 {
180         char *lockfname = "\\torture.lck";
181         fstring fname;
182         int fnum;
183         int fnum2;
184         pid_t pid2, pid = getpid();
185         int i, j;
186         char buf[1024];
187
188         fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
189                          DENY_NONE);
190         if (fnum2 == -1)
191                 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
192         if (fnum2 == -1) {
193                 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
194                 return False;
195         }
196
197
198         for (i=0;i<numops;i++) {
199                 unsigned n = (unsigned)sys_random()%10;
200                 if (i % 10 == 0) {
201                         printf("%d\r", i); fflush(stdout);
202                 }
203                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
204
205                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
206                         return False;
207                 }
208
209                 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
210                 if (fnum == -1) {
211                         printf("open failed (%s)\n", cli_errstr(c));
212                         break;
213                 }
214
215                 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
216                         printf("write failed (%s)\n", cli_errstr(c));
217                 }
218
219                 for (j=0;j<50;j++) {
220                         if (cli_write(c, fnum, 0, (char *)buf, 
221                                       sizeof(pid)+(j*sizeof(buf)), 
222                                       sizeof(buf)) != sizeof(buf)) {
223                                 printf("write failed (%s)\n", cli_errstr(c));
224                         }
225                 }
226
227                 pid2 = 0;
228
229                 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
230                         printf("read failed (%s)\n", cli_errstr(c));
231                 }
232
233                 if (pid2 != pid) {
234                         printf("data corruption!\n");
235                 }
236
237                 if (!cli_close(c, fnum)) {
238                         printf("close failed (%s)\n", cli_errstr(c));
239                 }
240
241                 if (!cli_unlink(c, fname)) {
242                         printf("unlink failed (%s)\n", cli_errstr(c));
243                 }
244
245                 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int), -1)) {
246                         printf("unlock failed (%s)\n", cli_errstr(c));
247                 }
248         }
249
250         cli_close(c, fnum2);
251         cli_unlink(c, lockfname);
252
253         printf("%d\n", i);
254
255         return True;
256 }
257
258 static void run_torture(int dummy)
259 {
260         struct cli_state cli;
261
262         cli = current_cli;
263
264         cli_sockopt(&cli, sockops);
265
266         rw_torture(&cli);
267         
268         close_connection(&cli);
269 }
270
271 int line_count = 0;
272
273 /* run a test that simulates an approximate netbench client load */
274 static void run_netbench(int client)
275 {
276         struct cli_state cli;
277         int i;
278         fstring fname;
279         pstring line;
280         char cname[20];
281         FILE *f;
282         char *params[20];
283
284         cli = current_cli;
285
286         cli_sockopt(&cli, sockops);
287
288         nb_setup(&cli);
289
290         slprintf(cname,sizeof(fname), "CLIENT%d", client);
291
292         f = fopen("client.txt", "r");
293
294         if (!f) {
295                 perror("client.txt");
296                 return;
297         }
298
299         while (fgets(line, sizeof(line)-1, f)) {
300                 line_count++;
301
302                 line[strlen(line)-1] = 0;
303
304                 /* printf("[%d] %s\n", line_count, line); */
305
306                 all_string_sub(line,"CLIENT1", cname, sizeof(line));
307                 
308                 for (i=0;i<20;i++) params[i] = "";
309
310                 /* parse the command parameters */
311                 params[0] = strtok(line," ");
312                 i = 0;
313                 while (params[i]) params[++i] = strtok(NULL," ");
314
315                 params[i] = "";
316
317                 if (i < 2) continue;
318
319                 if (strcmp(params[1],"REQUEST") == 0) {
320                         if (!strcmp(params[0],"SMBopenX")) {
321                                 fstrcpy(fname, params[5]);
322                         } else if (!strcmp(params[0],"SMBclose")) {
323                                 nb_close(atoi(params[3]));
324                         } else if (!strcmp(params[0],"SMBmkdir")) {
325                                 nb_mkdir(params[3]);
326                         } else if (!strcmp(params[0],"CREATE")) {
327                                 nb_create(params[3], atoi(params[5]));
328                         } else if (!strcmp(params[0],"SMBrmdir")) {
329                                 nb_rmdir(params[3]);
330                         } else if (!strcmp(params[0],"SMBunlink")) {
331                                 fstrcpy(fname, params[3]);
332                         } else if (!strcmp(params[0],"SMBmv")) {
333                                 nb_rename(params[3], params[5]);
334                         } else if (!strcmp(params[0],"SMBgetatr")) {
335                                 fstrcpy(fname, params[3]);
336                         } else if (!strcmp(params[0],"SMBwrite")) {
337                                 nb_write(atoi(params[3]), 
338                                          atoi(params[5]), atoi(params[7]));
339                         } else if (!strcmp(params[0],"SMBwritebraw")) {
340                                 nb_write(atoi(params[3]), 
341                                          atoi(params[7]), atoi(params[5]));
342                         } else if (!strcmp(params[0],"SMBreadbraw")) {
343                                 nb_read(atoi(params[3]), 
344                                          atoi(params[7]), atoi(params[5]));
345                         } else if (!strcmp(params[0],"SMBread")) {
346                                 nb_read(atoi(params[3]), 
347                                          atoi(params[5]), atoi(params[7]));
348                         }
349                 } else {
350                         if (!strcmp(params[0],"SMBopenX")) {
351                                 if (!strncmp(params[2], "ERR", 3)) continue;
352                                 nb_open(fname, atoi(params[3]), atoi(params[5]));
353                         } else if (!strcmp(params[0],"SMBgetatr")) {
354                                 if (!strncmp(params[2], "ERR", 3)) continue;
355                                 nb_stat(fname, atoi(params[3]));
356                         } else if (!strcmp(params[0],"SMBunlink")) {
357                                 if (!strncmp(params[2], "ERR", 3)) continue;
358                                 nb_unlink(fname);
359                         }
360                 }
361         }
362         fclose(f);
363
364         slprintf(fname,sizeof(fname), "CLIENTS/CLIENT%d", client);
365         rmdir(fname);
366         rmdir("CLIENTS");
367
368         printf("+");    
369
370         close_connection(&cli);
371 }
372
373
374 /* run a test that simulates an approximate netbench w9X client load */
375 static void run_nbw95(int dummy)
376 {
377         double t;
378         t = create_procs(run_netbench);
379         /* to produce a netbench result we scale accoding to the
380            netbench measured throughput for the run that produced the
381            sniff that was used to produce client.txt. That run used 2
382            clients and ran for 660 seconds to produce a result of
383            4MBit/sec. */
384         printf("Throughput %g MB/sec (NB=%g MB/sec  %g MBit/sec)\n", 
385                132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
386 }
387
388 /* run a test that simulates an approximate netbench wNT client load */
389 static void run_nbwnt(int dummy)
390 {
391         double t;
392         t = create_procs(run_netbench);
393         printf("Throughput %g MB/sec (NB=%g MB/sec  %g MBit/sec)\n", 
394                132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
395 }
396
397
398
399 /*
400   This test checks for two things:
401
402   1) correct support for retaining locks over a close (ie. the server
403      must not use posix semantics)
404   2) support for lock timeouts
405  */
406 static void run_locktest1(int dummy)
407 {
408         static struct cli_state cli1, cli2;
409         char *fname = "\\lockt1.lck";
410         int fnum1, fnum2, fnum3;
411         time_t t1, t2;
412
413         if (!open_connection(&cli1) || !open_connection(&cli2)) {
414                 return;
415         }
416         cli_sockopt(&cli1, sockops);
417         cli_sockopt(&cli2, sockops);
418
419         printf("starting locktest1\n");
420
421         cli_unlink(&cli1, fname);
422
423         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
424         if (fnum1 == -1) {
425                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
426                 return;
427         }
428         fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
429         if (fnum2 == -1) {
430                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
431                 return;
432         }
433         fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
434         if (fnum3 == -1) {
435                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
436                 return;
437         }
438
439         if (!cli_lock(&cli1, fnum1, 0, 4, 0)) {
440                 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
441                 return;
442         }
443
444
445         if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
446                 printf("lock2 succeeded! This is a locking bug\n");
447                 return;
448         } else {
449                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
450         }
451
452
453         printf("Testing lock timeouts\n");
454         t1 = time(NULL);
455         if (cli_lock(&cli2, fnum3, 0, 4, 10*1000)) {
456                 printf("lock3 succeeded! This is a locking bug\n");
457                 return;
458         } else {
459                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
460         }
461         t2 = time(NULL);
462
463         if (t2 - t1 < 5) {
464                 printf("error: This server appears not to support timed lock requests\n");
465         }
466
467         if (!cli_close(&cli1, fnum2)) {
468                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
469                 return;
470         }
471
472         if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
473                 printf("lock4 succeeded! This is a locking bug\n");
474                 return;
475         } else {
476                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
477         }
478
479         if (!cli_close(&cli1, fnum1)) {
480                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
481                 return;
482         }
483
484         if (!cli_close(&cli2, fnum3)) {
485                 printf("close3 failed (%s)\n", cli_errstr(&cli2));
486                 return;
487         }
488
489         if (!cli_unlink(&cli1, fname)) {
490                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
491                 return;
492         }
493
494
495         close_connection(&cli1);
496         close_connection(&cli2);
497
498         printf("Passed locktest1\n");
499 }
500
501
502 /*
503   This test checks that 
504
505   1) the server supports multiple locking contexts on the one SMB
506   connection, distinguished by PID.  
507
508   2) the server correctly fails overlapping locks made by the same PID (this
509      goes against POSIX behaviour, which is why it is tricky to implement)
510
511   3) the server denies unlock requests by an incorrect client PID
512 */
513 static void run_locktest2(int dummy)
514 {
515         static struct cli_state cli;
516         char *fname = "\\lockt2.lck";
517         int fnum1, fnum2, fnum3;
518
519         if (!open_connection(&cli)) {
520                 return;
521         }
522
523         cli_sockopt(&cli, sockops);
524
525         printf("starting locktest2\n");
526
527         cli_unlink(&cli, fname);
528
529         cli_setpid(&cli, 1);
530
531         fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
532         if (fnum1 == -1) {
533                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
534                 return;
535         }
536
537         fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
538         if (fnum2 == -1) {
539                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
540                 return;
541         }
542
543         cli_setpid(&cli, 2);
544
545         fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
546         if (fnum3 == -1) {
547                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
548                 return;
549         }
550
551         cli_setpid(&cli, 1);
552
553         if (!cli_lock(&cli, fnum1, 0, 4, 0)) {
554                 printf("lock1 failed (%s)\n", cli_errstr(&cli));
555                 return;
556         }
557
558         if (cli_lock(&cli, fnum2, 0, 4, 0)) {
559                 printf("lock2 succeeded! This is a locking bug\n");
560         } else {
561                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
562         }
563
564         cli_setpid(&cli, 2);
565
566         if (cli_unlock(&cli, fnum1, 0, 4, 0)) {
567                 printf("unlock1 succeeded! This is a locking bug\n");
568         }
569
570         if (cli_lock(&cli, fnum3, 0, 4, 0)) {
571                 printf("lock3 succeeded! This is a locking bug\n");
572         } else {
573                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
574         }
575
576         cli_setpid(&cli, 1);
577
578         if (!cli_close(&cli, fnum1)) {
579                 printf("close1 failed (%s)\n", cli_errstr(&cli));
580                 return;
581         }
582
583         if (!cli_close(&cli, fnum2)) {
584                 printf("close2 failed (%s)\n", cli_errstr(&cli));
585                 return;
586         }
587
588         if (!cli_close(&cli, fnum3)) {
589                 printf("close3 failed (%s)\n", cli_errstr(&cli));
590                 return;
591         }
592
593         close_connection(&cli);
594
595         printf("locktest2 finished\n");
596 }
597
598
599 /*
600   This test checks that 
601
602   1) the server supports the full offset range in lock requests
603 */
604 static void run_locktest3(int dummy)
605 {
606         static struct cli_state cli1, cli2;
607         char *fname = "\\lockt3.lck";
608         int fnum1, fnum2, i;
609         uint32 offset;
610
611 #define NEXT_OFFSET offset += (~(uint32)0) / numops
612
613         if (!open_connection(&cli1) || !open_connection(&cli2)) {
614                 return;
615         }
616         cli_sockopt(&cli1, sockops);
617         cli_sockopt(&cli2, sockops);
618
619         printf("starting locktest3\n");
620
621         cli_unlink(&cli1, fname);
622
623         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
624         if (fnum1 == -1) {
625                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
626                 return;
627         }
628         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
629         if (fnum2 == -1) {
630                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
631                 return;
632         }
633
634         for (offset=i=0;i<numops;i++) {
635                 NEXT_OFFSET;
636                 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
637                         printf("lock1 %d failed (%s)\n", 
638                                i,
639                                cli_errstr(&cli1));
640                         return;
641                 }
642
643                 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
644                         printf("lock2 %d failed (%s)\n", 
645                                i,
646                                cli_errstr(&cli1));
647                         return;
648                 }
649         }
650
651         for (offset=i=0;i<numops;i++) {
652                 NEXT_OFFSET;
653
654                 if (cli_lock(&cli1, fnum1, offset-2, 1, 0)) {
655                         printf("error: lock1 %d succeeded!\n", i);
656                         return;
657                 }
658
659                 if (cli_lock(&cli2, fnum2, offset-1, 1, 0)) {
660                         printf("error: lock2 %d succeeded!\n", i);
661                         return;
662                 }
663
664                 if (cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
665                         printf("error: lock3 %d succeeded!\n", i);
666                         return;
667                 }
668
669                 if (cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
670                         printf("error: lock4 %d succeeded!\n", i);
671                         return;
672                 }
673         }
674
675         for (offset=i=0;i<numops;i++) {
676                 NEXT_OFFSET;
677
678                 if (!cli_unlock(&cli1, fnum1, offset-1, 1, 0)) {
679                         printf("unlock1 %d failed (%s)\n", 
680                                i,
681                                cli_errstr(&cli1));
682                         return;
683                 }
684
685                 if (!cli_unlock(&cli2, fnum2, offset-2, 1, 0)) {
686                         printf("unlock2 %d failed (%s)\n", 
687                                i,
688                                cli_errstr(&cli1));
689                         return;
690                 }
691         }
692
693         if (!cli_close(&cli1, fnum1)) {
694                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
695         }
696
697         if (!cli_close(&cli2, fnum2)) {
698                 printf("close2 failed (%s)\n", cli_errstr(&cli2));
699         }
700
701         if (!cli_unlink(&cli1, fname)) {
702                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
703                 return;
704         }
705
706         close_connection(&cli1);
707         close_connection(&cli2);
708
709         printf("finished locktest3\n");
710 }
711
712
713 /*
714   this produces a matrix of deny mode behaviour
715  */
716 static void run_denytest(int dummy)
717 {
718         static struct cli_state cli1, cli2;
719         char *fname = "\\lockt1.lck";
720         int fnum1, fnum2;
721         int d1, d2, o1, o2, x=0;
722         struct {
723                 int v;
724                 char *name; 
725         } deny_modes[] = {
726                 {DENY_DOS, "DENY_DOS"},
727                 {DENY_ALL, "DENY_ALL"},
728                 {DENY_WRITE, "DENY_WRITE"},
729                 {DENY_READ, "DENY_READ"},
730                 {DENY_NONE, "DENY_NONE"},
731                 {DENY_FCB, "DENY_FCB"},
732                 {-1, NULL}};
733         struct {
734                 int v;
735                 char *name; 
736         } open_modes[] = {
737                 {O_RDWR, "O_RDWR"},
738                 {O_RDONLY, "O_RDONLY"},
739                 {O_WRONLY, "O_WRONLY"},
740                 {-1, NULL}};
741
742         if (!open_connection(&cli1) || !open_connection(&cli2)) {
743                 return;
744         }
745         cli_sockopt(&cli1, sockops);
746         cli_sockopt(&cli2, sockops);
747
748         printf("starting denytest\n");
749
750         cli_unlink(&cli1, fname);
751
752         fnum1 = cli_open(&cli1, fname, O_WRONLY|O_CREAT, DENY_NONE);
753         cli_write(&cli1, fnum1, 0, fname, 0, strlen(fname));
754         cli_close(&cli1, fnum1);
755
756         for (d1=0;deny_modes[d1].name;d1++) for (o1=0;open_modes[o1].name;o1++) 
757         for (d2=0;deny_modes[d2].name;d2++) for (o2=0;open_modes[o2].name;o2++) {
758
759                 fnum1 = cli_open(&cli1, fname, open_modes[o1].v, deny_modes[d1].v);
760                 fnum2 = cli_open(&cli2, fname, 
761                                  open_modes[o2].v | O_CREAT, 
762                                  deny_modes[d2].v);
763
764                 printf("%8s %10s    %8s %10s     ",
765                        open_modes[o1].name,
766                        deny_modes[d1].name,
767                        open_modes[o2].name,
768                        deny_modes[d2].name);
769
770                 if (fnum1 == -1) {
771                         printf("X");
772                 } else if (fnum2 == -1) {
773                         printf("-");
774                 } else {
775                         if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
776                                 printf("R");
777                         }
778                         if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
779                                 printf("W");
780                         }
781                 }
782
783                 printf("\n");
784                 cli_close(&cli1, fnum1);
785                 cli_close(&cli2, fnum2);
786         }
787
788         cli_unlink(&cli1, fname);
789
790         close_connection(&cli1);
791         close_connection(&cli2);
792
793         printf("finshed denytest\n");
794 }
795
796 /*
797 test whether fnums and tids open on one VC are available on another (a major
798 security hole)
799 */
800 static void run_fdpasstest(int dummy)
801 {
802         static struct cli_state cli1, cli2;
803         char *fname = "\\fdpass.tst";
804         int fnum1;
805         pstring buf;
806
807         if (!open_connection(&cli1) || !open_connection(&cli2)) {
808                 return;
809         }
810         cli_sockopt(&cli1, sockops);
811         cli_sockopt(&cli2, sockops);
812
813         printf("starting fdpasstest\n");
814
815         cli_unlink(&cli1, fname);
816
817         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
818         if (fnum1 == -1) {
819                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
820                 return;
821         }
822
823         if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
824                 printf("write failed (%s)\n", cli_errstr(&cli1));
825                 return;
826         }
827
828         cli2.vuid = cli1.vuid;
829         cli2.cnum = cli1.cnum;
830         cli2.pid = cli1.pid;
831
832
833         if (cli_read(&cli2, fnum1, buf, 0, 13) == 13) {
834                 printf("read succeeded! nasty security hole [%s]\n",
835                        buf);
836                 return;
837         }
838
839         cli_close(&cli1, fnum1);
840         cli_unlink(&cli1, fname);
841
842         close_connection(&cli1);
843         close_connection(&cli2);
844
845         printf("finished fdpasstest\n");
846 }
847
848
849 /*
850   This test checks that 
851
852   1) the server does not allow an unlink on a file that is open
853 */
854 static void run_unlinktest(int dummy)
855 {
856         static struct cli_state cli;
857         char *fname = "\\unlink.tst";
858         int fnum;
859
860         if (!open_connection(&cli)) {
861                 return;
862         }
863
864         cli_sockopt(&cli, sockops);
865
866         printf("starting unlink test\n");
867
868         cli_unlink(&cli, fname);
869
870         cli_setpid(&cli, 1);
871
872         fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
873         if (fnum == -1) {
874                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
875                 return;
876         }
877
878         if (cli_unlink(&cli, fname)) {
879                 printf("error: server allowed unlink on an open file\n");
880         }
881
882         cli_close(&cli, fnum);
883         cli_unlink(&cli, fname);
884
885         close_connection(&cli);
886
887         printf("unlink test finished\n");
888 }
889
890
891 /*
892 test how many open files this server supports on the one socket
893 */
894 static void run_maxfidtest(int dummy)
895 {
896         static struct cli_state cli;
897         char *template = "\\maxfid.%d.%d";
898         fstring fname;
899         int fnum;
900         int retries=4;
901         int n = numops;
902
903         cli = current_cli;
904
905         if (retries <= 0) {
906                 printf("failed to connect\n");
907                 return;
908         }
909
910         cli_sockopt(&cli, sockops);
911
912         fnum = 0;
913         while (1) {
914                 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
915                 if (cli_open(&cli, fname, 
916                              O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
917                     -1) {
918                         printf("open of %s failed (%s)\n", 
919                                fname, cli_errstr(&cli));
920                         printf("maximum fnum is %d\n", fnum);
921                         break;
922                 }
923                 fnum++;
924         }
925
926         printf("cleaning up\n");
927         while (fnum > n) {
928                 fnum--;
929                 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
930                 if (cli_unlink(&cli, fname)) {
931                         printf("unlink of %s failed (%s)\n", 
932                                fname, cli_errstr(&cli));
933                 }
934         }
935
936         printf("maxfid test finished\n");
937         close_connection(&cli);
938 }
939
940 /* generate a random buffer */
941 static void rand_buf(char *buf, int len)
942 {
943         while (len--) {
944                 *buf = (char)sys_random();
945                 buf++;
946         }
947 }
948
949 /* send random IPC commands */
950 static void run_randomipc(int dummy)
951 {
952         char *rparam = NULL;
953         char *rdata = NULL;
954         int rdrcnt,rprcnt;
955         pstring param;
956         int api, param_len, i;
957         static struct cli_state cli;
958
959         printf("starting random ipc test\n");
960
961         if (!open_connection(&cli)) {
962                 return;
963         }
964
965         for (i=0;i<50000;i++) {
966                 api = sys_random() % 500;
967                 param_len = (sys_random() % 64);
968
969                 rand_buf(param, param_len);
970   
971                 SSVAL(param,0,api); 
972
973                 cli_api(&cli, 
974                         param, param_len, 8,  
975                         NULL, 0, BUFFER_SIZE, 
976                         &rparam, &rprcnt,     
977                         &rdata, &rdrcnt);
978         }
979
980         close_connection(&cli);
981
982         printf("finished random ipc test\n");
983 }
984
985
986
987 static void browse_callback(const char *sname, uint32 stype, 
988                             const char *comment)
989 {
990         printf("\t%20.20s %08x %s\n", sname, stype, comment);
991 }
992
993
994
995 /*
996   This test checks the browse list code
997
998 */
999 static void run_browsetest(int dummy)
1000 {
1001         static struct cli_state cli;
1002
1003         printf("starting browse test\n");
1004
1005         if (!open_connection(&cli)) {
1006                 return;
1007         }
1008
1009         printf("domain list:\n");
1010         cli_NetServerEnum(&cli, cli.server_domain, 
1011                           SV_TYPE_DOMAIN_ENUM,
1012                           browse_callback);
1013
1014         printf("machine list:\n");
1015         cli_NetServerEnum(&cli, cli.server_domain, 
1016                           SV_TYPE_ALL,
1017                           browse_callback);
1018
1019         close_connection(&cli);
1020
1021         printf("browse test finished\n");
1022 }
1023
1024
1025 /*
1026   This checks how the getatr calls works
1027 */
1028 static void run_attrtest(int dummy)
1029 {
1030         static struct cli_state cli;
1031         int fnum;
1032         time_t t, t2;
1033         char *fname = "\\attrib.tst";
1034
1035         printf("starting attrib test\n");
1036
1037         if (!open_connection(&cli)) {
1038                 return;
1039         }
1040
1041         cli_unlink(&cli, fname);
1042         fnum = cli_open(&cli, fname, 
1043                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1044         cli_close(&cli, fnum);
1045         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1046                 printf("getatr failed (%s)\n", cli_errstr(&cli));
1047         }
1048
1049         if (abs(t - time(NULL)) > 2) {
1050                 printf("ERROR: SMBgetatr bug. time is %s",
1051                        ctime(&t));
1052                 t = time(NULL);
1053         }
1054
1055         t2 = t-60*60*24; /* 1 day ago */
1056
1057         if (!cli_setatr(&cli, fname, 0, t2)) {
1058                 printf("setatr failed (%s)\n", cli_errstr(&cli));
1059         }
1060
1061         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1062                 printf("getatr failed (%s)\n", cli_errstr(&cli));
1063         }
1064
1065         if (t != t2) {
1066                 printf("ERROR: getatr/setatr bug. times are\n%s",
1067                        ctime(&t));
1068                 printf("%s", ctime(&t2));
1069         }
1070
1071         cli_unlink(&cli, fname);
1072
1073         close_connection(&cli);
1074
1075         printf("attrib test finished\n");
1076 }
1077
1078
1079 /*
1080   This checks a couple of trans2 calls
1081 */
1082 static void run_trans2test(int dummy)
1083 {
1084         static struct cli_state cli;
1085         int fnum;
1086         size_t size;
1087         time_t c_time, a_time, m_time, w_time, m_time2;
1088         char *fname = "\\trans2.tst";
1089         char *dname = "\\trans2";
1090         char *fname2 = "\\trans2\\trans2.tst";
1091
1092         printf("starting trans2 test\n");
1093
1094         if (!open_connection(&cli)) {
1095                 return;
1096         }
1097
1098         cli_unlink(&cli, fname);
1099         fnum = cli_open(&cli, fname, 
1100                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1101         if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
1102                            NULL, NULL)) {
1103                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
1104         }
1105         cli_close(&cli, fnum);
1106
1107         sleep(2);
1108
1109         cli_unlink(&cli, fname);
1110         fnum = cli_open(&cli, fname, 
1111                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1112         cli_close(&cli, fnum);
1113
1114         if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
1115                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
1116         } else {
1117                 if (c_time != m_time) {
1118                         printf("create time=%s", ctime(&c_time));
1119                         printf("modify time=%s", ctime(&m_time));
1120                         printf("This system appears to have sticky create times\n");
1121                 }
1122                 if (a_time % (60*60) == 0) {
1123                         printf("access time=%s", ctime(&a_time));
1124                         printf("This system appears to set a midnight access time\n");
1125                 }
1126
1127                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1128                         printf("ERROR: totally incorrect times - maybe word reversed?\n");
1129                 }
1130         }
1131
1132
1133         cli_unlink(&cli, fname);
1134         fnum = cli_open(&cli, fname, 
1135                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1136         cli_close(&cli, fnum);
1137         if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time, 
1138                             &w_time, &size, NULL, NULL)) {
1139                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1140         } else {
1141                 if (w_time < 60*60*24*2) {
1142                         printf("write time=%s", ctime(&w_time));
1143                         printf("This system appears to set a initial 0 write time\n");
1144                 }
1145         }
1146
1147         cli_unlink(&cli, fname);
1148
1149
1150         /* check if the server updates the directory modification time
1151            when creating a new file */
1152         if (!cli_mkdir(&cli, dname)) {
1153                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
1154         }
1155         sleep(3);
1156         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time, 
1157                             &w_time, &size, NULL, NULL)) {
1158                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1159         }
1160
1161         fnum = cli_open(&cli, fname2, 
1162                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1163         cli_write(&cli, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
1164         cli_close(&cli, fnum);
1165         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2, 
1166                             &w_time, &size, NULL, NULL)) {
1167                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1168         } else {
1169                 if (m_time2 == m_time)
1170                         printf("This system does not update directory modification times\n");
1171         }
1172         cli_unlink(&cli, fname2);
1173         cli_rmdir(&cli, dname);
1174
1175
1176         close_connection(&cli);
1177
1178         printf("trans2 test finished\n");
1179 }
1180
1181
1182 /*
1183   this is a harness for some oplock tests
1184  */
1185 static void run_oplock(int dummy)
1186 {
1187         static struct cli_state cli1, cli2;
1188         char *fname = "\\lockt1.lck";
1189         char *fname2 = "\\lockt2.lck";
1190         int fnum1, fnum2;
1191
1192         printf("starting oplock test\n");
1193
1194         if (!open_connection(&cli1)) {
1195                 return;
1196         }
1197
1198         cli_unlink(&cli1, fname);
1199
1200         cli_sockopt(&cli1, sockops);
1201
1202         cli1.use_oplocks = True;
1203
1204         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1205         if (fnum1 == -1) {
1206                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1207                 return;
1208         }
1209
1210         cli1.use_oplocks = False;
1211
1212         cli_unlink(&cli1, fname);
1213         cli_unlink(&cli1, fname);
1214
1215         if (!cli_close(&cli1, fnum1)) {
1216                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
1217                 return;
1218         }
1219
1220         if (!cli_unlink(&cli1, fname)) {
1221                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1222                 return;
1223         }
1224
1225
1226         close_connection(&cli1);
1227
1228         printf("finished oplock test\n");
1229 }
1230
1231
1232 static void list_fn(file_info *finfo, const char *name)
1233 {
1234         
1235 }
1236
1237 /*
1238   test directory listing speed
1239  */
1240 static void run_dirtest(int dummy)
1241 {
1242         int i;
1243         static struct cli_state cli;
1244         int fnum;
1245         double t1;
1246
1247         printf("starting directory test\n");
1248
1249         if (!open_connection(&cli)) {
1250                 return;
1251         }
1252
1253         cli_sockopt(&cli, sockops);
1254
1255         srandom(0);
1256         for (i=0;i<numops;i++) {
1257                 fstring fname;
1258                 slprintf(fname, sizeof(fname), "%x", random());
1259                 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
1260                 if (fnum == -1) {
1261                         fprintf(stderr,"Failed to open %s\n", fname);
1262                         return;
1263                 }
1264                 cli_close(&cli, fnum);
1265         }
1266
1267         t1 = end_timer();
1268
1269         printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn));
1270         printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn));
1271         printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn));
1272
1273         printf("dirtest core %g seconds\n", end_timer() - t1);
1274
1275         srandom(0);
1276         for (i=0;i<numops;i++) {
1277                 fstring fname;
1278                 slprintf(fname, sizeof(fname), "%x", random());
1279                 cli_unlink(&cli, fname);
1280         }
1281
1282         close_connection(&cli);
1283
1284         printf("finished dirtest\n");
1285 }
1286
1287
1288
1289 static double create_procs(void (*fn)(int))
1290 {
1291         int i, status;
1292         volatile int *child_status;
1293         int synccount;
1294         int tries = 8;
1295
1296         start_timer();
1297
1298         synccount = 0;
1299
1300         child_status = (volatile int *)shm_setup(sizeof(int)*nprocs);
1301         if (!child_status) {
1302                 printf("Failed to setup shared memory\n");
1303                 return end_timer();
1304         }
1305
1306         memset((char *)child_status, 0, sizeof(int)*nprocs);
1307
1308         for (i=0;i<nprocs;i++) {
1309                 if (fork() == 0) {
1310                         pid_t mypid = getpid();
1311                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
1312
1313                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
1314
1315                         while (1) {
1316                                 memset(&current_cli, 0, sizeof(current_cli));
1317                                 if (open_connection(&current_cli)) break;
1318                                 if (tries-- == 0) {
1319                                         printf("pid %d failed to start\n", (int)getpid());
1320                                         _exit(1);
1321                                 }
1322                                 msleep(10);
1323                         }
1324
1325                         child_status[i] = getpid();
1326
1327                         while (child_status[i]) msleep(2);
1328
1329                         fn(i);
1330                         _exit(0);
1331                 }
1332         }
1333
1334         do {
1335                 synccount = 0;
1336                 for (i=0;i<nprocs;i++) {
1337                         if (child_status[i]) synccount++;
1338                 }
1339                 if (synccount == nprocs) break;
1340                 msleep(10);
1341         } while (end_timer() < 30);
1342
1343         if (synccount != nprocs) {
1344                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
1345                 return end_timer();
1346         }
1347
1348         /* start the client load */
1349         start_timer();
1350
1351         for (i=0;i<nprocs;i++) {
1352                 child_status[i] = 0;
1353         }
1354
1355         printf("%d clients started\n", nprocs);
1356
1357         for (i=0;i<nprocs;i++) {
1358                 waitpid(0, &status, 0);
1359                 printf("*");
1360         }
1361         printf("\n");
1362         return end_timer();
1363 }
1364
1365
1366 #define FLAG_MULTIPROC 1
1367
1368 static struct {
1369         char *name;
1370         void (*fn)(int);
1371         unsigned flags;
1372 } torture_ops[] = {
1373         {"FDPASS", run_fdpasstest, 0},
1374         {"LOCK1",  run_locktest1,  0},
1375         {"LOCK2",  run_locktest2,  0},
1376         {"LOCK3",  run_locktest3,  0},
1377         {"UNLINK", run_unlinktest, 0},
1378         {"BROWSE", run_browsetest, 0},
1379         {"ATTR",   run_attrtest,   0},
1380         {"TRANS2", run_trans2test, 0},
1381         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
1382         {"TORTURE",run_torture,    FLAG_MULTIPROC},
1383         {"RANDOMIPC", run_randomipc, 0},
1384         {"NBW95",  run_nbw95, 0},
1385         {"NBWNT",  run_nbwnt, 0},
1386         {"OPLOCK",  run_oplock, 0},
1387         {"DIR",  run_dirtest, 0},
1388         {"DENY",  run_denytest, 0},
1389         {NULL, NULL, 0}};
1390
1391
1392 /****************************************************************************
1393 run a specified test or "ALL"
1394 ****************************************************************************/
1395 static void run_test(char *name)
1396 {
1397         int i;
1398         if (strequal(name,"ALL")) {
1399                 for (i=0;torture_ops[i].name;i++) {
1400                         run_test(torture_ops[i].name);
1401                 }
1402         }
1403         
1404         for (i=0;torture_ops[i].name;i++) {
1405                 if (strequal(name, torture_ops[i].name)) {
1406                         start_timer();
1407                         printf("Running %s\n", name);
1408                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
1409                                 create_procs(torture_ops[i].fn);
1410                         } else {
1411                                 torture_ops[i].fn(0);
1412                         }
1413                         printf("%s took %g secs\n\n", name, end_timer());
1414                 }
1415         }
1416 }
1417
1418
1419 static void usage(void)
1420 {
1421         int i;
1422
1423         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
1424
1425         printf("\t-U user%%pass\n");
1426         printf("\t-N numprocs\n");
1427         printf("\t-n my_netbios_name\n");
1428         printf("\t-W workgroup\n");
1429         printf("\t-o num_operations\n");
1430         printf("\t-O socket_options\n");
1431         printf("\t-m maximum protocol\n");
1432         printf("\n\n");
1433
1434         printf("tests are:");
1435         for (i=0;torture_ops[i].name;i++) {
1436                 printf(" %s", torture_ops[i].name);
1437         }
1438         printf("\n");
1439
1440         printf("default test is ALL\n");
1441         
1442         exit(1);
1443 }
1444
1445
1446
1447
1448
1449 /****************************************************************************
1450   main program
1451 ****************************************************************************/
1452  int main(int argc,char *argv[])
1453 {
1454         int opt, i;
1455         char *p;
1456         int gotpass = 0;
1457         extern char *optarg;
1458         extern int optind;
1459         extern FILE *dbf;
1460         static pstring servicesf = CONFIGFILE;
1461
1462         dbf = stdout;
1463
1464         setbuffer(stdout, NULL, 0);
1465
1466         charset_initialise();
1467
1468         lp_load(servicesf,True,False,False);
1469         load_interfaces();
1470
1471         if (argc < 2) {
1472                 usage();
1473         }
1474
1475         for(p = argv[1]; *p; p++)
1476           if(*p == '\\')
1477             *p = '/';
1478  
1479         if (strncmp(argv[1], "//", 2)) {
1480                 usage();
1481         }
1482
1483         fstrcpy(host, &argv[1][2]);
1484         p = strchr(&host[2],'/');
1485         if (!p) {
1486                 usage();
1487         }
1488         *p = 0;
1489         fstrcpy(share, p+1);
1490
1491         get_myname(myname);
1492
1493         if (*username == 0 && getenv("LOGNAME")) {
1494           pstrcpy(username,getenv("LOGNAME"));
1495         }
1496
1497         argc--;
1498         argv++;
1499
1500
1501         fstrcpy(workgroup, lp_workgroup());
1502
1503         while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
1504                 switch (opt) {
1505                 case 'W':
1506                         fstrcpy(workgroup,optarg);
1507                         break;
1508                 case 'm':
1509                         max_protocol = interpret_protocol(optarg, max_protocol);
1510                         break;
1511                 case 'N':
1512                         nprocs = atoi(optarg);
1513                         break;
1514                 case 'o':
1515                         numops = atoi(optarg);
1516                         break;
1517                 case 'O':
1518                         sockops = optarg;
1519                         break;
1520                 case 'n':
1521                         fstrcpy(myname, optarg);
1522                         break;
1523                 case 'U':
1524                         pstrcpy(username,optarg);
1525                         p = strchr(username,'%');
1526                         if (p) {
1527                                 *p = 0;
1528                                 pstrcpy(password, p+1);
1529                                 gotpass = 1;
1530                         }
1531                         break;
1532                 default:
1533                         printf("Unknown option %c (%d)\n", (char)opt, opt);
1534                         usage();
1535                 }
1536         }
1537
1538
1539         while (!gotpass) {
1540                 p = getpass("Password:");
1541                 if (p) {
1542                         pstrcpy(password, p);
1543                         gotpass = 1;
1544                 }
1545         }
1546
1547         printf("host=%s share=%s user=%s myname=%s\n", 
1548                host, share, username, myname);
1549
1550         if (argc == 1) {
1551                 run_test("ALL");
1552         } else {
1553                 for (i=1;i<argc;i++) {
1554                         run_test(argv[i]);
1555                 }
1556         }
1557
1558         return(0);
1559 }