Pass struct smb_request to file_new
[Samba/gebeck_regimport.git] / source4 / client / smbmount.c
blob37c9eaadc47b3c2f541a46e6c614ba5ed02e1577
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"
21 #include "system/passwd.h"
23 #include <mntent.h>
24 #include <asm/types.h>
25 #include <linux/smb_fs.h>
27 static pstring credentials;
28 static pstring my_netbios_name;
29 static pstring password;
30 static pstring username;
31 static pstring workgroup;
32 static pstring mpoint;
33 static pstring service;
34 static pstring options;
36 static struct in_addr dest_ip;
37 static bool have_ip;
38 static int smb_port = 0;
39 static bool got_user;
40 static bool got_pass;
41 static uid_t mount_uid;
42 static gid_t mount_gid;
43 static int mount_ro;
44 static uint_t mount_fmask;
45 static uint_t mount_dmask;
46 static bool use_kerberos;
47 /* TODO: Add code to detect smbfs version in kernel */
48 static bool status32_smbfs = false;
50 static void usage(void);
52 static void exit_parent(int sig)
54 /* parent simply exits when child says go... */
55 exit(0);
58 static void daemonize(void)
60 int j, status;
61 pid_t child_pid;
63 signal( SIGTERM, exit_parent );
65 if ((child_pid = sys_fork()) < 0) {
66 DEBUG(0,("could not fork\n"));
69 if (child_pid > 0) {
70 while( 1 ) {
71 j = waitpid( child_pid, &status, 0 );
72 if( j < 0 ) {
73 if( EINTR == errno ) {
74 continue;
76 status = errno;
78 break;
81 /* If we get here - the child exited with some error status */
82 if (WIFSIGNALED(status))
83 exit(128 + WTERMSIG(status));
84 else
85 exit(WEXITSTATUS(status));
88 signal( SIGTERM, SIG_DFL );
89 chdir("/");
92 static void close_our_files(int client_fd)
94 int i;
95 struct rlimit limits;
97 getrlimit(RLIMIT_NOFILE,&limits);
98 for (i = 0; i< limits.rlim_max; i++) {
99 if (i == client_fd)
100 continue;
101 close(i);
105 static void usr1_handler(int x)
107 return;
111 /*****************************************************
112 return a connection to a server
113 *******************************************************/
114 static struct smbcli_state *do_connection(const char *the_service, bool unicode, int maxprotocol,
115 struct smbcli_session_options session_options)
117 struct smbcli_state *c;
118 struct nmb_name called, calling;
119 char *server_n;
120 struct in_addr ip;
121 pstring server;
122 char *share;
124 if (the_service[0] != '\\' || the_service[1] != '\\') {
125 usage();
126 exit(1);
129 pstrcpy(server, the_service+2);
130 share = strchr_m(server,'\\');
131 if (!share) {
132 usage();
133 exit(1);
135 *share = 0;
136 share++;
138 server_n = server;
140 make_nmb_name(&calling, my_netbios_name, 0x0);
141 choose_called_name(&called, server, 0x20);
143 again:
144 zero_ip(&ip);
145 if (have_ip) ip = dest_ip;
147 /* have to open a new connection */
148 if (!(c=smbcli_initialise(NULL)) || (smbcli_set_port(c, smb_port) != smb_port) ||
149 !smbcli_connect(c, server_n, &ip)) {
150 DEBUG(0,("%d: Connection to %s failed\n", sys_getpid(), server_n));
151 if (c) {
152 talloc_free(c);
154 return NULL;
157 /* SPNEGO doesn't work till we get NTSTATUS error support */
158 /* But it is REQUIRED for kerberos authentication */
159 if(!use_kerberos) c->use_spnego = false;
161 /* The kernel doesn't yet know how to sign it's packets */
162 c->sign_info.allow_smb_signing = false;
164 /* Use kerberos authentication if specified */
165 c->use_kerberos = use_kerberos;
167 if (!smbcli_session_request(c, &calling, &called)) {
168 char *p;
169 DEBUG(0,("%d: session request to %s failed (%s)\n",
170 sys_getpid(), called.name, smbcli_errstr(c)));
171 talloc_free(c);
172 if ((p=strchr_m(called.name, '.'))) {
173 *p = 0;
174 goto again;
176 if (strcmp(called.name, "*SMBSERVER")) {
177 make_nmb_name(&called , "*SMBSERVER", 0x20);
178 goto again;
180 return NULL;
183 DEBUG(4,("%d: session request ok\n", sys_getpid()));
185 if (!smbcli_negprot(c, unicode, maxprotocol)) {
186 DEBUG(0,("%d: protocol negotiation failed\n", sys_getpid()));
187 talloc_free(c);
188 return NULL;
191 if (!got_pass) {
192 char *pass = getpass("Password: ");
193 if (pass) {
194 pstrcpy(password, pass);
198 /* This should be right for current smbfs. Future versions will support
199 large files as well as unicode and oplocks. */
200 if (status32_smbfs) {
201 c->capabilities &= ~(CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS |
202 CAP_NT_FIND | CAP_LEVEL_II_OPLOCKS);
204 else {
205 c->capabilities &= ~(CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS |
206 CAP_NT_FIND | CAP_STATUS32 |
207 CAP_LEVEL_II_OPLOCKS);
208 c->force_dos_errors = true;
211 if (!smbcli_session_setup(c, username,
212 password, strlen(password),
213 password, strlen(password),
214 workgroup, session_options)) {
215 /* if a password was not supplied then try again with a
216 null username */
217 if (password[0] || !username[0] ||
218 !smbcli_session_setup(c, "", "", 0, "", 0, workgroup,
219 session_options)) {
220 DEBUG(0,("%d: session setup failed: %s\n",
221 sys_getpid(), smbcli_errstr(c)));
222 talloc_free(c);
223 return NULL;
225 DEBUG(0,("Anonymous login successful\n"));
228 DEBUG(4,("%d: session setup ok\n", sys_getpid()));
230 if (!smbcli_tconX(c, share, "?????", password, strlen(password)+1)) {
231 DEBUG(0,("%d: tree connect failed: %s\n",
232 sys_getpid(), smbcli_errstr(c)));
233 talloc_free(c);
234 return NULL;
237 DEBUG(4,("%d: tconx ok\n", sys_getpid()));
239 got_pass = true;
241 return c;
245 /****************************************************************************
246 unmount smbfs (this is a bailout routine to clean up if a reconnect fails)
247 Code blatently stolen from smbumount.c
248 -mhw-
249 ****************************************************************************/
250 static void smb_umount(const char *mount_point)
252 int fd;
253 struct mntent *mnt;
254 FILE* mtab;
255 FILE* new_mtab;
257 /* Programmers Note:
258 This routine only gets called to the scene of a disaster
259 to shoot the survivors... A connection that was working
260 has now apparently failed. We have an active mount point
261 (presumably) that we need to dump. If we get errors along
262 the way - make some noise, but we are already turning out
263 the lights to exit anyways...
265 if (umount(mount_point) != 0) {
266 DEBUG(0,("%d: Could not umount %s: %s\n",
267 sys_getpid(), mount_point, strerror(errno)));
268 return;
271 if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) {
272 DEBUG(0,("%d: Can't get "MOUNTED"~ lock file", sys_getpid()));
273 return;
276 close(fd);
278 if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
279 DEBUG(0,("%d: Can't open " MOUNTED ": %s\n",
280 sys_getpid(), strerror(errno)));
281 return;
284 #define MOUNTED_TMP MOUNTED".tmp"
286 if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) {
287 DEBUG(0,("%d: Can't open " MOUNTED_TMP ": %s\n",
288 sys_getpid(), strerror(errno)));
289 endmntent(mtab);
290 return;
293 while ((mnt = getmntent(mtab)) != NULL) {
294 if (strcmp(mnt->mnt_dir, mount_point) != 0) {
295 addmntent(new_mtab, mnt);
299 endmntent(mtab);
301 if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
302 DEBUG(0,("%d: Error changing mode of %s: %s\n",
303 sys_getpid(), MOUNTED_TMP, strerror(errno)));
304 return;
307 endmntent(new_mtab);
309 if (rename(MOUNTED_TMP, MOUNTED) < 0) {
310 DEBUG(0,("%d: Cannot rename %s to %s: %s\n",
311 sys_getpid(), MOUNTED, MOUNTED_TMP, strerror(errno)));
312 return;
315 if (unlink(MOUNTED"~") == -1) {
316 DEBUG(0,("%d: Can't remove "MOUNTED"~", sys_getpid()));
317 return;
323 * Call the smbfs ioctl to install a connection socket,
324 * then wait for a signal to reconnect. Note that we do
325 * not exit after open_sockets() or send_login() errors,
326 * as the smbfs mount would then have no way to recover.
328 static void send_fs_socket(struct loadparm_context *lp_ctx,
329 const char *the_service, const char *mount_point, struct smbcli_state *c)
331 int fd, closed = 0, res = 1;
332 pid_t parentpid = getppid();
333 struct smb_conn_opt conn_options;
334 struct smbcli_session_options session_options;
336 lp_smbcli_session_options(lp_ctx, &session_options);
338 memset(&conn_options, 0, sizeof(conn_options));
340 while (1) {
341 if ((fd = open(mount_point, O_RDONLY)) < 0) {
342 DEBUG(0,("mount.smbfs[%d]: can't open %s\n",
343 sys_getpid(), mount_point));
344 break;
347 conn_options.fd = c->fd;
348 conn_options.protocol = c->protocol;
349 conn_options.case_handling = SMB_CASE_DEFAULT;
350 conn_options.max_xmit = c->max_xmit;
351 conn_options.server_uid = c->vuid;
352 conn_options.tid = c->cnum;
353 conn_options.secmode = c->sec_mode;
354 conn_options.rawmode = 0;
355 conn_options.sesskey = c->sesskey;
356 conn_options.maxraw = 0;
357 conn_options.capabilities = c->capabilities;
358 conn_options.serverzone = c->serverzone/60;
360 res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options);
361 if (res != 0) {
362 DEBUG(0,("mount.smbfs[%d]: ioctl failed, res=%d\n",
363 sys_getpid(), res));
364 close(fd);
365 break;
368 if (parentpid) {
369 /* Ok... We are going to kill the parent. Now
370 is the time to break the process group... */
371 setsid();
372 /* Send a signal to the parent to terminate */
373 kill(parentpid, SIGTERM);
374 parentpid = 0;
377 close(fd);
379 /* This looks wierd but we are only closing the userspace
380 side, the connection has already been passed to smbfs and
381 it has increased the usage count on the socket.
383 If we don't do this we will "leak" sockets and memory on
384 each reconnection we have to make. */
385 talloc_free(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"); /* sneaky ... */
402 setup_logging("mount.smbfs", DEBUG_STDERR);
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,
416 lp_unicode(lp_ctx),
417 lp_cli_maxprotocol(lp_ctx),
418 session_options);
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(struct loadparm_context *lp_ctx)
433 char mount_point[MAXPATHLEN+1];
434 pstring tmp;
435 pstring svc2;
436 struct smbcli_state *c;
437 char *args[20];
438 int i, status;
439 struct smbcli_session_options session_options;
441 if (realpath(mpoint, mount_point) == NULL) {
442 fprintf(stderr, "Could not resolve mount point %s\n", mpoint);
443 return;
446 lp_smbcli_session_options(lp_ctx, &session_options);
448 c = do_connection(service, lp_unicode(lp_ctx), lp_cli_maxprotocol(lp_ctx),
449 session_options);
450 if (!c) {
451 fprintf(stderr,"SMB connection failed\n");
452 exit(1);
456 Set up to return as a daemon child and wait in the parent
457 until the child say it's ready...
459 daemonize();
461 pstrcpy(svc2, service);
462 string_replace(svc2, '\\','/');
463 string_replace(svc2, ' ','_');
465 memset(args, 0, sizeof(args[0])*20);
467 i=0;
468 args[i++] = "smbmnt";
470 args[i++] = mount_point;
471 args[i++] = "-s";
472 args[i++] = svc2;
474 if (mount_ro) {
475 args[i++] = "-r";
477 if (mount_uid) {
478 slprintf(tmp, sizeof(tmp)-1, "%d", mount_uid);
479 args[i++] = "-u";
480 args[i++] = smb_xstrdup(tmp);
482 if (mount_gid) {
483 slprintf(tmp, sizeof(tmp)-1, "%d", mount_gid);
484 args[i++] = "-g";
485 args[i++] = smb_xstrdup(tmp);
487 if (mount_fmask) {
488 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_fmask);
489 args[i++] = "-f";
490 args[i++] = smb_xstrdup(tmp);
492 if (mount_dmask) {
493 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_dmask);
494 args[i++] = "-d";
495 args[i++] = smb_xstrdup(tmp);
497 if (options) {
498 args[i++] = "-o";
499 args[i++] = options;
502 if (sys_fork() == 0) {
503 char *smbmnt_path;
505 asprintf(&smbmnt_path, "%s/smbmnt", dyn_BINDIR);
507 if (file_exist(smbmnt_path)) {
508 execv(smbmnt_path, args);
509 fprintf(stderr,
510 "smbfs/init_mount: execv of %s failed. Error was %s.",
511 smbmnt_path, strerror(errno));
512 } else {
513 execvp("smbmnt", args);
514 fprintf(stderr,
515 "smbfs/init_mount: execv of %s failed. Error was %s.",
516 "smbmnt", strerror(errno));
518 free(smbmnt_path);
519 exit(1);
522 if (waitpid(-1, &status, 0) == -1) {
523 fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) );
524 /* FIXME: do some proper error handling */
525 exit(1);
528 if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
529 fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status));
530 /* FIXME: do some proper error handling */
531 exit(1);
532 } else if (WIFSIGNALED(status)) {
533 fprintf(stderr, "smbmnt killed by signal %d\n", WTERMSIG(status));
534 exit(1);
537 /* Ok... This is the rubicon for that mount point... At any point
538 after this, if the connections fail and can not be reconstructed
539 for any reason, we will have to unmount the mount point. There
540 is no exit from the next call...
542 send_fs_socket(lp_ctx, service, mount_point, c);
546 /****************************************************************************
547 get a password from a a file or file descriptor
548 exit on failure (from smbclient, move to libsmb or shared .c file?)
549 ****************************************************************************/
550 static void get_password_file(void)
552 int fd = -1;
553 char *p;
554 bool close_it = false;
555 pstring spec;
556 char pass[128];
558 if ((p = getenv("PASSWD_FD")) != NULL) {
559 pstrcpy(spec, "descriptor ");
560 pstrcat(spec, p);
561 sscanf(p, "%d", &fd);
562 close_it = false;
563 } else if ((p = getenv("PASSWD_FILE")) != NULL) {
564 fd = open(p, O_RDONLY, 0);
565 pstrcpy(spec, p);
566 if (fd < 0) {
567 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
568 spec, strerror(errno));
569 exit(1);
571 close_it = true;
574 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
575 p && p - pass < sizeof(pass);) {
576 switch (read(fd, p, 1)) {
577 case 1:
578 if (*p != '\n' && *p != '\0') {
579 *++p = '\0'; /* advance p, and null-terminate pass */
580 break;
582 case 0:
583 if (p - pass) {
584 *p = '\0'; /* null-terminate it, just in case... */
585 p = NULL; /* then force the loop condition to become false */
586 break;
587 } else {
588 fprintf(stderr, "Error reading password from file %s: %s\n",
589 spec, "empty password\n");
590 exit(1);
593 default:
594 fprintf(stderr, "Error reading password from file %s: %s\n",
595 spec, strerror(errno));
596 exit(1);
599 pstrcpy(password, pass);
600 if (close_it)
601 close(fd);
604 /****************************************************************************
605 get username and password from a credentials file
606 exit on failure (from smbclient, move to libsmb or shared .c file?)
607 ****************************************************************************/
608 static void read_credentials_file(char *filename)
610 FILE *auth;
611 fstring buf;
612 uint16_t len = 0;
613 char *ptr, *val, *param;
615 if ((auth=sys_fopen(filename, "r")) == NULL)
617 /* fail if we can't open the credentials file */
618 DEBUG(0,("ERROR: Unable to open credentials file!\n"));
619 exit (-1);
622 while (!feof(auth))
624 /* get a line from the file */
625 if (!fgets (buf, sizeof(buf), auth))
626 continue;
627 len = strlen(buf);
629 if ((len) && (buf[len-1]=='\n'))
631 buf[len-1] = '\0';
632 len--;
634 if (len == 0)
635 continue;
637 /* break up the line into parameter & value.
638 will need to eat a little whitespace possibly */
639 param = buf;
640 if (!(ptr = strchr (buf, '=')))
641 continue;
642 val = ptr+1;
643 *ptr = '\0';
645 /* eat leading white space */
646 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
647 val++;
649 if (strwicmp("password", param) == 0)
651 pstrcpy(password, val);
652 got_pass = true;
654 else if (strwicmp("username", param) == 0) {
655 pstrcpy(username, val);
658 memset(buf, 0, sizeof(buf));
660 fclose(auth);
664 /****************************************************************************
665 usage on the program
666 ****************************************************************************/
667 static void usage(void)
669 printf("Usage: mount.smbfs service mountpoint [-o options,...]\n");
671 printf("Version %s\n\n",VERSION);
673 printf(
674 "Options:\n\
675 username=<arg> SMB username\n\
676 password=<arg> SMB password\n\
677 credentials=<filename> file with username/password\n\
678 krb use kerberos (active directory)\n\
679 netbiosname=<arg> source NetBIOS name\n\
680 uid=<arg> mount uid or username\n\
681 gid=<arg> mount gid or groupname\n\
682 port=<arg> remote SMB port number\n\
683 fmask=<arg> file umask\n\
684 dmask=<arg> directory umask\n\
685 debug=<arg> debug level\n\
686 ip=<arg> destination host or IP address\n\
687 workgroup=<arg> workgroup on destination\n\
688 sockopt=<arg> TCP socket options\n\
689 scope=<arg> NetBIOS scope\n\
690 iocharset=<arg> Linux charset (iso8859-1, utf8)\n\
691 codepage=<arg> server codepage (cp850)\n\
692 ttl=<arg> dircache time to live\n\
693 guest don't prompt for a password\n\
694 ro mount read-only\n\
695 rw mount read-write\n\
697 This command is designed to be run from within /bin/mount by giving\n\
698 the option '-t smbfs'. For example:\n\
699 mount -t smbfs -o username=tridge,password=foobar //fjall/test /data/test\n\
704 /****************************************************************************
705 Argument parsing for mount.smbfs interface
706 mount will call us like this:
707 mount.smbfs device mountpoint -o <options>
709 <options> is never empty, containing at least rw or ro
710 ****************************************************************************/
711 static void parse_mount_smb(int argc, char **argv)
713 int opt;
714 char *opts;
715 char *opteq;
716 extern char *optarg;
717 int val;
718 char *p;
720 /* FIXME: This function can silently fail if the arguments are
721 * not in the expected order.
723 > The arguments syntax of smbmount 2.2.3a (smbfs of Debian stable)
724 > requires that one gives "-o" before further options like username=...
725 > . Without -o, the username=.. setting is *silently* ignored. I've
726 > spent about an hour trying to find out why I couldn't log in now..
731 if (argc < 2 || argv[1][0] == '-') {
732 usage();
733 exit(1);
736 pstrcpy(service, argv[1]);
737 pstrcpy(mpoint, argv[2]);
739 /* Convert any '/' characters in the service name to
740 '\' characters */
741 string_replace(service, '/','\\');
742 argc -= 2;
743 argv += 2;
745 opt = getopt(argc, argv, "o:");
746 if(opt != 'o') {
747 return;
750 options[0] = 0;
751 p = options;
754 * option parsing from nfsmount.c (util-linux-2.9u)
756 for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) {
757 DEBUG(3, ("opts: %s\n", opts));
758 if ((opteq = strchr_m(opts, '='))) {
759 val = atoi(opteq + 1);
760 *opteq = '\0';
762 if (!strcmp(opts, "username") ||
763 !strcmp(opts, "logon")) {
764 char *lp;
765 got_user = true;
766 pstrcpy(username,opteq+1);
767 if ((lp=strchr_m(username,'%'))) {
768 *lp = 0;
769 pstrcpy(password,lp+1);
770 got_pass = true;
771 memset(strchr_m(opteq+1,'%')+1,'X',strlen(password));
773 if ((lp=strchr_m(username,'/'))) {
774 *lp = 0;
775 pstrcpy(workgroup,lp+1);
777 } else if(!strcmp(opts, "passwd") ||
778 !strcmp(opts, "password")) {
779 pstrcpy(password,opteq+1);
780 got_pass = true;
781 memset(opteq+1,'X',strlen(password));
782 } else if(!strcmp(opts, "credentials")) {
783 pstrcpy(credentials,opteq+1);
784 } else if(!strcmp(opts, "netbiosname")) {
785 pstrcpy(my_netbios_name,opteq+1);
786 } else if(!strcmp(opts, "uid")) {
787 mount_uid = nametouid(opteq+1);
788 } else if(!strcmp(opts, "gid")) {
789 mount_gid = nametogid(opteq+1);
790 } else if(!strcmp(opts, "port")) {
791 smb_port = val;
792 } else if(!strcmp(opts, "fmask")) {
793 mount_fmask = strtol(opteq+1, NULL, 8);
794 } else if(!strcmp(opts, "dmask")) {
795 mount_dmask = strtol(opteq+1, NULL, 8);
796 } else if(!strcmp(opts, "debug")) {
797 DEBUGLEVEL = val;
798 } else if(!strcmp(opts, "ip")) {
799 dest_ip = interpret_addr2(opteq+1);
800 if (is_zero_ip(dest_ip)) {
801 fprintf(stderr,"Can't resolve address %s\n", opteq+1);
802 exit(1);
804 have_ip = true;
805 } else if(!strcmp(opts, "workgroup")) {
806 pstrcpy(workgroup,opteq+1);
807 } else if(!strcmp(opts, "sockopt")) {
808 lp_set_cmdline("socket options", opteq+1);
809 } else if(!strcmp(opts, "scope")) {
810 lp_set_cmdline("netbios scope", opteq+1);
811 } else {
812 slprintf(p, sizeof(pstring) - (p - options) - 1, "%s=%s,", opts, opteq+1);
813 p += strlen(p);
815 } else {
816 val = 1;
817 if(!strcmp(opts, "nocaps")) {
818 fprintf(stderr, "Unhandled option: %s\n", opteq+1);
819 exit(1);
820 } else if(!strcmp(opts, "guest")) {
821 *password = '\0';
822 got_pass = true;
823 } else if(!strcmp(opts, "krb")) {
824 #ifdef HAVE_KRB5
826 use_kerberos = true;
827 if(!status32_smbfs)
828 fprintf(stderr, "Warning: kerberos support will only work for samba servers\n");
829 #else
830 fprintf(stderr,"No kerberos support compiled in\n");
831 exit(1);
832 #endif
833 } else if(!strcmp(opts, "rw")) {
834 mount_ro = 0;
835 } else if(!strcmp(opts, "ro")) {
836 mount_ro = 1;
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;
865 struct loadparm_context *lp_ctx;
867 DEBUGLEVEL = 1;
869 /* here we are interactive, even if run from autofs */
870 setup_logging("mount.smbfs",DEBUG_STDERR);
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 if (getenv("USER")) {
884 pstrcpy(username,getenv("USER"));
886 if ((p=strchr_m(username,'%'))) {
887 *p = 0;
888 pstrcpy(password,p+1);
889 got_pass = true;
890 memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password));
892 strupper(username);
895 if (getenv("PASSWD")) {
896 pstrcpy(password, getenv("PASSWD"));
897 got_pass = true;
900 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
901 get_password_file();
902 got_pass = true;
905 if (*username == 0 && getenv("LOGNAME")) {
906 pstrcpy(username,getenv("LOGNAME"));
909 lp_ctx = loadparm_init(talloc_autofree_context());
911 if (!lp_load(lp_ctx, dyn_CONFIGFILE)) {
912 fprintf(stderr, "Can't load %s - run testparm to debug it\n",
913 lp_config_file());
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", VERSION));
928 if (*workgroup == 0) {
929 pstrcpy(workgroup, lp_workgroup());
932 if (!*my_netbios_name) {
933 pstrcpy(my_netbios_name, myhostname());
935 strupper(my_netbios_name);
937 init_mount(lp_ctx);
938 return 0;