skel_ -> cap_
[Samba/gebeck_regimport.git] / source3 / client / smbmount.c
blob6e8d9f5bca7e9710055d118ad331ef76b368d161
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 #define NO_SYSLOG
23 #include "includes.h"
25 #include <mntent.h>
26 #include <asm/types.h>
27 #include <linux/smb_fs.h>
29 extern BOOL in_client;
30 extern pstring user_socket_options;
32 static pstring credentials;
33 static pstring my_netbios_name;
34 static pstring password;
35 static pstring username;
36 static pstring workgroup;
37 static pstring mpoint;
38 static pstring service;
39 static pstring options;
41 static struct in_addr dest_ip;
42 static BOOL have_ip;
43 static int smb_port = 0;
44 static BOOL got_user;
45 static BOOL got_pass;
46 static uid_t mount_uid;
47 static gid_t mount_gid;
48 static int mount_ro;
49 static unsigned mount_fmask;
50 static unsigned mount_dmask;
51 static BOOL use_kerberos;
52 /* TODO: Add code to detect smbfs version in kernel */
53 static BOOL status32_smbfs = False;
54 static BOOL smbfs_has_unicode = False;
55 static BOOL smbfs_has_lfs = False;
57 static void usage(void);
59 static void exit_parent(int sig)
61 /* parent simply exits when child says go... */
62 exit(0);
65 static void daemonize(void)
67 int j, status;
68 pid_t child_pid;
70 signal( SIGTERM, exit_parent );
72 if ((child_pid = sys_fork()) < 0) {
73 DEBUG(0,("could not fork\n"));
76 if (child_pid > 0) {
77 while( 1 ) {
78 j = waitpid( child_pid, &status, 0 );
79 if( j < 0 ) {
80 if( EINTR == errno ) {
81 continue;
83 status = errno;
85 break;
88 /* If we get here - the child exited with some error status */
89 if (WIFSIGNALED(status))
90 exit(128 + WTERMSIG(status));
91 else
92 exit(WEXITSTATUS(status));
95 signal( SIGTERM, SIG_DFL );
96 chdir("/");
99 static void close_our_files(int client_fd)
101 int i;
102 struct rlimit limits;
104 getrlimit(RLIMIT_NOFILE,&limits);
105 for (i = 0; i< limits.rlim_max; i++) {
106 if (i == client_fd)
107 continue;
108 close(i);
112 static void usr1_handler(int x)
114 return;
118 /*****************************************************
119 return a connection to a server
120 *******************************************************/
121 static struct cli_state *do_connection(char *the_service)
123 struct cli_state *c;
124 struct nmb_name called, calling;
125 char *server_n;
126 struct in_addr ip;
127 pstring server;
128 char *share;
130 if (the_service[0] != '\\' || the_service[1] != '\\') {
131 usage();
132 exit(1);
135 pstrcpy(server, the_service+2);
136 share = strchr_m(server,'\\');
137 if (!share) {
138 usage();
139 exit(1);
141 *share = 0;
142 share++;
144 server_n = server;
146 make_nmb_name(&calling, my_netbios_name, 0x0);
147 make_nmb_name(&called , server, 0x20);
149 again:
150 zero_ip(&ip);
151 if (have_ip) ip = dest_ip;
153 /* have to open a new connection */
154 if (!(c=cli_initialise(NULL)) || (cli_set_port(c, smb_port) != smb_port) ||
155 !cli_connect(c, server_n, &ip)) {
156 DEBUG(0,("%d: Connection to %s failed\n", sys_getpid(), server_n));
157 if (c) {
158 cli_shutdown(c);
160 return NULL;
163 /* SPNEGO doesn't work till we get NTSTATUS error support */
164 /* But it is REQUIRED for kerberos authentication */
165 if(!use_kerberos) c->use_spnego = False;
167 /* The kernel doesn't yet know how to sign it's packets */
168 c->sign_info.allow_smb_signing = False;
170 /* Use kerberos authentication if specified */
171 c->use_kerberos = use_kerberos;
173 if (!cli_session_request(c, &calling, &called)) {
174 char *p;
175 DEBUG(0,("%d: session request to %s failed (%s)\n",
176 sys_getpid(), called.name, cli_errstr(c)));
177 cli_shutdown(c);
178 if ((p=strchr_m(called.name, '.'))) {
179 *p = 0;
180 goto again;
182 if (strcmp(called.name, "*SMBSERVER")) {
183 make_nmb_name(&called , "*SMBSERVER", 0x20);
184 goto again;
186 return NULL;
189 DEBUG(4,("%d: session request ok\n", sys_getpid()));
191 if (!cli_negprot(c)) {
192 DEBUG(0,("%d: protocol negotiation failed\n", sys_getpid()));
193 cli_shutdown(c);
194 return NULL;
197 if (!got_pass) {
198 char *pass = getpass("Password: ");
199 if (pass) {
200 pstrcpy(password, pass);
204 /* This should be right for current smbfs. Future versions will support
205 large files as well as unicode and oplocks. */
206 c->capabilities &= ~(CAP_NT_SMBS | CAP_NT_FIND | CAP_LEVEL_II_OPLOCKS);
207 if (!smbfs_has_lfs)
208 c->capabilities &= ~CAP_LARGE_FILES;
209 if (!smbfs_has_unicode)
210 c->capabilities &= ~CAP_UNICODE;
211 if (!status32_smbfs) {
212 c->capabilities &= ~CAP_STATUS32;
213 c->force_dos_errors = True;
216 if (!cli_session_setup(c, username,
217 password, strlen(password),
218 password, strlen(password),
219 workgroup)) {
220 /* if a password was not supplied then try again with a
221 null username */
222 if (password[0] || !username[0] ||
223 !cli_session_setup(c, "", "", 0, "", 0, workgroup)) {
224 DEBUG(0,("%d: session setup failed: %s\n",
225 sys_getpid(), cli_errstr(c)));
226 cli_shutdown(c);
227 return NULL;
229 DEBUG(0,("Anonymous login successful\n"));
232 DEBUG(4,("%d: session setup ok\n", sys_getpid()));
234 if (!cli_send_tconX(c, share, "?????",
235 password, strlen(password)+1)) {
236 DEBUG(0,("%d: tree connect failed: %s\n",
237 sys_getpid(), cli_errstr(c)));
238 cli_shutdown(c);
239 return NULL;
242 DEBUG(4,("%d: tconx ok\n", sys_getpid()));
244 got_pass = True;
246 return c;
250 /****************************************************************************
251 unmount smbfs (this is a bailout routine to clean up if a reconnect fails)
252 Code blatently stolen from smbumount.c
253 -mhw-
254 ****************************************************************************/
255 static void smb_umount(char *mount_point)
257 int fd;
258 struct mntent *mnt;
259 FILE* mtab;
260 FILE* new_mtab;
262 /* Programmers Note:
263 This routine only gets called to the scene of a disaster
264 to shoot the survivors... A connection that was working
265 has now apparently failed. We have an active mount point
266 (presumably) that we need to dump. If we get errors along
267 the way - make some noise, but we are already turning out
268 the lights to exit anyways...
270 if (umount(mount_point) != 0) {
271 DEBUG(0,("%d: Could not umount %s: %s\n",
272 sys_getpid(), mount_point, strerror(errno)));
273 return;
276 if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) {
277 DEBUG(0,("%d: Can't get "MOUNTED"~ lock file", sys_getpid()));
278 return;
281 close(fd);
283 if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
284 DEBUG(0,("%d: Can't open " MOUNTED ": %s\n",
285 sys_getpid(), strerror(errno)));
286 return;
289 #define MOUNTED_TMP MOUNTED".tmp"
291 if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) {
292 DEBUG(0,("%d: Can't open " MOUNTED_TMP ": %s\n",
293 sys_getpid(), strerror(errno)));
294 endmntent(mtab);
295 return;
298 while ((mnt = getmntent(mtab)) != NULL) {
299 if (strcmp(mnt->mnt_dir, mount_point) != 0) {
300 addmntent(new_mtab, mnt);
304 endmntent(mtab);
306 if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
307 DEBUG(0,("%d: Error changing mode of %s: %s\n",
308 sys_getpid(), MOUNTED_TMP, strerror(errno)));
309 return;
312 endmntent(new_mtab);
314 if (rename(MOUNTED_TMP, MOUNTED) < 0) {
315 DEBUG(0,("%d: Cannot rename %s to %s: %s\n",
316 sys_getpid(), MOUNTED, MOUNTED_TMP, strerror(errno)));
317 return;
320 if (unlink(MOUNTED"~") == -1) {
321 DEBUG(0,("%d: Can't remove "MOUNTED"~", sys_getpid()));
322 return;
328 * Call the smbfs ioctl to install a connection socket,
329 * then wait for a signal to reconnect. Note that we do
330 * not exit after open_sockets() or send_login() errors,
331 * as the smbfs mount would then have no way to recover.
333 static void send_fs_socket(char *the_service, char *mount_point, struct cli_state *c)
335 int fd, closed = 0, res = 1;
336 pid_t parentpid = getppid();
337 struct smb_conn_opt conn_options;
339 memset(&conn_options, 0, sizeof(conn_options));
341 while (1) {
342 if ((fd = open(mount_point, O_RDONLY)) < 0) {
343 DEBUG(0,("mount.smbfs[%d]: can't open %s\n",
344 sys_getpid(), mount_point));
345 break;
348 conn_options.fd = c->fd;
349 conn_options.protocol = c->protocol;
350 conn_options.case_handling = SMB_CASE_DEFAULT;
351 conn_options.max_xmit = c->max_xmit;
352 conn_options.server_uid = c->vuid;
353 conn_options.tid = c->cnum;
354 conn_options.secmode = c->sec_mode;
355 conn_options.rawmode = 0;
356 conn_options.sesskey = c->sesskey;
357 conn_options.maxraw = 0;
358 conn_options.capabilities = c->capabilities;
359 conn_options.serverzone = c->serverzone/60;
361 res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options);
362 if (res != 0) {
363 DEBUG(0,("mount.smbfs[%d]: ioctl failed, res=%d\n",
364 sys_getpid(), res));
365 close(fd);
366 break;
369 if (parentpid) {
370 /* Ok... We are going to kill the parent. Now
371 is the time to break the process group... */
372 setsid();
373 /* Send a signal to the parent to terminate */
374 kill(parentpid, SIGTERM);
375 parentpid = 0;
378 close(fd);
380 /* This looks wierd but we are only closing the userspace
381 side, the connection has already been passed to smbfs and
382 it has increased the usage count on the socket.
384 If we don't do this we will "leak" sockets and memory on
385 each reconnection we have to make. */
386 cli_shutdown(c);
387 c = NULL;
389 if (!closed) {
390 /* redirect stdout & stderr since we can't know that
391 the library functions we use are using DEBUG. */
392 if ( (fd = open("/dev/null", O_WRONLY)) < 0)
393 DEBUG(2,("mount.smbfs: can't open /dev/null\n"));
394 close_our_files(fd);
395 if (fd >= 0) {
396 dup2(fd, STDOUT_FILENO);
397 dup2(fd, STDERR_FILENO);
398 close(fd);
401 /* here we are no longer interactive */
402 set_remote_machine_name("smbmount", False); /* sneaky ... */
403 setup_logging("mount.smbfs", False);
404 reopen_logs();
405 DEBUG(0, ("mount.smbfs: entering daemon mode for service %s, pid=%d\n", the_service, sys_getpid()));
407 closed = 1;
410 /* Wait for a signal from smbfs ... but don't continue
411 until we actually get a new connection. */
412 while (!c) {
413 CatchSignal(SIGUSR1, &usr1_handler);
414 pause();
415 DEBUG(2,("mount.smbfs[%d]: got signal, getting new socket\n", sys_getpid()));
416 c = do_connection(the_service);
420 smb_umount(mount_point);
421 DEBUG(2,("mount.smbfs[%d]: exit\n", sys_getpid()));
422 exit(1);
427 * Mount a smbfs
429 static void init_mount(void)
431 char mount_point[PATH_MAX+1];
432 pstring tmp;
433 pstring svc2;
434 struct cli_state *c;
435 char *args[20];
436 int i, status;
438 if (realpath(mpoint, mount_point) == NULL) {
439 fprintf(stderr, "Could not resolve mount point %s\n", mpoint);
440 return;
444 c = do_connection(service);
445 if (!c) {
446 fprintf(stderr,"SMB connection failed\n");
447 exit(1);
451 Set up to return as a daemon child and wait in the parent
452 until the child say it's ready...
454 daemonize();
456 pstrcpy(svc2, service);
457 string_replace(svc2, '\\','/');
458 string_replace(svc2, ' ','_');
460 memset(args, 0, sizeof(args[0])*20);
462 i=0;
463 args[i++] = "smbmnt";
465 args[i++] = mount_point;
466 args[i++] = "-s";
467 args[i++] = svc2;
469 if (mount_ro) {
470 args[i++] = "-r";
472 if (mount_uid) {
473 slprintf(tmp, sizeof(tmp)-1, "%d", mount_uid);
474 args[i++] = "-u";
475 args[i++] = smb_xstrdup(tmp);
477 if (mount_gid) {
478 slprintf(tmp, sizeof(tmp)-1, "%d", mount_gid);
479 args[i++] = "-g";
480 args[i++] = smb_xstrdup(tmp);
482 if (mount_fmask) {
483 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_fmask);
484 args[i++] = "-f";
485 args[i++] = smb_xstrdup(tmp);
487 if (mount_dmask) {
488 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_dmask);
489 args[i++] = "-d";
490 args[i++] = smb_xstrdup(tmp);
492 if (options) {
493 args[i++] = "-o";
494 args[i++] = options;
497 if (sys_fork() == 0) {
498 char *smbmnt_path;
500 asprintf(&smbmnt_path, "%s/smbmnt", dyn_BINDIR);
502 if (file_exist(smbmnt_path, NULL)) {
503 execv(smbmnt_path, args);
504 fprintf(stderr,
505 "smbfs/init_mount: execv of %s failed. Error was %s.",
506 smbmnt_path, strerror(errno));
507 } else {
508 execvp("smbmnt", args);
509 fprintf(stderr,
510 "smbfs/init_mount: execv of %s failed. Error was %s.",
511 "smbmnt", strerror(errno));
513 free(smbmnt_path);
514 exit(1);
517 if (waitpid(-1, &status, 0) == -1) {
518 fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) );
519 /* FIXME: do some proper error handling */
520 exit(1);
523 if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
524 fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status));
525 /* FIXME: do some proper error handling */
526 exit(1);
527 } else if (WIFSIGNALED(status)) {
528 fprintf(stderr, "smbmnt killed by signal %d\n", WTERMSIG(status));
529 exit(1);
532 /* Ok... This is the rubicon for that mount point... At any point
533 after this, if the connections fail and can not be reconstructed
534 for any reason, we will have to unmount the mount point. There
535 is no exit from the next call...
537 send_fs_socket(service, mount_point, c);
541 /****************************************************************************
542 get a password from a a file or file descriptor
543 exit on failure (from smbclient, move to libsmb or shared .c file?)
544 ****************************************************************************/
545 static void get_password_file(void)
547 int fd = -1;
548 char *p;
549 BOOL close_it = False;
550 pstring spec;
551 char pass[128];
553 if ((p = getenv("PASSWD_FD")) != NULL) {
554 pstrcpy(spec, "descriptor ");
555 pstrcat(spec, p);
556 sscanf(p, "%d", &fd);
557 close_it = False;
558 } else if ((p = getenv("PASSWD_FILE")) != NULL) {
559 fd = sys_open(p, O_RDONLY, 0);
560 pstrcpy(spec, p);
561 if (fd < 0) {
562 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
563 spec, strerror(errno));
564 exit(1);
566 close_it = True;
569 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
570 p && p - pass < sizeof(pass);) {
571 switch (read(fd, p, 1)) {
572 case 1:
573 if (*p != '\n' && *p != '\0') {
574 *++p = '\0'; /* advance p, and null-terminate pass */
575 break;
577 case 0:
578 if (p - pass) {
579 *p = '\0'; /* null-terminate it, just in case... */
580 p = NULL; /* then force the loop condition to become false */
581 break;
582 } else {
583 fprintf(stderr, "Error reading password from file %s: %s\n",
584 spec, "empty password\n");
585 exit(1);
588 default:
589 fprintf(stderr, "Error reading password from file %s: %s\n",
590 spec, strerror(errno));
591 exit(1);
594 pstrcpy(password, pass);
595 if (close_it)
596 close(fd);
599 /****************************************************************************
600 get username and password from a credentials file
601 exit on failure (from smbclient, move to libsmb or shared .c file?)
602 ****************************************************************************/
603 static void read_credentials_file(char *filename)
605 FILE *auth;
606 fstring buf;
607 uint16 len = 0;
608 char *ptr, *val, *param;
610 if ((auth=sys_fopen(filename, "r")) == NULL)
612 /* fail if we can't open the credentials file */
613 DEBUG(0,("ERROR: Unable to open credentials file!\n"));
614 exit (-1);
617 while (!feof(auth))
619 /* get a line from the file */
620 if (!fgets (buf, sizeof(buf), auth))
621 continue;
622 len = strlen(buf);
624 if ((len) && (buf[len-1]=='\n'))
626 buf[len-1] = '\0';
627 len--;
629 if (len == 0)
630 continue;
632 /* break up the line into parameter & value.
633 will need to eat a little whitespace possibly */
634 param = buf;
635 if (!(ptr = strchr (buf, '=')))
636 continue;
637 val = ptr+1;
638 *ptr = '\0';
640 /* eat leading white space */
641 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
642 val++;
644 if (strwicmp("password", param) == 0)
646 pstrcpy(password, val);
647 got_pass = True;
649 else if (strwicmp("username", param) == 0) {
650 pstrcpy(username, val);
653 memset(buf, 0, sizeof(buf));
655 fclose(auth);
659 /****************************************************************************
660 usage on the program
661 ****************************************************************************/
662 static void usage(void)
664 printf("Usage: mount.smbfs service mountpoint [-o options,...]\n");
666 printf("Version %s\n\n",SAMBA_VERSION_STRING);
668 printf(
669 "Options:\n\
670 username=<arg> SMB username\n\
671 password=<arg> SMB password\n\
672 credentials=<filename> file with username/password\n\
673 krb use kerberos (active directory)\n\
674 netbiosname=<arg> source NetBIOS name\n\
675 uid=<arg> mount uid or username\n\
676 gid=<arg> mount gid or groupname\n\
677 port=<arg> remote SMB port number\n\
678 fmask=<arg> file umask\n\
679 dmask=<arg> directory umask\n\
680 debug=<arg> debug level\n\
681 ip=<arg> destination host or IP address\n\
682 workgroup=<arg> workgroup on destination\n\
683 sockopt=<arg> TCP socket options\n\
684 scope=<arg> NetBIOS scope\n\
685 iocharset=<arg> Linux charset (iso8859-1, utf8)\n\
686 codepage=<arg> server codepage (cp850)\n\
687 unicode use unicode when communicating with server\n\
688 lfs large file system support\n\
689 ttl=<arg> dircache time to live\n\
690 guest don't prompt for a password\n\
691 ro mount read-only\n\
692 rw mount read-write\n\
694 This command is designed to be run from within /bin/mount by giving\n\
695 the option '-t smbfs'. For example:\n\
696 mount -t smbfs -o username=tridge,password=foobar //fjall/test /data/test\n\
701 /****************************************************************************
702 Argument parsing for mount.smbfs interface
703 mount will call us like this:
704 mount.smbfs device mountpoint -o <options>
706 <options> is never empty, containing at least rw or ro
707 ****************************************************************************/
708 static void parse_mount_smb(int argc, char **argv)
710 int opt;
711 char *opts;
712 char *opteq;
713 extern char *optarg;
714 int val;
715 char *p;
717 /* FIXME: This function can silently fail if the arguments are
718 * not in the expected order.
720 > The arguments syntax of smbmount 2.2.3a (smbfs of Debian stable)
721 > requires that one gives "-o" before further options like username=...
722 > . Without -o, the username=.. setting is *silently* ignored. I've
723 > spent about an hour trying to find out why I couldn't log in now..
728 if (argc < 2 || argv[1][0] == '-') {
729 usage();
730 exit(1);
733 pstrcpy(service, argv[1]);
734 pstrcpy(mpoint, argv[2]);
736 /* Convert any '/' characters in the service name to
737 '\' characters */
738 string_replace(service, '/','\\');
739 argc -= 2;
740 argv += 2;
742 opt = getopt(argc, argv, "o:");
743 if(opt != 'o') {
744 return;
747 options[0] = 0;
748 p = options;
751 * option parsing from nfsmount.c (util-linux-2.9u)
753 for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) {
754 DEBUG(3, ("opts: %s\n", opts));
755 if ((opteq = strchr_m(opts, '='))) {
756 val = atoi(opteq + 1);
757 *opteq = '\0';
759 if (!strcmp(opts, "username") ||
760 !strcmp(opts, "logon")) {
761 char *lp;
762 got_user = True;
763 pstrcpy(username,opteq+1);
764 if ((lp=strchr_m(username,'%'))) {
765 *lp = 0;
766 pstrcpy(password,lp+1);
767 got_pass = True;
768 memset(strchr_m(opteq+1,'%')+1,'X',strlen(password));
770 if ((lp=strchr_m(username,'/'))) {
771 *lp = 0;
772 pstrcpy(workgroup,lp+1);
774 } else if(!strcmp(opts, "passwd") ||
775 !strcmp(opts, "password")) {
776 pstrcpy(password,opteq+1);
777 got_pass = True;
778 memset(opteq+1,'X',strlen(password));
779 } else if(!strcmp(opts, "credentials")) {
780 pstrcpy(credentials,opteq+1);
781 } else if(!strcmp(opts, "netbiosname")) {
782 pstrcpy(my_netbios_name,opteq+1);
783 } else if(!strcmp(opts, "uid")) {
784 mount_uid = nametouid(opteq+1);
785 } else if(!strcmp(opts, "gid")) {
786 mount_gid = nametogid(opteq+1);
787 } else if(!strcmp(opts, "port")) {
788 smb_port = val;
789 } else if(!strcmp(opts, "fmask")) {
790 mount_fmask = strtol(opteq+1, NULL, 8);
791 } else if(!strcmp(opts, "dmask")) {
792 mount_dmask = strtol(opteq+1, NULL, 8);
793 } else if(!strcmp(opts, "debug")) {
794 DEBUGLEVEL = val;
795 } else if(!strcmp(opts, "ip")) {
796 dest_ip = *interpret_addr2(opteq+1);
797 if (is_zero_ip(dest_ip)) {
798 fprintf(stderr,"Can't resolve address %s\n", opteq+1);
799 exit(1);
801 have_ip = True;
802 } else if(!strcmp(opts, "workgroup")) {
803 pstrcpy(workgroup,opteq+1);
804 } else if(!strcmp(opts, "sockopt")) {
805 pstrcpy(user_socket_options,opteq+1);
806 } else if(!strcmp(opts, "scope")) {
807 set_global_scope(opteq+1);
808 } else {
809 slprintf(p, sizeof(pstring) - (p - options) - 1, "%s=%s,", opts, opteq+1);
810 p += strlen(p);
812 } else {
813 val = 1;
814 if(!strcmp(opts, "nocaps")) {
815 fprintf(stderr, "Unhandled option: %s\n", opteq+1);
816 exit(1);
817 } else if(!strcmp(opts, "guest")) {
818 *password = '\0';
819 got_pass = True;
820 } else if(!strcmp(opts, "krb")) {
821 #ifdef HAVE_KRB5
823 use_kerberos = True;
824 if(!status32_smbfs)
825 fprintf(stderr, "Warning: kerberos support will only work for samba servers\n");
826 #else
827 fprintf(stderr,"No kerberos support compiled in\n");
828 exit(1);
829 #endif
830 } else if(!strcmp(opts, "rw")) {
831 mount_ro = 0;
832 } else if(!strcmp(opts, "ro")) {
833 mount_ro = 1;
834 } else if(!strcmp(opts, "unicode")) {
835 smbfs_has_unicode = True;
836 } else if(!strcmp(opts, "lfs")) {
837 smbfs_has_lfs = True;
838 } else {
839 strncpy(p, opts, sizeof(pstring) - (p - options) - 1);
840 p += strlen(opts);
841 *p++ = ',';
842 *p = 0;
847 if (!*service) {
848 usage();
849 exit(1);
852 if (p != options) {
853 *(p-1) = 0; /* remove trailing , */
854 DEBUG(3,("passthrough options '%s'\n", options));
858 /****************************************************************************
859 main program
860 ****************************************************************************/
861 int main(int argc,char *argv[])
863 extern char *optarg;
864 extern int optind;
865 char *p;
867 DEBUGLEVEL = 1;
869 /* here we are interactive, even if run from autofs */
870 setup_logging("mount.smbfs",True);
872 #if 0 /* JRA - Urban says not needed ? */
873 /* CLI_FORCE_ASCII=false makes smbmount negotiate unicode. The default
874 is to not announce any unicode capabilities as current smbfs does
875 not support it. */
876 p = getenv("CLI_FORCE_ASCII");
877 if (p && !strcmp(p, "false"))
878 unsetenv("CLI_FORCE_ASCII");
879 else
880 setenv("CLI_FORCE_ASCII", "true", 1);
881 #endif
883 in_client = True; /* Make sure that we tell lp_load we are */
885 if (getenv("USER")) {
886 pstrcpy(username,getenv("USER"));
888 if ((p=strchr_m(username,'%'))) {
889 *p = 0;
890 pstrcpy(password,p+1);
891 got_pass = True;
892 memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password));
894 strupper_m(username);
897 if (getenv("PASSWD")) {
898 pstrcpy(password,getenv("PASSWD"));
899 got_pass = True;
902 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
903 get_password_file();
904 got_pass = True;
907 if (*username == 0 && getenv("LOGNAME")) {
908 pstrcpy(username,getenv("LOGNAME"));
911 if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
912 fprintf(stderr, "Can't load %s - run testparm to debug it\n",
913 dyn_CONFIGFILE);
916 parse_mount_smb(argc, argv);
918 if (use_kerberos && !got_user) {
919 got_pass = True;
922 if (*credentials != 0) {
923 read_credentials_file(credentials);
926 DEBUG(3,("mount.smbfs started (version %s)\n", SAMBA_VERSION_STRING));
928 if (*workgroup == 0) {
929 pstrcpy(workgroup,lp_workgroup());
932 load_interfaces();
933 if (!*my_netbios_name) {
934 pstrcpy(my_netbios_name, myhostname());
936 strupper_m(my_netbios_name);
938 init_mount();
939 return 0;