r12912: patch from Tony Mountifield <tony@softins.co.uk> for BUG 3327 (fix bad access...
[Samba/gbeck.git] / source3 / client / smbmount.c
blobd8254ef23a7abbb47ac7723e55d64ce3a251a12b
1 /*
2 Unix SMB/CIFS implementation.
3 SMBFS mount program
4 Copyright (C) Andrew Tridgell 1999
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
23 #include <mntent.h>
24 #include <asm/types.h>
25 #include <linux/smb_fs.h>
27 extern BOOL in_client;
28 extern pstring user_socket_options;
30 static pstring credentials;
31 static pstring my_netbios_name;
32 static pstring password;
33 static pstring username;
34 static pstring workgroup;
35 static pstring mpoint;
36 static pstring service;
37 static pstring options;
39 static struct in_addr dest_ip;
40 static BOOL have_ip;
41 static int smb_port = 0;
42 static BOOL got_user;
43 static BOOL got_pass;
44 static uid_t mount_uid;
45 static gid_t mount_gid;
46 static int mount_ro;
47 static unsigned mount_fmask;
48 static unsigned mount_dmask;
49 static BOOL use_kerberos;
50 /* TODO: Add code to detect smbfs version in kernel */
51 static BOOL status32_smbfs = False;
52 static BOOL smbfs_has_unicode = False;
53 static BOOL smbfs_has_lfs = False;
55 static void usage(void);
57 static void exit_parent(int sig)
59 /* parent simply exits when child says go... */
60 exit(0);
63 static void daemonize(void)
65 int j, status;
66 pid_t child_pid;
68 signal( SIGTERM, exit_parent );
70 if ((child_pid = sys_fork()) < 0) {
71 DEBUG(0,("could not fork\n"));
74 if (child_pid > 0) {
75 while( 1 ) {
76 j = waitpid( child_pid, &status, 0 );
77 if( j < 0 ) {
78 if( EINTR == errno ) {
79 continue;
81 status = errno;
83 break;
86 /* If we get here - the child exited with some error status */
87 if (WIFSIGNALED(status))
88 exit(128 + WTERMSIG(status));
89 else
90 exit(WEXITSTATUS(status));
93 signal( SIGTERM, SIG_DFL );
94 chdir("/");
97 static void close_our_files(int client_fd)
99 int i;
100 struct rlimit limits;
102 getrlimit(RLIMIT_NOFILE,&limits);
103 for (i = 0; i< limits.rlim_max; i++) {
104 if (i == client_fd)
105 continue;
106 close(i);
110 static void usr1_handler(int x)
112 return;
116 /*****************************************************
117 return a connection to a server
118 *******************************************************/
119 static struct cli_state *do_connection(char *the_service)
121 struct cli_state *c;
122 struct nmb_name called, calling;
123 char *server_n;
124 struct in_addr ip;
125 pstring server;
126 char *share;
128 if (the_service[0] != '\\' || the_service[1] != '\\') {
129 usage();
130 exit(1);
133 pstrcpy(server, the_service+2);
134 share = strchr_m(server,'\\');
135 if (!share) {
136 usage();
137 exit(1);
139 *share = 0;
140 share++;
142 server_n = server;
144 make_nmb_name(&calling, my_netbios_name, 0x0);
145 make_nmb_name(&called , server, 0x20);
147 again:
148 zero_ip(&ip);
149 if (have_ip) ip = dest_ip;
151 /* have to open a new connection */
152 if (!(c=cli_initialise(NULL)) || (cli_set_port(c, smb_port) != smb_port) ||
153 !cli_connect(c, server_n, &ip)) {
154 DEBUG(0,("%d: Connection to %s failed\n", sys_getpid(), server_n));
155 if (c) {
156 cli_shutdown(c);
158 return NULL;
161 /* SPNEGO doesn't work till we get NTSTATUS error support */
162 /* But it is REQUIRED for kerberos authentication */
163 if(!use_kerberos) c->use_spnego = False;
165 /* The kernel doesn't yet know how to sign it's packets */
166 c->sign_info.allow_smb_signing = False;
168 /* Use kerberos authentication if specified */
169 c->use_kerberos = use_kerberos;
171 if (!cli_session_request(c, &calling, &called)) {
172 char *p;
173 DEBUG(0,("%d: session request to %s failed (%s)\n",
174 sys_getpid(), called.name, cli_errstr(c)));
175 cli_shutdown(c);
176 if ((p=strchr_m(called.name, '.'))) {
177 *p = 0;
178 goto again;
180 if (strcmp(called.name, "*SMBSERVER")) {
181 make_nmb_name(&called , "*SMBSERVER", 0x20);
182 goto again;
184 return NULL;
187 DEBUG(4,("%d: session request ok\n", sys_getpid()));
189 if (!cli_negprot(c)) {
190 DEBUG(0,("%d: protocol negotiation failed\n", sys_getpid()));
191 cli_shutdown(c);
192 return NULL;
195 if (!got_pass) {
196 char *pass = getpass("Password: ");
197 if (pass) {
198 pstrcpy(password, pass);
202 /* This should be right for current smbfs. Future versions will support
203 large files as well as unicode and oplocks. */
204 c->capabilities &= ~(CAP_NT_SMBS | CAP_NT_FIND | CAP_LEVEL_II_OPLOCKS);
205 if (!smbfs_has_lfs)
206 c->capabilities &= ~CAP_LARGE_FILES;
207 if (!smbfs_has_unicode)
208 c->capabilities &= ~CAP_UNICODE;
209 if (!status32_smbfs) {
210 c->capabilities &= ~CAP_STATUS32;
211 c->force_dos_errors = True;
214 if (!cli_session_setup(c, username,
215 password, strlen(password),
216 password, strlen(password),
217 workgroup)) {
218 /* if a password was not supplied then try again with a
219 null username */
220 if (password[0] || !username[0] ||
221 !cli_session_setup(c, "", "", 0, "", 0, workgroup)) {
222 DEBUG(0,("%d: session setup failed: %s\n",
223 sys_getpid(), cli_errstr(c)));
224 cli_shutdown(c);
225 return NULL;
227 DEBUG(0,("Anonymous login successful\n"));
230 DEBUG(4,("%d: session setup ok\n", sys_getpid()));
232 if (!cli_send_tconX(c, share, "?????",
233 password, strlen(password)+1)) {
234 DEBUG(0,("%d: tree connect failed: %s\n",
235 sys_getpid(), cli_errstr(c)));
236 cli_shutdown(c);
237 return NULL;
240 DEBUG(4,("%d: tconx ok\n", sys_getpid()));
242 got_pass = True;
244 return c;
248 /****************************************************************************
249 unmount smbfs (this is a bailout routine to clean up if a reconnect fails)
250 Code blatently stolen from smbumount.c
251 -mhw-
252 ****************************************************************************/
253 static void smb_umount(char *mount_point)
255 int fd;
256 struct mntent *mnt;
257 FILE* mtab;
258 FILE* new_mtab;
260 /* Programmers Note:
261 This routine only gets called to the scene of a disaster
262 to shoot the survivors... A connection that was working
263 has now apparently failed. We have an active mount point
264 (presumably) that we need to dump. If we get errors along
265 the way - make some noise, but we are already turning out
266 the lights to exit anyways...
268 if (umount(mount_point) != 0) {
269 DEBUG(0,("%d: Could not umount %s: %s\n",
270 sys_getpid(), mount_point, strerror(errno)));
271 return;
274 if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) {
275 DEBUG(0,("%d: Can't get "MOUNTED"~ lock file", sys_getpid()));
276 return;
279 close(fd);
281 if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
282 DEBUG(0,("%d: Can't open " MOUNTED ": %s\n",
283 sys_getpid(), strerror(errno)));
284 return;
287 #define MOUNTED_TMP MOUNTED".tmp"
289 if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) {
290 DEBUG(0,("%d: Can't open " MOUNTED_TMP ": %s\n",
291 sys_getpid(), strerror(errno)));
292 endmntent(mtab);
293 return;
296 while ((mnt = getmntent(mtab)) != NULL) {
297 if (strcmp(mnt->mnt_dir, mount_point) != 0) {
298 addmntent(new_mtab, mnt);
302 endmntent(mtab);
304 if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
305 DEBUG(0,("%d: Error changing mode of %s: %s\n",
306 sys_getpid(), MOUNTED_TMP, strerror(errno)));
307 return;
310 endmntent(new_mtab);
312 if (rename(MOUNTED_TMP, MOUNTED) < 0) {
313 DEBUG(0,("%d: Cannot rename %s to %s: %s\n",
314 sys_getpid(), MOUNTED, MOUNTED_TMP, strerror(errno)));
315 return;
318 if (unlink(MOUNTED"~") == -1) {
319 DEBUG(0,("%d: Can't remove "MOUNTED"~", sys_getpid()));
320 return;
326 * Call the smbfs ioctl to install a connection socket,
327 * then wait for a signal to reconnect. Note that we do
328 * not exit after open_sockets() or send_login() errors,
329 * as the smbfs mount would then have no way to recover.
331 static void send_fs_socket(char *the_service, char *mount_point, struct cli_state *c)
333 int fd, closed = 0, res = 1;
334 pid_t parentpid = getppid();
335 struct smb_conn_opt conn_options;
337 memset(&conn_options, 0, sizeof(conn_options));
339 while (1) {
340 if ((fd = open(mount_point, O_RDONLY)) < 0) {
341 DEBUG(0,("mount.smbfs[%d]: can't open %s\n",
342 sys_getpid(), mount_point));
343 break;
346 conn_options.fd = c->fd;
347 conn_options.protocol = c->protocol;
348 conn_options.case_handling = SMB_CASE_DEFAULT;
349 conn_options.max_xmit = c->max_xmit;
350 conn_options.server_uid = c->vuid;
351 conn_options.tid = c->cnum;
352 conn_options.secmode = c->sec_mode;
353 conn_options.rawmode = 0;
354 conn_options.sesskey = c->sesskey;
355 conn_options.maxraw = 0;
356 conn_options.capabilities = c->capabilities;
357 conn_options.serverzone = c->serverzone/60;
359 res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options);
360 if (res != 0) {
361 DEBUG(0,("mount.smbfs[%d]: ioctl failed, res=%d\n",
362 sys_getpid(), res));
363 close(fd);
364 break;
367 if (parentpid) {
368 /* Ok... We are going to kill the parent. Now
369 is the time to break the process group... */
370 setsid();
371 /* Send a signal to the parent to terminate */
372 kill(parentpid, SIGTERM);
373 parentpid = 0;
376 close(fd);
378 /* This looks wierd but we are only closing the userspace
379 side, the connection has already been passed to smbfs and
380 it has increased the usage count on the socket.
382 If we don't do this we will "leak" sockets and memory on
383 each reconnection we have to make. */
384 c->smb_rw_error = DO_NOT_DO_TDIS;
385 cli_shutdown(c);
386 c = NULL;
388 if (!closed) {
389 /* close the name cache so that close_our_files() doesn't steal its FD */
390 namecache_shutdown();
392 /* redirect stdout & stderr since we can't know that
393 the library functions we use are using DEBUG. */
394 if ( (fd = open("/dev/null", O_WRONLY)) < 0)
395 DEBUG(2,("mount.smbfs: can't open /dev/null\n"));
396 close_our_files(fd);
397 if (fd >= 0) {
398 dup2(fd, STDOUT_FILENO);
399 dup2(fd, STDERR_FILENO);
400 close(fd);
403 /* here we are no longer interactive */
404 set_remote_machine_name("smbmount", False); /* sneaky ... */
405 setup_logging("mount.smbfs", False);
406 reopen_logs();
407 DEBUG(0, ("mount.smbfs: entering daemon mode for service %s, pid=%d\n", the_service, sys_getpid()));
409 closed = 1;
412 /* Wait for a signal from smbfs ... but don't continue
413 until we actually get a new connection. */
414 while (!c) {
415 CatchSignal(SIGUSR1, &usr1_handler);
416 pause();
417 DEBUG(2,("mount.smbfs[%d]: got signal, getting new socket\n", sys_getpid()));
418 c = do_connection(the_service);
422 smb_umount(mount_point);
423 DEBUG(2,("mount.smbfs[%d]: exit\n", sys_getpid()));
424 exit(1);
429 * Mount a smbfs
431 static void init_mount(void)
433 char mount_point[PATH_MAX+1];
434 pstring tmp;
435 pstring svc2;
436 struct cli_state *c;
437 char *args[20];
438 int i, status;
440 if (realpath(mpoint, mount_point) == NULL) {
441 fprintf(stderr, "Could not resolve mount point %s\n", mpoint);
442 return;
446 c = do_connection(service);
447 if (!c) {
448 fprintf(stderr,"SMB connection failed\n");
449 exit(1);
453 Set up to return as a daemon child and wait in the parent
454 until the child say it's ready...
456 daemonize();
458 pstrcpy(svc2, service);
459 string_replace(svc2, '\\','/');
460 string_replace(svc2, ' ','_');
462 memset(args, 0, sizeof(args[0])*20);
464 i=0;
465 args[i++] = "smbmnt";
467 args[i++] = mount_point;
468 args[i++] = "-s";
469 args[i++] = svc2;
471 if (mount_ro) {
472 args[i++] = "-r";
474 if (mount_uid) {
475 slprintf(tmp, sizeof(tmp)-1, "%d", mount_uid);
476 args[i++] = "-u";
477 args[i++] = smb_xstrdup(tmp);
479 if (mount_gid) {
480 slprintf(tmp, sizeof(tmp)-1, "%d", mount_gid);
481 args[i++] = "-g";
482 args[i++] = smb_xstrdup(tmp);
484 if (mount_fmask) {
485 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_fmask);
486 args[i++] = "-f";
487 args[i++] = smb_xstrdup(tmp);
489 if (mount_dmask) {
490 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_dmask);
491 args[i++] = "-d";
492 args[i++] = smb_xstrdup(tmp);
494 if (options) {
495 args[i++] = "-o";
496 args[i++] = options;
499 if (sys_fork() == 0) {
500 char *smbmnt_path;
502 asprintf(&smbmnt_path, "%s/smbmnt", dyn_BINDIR);
504 if (file_exist(smbmnt_path, NULL)) {
505 execv(smbmnt_path, args);
506 fprintf(stderr,
507 "smbfs/init_mount: execv of %s failed. Error was %s.",
508 smbmnt_path, strerror(errno));
509 } else {
510 execvp("smbmnt", args);
511 fprintf(stderr,
512 "smbfs/init_mount: execv of %s failed. Error was %s.",
513 "smbmnt", strerror(errno));
515 free(smbmnt_path);
516 exit(1);
519 if (waitpid(-1, &status, 0) == -1) {
520 fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) );
521 /* FIXME: do some proper error handling */
522 exit(1);
525 if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
526 fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status));
527 /* FIXME: do some proper error handling */
528 exit(1);
529 } else if (WIFSIGNALED(status)) {
530 fprintf(stderr, "smbmnt killed by signal %d\n", WTERMSIG(status));
531 exit(1);
534 /* Ok... This is the rubicon for that mount point... At any point
535 after this, if the connections fail and can not be reconstructed
536 for any reason, we will have to unmount the mount point. There
537 is no exit from the next call...
539 send_fs_socket(service, mount_point, c);
543 /****************************************************************************
544 get a password from a a file or file descriptor
545 exit on failure (from smbclient, move to libsmb or shared .c file?)
546 ****************************************************************************/
547 static void get_password_file(void)
549 int fd = -1;
550 char *p;
551 BOOL close_it = False;
552 pstring spec;
553 char pass[128];
555 if ((p = getenv("PASSWD_FD")) != NULL) {
556 pstrcpy(spec, "descriptor ");
557 pstrcat(spec, p);
558 sscanf(p, "%d", &fd);
559 close_it = False;
560 } else if ((p = getenv("PASSWD_FILE")) != NULL) {
561 fd = sys_open(p, O_RDONLY, 0);
562 pstrcpy(spec, p);
563 if (fd < 0) {
564 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
565 spec, strerror(errno));
566 exit(1);
568 close_it = True;
571 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
572 p && p - pass < sizeof(pass);) {
573 switch (read(fd, p, 1)) {
574 case 1:
575 if (*p != '\n' && *p != '\0') {
576 *++p = '\0'; /* advance p, and null-terminate pass */
577 break;
579 case 0:
580 if (p - pass) {
581 *p = '\0'; /* null-terminate it, just in case... */
582 p = NULL; /* then force the loop condition to become false */
583 break;
584 } else {
585 fprintf(stderr, "Error reading password from file %s: %s\n",
586 spec, "empty password\n");
587 exit(1);
590 default:
591 fprintf(stderr, "Error reading password from file %s: %s\n",
592 spec, strerror(errno));
593 exit(1);
596 pstrcpy(password, pass);
597 if (close_it)
598 close(fd);
601 /****************************************************************************
602 get username and password from a credentials file
603 exit on failure (from smbclient, move to libsmb or shared .c file?)
604 ****************************************************************************/
605 static void read_credentials_file(char *filename)
607 FILE *auth;
608 fstring buf;
609 uint16 len = 0;
610 char *ptr, *val, *param;
612 if ((auth=sys_fopen(filename, "r")) == NULL)
614 /* fail if we can't open the credentials file */
615 DEBUG(0,("ERROR: Unable to open credentials file!\n"));
616 exit (-1);
619 while (!feof(auth))
621 /* get a line from the file */
622 if (!fgets (buf, sizeof(buf), auth))
623 continue;
624 len = strlen(buf);
626 if ((len) && (buf[len-1]=='\n'))
628 buf[len-1] = '\0';
629 len--;
631 if (len == 0)
632 continue;
634 /* break up the line into parameter & value.
635 will need to eat a little whitespace possibly */
636 param = buf;
637 if (!(ptr = strchr (buf, '=')))
638 continue;
639 val = ptr+1;
640 *ptr = '\0';
642 /* eat leading white space */
643 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
644 val++;
646 if (strwicmp("password", param) == 0)
648 pstrcpy(password, val);
649 got_pass = True;
651 else if (strwicmp("username", param) == 0) {
652 pstrcpy(username, val);
655 memset(buf, 0, sizeof(buf));
657 fclose(auth);
661 /****************************************************************************
662 usage on the program
663 ****************************************************************************/
664 static void usage(void)
666 printf("Usage: mount.smbfs service mountpoint [-o options,...]\n");
668 printf("Version %s\n\n",SAMBA_VERSION_STRING);
670 printf(
671 "Options:\n\
672 username=<arg> SMB username\n\
673 password=<arg> SMB password\n\
674 credentials=<filename> file with username/password\n\
675 krb use kerberos (active directory)\n\
676 netbiosname=<arg> source NetBIOS name\n\
677 uid=<arg> mount uid or username\n\
678 gid=<arg> mount gid or groupname\n\
679 port=<arg> remote SMB port number\n\
680 fmask=<arg> file umask\n\
681 dmask=<arg> directory umask\n\
682 debug=<arg> debug level\n\
683 ip=<arg> destination host or IP address\n\
684 workgroup=<arg> workgroup on destination\n\
685 sockopt=<arg> TCP socket options\n\
686 scope=<arg> NetBIOS scope\n\
687 iocharset=<arg> Linux charset (iso8859-1, utf8)\n\
688 codepage=<arg> server codepage (cp850)\n\
689 unicode use unicode when communicating with server\n\
690 lfs large file system support\n\
691 ttl=<arg> dircache time to live\n\
692 guest don't prompt for a password\n\
693 ro mount read-only\n\
694 rw mount read-write\n\
696 This command is designed to be run from within /bin/mount by giving\n\
697 the option '-t smbfs'. For example:\n\
698 mount -t smbfs -o username=tridge,password=foobar //fjall/test /data/test\n\
703 /****************************************************************************
704 Argument parsing for mount.smbfs interface
705 mount will call us like this:
706 mount.smbfs device mountpoint -o <options>
708 <options> is never empty, containing at least rw or ro
709 ****************************************************************************/
710 static void parse_mount_smb(int argc, char **argv)
712 int opt;
713 char *opts;
714 char *opteq;
715 extern char *optarg;
716 int val;
717 char *p;
719 /* FIXME: This function can silently fail if the arguments are
720 * not in the expected order.
722 > The arguments syntax of smbmount 2.2.3a (smbfs of Debian stable)
723 > requires that one gives "-o" before further options like username=...
724 > . Without -o, the username=.. setting is *silently* ignored. I've
725 > spent about an hour trying to find out why I couldn't log in now..
730 if (argc < 2 || argv[1][0] == '-') {
731 usage();
732 exit(1);
735 pstrcpy(service, argv[1]);
736 pstrcpy(mpoint, argv[2]);
738 /* Convert any '/' characters in the service name to
739 '\' characters */
740 string_replace(service, '/','\\');
741 argc -= 2;
742 argv += 2;
744 opt = getopt(argc, argv, "o:");
745 if(opt != 'o') {
746 return;
749 options[0] = 0;
750 p = options;
753 * option parsing from nfsmount.c (util-linux-2.9u)
755 for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) {
756 DEBUG(3, ("opts: %s\n", opts));
757 if ((opteq = strchr_m(opts, '='))) {
758 val = atoi(opteq + 1);
759 *opteq = '\0';
761 if (!strcmp(opts, "username") ||
762 !strcmp(opts, "logon")) {
763 char *lp;
764 got_user = True;
765 pstrcpy(username,opteq+1);
766 if ((lp=strchr_m(username,'%'))) {
767 *lp = 0;
768 pstrcpy(password,lp+1);
769 got_pass = True;
770 memset(strchr_m(opteq+1,'%')+1,'X',strlen(password));
772 if ((lp=strchr_m(username,'/'))) {
773 *lp = 0;
774 pstrcpy(workgroup,lp+1);
776 } else if(!strcmp(opts, "passwd") ||
777 !strcmp(opts, "password")) {
778 pstrcpy(password,opteq+1);
779 got_pass = True;
780 memset(opteq+1,'X',strlen(password));
781 } else if(!strcmp(opts, "credentials")) {
782 pstrcpy(credentials,opteq+1);
783 } else if(!strcmp(opts, "netbiosname")) {
784 pstrcpy(my_netbios_name,opteq+1);
785 } else if(!strcmp(opts, "uid")) {
786 mount_uid = nametouid(opteq+1);
787 } else if(!strcmp(opts, "gid")) {
788 mount_gid = nametogid(opteq+1);
789 } else if(!strcmp(opts, "port")) {
790 smb_port = val;
791 } else if(!strcmp(opts, "fmask")) {
792 mount_fmask = strtol(opteq+1, NULL, 8);
793 } else if(!strcmp(opts, "dmask")) {
794 mount_dmask = strtol(opteq+1, NULL, 8);
795 } else if(!strcmp(opts, "debug")) {
796 DEBUGLEVEL = val;
797 } else if(!strcmp(opts, "ip")) {
798 dest_ip = *interpret_addr2(opteq+1);
799 if (is_zero_ip(dest_ip)) {
800 fprintf(stderr,"Can't resolve address %s\n", opteq+1);
801 exit(1);
803 have_ip = True;
804 } else if(!strcmp(opts, "workgroup")) {
805 pstrcpy(workgroup,opteq+1);
806 } else if(!strcmp(opts, "sockopt")) {
807 pstrcpy(user_socket_options,opteq+1);
808 } else if(!strcmp(opts, "scope")) {
809 set_global_scope(opteq+1);
810 } else {
811 slprintf(p, sizeof(pstring) - (p - options) - 1, "%s=%s,", opts, opteq+1);
812 p += strlen(p);
814 } else {
815 val = 1;
816 if(!strcmp(opts, "nocaps")) {
817 fprintf(stderr, "Unhandled option: %s\n", opteq+1);
818 exit(1);
819 } else if(!strcmp(opts, "guest")) {
820 *password = '\0';
821 got_pass = True;
822 } else if(!strcmp(opts, "krb")) {
823 #ifdef HAVE_KRB5
825 use_kerberos = True;
826 if(!status32_smbfs)
827 fprintf(stderr, "Warning: kerberos support will only work for samba servers\n");
828 #else
829 fprintf(stderr,"No kerberos support compiled in\n");
830 exit(1);
831 #endif
832 } else if(!strcmp(opts, "rw")) {
833 mount_ro = 0;
834 } else if(!strcmp(opts, "ro")) {
835 mount_ro = 1;
836 } else if(!strcmp(opts, "unicode")) {
837 smbfs_has_unicode = True;
838 } else if(!strcmp(opts, "lfs")) {
839 smbfs_has_lfs = True;
840 } else {
841 strncpy(p, opts, sizeof(pstring) - (p - options) - 1);
842 p += strlen(opts);
843 *p++ = ',';
844 *p = 0;
849 if (!*service) {
850 usage();
851 exit(1);
854 if (p != options) {
855 *(p-1) = 0; /* remove trailing , */
856 DEBUG(3,("passthrough options '%s'\n", options));
860 /****************************************************************************
861 main program
862 ****************************************************************************/
863 int main(int argc,char *argv[])
865 extern char *optarg;
866 extern int optind;
867 char *p;
869 DEBUGLEVEL = 1;
871 /* here we are interactive, even if run from autofs */
872 setup_logging("mount.smbfs",True);
874 #if 0 /* JRA - Urban says not needed ? */
875 /* CLI_FORCE_ASCII=false makes smbmount negotiate unicode. The default
876 is to not announce any unicode capabilities as current smbfs does
877 not support it. */
878 p = getenv("CLI_FORCE_ASCII");
879 if (p && !strcmp(p, "false"))
880 unsetenv("CLI_FORCE_ASCII");
881 else
882 setenv("CLI_FORCE_ASCII", "true", 1);
883 #endif
885 in_client = True; /* Make sure that we tell lp_load we are */
887 if (getenv("USER")) {
888 pstrcpy(username,getenv("USER"));
890 if ((p=strchr_m(username,'%'))) {
891 *p = 0;
892 pstrcpy(password,p+1);
893 got_pass = True;
894 memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password));
896 strupper_m(username);
899 if (getenv("PASSWD")) {
900 pstrcpy(password,getenv("PASSWD"));
901 got_pass = True;
904 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
905 get_password_file();
906 got_pass = True;
909 if (*username == 0 && getenv("LOGNAME")) {
910 pstrcpy(username,getenv("LOGNAME"));
913 if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
914 fprintf(stderr, "Can't load %s - run testparm to debug it\n",
915 dyn_CONFIGFILE);
918 parse_mount_smb(argc, argv);
920 if (use_kerberos && !got_user) {
921 got_pass = True;
924 if (*credentials != 0) {
925 read_credentials_file(credentials);
928 DEBUG(3,("mount.smbfs started (version %s)\n", SAMBA_VERSION_STRING));
930 if (*workgroup == 0) {
931 pstrcpy(workgroup,lp_workgroup());
934 load_interfaces();
935 if (!*my_netbios_name) {
936 pstrcpy(my_netbios_name, myhostname());
938 strupper_m(my_netbios_name);
940 init_mount();
941 return 0;