r8814: sync for 3.0.20rc1 (up to r8805 from 3.0 tree)
[Samba.git] / source / client / smbmount.c
blob4438964b83857f29b61d5800135ffb25b7cd3610
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 /* redirect stdout & stderr since we can't know that
390 the library functions we use are using DEBUG. */
391 if ( (fd = open("/dev/null", O_WRONLY)) < 0)
392 DEBUG(2,("mount.smbfs: can't open /dev/null\n"));
393 close_our_files(fd);
394 if (fd >= 0) {
395 dup2(fd, STDOUT_FILENO);
396 dup2(fd, STDERR_FILENO);
397 close(fd);
400 /* here we are no longer interactive */
401 set_remote_machine_name("smbmount", False); /* sneaky ... */
402 setup_logging("mount.smbfs", False);
403 reopen_logs();
404 DEBUG(0, ("mount.smbfs: entering daemon mode for service %s, pid=%d\n", the_service, sys_getpid()));
406 closed = 1;
409 /* Wait for a signal from smbfs ... but don't continue
410 until we actually get a new connection. */
411 while (!c) {
412 CatchSignal(SIGUSR1, &usr1_handler);
413 pause();
414 DEBUG(2,("mount.smbfs[%d]: got signal, getting new socket\n", sys_getpid()));
415 c = do_connection(the_service);
419 smb_umount(mount_point);
420 DEBUG(2,("mount.smbfs[%d]: exit\n", sys_getpid()));
421 exit(1);
426 * Mount a smbfs
428 static void init_mount(void)
430 char mount_point[PATH_MAX+1];
431 pstring tmp;
432 pstring svc2;
433 struct cli_state *c;
434 char *args[20];
435 int i, status;
437 if (realpath(mpoint, mount_point) == NULL) {
438 fprintf(stderr, "Could not resolve mount point %s\n", mpoint);
439 return;
443 c = do_connection(service);
444 if (!c) {
445 fprintf(stderr,"SMB connection failed\n");
446 exit(1);
450 Set up to return as a daemon child and wait in the parent
451 until the child say it's ready...
453 daemonize();
455 pstrcpy(svc2, service);
456 string_replace(svc2, '\\','/');
457 string_replace(svc2, ' ','_');
459 memset(args, 0, sizeof(args[0])*20);
461 i=0;
462 args[i++] = "smbmnt";
464 args[i++] = mount_point;
465 args[i++] = "-s";
466 args[i++] = svc2;
468 if (mount_ro) {
469 args[i++] = "-r";
471 if (mount_uid) {
472 slprintf(tmp, sizeof(tmp)-1, "%d", mount_uid);
473 args[i++] = "-u";
474 args[i++] = smb_xstrdup(tmp);
476 if (mount_gid) {
477 slprintf(tmp, sizeof(tmp)-1, "%d", mount_gid);
478 args[i++] = "-g";
479 args[i++] = smb_xstrdup(tmp);
481 if (mount_fmask) {
482 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_fmask);
483 args[i++] = "-f";
484 args[i++] = smb_xstrdup(tmp);
486 if (mount_dmask) {
487 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_dmask);
488 args[i++] = "-d";
489 args[i++] = smb_xstrdup(tmp);
491 if (options) {
492 args[i++] = "-o";
493 args[i++] = options;
496 if (sys_fork() == 0) {
497 char *smbmnt_path;
499 asprintf(&smbmnt_path, "%s/smbmnt", dyn_BINDIR);
501 if (file_exist(smbmnt_path, NULL)) {
502 execv(smbmnt_path, args);
503 fprintf(stderr,
504 "smbfs/init_mount: execv of %s failed. Error was %s.",
505 smbmnt_path, strerror(errno));
506 } else {
507 execvp("smbmnt", args);
508 fprintf(stderr,
509 "smbfs/init_mount: execv of %s failed. Error was %s.",
510 "smbmnt", strerror(errno));
512 free(smbmnt_path);
513 exit(1);
516 if (waitpid(-1, &status, 0) == -1) {
517 fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) );
518 /* FIXME: do some proper error handling */
519 exit(1);
522 if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
523 fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status));
524 /* FIXME: do some proper error handling */
525 exit(1);
526 } else if (WIFSIGNALED(status)) {
527 fprintf(stderr, "smbmnt killed by signal %d\n", WTERMSIG(status));
528 exit(1);
531 /* Ok... This is the rubicon for that mount point... At any point
532 after this, if the connections fail and can not be reconstructed
533 for any reason, we will have to unmount the mount point. There
534 is no exit from the next call...
536 send_fs_socket(service, mount_point, c);
540 /****************************************************************************
541 get a password from a a file or file descriptor
542 exit on failure (from smbclient, move to libsmb or shared .c file?)
543 ****************************************************************************/
544 static void get_password_file(void)
546 int fd = -1;
547 char *p;
548 BOOL close_it = False;
549 pstring spec;
550 char pass[128];
552 if ((p = getenv("PASSWD_FD")) != NULL) {
553 pstrcpy(spec, "descriptor ");
554 pstrcat(spec, p);
555 sscanf(p, "%d", &fd);
556 close_it = False;
557 } else if ((p = getenv("PASSWD_FILE")) != NULL) {
558 fd = sys_open(p, O_RDONLY, 0);
559 pstrcpy(spec, p);
560 if (fd < 0) {
561 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
562 spec, strerror(errno));
563 exit(1);
565 close_it = True;
568 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
569 p && p - pass < sizeof(pass);) {
570 switch (read(fd, p, 1)) {
571 case 1:
572 if (*p != '\n' && *p != '\0') {
573 *++p = '\0'; /* advance p, and null-terminate pass */
574 break;
576 case 0:
577 if (p - pass) {
578 *p = '\0'; /* null-terminate it, just in case... */
579 p = NULL; /* then force the loop condition to become false */
580 break;
581 } else {
582 fprintf(stderr, "Error reading password from file %s: %s\n",
583 spec, "empty password\n");
584 exit(1);
587 default:
588 fprintf(stderr, "Error reading password from file %s: %s\n",
589 spec, strerror(errno));
590 exit(1);
593 pstrcpy(password, pass);
594 if (close_it)
595 close(fd);
598 /****************************************************************************
599 get username and password from a credentials file
600 exit on failure (from smbclient, move to libsmb or shared .c file?)
601 ****************************************************************************/
602 static void read_credentials_file(char *filename)
604 FILE *auth;
605 fstring buf;
606 uint16 len = 0;
607 char *ptr, *val, *param;
609 if ((auth=sys_fopen(filename, "r")) == NULL)
611 /* fail if we can't open the credentials file */
612 DEBUG(0,("ERROR: Unable to open credentials file!\n"));
613 exit (-1);
616 while (!feof(auth))
618 /* get a line from the file */
619 if (!fgets (buf, sizeof(buf), auth))
620 continue;
621 len = strlen(buf);
623 if ((len) && (buf[len-1]=='\n'))
625 buf[len-1] = '\0';
626 len--;
628 if (len == 0)
629 continue;
631 /* break up the line into parameter & value.
632 will need to eat a little whitespace possibly */
633 param = buf;
634 if (!(ptr = strchr (buf, '=')))
635 continue;
636 val = ptr+1;
637 *ptr = '\0';
639 /* eat leading white space */
640 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
641 val++;
643 if (strwicmp("password", param) == 0)
645 pstrcpy(password, val);
646 got_pass = True;
648 else if (strwicmp("username", param) == 0) {
649 pstrcpy(username, val);
652 memset(buf, 0, sizeof(buf));
654 fclose(auth);
658 /****************************************************************************
659 usage on the program
660 ****************************************************************************/
661 static void usage(void)
663 printf("Usage: mount.smbfs service mountpoint [-o options,...]\n");
665 printf("Version %s\n\n",SAMBA_VERSION_STRING);
667 printf(
668 "Options:\n\
669 username=<arg> SMB username\n\
670 password=<arg> SMB password\n\
671 credentials=<filename> file with username/password\n\
672 krb use kerberos (active directory)\n\
673 netbiosname=<arg> source NetBIOS name\n\
674 uid=<arg> mount uid or username\n\
675 gid=<arg> mount gid or groupname\n\
676 port=<arg> remote SMB port number\n\
677 fmask=<arg> file umask\n\
678 dmask=<arg> directory umask\n\
679 debug=<arg> debug level\n\
680 ip=<arg> destination host or IP address\n\
681 workgroup=<arg> workgroup on destination\n\
682 sockopt=<arg> TCP socket options\n\
683 scope=<arg> NetBIOS scope\n\
684 iocharset=<arg> Linux charset (iso8859-1, utf8)\n\
685 codepage=<arg> server codepage (cp850)\n\
686 unicode use unicode when communicating with server\n\
687 lfs large file system support\n\
688 ttl=<arg> dircache time to live\n\
689 guest don't prompt for a password\n\
690 ro mount read-only\n\
691 rw mount read-write\n\
693 This command is designed to be run from within /bin/mount by giving\n\
694 the option '-t smbfs'. For example:\n\
695 mount -t smbfs -o username=tridge,password=foobar //fjall/test /data/test\n\
700 /****************************************************************************
701 Argument parsing for mount.smbfs interface
702 mount will call us like this:
703 mount.smbfs device mountpoint -o <options>
705 <options> is never empty, containing at least rw or ro
706 ****************************************************************************/
707 static void parse_mount_smb(int argc, char **argv)
709 int opt;
710 char *opts;
711 char *opteq;
712 extern char *optarg;
713 int val;
714 char *p;
716 /* FIXME: This function can silently fail if the arguments are
717 * not in the expected order.
719 > The arguments syntax of smbmount 2.2.3a (smbfs of Debian stable)
720 > requires that one gives "-o" before further options like username=...
721 > . Without -o, the username=.. setting is *silently* ignored. I've
722 > spent about an hour trying to find out why I couldn't log in now..
727 if (argc < 2 || argv[1][0] == '-') {
728 usage();
729 exit(1);
732 pstrcpy(service, argv[1]);
733 pstrcpy(mpoint, argv[2]);
735 /* Convert any '/' characters in the service name to
736 '\' characters */
737 string_replace(service, '/','\\');
738 argc -= 2;
739 argv += 2;
741 opt = getopt(argc, argv, "o:");
742 if(opt != 'o') {
743 return;
746 options[0] = 0;
747 p = options;
750 * option parsing from nfsmount.c (util-linux-2.9u)
752 for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) {
753 DEBUG(3, ("opts: %s\n", opts));
754 if ((opteq = strchr_m(opts, '='))) {
755 val = atoi(opteq + 1);
756 *opteq = '\0';
758 if (!strcmp(opts, "username") ||
759 !strcmp(opts, "logon")) {
760 char *lp;
761 got_user = True;
762 pstrcpy(username,opteq+1);
763 if ((lp=strchr_m(username,'%'))) {
764 *lp = 0;
765 pstrcpy(password,lp+1);
766 got_pass = True;
767 memset(strchr_m(opteq+1,'%')+1,'X',strlen(password));
769 if ((lp=strchr_m(username,'/'))) {
770 *lp = 0;
771 pstrcpy(workgroup,lp+1);
773 } else if(!strcmp(opts, "passwd") ||
774 !strcmp(opts, "password")) {
775 pstrcpy(password,opteq+1);
776 got_pass = True;
777 memset(opteq+1,'X',strlen(password));
778 } else if(!strcmp(opts, "credentials")) {
779 pstrcpy(credentials,opteq+1);
780 } else if(!strcmp(opts, "netbiosname")) {
781 pstrcpy(my_netbios_name,opteq+1);
782 } else if(!strcmp(opts, "uid")) {
783 mount_uid = nametouid(opteq+1);
784 } else if(!strcmp(opts, "gid")) {
785 mount_gid = nametogid(opteq+1);
786 } else if(!strcmp(opts, "port")) {
787 smb_port = val;
788 } else if(!strcmp(opts, "fmask")) {
789 mount_fmask = strtol(opteq+1, NULL, 8);
790 } else if(!strcmp(opts, "dmask")) {
791 mount_dmask = strtol(opteq+1, NULL, 8);
792 } else if(!strcmp(opts, "debug")) {
793 DEBUGLEVEL = val;
794 } else if(!strcmp(opts, "ip")) {
795 dest_ip = *interpret_addr2(opteq+1);
796 if (is_zero_ip(dest_ip)) {
797 fprintf(stderr,"Can't resolve address %s\n", opteq+1);
798 exit(1);
800 have_ip = True;
801 } else if(!strcmp(opts, "workgroup")) {
802 pstrcpy(workgroup,opteq+1);
803 } else if(!strcmp(opts, "sockopt")) {
804 pstrcpy(user_socket_options,opteq+1);
805 } else if(!strcmp(opts, "scope")) {
806 set_global_scope(opteq+1);
807 } else {
808 slprintf(p, sizeof(pstring) - (p - options) - 1, "%s=%s,", opts, opteq+1);
809 p += strlen(p);
811 } else {
812 val = 1;
813 if(!strcmp(opts, "nocaps")) {
814 fprintf(stderr, "Unhandled option: %s\n", opteq+1);
815 exit(1);
816 } else if(!strcmp(opts, "guest")) {
817 *password = '\0';
818 got_pass = True;
819 } else if(!strcmp(opts, "krb")) {
820 #ifdef HAVE_KRB5
822 use_kerberos = True;
823 if(!status32_smbfs)
824 fprintf(stderr, "Warning: kerberos support will only work for samba servers\n");
825 #else
826 fprintf(stderr,"No kerberos support compiled in\n");
827 exit(1);
828 #endif
829 } else if(!strcmp(opts, "rw")) {
830 mount_ro = 0;
831 } else if(!strcmp(opts, "ro")) {
832 mount_ro = 1;
833 } else if(!strcmp(opts, "unicode")) {
834 smbfs_has_unicode = True;
835 } else if(!strcmp(opts, "lfs")) {
836 smbfs_has_lfs = True;
837 } else {
838 strncpy(p, opts, sizeof(pstring) - (p - options) - 1);
839 p += strlen(opts);
840 *p++ = ',';
841 *p = 0;
846 if (!*service) {
847 usage();
848 exit(1);
851 if (p != options) {
852 *(p-1) = 0; /* remove trailing , */
853 DEBUG(3,("passthrough options '%s'\n", options));
857 /****************************************************************************
858 main program
859 ****************************************************************************/
860 int main(int argc,char *argv[])
862 extern char *optarg;
863 extern int optind;
864 char *p;
866 DEBUGLEVEL = 1;
868 /* here we are interactive, even if run from autofs */
869 setup_logging("mount.smbfs",True);
871 #if 0 /* JRA - Urban says not needed ? */
872 /* CLI_FORCE_ASCII=false makes smbmount negotiate unicode. The default
873 is to not announce any unicode capabilities as current smbfs does
874 not support it. */
875 p = getenv("CLI_FORCE_ASCII");
876 if (p && !strcmp(p, "false"))
877 unsetenv("CLI_FORCE_ASCII");
878 else
879 setenv("CLI_FORCE_ASCII", "true", 1);
880 #endif
882 in_client = True; /* Make sure that we tell lp_load we are */
884 if (getenv("USER")) {
885 pstrcpy(username,getenv("USER"));
887 if ((p=strchr_m(username,'%'))) {
888 *p = 0;
889 pstrcpy(password,p+1);
890 got_pass = True;
891 memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password));
893 strupper_m(username);
896 if (getenv("PASSWD")) {
897 pstrcpy(password,getenv("PASSWD"));
898 got_pass = True;
901 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
902 get_password_file();
903 got_pass = True;
906 if (*username == 0 && getenv("LOGNAME")) {
907 pstrcpy(username,getenv("LOGNAME"));
910 if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
911 fprintf(stderr, "Can't load %s - run testparm to debug it\n",
912 dyn_CONFIGFILE);
915 parse_mount_smb(argc, argv);
917 if (use_kerberos && !got_user) {
918 got_pass = True;
921 if (*credentials != 0) {
922 read_credentials_file(credentials);
925 DEBUG(3,("mount.smbfs started (version %s)\n", SAMBA_VERSION_STRING));
927 if (*workgroup == 0) {
928 pstrcpy(workgroup,lp_workgroup());
931 load_interfaces();
932 if (!*my_netbios_name) {
933 pstrcpy(my_netbios_name, myhostname());
935 strupper_m(my_netbios_name);
937 init_mount();
938 return 0;