Add mount.cifs as a wrapper for mount.cifs.
[Samba.git] / source / client / smbmount.c
blobee4b180a89f93bac7997a7719a6742cf7b8d431f
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 3 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, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
22 #include <mntent.h>
23 #include <asm/types.h>
24 #include <linux/smb_fs.h>
26 extern bool in_client;
27 extern char *optarg;
28 extern int optind;
30 static char *credentials;
31 static fstring my_netbios_name;
32 static char *password;
33 static char *username;
34 static fstring workgroup;
35 static char *mpoint;
36 static char *service;
37 static char *options;
39 static struct sockaddr_storage 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 sockaddr_storage ip;
125 char *server;
126 char *share;
127 const char *c_username;
128 const char *c_password;
129 TALLOC_CTX *ctx = talloc_tos();
131 if (the_service[0] != '\\' || the_service[1] != '\\') {
132 usage();
133 exit(1);
136 server = talloc_strdup(ctx, the_service+2);
137 if (!server) {
138 fprintf(stderr,"Out of memory\n");
139 exit(ENOMEM);
141 share = strchr_m(server,'\\');
142 if (!share) {
143 usage();
144 exit(1);
146 *share = 0;
147 share++;
149 server_n = server;
151 make_nmb_name(&calling, my_netbios_name, 0x0);
152 make_nmb_name(&called , server, 0x20);
154 again:
155 zero_addr(&ip);
156 if (have_ip) ip = dest_ip;
158 /* have to open a new connection */
159 if (!(c=cli_initialise()) || (cli_set_port(c, smb_port) != smb_port) ||
160 !NT_STATUS_IS_OK(cli_connect(c, server_n, &ip))) {
161 DEBUG(0,("%d: Connection to %s failed\n", sys_getpid(), server_n));
162 if (c) {
163 cli_shutdown(c);
165 return NULL;
168 /* SPNEGO doesn't work till we get NTSTATUS error support */
169 /* But it is REQUIRED for kerberos authentication */
170 if(!use_kerberos) c->use_spnego = False;
172 /* The kernel doesn't yet know how to sign it's packets */
173 c->sign_info.allow_smb_signing = False;
175 /* Use kerberos authentication if specified */
176 c->use_kerberos = use_kerberos;
178 if (!cli_session_request(c, &calling, &called)) {
179 char *p;
180 DEBUG(0,("%d: session request to %s failed (%s)\n",
181 sys_getpid(), called.name, cli_errstr(c)));
182 cli_shutdown(c);
183 if ((p=strchr_m(called.name, '.'))) {
184 *p = 0;
185 goto again;
187 if (strcmp(called.name, "*SMBSERVER")) {
188 make_nmb_name(&called , "*SMBSERVER", 0x20);
189 goto again;
191 return NULL;
194 DEBUG(4,("%d: session request ok\n", sys_getpid()));
196 if (!cli_negprot(c)) {
197 DEBUG(0,("%d: protocol negotiation failed\n", sys_getpid()));
198 cli_shutdown(c);
199 return NULL;
202 if (!got_pass) {
203 char *pass = getpass("Password: ");
204 if (pass) {
205 password = talloc_strdup(talloc_tos(), pass);
206 if (!password) {
207 return NULL;
212 /* This should be right for current smbfs. Future versions will support
213 large files as well as unicode and oplocks. */
214 c->capabilities &= ~(CAP_NT_SMBS | CAP_NT_FIND | CAP_LEVEL_II_OPLOCKS);
215 if (!smbfs_has_lfs)
216 c->capabilities &= ~CAP_LARGE_FILES;
217 if (!smbfs_has_unicode)
218 c->capabilities &= ~CAP_UNICODE;
219 if (!status32_smbfs) {
220 c->capabilities &= ~CAP_STATUS32;
221 c->force_dos_errors = True;
224 c_password = password ? password : "";
225 c_username = username ? username : "";
227 if (!NT_STATUS_IS_OK(cli_session_setup(c,
228 c_username,
229 c_password, strlen(c_password),
230 c_password, strlen(c_password),
231 workgroup))) {
232 /* if a password was not supplied then try again with a
233 null username */
234 if (c_password[0] || !c_username[0] ||
235 !NT_STATUS_IS_OK(cli_session_setup(c, "", "", 0, "", 0, workgroup))) {
236 DEBUG(0,("%d: session setup failed: %s\n",
237 sys_getpid(), cli_errstr(c)));
238 cli_shutdown(c);
239 return NULL;
241 DEBUG(0,("Anonymous login successful\n"));
244 DEBUG(4,("%d: session setup ok\n", sys_getpid()));
246 if (!cli_send_tconX(c, share, "?????",
247 c_password, strlen(c_password)+1)) {
248 DEBUG(0,("%d: tree connect failed: %s\n",
249 sys_getpid(), cli_errstr(c)));
250 cli_shutdown(c);
251 return NULL;
254 DEBUG(4,("%d: tconx ok\n", sys_getpid()));
256 got_pass = True;
258 return c;
261 /****************************************************************************
262 unmount smbfs (this is a bailout routine to clean up if a reconnect fails)
263 Code blatently stolen from smbumount.c
264 -mhw-
265 ****************************************************************************/
266 static void smb_umount(char *mount_point)
268 int fd;
269 struct mntent *mnt;
270 FILE* mtab;
271 FILE* new_mtab;
273 /* Programmers Note:
274 This routine only gets called to the scene of a disaster
275 to shoot the survivors... A connection that was working
276 has now apparently failed. We have an active mount point
277 (presumably) that we need to dump. If we get errors along
278 the way - make some noise, but we are already turning out
279 the lights to exit anyways...
281 if (umount(mount_point) != 0) {
282 DEBUG(0,("%d: Could not umount %s: %s\n",
283 sys_getpid(), mount_point, strerror(errno)));
284 return;
287 if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) {
288 DEBUG(0,("%d: Can't get "MOUNTED"~ lock file", sys_getpid()));
289 return;
292 close(fd);
294 if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
295 DEBUG(0,("%d: Can't open " MOUNTED ": %s\n",
296 sys_getpid(), strerror(errno)));
297 return;
300 #define MOUNTED_TMP MOUNTED".tmp"
302 if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) {
303 DEBUG(0,("%d: Can't open " MOUNTED_TMP ": %s\n",
304 sys_getpid(), strerror(errno)));
305 endmntent(mtab);
306 return;
309 while ((mnt = getmntent(mtab)) != NULL) {
310 if (strcmp(mnt->mnt_dir, mount_point) != 0) {
311 addmntent(new_mtab, mnt);
315 endmntent(mtab);
317 if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
318 DEBUG(0,("%d: Error changing mode of %s: %s\n",
319 sys_getpid(), MOUNTED_TMP, strerror(errno)));
320 return;
323 endmntent(new_mtab);
325 if (rename(MOUNTED_TMP, MOUNTED) < 0) {
326 DEBUG(0,("%d: Cannot rename %s to %s: %s\n",
327 sys_getpid(), MOUNTED, MOUNTED_TMP, strerror(errno)));
328 return;
331 if (unlink(MOUNTED"~") == -1) {
332 DEBUG(0,("%d: Can't remove "MOUNTED"~", sys_getpid()));
333 return;
339 * Call the smbfs ioctl to install a connection socket,
340 * then wait for a signal to reconnect. Note that we do
341 * not exit after open_sockets() or send_login() errors,
342 * as the smbfs mount would then have no way to recover.
344 static void send_fs_socket(char *the_service, char *mount_point, struct cli_state *c)
346 int fd, closed = 0, res = 1;
347 pid_t parentpid = getppid();
348 struct smb_conn_opt conn_options;
350 memset(&conn_options, 0, sizeof(conn_options));
352 while (1) {
353 if ((fd = open(mount_point, O_RDONLY)) < 0) {
354 DEBUG(0,("mount.smbfs[%d]: can't open %s\n",
355 sys_getpid(), mount_point));
356 break;
359 conn_options.fd = c->fd;
360 conn_options.protocol = c->protocol;
361 conn_options.case_handling = SMB_CASE_DEFAULT;
362 conn_options.max_xmit = c->max_xmit;
363 conn_options.server_uid = c->vuid;
364 conn_options.tid = c->cnum;
365 conn_options.secmode = c->sec_mode;
366 conn_options.rawmode = 0;
367 conn_options.sesskey = c->sesskey;
368 conn_options.maxraw = 0;
369 conn_options.capabilities = c->capabilities;
370 conn_options.serverzone = c->serverzone/60;
372 res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options);
373 if (res != 0) {
374 DEBUG(0,("mount.smbfs[%d]: ioctl failed, res=%d\n",
375 sys_getpid(), res));
376 close(fd);
377 break;
380 if (parentpid) {
381 /* Ok... We are going to kill the parent. Now
382 is the time to break the process group... */
383 setsid();
384 /* Send a signal to the parent to terminate */
385 kill(parentpid, SIGTERM);
386 parentpid = 0;
389 close(fd);
391 /* This looks wierd but we are only closing the userspace
392 side, the connection has already been passed to smbfs and
393 it has increased the usage count on the socket.
395 If we don't do this we will "leak" sockets and memory on
396 each reconnection we have to make. */
397 c->smb_rw_error = SMB_DO_NOT_DO_TDIS;
398 cli_shutdown(c);
399 c = NULL;
401 if (!closed) {
402 /* close the name cache so that close_our_files() doesn't steal its FD */
403 namecache_shutdown();
405 /* redirect stdout & stderr since we can't know that
406 the library functions we use are using DEBUG. */
407 if ( (fd = open("/dev/null", O_WRONLY)) < 0)
408 DEBUG(2,("mount.smbfs: can't open /dev/null\n"));
409 close_our_files(fd);
410 if (fd >= 0) {
411 dup2(fd, STDOUT_FILENO);
412 dup2(fd, STDERR_FILENO);
413 close(fd);
416 /* here we are no longer interactive */
417 set_remote_machine_name("smbmount", False); /* sneaky ... */
418 setup_logging("mount.smbfs", False);
419 reopen_logs();
420 DEBUG(0, ("mount.smbfs: entering daemon mode for service %s, pid=%d\n", the_service, sys_getpid()));
422 closed = 1;
425 /* Wait for a signal from smbfs ... but don't continue
426 until we actually get a new connection. */
427 while (!c) {
428 CatchSignal(SIGUSR1, &usr1_handler);
429 pause();
430 DEBUG(2,("mount.smbfs[%d]: got signal, getting new socket\n", sys_getpid()));
431 c = do_connection(the_service);
435 smb_umount(mount_point);
436 DEBUG(2,("mount.smbfs[%d]: exit\n", sys_getpid()));
437 exit(1);
442 * Mount a smbfs
445 #define NUM_ARGS 20
447 static void init_mount(void)
449 char mount_point[PATH_MAX+1];
450 TALLOC_CTX *ctx = talloc_tos();
451 char *svc2;
452 struct cli_state *c;
453 const char *args[NUM_ARGS];
454 int i, status;
456 if (realpath(mpoint, mount_point) == NULL) {
457 fprintf(stderr, "Could not resolve mount point %s\n", mpoint);
458 return;
462 c = do_connection(service);
463 if (!c) {
464 fprintf(stderr,"SMB connection failed\n");
465 exit(1);
469 Set up to return as a daemon child and wait in the parent
470 until the child say it's ready...
472 daemonize();
474 svc2 = talloc_strdup(ctx, service);
475 if (!svc2) {
476 fprintf(stderr, "Out of memory.\n");
477 exit(ENOMEM);
479 string_replace(svc2, '\\','/');
480 string_replace(svc2, ' ','_');
482 memset(args, 0, sizeof(args[0])*NUM_ARGS);
484 i=0;
485 args[i++] = "smbmnt";
487 args[i++] = mount_point;
488 args[i++] = "-s";
489 args[i++] = svc2;
491 if (mount_ro && i < NUM_ARGS-2) {
492 args[i++] = "-r";
494 if (mount_uid && i < NUM_ARGS-3) {
495 args[i++] = "-u";
496 args[i] = talloc_asprintf(ctx, "%d", mount_uid);
497 if (!args[i]) {
498 fprintf(stderr, "Out of memory.\n");
499 exit(ENOMEM);
501 i++;
503 if (mount_gid && i < NUM_ARGS-3) {
504 args[i++] = "-g";
505 args[i] = talloc_asprintf(ctx, "%d", mount_gid);
506 if (!args[i]) {
507 fprintf(stderr, "Out of memory.\n");
508 exit(ENOMEM);
510 i++;
512 if (mount_fmask && i < NUM_ARGS-3) {
513 args[i++] = "-f";
514 args[i] = talloc_asprintf(ctx, "0%o", mount_fmask);
515 if (!args[i]) {
516 fprintf(stderr, "Out of memory.\n");
517 exit(ENOMEM);
519 i++;
521 if (mount_dmask && i < NUM_ARGS-3) {
522 args[i++] = "-d";
523 args[i] = talloc_asprintf(ctx, "0%o", mount_dmask);
524 if (!args[i]) {
525 fprintf(stderr, "Out of memory.\n");
526 exit(ENOMEM);
528 i++;
530 if (options && i < NUM_ARGS-3) {
531 args[i++] = "-o";
532 args[i++] = options;
535 if (sys_fork() == 0) {
536 char *smbmnt_path;
538 asprintf(&smbmnt_path, "%s/smbmnt", get_dyn_BINDIR());
540 if (file_exist(smbmnt_path, NULL)) {
541 execv(smbmnt_path, (char * const *)args);
542 fprintf(stderr,
543 "smbfs/init_mount: execv of %s failed. Error was %s.",
544 smbmnt_path, strerror(errno));
545 } else {
546 execvp("smbmnt", (char * const *)args);
547 fprintf(stderr,
548 "smbfs/init_mount: execv of %s failed. Error was %s.",
549 "smbmnt", strerror(errno));
551 free(smbmnt_path);
552 exit(1);
555 if (waitpid(-1, &status, 0) == -1) {
556 fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) );
557 /* FIXME: do some proper error handling */
558 exit(1);
561 if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
562 fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status));
563 /* FIXME: do some proper error handling */
564 exit(1);
565 } else if (WIFSIGNALED(status)) {
566 fprintf(stderr, "smbmnt killed by signal %d\n", WTERMSIG(status));
567 exit(1);
570 /* Ok... This is the rubicon for that mount point... At any point
571 after this, if the connections fail and can not be reconstructed
572 for any reason, we will have to unmount the mount point. There
573 is no exit from the next call...
575 send_fs_socket(service, mount_point, c);
579 /****************************************************************************
580 get a password from a a file or file descriptor
581 exit on failure (from smbclient, move to libsmb or shared .c file?)
582 ****************************************************************************/
584 static void get_password_file(void)
586 int fd = -1;
587 char *p;
588 bool close_it = False;
589 char *spec = NULL;
590 TALLOC_CTX *ctx = talloc_tos();
591 char pass[128];
593 if ((p = getenv("PASSWD_FD")) != NULL) {
594 spec = talloc_asprintf(ctx,
595 "descriptor %s",
597 if (!spec) {
598 fprintf(stderr, "Out of memory.\n");
599 exit(ENOMEM);
601 fd = atoi(p);
602 close_it = False;
603 } else if ((p = getenv("PASSWD_FILE")) != NULL) {
604 fd = sys_open(p, O_RDONLY, 0);
605 spec = talloc_strdup(ctx, p);
606 if (!spec) {
607 fprintf(stderr, "Out of memory.\n");
608 exit(ENOMEM);
610 if (fd < 0) {
611 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
612 spec, strerror(errno));
613 exit(1);
615 close_it = True;
618 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
619 p && p - pass < sizeof(pass);) {
620 switch (read(fd, p, 1)) {
621 case 1:
622 if (*p != '\n' && *p != '\0') {
623 *++p = '\0'; /* advance p, and null-terminate pass */
624 break;
626 case 0:
627 if (p - pass) {
628 *p = '\0'; /* null-terminate it, just in case... */
629 p = NULL; /* then force the loop condition to become false */
630 break;
631 } else {
632 fprintf(stderr, "Error reading password from file %s: %s\n",
633 spec, "empty password\n");
634 exit(1);
637 default:
638 fprintf(stderr, "Error reading password from file %s: %s\n",
639 spec, strerror(errno));
640 exit(1);
643 password = talloc_strdup(ctx, pass);
644 if (close_it)
645 close(fd);
648 /****************************************************************************
649 get username and password from a credentials file
650 exit on failure (from smbclient, move to libsmb or shared .c file?)
651 ****************************************************************************/
653 static void read_credentials_file(const char *filename)
655 FILE *auth;
656 fstring buf;
657 uint16 len = 0;
658 char *ptr, *val, *param;
660 if ((auth=sys_fopen(filename, "r")) == NULL)
662 /* fail if we can't open the credentials file */
663 DEBUG(0,("ERROR: Unable to open credentials file!\n"));
664 exit (-1);
667 while (!feof(auth))
669 /* get a line from the file */
670 if (!fgets (buf, sizeof(buf), auth))
671 continue;
672 len = strlen(buf);
674 if ((len) && (buf[len-1]=='\n'))
676 buf[len-1] = '\0';
677 len--;
679 if (len == 0)
680 continue;
682 /* break up the line into parameter & value.
683 will need to eat a little whitespace possibly */
684 param = buf;
685 if (!(ptr = strchr (buf, '=')))
686 continue;
687 val = ptr+1;
688 *ptr = '\0';
690 /* eat leading white space */
691 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
692 val++;
694 if (strwicmp("password", param) == 0)
696 password = talloc_strdup(talloc_tos(),val);
697 got_pass = True;
699 else if (strwicmp("username", param) == 0) {
700 username = talloc_strdup(talloc_tos(), val);
703 memset(buf, 0, sizeof(buf));
705 fclose(auth);
709 /****************************************************************************
710 usage on the program
711 ****************************************************************************/
712 static void usage(void)
714 printf("Usage: mount.smbfs service mountpoint [-o options,...]\n");
716 printf("Version %s\n\n",SAMBA_VERSION_STRING);
718 printf("Please be aware that smbfs is deprecated in favor of "
719 "cifs\n\n");
721 printf(
722 "Options:\n\
723 username=<arg> SMB username\n\
724 password=<arg> SMB password\n\
725 credentials=<filename> file with username/password\n\
726 krb use kerberos (active directory)\n\
727 netbiosname=<arg> source NetBIOS name\n\
728 uid=<arg> mount uid or username\n\
729 gid=<arg> mount gid or groupname\n\
730 port=<arg> remote SMB port number\n\
731 fmask=<arg> file umask\n\
732 dmask=<arg> directory umask\n\
733 debug=<arg> debug level\n\
734 ip=<arg> destination host or IP address\n\
735 workgroup=<arg> workgroup on destination\n\
736 sockopt=<arg> TCP socket options\n\
737 scope=<arg> NetBIOS scope\n\
738 iocharset=<arg> Linux charset (iso8859-1, utf8)\n\
739 codepage=<arg> server codepage (cp850)\n\
740 unicode use unicode when communicating with server\n\
741 lfs large file system support\n\
742 ttl=<arg> dircache time to live\n\
743 guest don't prompt for a password\n\
744 ro mount read-only\n\
745 rw mount read-write\n\
747 This command is designed to be run from within /bin/mount by giving\n\
748 the option '-t smbfs'. For example:\n\
749 mount -t smbfs -o username=tridge,password=foobar //fjall/test /data/test\n\
754 /****************************************************************************
755 Argument parsing for mount.smbfs interface
756 mount will call us like this:
757 mount.smbfs device mountpoint -o <options>
759 <options> is never empty, containing at least rw or ro
760 ****************************************************************************/
761 static void parse_mount_smb(int argc, char **argv)
763 int opt;
764 char *opts;
765 char *opteq;
766 int val;
767 char *saveptr = NULL;
768 TALLOC_CTX *ctx = talloc_tos();
770 /* FIXME: This function can silently fail if the arguments are
771 * not in the expected order.
773 > The arguments syntax of smbmount 2.2.3a (smbfs of Debian stable)
774 > requires that one gives "-o" before further options like username=...
775 > . Without -o, the username=.. setting is *silently* ignored. I've
776 > spent about an hour trying to find out why I couldn't log in now..
781 if (argc < 2 || argv[1][0] == '-') {
782 usage();
783 exit(1);
786 service = talloc_strdup(ctx, argv[1]);
787 if (!service) {
788 fprintf(stderr,"Out of memory\n");
789 exit(ENOMEM);
791 mpoint = talloc_strdup(ctx, argv[2]);
792 if (!mpoint) {
793 fprintf(stderr,"Out of memory\n");
794 exit(ENOMEM);
797 /* Convert any '/' characters in the service name to
798 '\' characters */
799 string_replace(service, '/','\\');
800 argc -= 2;
801 argv += 2;
803 opt = getopt(argc, argv, "o:");
804 if(opt != 'o') {
805 return;
808 options = talloc_strdup(ctx, "");
809 if (!options) {
810 fprintf(stderr,"Out of memory\n");
811 exit(ENOMEM);
815 * option parsing from nfsmount.c (util-linux-2.9u)
817 for (opts = strtok_r(optarg, ",", &saveptr); opts;
818 opts = strtok_r(NULL, ",", &saveptr)) {
819 DEBUG(3, ("opts: %s\n", opts));
820 if ((opteq = strchr_m(opts, '='))) {
821 val = atoi(opteq + 1);
822 *opteq = '\0';
824 if (!strcmp(opts, "username") ||
825 !strcmp(opts, "logon")) {
826 char *lp;
827 got_user = True;
828 username = talloc_strdup(ctx, opteq+1);
829 if (!username) {
830 fprintf(stderr,"Out of memory\n");
831 exit(ENOMEM);
833 if ((lp=strchr_m(username,'%'))) {
834 *lp = 0;
835 password = talloc_strdup(ctx, lp+1);
836 if (!password) {
837 fprintf(stderr,"Out of memory\n");
838 exit(ENOMEM);
840 got_pass = True;
841 memset(strchr_m(opteq+1,'%')+1,'X',strlen(password));
843 if ((lp=strchr_m(username,'/'))) {
844 *lp = 0;
845 fstrcpy(workgroup,lp+1);
847 } else if(!strcmp(opts, "passwd") ||
848 !strcmp(opts, "password")) {
849 password = talloc_strdup(ctx,opteq+1);
850 if (!password) {
851 fprintf(stderr,"Out of memory\n");
852 exit(ENOMEM);
854 got_pass = True;
855 memset(opteq+1,'X',strlen(password));
856 } else if(!strcmp(opts, "credentials")) {
857 credentials = talloc_strdup(ctx,opteq+1);
858 if (!credentials) {
859 fprintf(stderr,"Out of memory\n");
860 exit(ENOMEM);
862 } else if(!strcmp(opts, "netbiosname")) {
863 fstrcpy(my_netbios_name,opteq+1);
864 } else if(!strcmp(opts, "uid")) {
865 mount_uid = nametouid(opteq+1);
866 } else if(!strcmp(opts, "gid")) {
867 mount_gid = nametogid(opteq+1);
868 } else if(!strcmp(opts, "port")) {
869 smb_port = val;
870 } else if(!strcmp(opts, "fmask")) {
871 mount_fmask = strtol(opteq+1, NULL, 8);
872 } else if(!strcmp(opts, "dmask")) {
873 mount_dmask = strtol(opteq+1, NULL, 8);
874 } else if(!strcmp(opts, "debug")) {
875 DEBUGLEVEL = val;
876 } else if(!strcmp(opts, "ip")) {
877 if (!interpret_string_addr(&dest_ip, opteq+1,
878 0)) {
879 fprintf(stderr,"Can't resolve address %s\n", opteq+1);
880 exit(1);
882 have_ip = True;
883 } else if(!strcmp(opts, "workgroup")) {
884 fstrcpy(workgroup,opteq+1);
885 } else if(!strcmp(opts, "sockopt")) {
886 lp_do_parameter(-1, "socket options", opteq+1);
887 } else if(!strcmp(opts, "scope")) {
888 set_global_scope(opteq+1);
889 } else {
890 options = talloc_asprintf_append(options,
891 "%s=%s,",
892 opts, opteq+1);
893 if (!options) {
894 fprintf(stderr,"Out of memory\n");
895 exit(ENOMEM);
898 } else {
899 val = 1;
900 if(!strcmp(opts, "nocaps")) {
901 fprintf(stderr, "Unhandled option: %s\n", opteq+1);
902 exit(1);
903 } else if(!strcmp(opts, "guest")) {
904 password = talloc_strdup(talloc_tos(), "");
905 if (!password) {
906 fprintf(stderr,"Out of memory\n");
907 exit(ENOMEM);
909 got_pass = True;
910 } else if(!strcmp(opts, "krb")) {
911 #ifdef HAVE_KRB5
913 use_kerberos = True;
914 if(!status32_smbfs)
915 fprintf(stderr, "Warning: kerberos support will only work for samba servers\n");
916 #else
917 fprintf(stderr,"No kerberos support compiled in\n");
918 exit(1);
919 #endif
920 } else if(!strcmp(opts, "rw")) {
921 mount_ro = 0;
922 } else if(!strcmp(opts, "ro")) {
923 mount_ro = 1;
924 } else if(!strcmp(opts, "unicode")) {
925 smbfs_has_unicode = True;
926 } else if(!strcmp(opts, "lfs")) {
927 smbfs_has_lfs = True;
928 } else {
929 options = talloc_asprintf_append(options,
930 "%s,",
931 opts);
932 if (!options) {
933 fprintf(stderr,"Out of memory\n");
934 exit(ENOMEM);
940 if (!service || !*service) {
941 usage();
942 exit(1);
945 if (options && *options && options[strlen(options)-1] == ',') {
946 options[strlen(options)-1] = '\0'; /* remove trailing , */
947 DEBUG(3,("passthrough options '%s'\n", options));
951 /****************************************************************************
952 main program
953 ****************************************************************************/
954 int main(int argc,char *argv[])
956 TALLOC_CTX *frame = talloc_stackframe();
957 char *p;
959 DEBUGLEVEL = 1;
961 load_case_tables();
963 /* here we are interactive, even if run from autofs */
964 setup_logging("mount.smbfs",True);
966 #if 0 /* JRA - Urban says not needed ? */
967 /* CLI_FORCE_ASCII=false makes smbmount negotiate unicode. The default
968 is to not announce any unicode capabilities as current smbfs does
969 not support it. */
970 p = getenv("CLI_FORCE_ASCII");
971 if (p && !strcmp(p, "false"))
972 unsetenv("CLI_FORCE_ASCII");
973 else
974 setenv("CLI_FORCE_ASCII", "true", 1);
975 #endif
977 in_client = True; /* Make sure that we tell lp_load we are */
979 if (getenv("USER")) {
980 username = talloc_strdup(frame, getenv("USER"));
981 if (!username) {
982 exit(ENOMEM);
985 if ((p=strchr_m(username,'%'))) {
986 *p = 0;
987 password = talloc_strdup(frame, p+1);
988 if (!password) {
989 exit(ENOMEM);
991 got_pass = True;
992 memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password));
994 strupper_m(username);
997 if (getenv("PASSWD")) {
998 password = talloc_strdup(frame, getenv("PASSWD"));
999 if (!password) {
1000 exit(ENOMEM);
1002 got_pass = True;
1005 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
1006 get_password_file();
1007 got_pass = True;
1010 if ((!username || *username == 0) && getenv("LOGNAME")) {
1011 username = talloc_strdup(frame, getenv("LOGNAME"));
1012 if (!username) {
1013 exit(ENOMEM);
1017 if (!lp_load(get_dyn_CONFIGFILE(),True,False,False,True)) {
1018 fprintf(stderr, "Can't load %s - run testparm to debug it\n",
1019 get_dyn_CONFIGFILE());
1022 parse_mount_smb(argc, argv);
1024 if (use_kerberos && !got_user) {
1025 got_pass = True;
1028 if (credentials && *credentials != 0) {
1029 read_credentials_file(credentials);
1032 DEBUG(3,("mount.smbfs started (version %s)\n", SAMBA_VERSION_STRING));
1034 if (*workgroup == 0) {
1035 fstrcpy(workgroup,lp_workgroup());
1038 load_interfaces();
1039 if (!*my_netbios_name) {
1040 fstrcpy(my_netbios_name, myhostname());
1042 strupper_m(my_netbios_name);
1044 init_mount();
1045 TALLOC_FREE(frame);
1046 return 0;