1/* 2 Unix SMB/Netbios implementation. 3 Version 2.0. 4 SMBFS mount program 5 Copyright (C) Andrew Tridgell 1999 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20*/ 21 22#define NO_SYSLOG 23 24#include "includes.h" 25 26#include <mntent.h> 27#include <asm/types.h> 28#include <linux/smb_fs.h> 29 30extern struct in_addr ipzero; 31extern int DEBUGLEVEL; 32extern BOOL in_client; 33extern pstring user_socket_options; 34extern BOOL append_log; 35extern fstring remote_machine; 36 37static pstring credentials; 38static pstring my_netbios_name; 39static pstring password; 40static pstring username; 41static pstring workgroup; 42static pstring mpoint; 43static pstring service; 44static pstring options; 45 46static struct in_addr dest_ip; 47static BOOL have_ip; 48static int smb_port = 139; 49static BOOL got_pass; 50static uid_t mount_uid; 51static gid_t mount_gid; 52static int mount_ro; 53static unsigned mount_fmask; 54static unsigned mount_dmask; 55 56static void usage(void); 57 58static void exit_parent(int sig) 59{ 60 /* parent simply exits when child says go... */ 61 exit(0); 62} 63 64static void daemonize(void) 65{ 66 int j, status; 67 pid_t child_pid; 68 69 signal( SIGTERM, exit_parent ); 70 71 if ((child_pid = fork()) < 0) { 72 DEBUG(0,("could not fork\n")); 73 } 74 75 if (child_pid > 0) { 76 while( 1 ) { 77 j = waitpid( child_pid, &status, 0 ); 78 if( j < 0 ) { 79 if( EINTR == errno ) { 80 continue; 81 } 82 status = errno; 83 } 84 break; 85 } 86 /* If we get here - the child exited with some error status */ 87 exit(status); 88 } 89 90 signal( SIGTERM, SIG_DFL ); 91 chdir("/"); 92} 93 94static void close_our_files(int client_fd) 95{ 96 int i; 97 struct rlimit limits; 98 99 getrlimit(RLIMIT_NOFILE,&limits); 100 for (i = 0; i< limits.rlim_max; i++) { 101 if (i == client_fd) 102 continue; 103 close(i); 104 } 105} 106 107static void usr1_handler(int x) 108{ 109 return; 110} 111 112 113/***************************************************** 114return a connection to a server 115*******************************************************/ 116 117static struct cli_state *do_connection(char *svc_name) 118{ 119 struct cli_state *c; 120 struct nmb_name called, calling; 121 char *server_n; 122 struct in_addr ip; 123 pstring server; 124 char *share; 125 126 if (svc_name[0] != '\\' || svc_name[1] != '\\') { 127 usage(); 128 exit(1); 129 } 130 131 pstrcpy(server, svc_name+2); 132 share = strchr(server,'\\'); 133 if (!share) { 134 usage(); 135 exit(1); 136 } 137 *share = 0; 138 share++; 139 140 server_n = server; 141 142 ip = ipzero; 143 144 make_nmb_name(&calling, my_netbios_name, 0x0); 145 make_nmb_name(&called , server, 0x20); 146 147 again: 148 ip = ipzero; 149 if (have_ip) ip = dest_ip; 150 151 /* have to open a new connection */ 152 if (!(c=cli_initialise(NULL)) || (cli_set_port(c, smb_port) == 0) || 153 !cli_connect(c, server_n, &ip)) { 154 DEBUG(0,("%d: Connection to %s failed\n", getpid(), server_n)); 155 if (c) { 156 cli_shutdown(c); 157 } 158 return NULL; 159 } 160 161 if (!cli_session_request(c, &calling, &called)) { 162 char *p; 163 DEBUG(0,("%d: session request to %s failed (%s)\n", 164 getpid(), called.name, cli_errstr(c))); 165 cli_shutdown(c); 166 if ((p=strchr(called.name, '.'))) { 167 *p = 0; 168 goto again; 169 } 170 if (strcmp(called.name, "*SMBSERVER")) { 171 make_nmb_name(&called , "*SMBSERVER", 0x20); 172 goto again; 173 } 174 return NULL; 175 } 176 177 DEBUG(4,("%d: session request ok\n", getpid())); 178 179 if (!cli_negprot(c)) { 180 DEBUG(0,("%d: protocol negotiation failed\n", getpid())); 181 cli_shutdown(c); 182 return NULL; 183 } 184 185 if (!got_pass) { 186 char *pass = getpass("Password: "); 187 if (pass) { 188 pstrcpy(password, pass); 189 } 190 } 191 192 /* This should be right for current smbfs. Future versions will support 193 large files as well as unicode and oplocks. */ 194 c->capabilities &= ~(CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS | 195 CAP_NT_FIND | CAP_STATUS32 | CAP_LEVEL_II_OPLOCKS); 196 if (!cli_session_setup(c, username, 197 password, strlen(password), 198 password, strlen(password), 199 workgroup)) { 200 /* if a password was not supplied then try again with a 201 null username */ 202 if (password[0] || !username[0] || 203 !cli_session_setup(c, "", "", 0, "", 0, workgroup)) { 204 DEBUG(0,("%d: session setup failed: %s\n", 205 getpid(), cli_errstr(c))); 206 cli_shutdown(c); 207 return NULL; 208 } 209 DEBUG(0,("Anonymous login successful\n")); 210 } 211 212 DEBUG(4,("%d: session setup ok\n", getpid())); 213 214 if (!cli_send_tconX(c, share, "?????", 215 password, strlen(password)+1)) { 216 DEBUG(0,("%d: tree connect failed: %s\n", 217 getpid(), cli_errstr(c))); 218 cli_shutdown(c); 219 return NULL; 220 } 221 222 DEBUG(4,("%d: tconx ok\n", getpid())); 223 224 got_pass = True; 225 226 return c; 227} 228 229 230/**************************************************************************** 231unmount smbfs (this is a bailout routine to clean up if a reconnect fails) 232 Code blatently stolen from smbumount.c 233 -mhw- 234****************************************************************************/ 235static void smb_umount(char *mount_point) 236{ 237 int fd; 238 struct mntent *mnt; 239 FILE* mtab; 240 FILE* new_mtab; 241 242 /* Programmers Note: 243 This routine only gets called to the scene of a disaster 244 to shoot the survivors... A connection that was working 245 has now apparently failed. We have an active mount point 246 (presumably) that we need to dump. If we get errors along 247 the way - make some noise, but we are already turning out 248 the lights to exit anyways... 249 */ 250 if (umount(mount_point) != 0) { 251 DEBUG(0,("%d: Could not umount %s: %s\n", 252 getpid(), mount_point, strerror(errno))); 253 return; 254 } 255 256 if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) { 257 DEBUG(0,("%d: Can't get "MOUNTED"~ lock file", getpid())); 258 return; 259 } 260 261 close(fd); 262 263 if ((mtab = setmntent(MOUNTED, "r")) == NULL) { 264 DEBUG(0,("%d: Can't open " MOUNTED ": %s\n", 265 getpid(), strerror(errno))); 266 return; 267 } 268 269#define MOUNTED_TMP MOUNTED".tmp" 270 271 if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) { 272 DEBUG(0,("%d: Can't open " MOUNTED_TMP ": %s\n", 273 getpid(), strerror(errno))); 274 endmntent(mtab); 275 return; 276 } 277 278 while ((mnt = getmntent(mtab)) != NULL) { 279 if (strcmp(mnt->mnt_dir, mount_point) != 0) { 280 addmntent(new_mtab, mnt); 281 } 282 } 283 284 endmntent(mtab); 285 286 if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { 287 DEBUG(0,("%d: Error changing mode of %s: %s\n", 288 getpid(), MOUNTED_TMP, strerror(errno))); 289 return; 290 } 291 292 endmntent(new_mtab); 293 294 if (rename(MOUNTED_TMP, MOUNTED) < 0) { 295 DEBUG(0,("%d: Cannot rename %s to %s: %s\n", 296 getpid(), MOUNTED, MOUNTED_TMP, strerror(errno))); 297 return; 298 } 299 300 if (unlink(MOUNTED"~") == -1) { 301 DEBUG(0,("%d: Can't remove "MOUNTED"~", getpid())); 302 return; 303 } 304} 305 306 307/* 308 * Call the smbfs ioctl to install a connection socket, 309 * then wait for a signal to reconnect. Note that we do 310 * not exit after open_sockets() or send_login() errors, 311 * as the smbfs mount would then have no way to recover. 312 */ 313static void send_fs_socket(char *svc_name, char *mount_point, struct cli_state *c) 314{ 315 int fd, closed = 0, res = 1; 316 pid_t parentpid = getppid(); 317 struct smb_conn_opt conn_options; 318 319 memset(&conn_options, 0, sizeof(conn_options)); 320 321 while (1) { 322 if ((fd = open(mount_point, O_RDONLY)) < 0) { 323 DEBUG(0,("mount.smbfs[%d]: can't open %s\n", 324 getpid(), mount_point)); 325 break; 326 } 327 328 conn_options.fd = c->fd; 329 conn_options.protocol = c->protocol; 330 conn_options.case_handling = SMB_CASE_DEFAULT; 331 conn_options.max_xmit = c->max_xmit; 332 conn_options.server_uid = c->vuid; 333 conn_options.tid = c->cnum; 334 conn_options.secmode = c->sec_mode; 335 conn_options.rawmode = 0; 336 conn_options.sesskey = c->sesskey; 337 conn_options.maxraw = 0; 338 conn_options.capabilities = c->capabilities; 339 conn_options.serverzone = c->serverzone/60; 340 341 res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options); 342 if (res != 0) { 343 DEBUG(0,("mount.smbfs[%d]: ioctl failed, res=%d\n", 344 getpid(), res)); 345 close(fd); 346 break; 347 } 348 349 if (parentpid) { 350 /* Ok... We are going to kill the parent. Now 351 is the time to break the process group... */ 352 setsid(); 353 /* Send a signal to the parent to terminate */ 354 kill(parentpid, SIGTERM); 355 parentpid = 0; 356 } 357 358 close(fd); 359 360 /* This looks wierd but we are only closing the userspace 361 side, the connection has already been passed to smbfs and 362 it has increased the usage count on the socket. 363 364 If we don't do this we will "leak" sockets and memory on 365 each reconnection we have to make. */ 366 cli_shutdown(c); 367 c = NULL; 368 369 if (!closed) { 370 /* redirect stdout & stderr since we can't know that 371 the library functions we use are using DEBUG. */ 372 if ( (fd = open("/dev/null", O_WRONLY)) < 0) 373 DEBUG(2,("mount.smbfs: can't open /dev/null\n")); 374 close_our_files(fd); 375 if (fd >= 0) { 376 dup2(fd, STDOUT_FILENO); 377 dup2(fd, STDERR_FILENO); 378 close(fd); 379 } 380 381 /* here we are no longer interactive */ 382 pstrcpy(remote_machine, "smbmount"); /* sneaky ... */ 383 setup_logging("mount.smbfs", False); 384 append_log = True; 385 reopen_logs(); 386 DEBUG(0, ("mount.smbfs: entering daemon mode for service %s, pid=%d\n", svc_name, getpid())); 387 388 closed = 1; 389 } 390 391 /* Wait for a signal from smbfs ... but don't continue 392 until we actually get a new connection. */ 393 while (!c) { 394 CatchSignal(SIGUSR1, &usr1_handler); 395 pause(); 396 DEBUG(2,("mount.smbfs[%d]: got signal, getting new socket\n", getpid())); 397 c = do_connection(svc_name); 398 } 399 } 400 401 smb_umount(mount_point); 402 DEBUG(2,("mount.smbfs[%d]: exit\n", getpid())); 403 exit(1); 404} 405 406/********************************************************* 407a strdup with exit 408**********************************************************/ 409static char *xstrdup(char *s) 410{ 411 s = strdup(s); 412 if (!s) { 413 fprintf(stderr,"out of memory\n"); 414 exit(1); 415 } 416 return s; 417} 418 419 420/**************************************************************************** 421mount smbfs 422****************************************************************************/ 423static void init_mount(void) 424{ 425 char mount_point[MAXPATHLEN+1]; 426 pstring tmp; 427 pstring svc2; 428 struct cli_state *c; 429 char *args[20]; 430 int i, status; 431 432 if (realpath(mpoint, mount_point) == NULL) { 433 fprintf(stderr, "Could not resolve mount point %s\n", mpoint); 434 return; 435 } 436 437 438 c = do_connection(service); 439 if (!c) { 440 fprintf(stderr,"SMB connection failed\n"); 441 exit(1); 442 } 443 444 /* 445 Set up to return as a daemon child and wait in the parent 446 until the child say it's ready... 447 */ 448 daemonize(); 449 450 pstrcpy(svc2, service); 451 string_replace(svc2, '\\','/'); 452 string_replace(svc2, ' ','_'); 453 454 memset(args, 0, sizeof(args[0])*20); 455 456 i=0; 457 args[i++] = "smbmnt"; 458 459 args[i++] = mount_point; 460 args[i++] = "-s"; 461 args[i++] = svc2; 462 463 if (mount_ro) { 464 args[i++] = "-r"; 465 } 466 if (mount_uid) { 467 slprintf(tmp, sizeof(tmp)-1, "%d", mount_uid); 468 args[i++] = "-u"; 469 args[i++] = xstrdup(tmp); 470 } 471 if (mount_gid) { 472 slprintf(tmp, sizeof(tmp)-1, "%d", mount_gid); 473 args[i++] = "-g"; 474 args[i++] = xstrdup(tmp); 475 } 476 if (mount_fmask) { 477 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_fmask); 478 args[i++] = "-f"; 479 args[i++] = xstrdup(tmp); 480 } 481 if (mount_dmask) { 482 slprintf(tmp, sizeof(tmp)-1, "0%o", mount_dmask); 483 args[i++] = "-d"; 484 args[i++] = xstrdup(tmp); 485 } 486 if (options) { 487 args[i++] = "-o"; 488 args[i++] = options; 489 } 490 491 if (fork() == 0) { 492 if (file_exist(BINDIR "/smbmnt", NULL)) { 493 execv(BINDIR "/smbmnt", args); 494 fprintf(stderr,"execv of %s failed. Error was %s.", BINDIR "/smbmnt", strerror(errno)); 495 } else { 496 execvp("smbmnt", args); 497 fprintf(stderr,"execvp of smbmnt failed. Error was %s.", strerror(errno) ); 498 } 499 exit(1); 500 } 501 502 if (waitpid(-1, &status, 0) == -1) { 503 fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) ); 504 /* FIXME: do some proper error handling */ 505 exit(1); 506 } 507 508 if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { 509 fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status)); 510 /* FIXME: do some proper error handling */ 511 exit(1); 512 } 513 514 /* Ok... This is the rubicon for that mount point... At any point 515 after this, if the connections fail and can not be reconstructed 516 for any reason, we will have to unmount the mount point. There 517 is no exit from the next call... 518 */ 519 send_fs_socket(service, mount_point, c); 520} 521 522 523/**************************************************************************** 524get a password from a a file or file descriptor 525exit on failure (from smbclient, move to libsmb or shared .c file?) 526****************************************************************************/ 527static void get_password_file(void) 528{ 529 int fd = -1; 530 char *p; 531 BOOL close_it = False; 532 pstring spec; 533 char pass[128]; 534 535 if ((p = getenv("PASSWD_FD")) != NULL) { 536 pstrcpy(spec, "descriptor "); 537 pstrcat(spec, p); 538 sscanf(p, "%d", &fd); 539 close_it = False; 540 } else if ((p = getenv("PASSWD_FILE")) != NULL) { 541 fd = sys_open(p, O_RDONLY, 0); 542 pstrcpy(spec, p); 543 if (fd < 0) { 544 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", 545 spec, strerror(errno)); 546 exit(1); 547 } 548 close_it = True; 549 } 550 551 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ 552 p && p - pass < sizeof(pass);) { 553 switch (read(fd, p, 1)) { 554 case 1: 555 if (*p != '\n' && *p != '\0') { 556 *++p = '\0'; /* advance p, and null-terminate pass */ 557 break; 558 } 559 case 0: 560 if (p - pass) { 561 *p = '\0'; /* null-terminate it, just in case... */ 562 p = NULL; /* then force the loop condition to become false */ 563 break; 564 } else { 565 fprintf(stderr, "Error reading password from file %s: %s\n", 566 spec, "empty password\n"); 567 exit(1); 568 } 569 570 default: 571 fprintf(stderr, "Error reading password from file %s: %s\n", 572 spec, strerror(errno)); 573 exit(1); 574 } 575 } 576 pstrcpy(password, pass); 577 if (close_it) 578 close(fd); 579} 580 581/**************************************************************************** 582get username and password from a credentials file 583exit on failure (from smbclient, move to libsmb or shared .c file?) 584****************************************************************************/ 585static void read_credentials_file(char *filename) 586{ 587 FILE *auth; 588 fstring buf; 589 uint16 len = 0; 590 char *ptr, *val, *param; 591 592 if ((auth=sys_fopen(filename, "r")) == NULL) 593 { 594 /* fail if we can't open the credentials file */ 595 DEBUG(0,("ERROR: Unable to open credentials file!\n")); 596 exit (-1); 597 } 598 599 while (!feof(auth)) 600 { 601 /* get a line from the file */ 602 if (!fgets (buf, sizeof(buf), auth)) 603 continue; 604 len = strlen(buf); 605 606 if ((len) && (buf[len-1]=='\n')) 607 { 608 buf[len-1] = '\0'; 609 len--; 610 } 611 if (len == 0) 612 continue; 613 614 /* break up the line into parameter & value. 615 will need to eat a little whitespace possibly */ 616 param = buf; 617 if (!(ptr = strchr (buf, '='))) 618 continue; 619 val = ptr+1; 620 *ptr = '\0'; 621 622 /* eat leading white space */ 623 while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) 624 val++; 625 626 if (strstr(param, "password") == 0) 627 { 628 pstrcpy(password, val); 629 got_pass = True; 630 } 631 else if (strstr(param, "username") == 0) 632 pstrcpy(username, val); 633 634 memset(buf, 0, sizeof(buf)); 635 } 636 fclose(auth); 637} 638 639 640/**************************************************************************** 641usage on the program 642****************************************************************************/ 643static void usage(void) 644{ 645 printf("Usage: mount.smbfs service mountpoint [-o options,...]\n"); 646 647 printf("Version %s\n\n",VERSION); 648 649 printf( 650"Options:\n\ 651 username=<arg> SMB username\n\ 652 password=<arg> SMB password\n\ 653 credentials=<filename> file with username/password\n\ 654 netbiosname=<arg> source NetBIOS name\n\ 655 uid=<arg> mount uid or username\n\ 656 gid=<arg> mount gid or groupname\n\ 657 port=<arg> remote SMB port number\n\ 658 fmask=<arg> file umask\n\ 659 dmask=<arg> directory umask\n\ 660 debug=<arg> debug level\n\ 661 ip=<arg> destination host or IP address\n\ 662 workgroup=<arg> workgroup on destination\n\ 663 sockopt=<arg> TCP socket options\n\ 664 scope=<arg> NetBIOS scope\n\ 665 iocharset=<arg> Linux charset (iso8859-1, utf8)\n\ 666 codepage=<arg> server codepage (cp850)\n\ 667 ttl=<arg> dircache time to live\n\ 668 guest don't prompt for a password\n\ 669 ro mount read-only\n\ 670 rw mount read-write\n\ 671\n\ 672This command is designed to be run from within /bin/mount by giving\n\ 673the option '-t smbfs'. For example:\n\ 674 mount -t smbfs -o username=tridge,password=foobar //fjall/test /data/test\n\ 675"); 676} 677 678 679/**************************************************************************** 680 Argument parsing for mount.smbfs interface 681 mount will call us like this: 682 mount.smbfs device mountpoint -o <options> 683 684 <options> is never empty, containing at least rw or ro 685 ****************************************************************************/ 686static void parse_mount_smb(int argc, char **argv) 687{ 688 int opt; 689 char *opts; 690 char *opteq; 691 extern char *optarg; 692 int val; 693 extern pstring global_scope; 694 char *p; 695 696 if (argc < 2 || argv[1][0] == '-') { 697 usage(); 698 exit(1); 699 } 700 701 pstrcpy(service, argv[1]); 702 pstrcpy(mpoint, argv[2]); 703 704 /* Convert any '/' characters in the service name to 705 '\' characters */ 706 string_replace(service, '/','\\'); 707 argc -= 2; 708 argv += 2; 709 710 opt = getopt(argc, argv, "o:"); 711 if(opt != 'o') { 712 return; 713 } 714 715 options[0] = 0; 716 p = options; 717 718 /* 719 * option parsing from nfsmount.c (util-linux-2.9u) 720 */ 721 for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) { 722 DEBUG(3, ("opts: %s\n", opts)); 723 if ((opteq = strchr(opts, '='))) { 724 val = atoi(opteq + 1); 725 *opteq = '\0'; 726 727 if (!strcmp(opts, "username") || 728 !strcmp(opts, "logon")) { 729 char *lp; 730 pstrcpy(username,opteq+1); 731 if ((lp=strchr(username,'%'))) { 732 *lp = 0; 733 pstrcpy(password,lp+1); 734 got_pass = True; 735 memset(strchr(opteq+1,'%')+1,'X',strlen(password)); 736 } 737 if ((lp=strchr(username,'/'))) { 738 *lp = 0; 739 pstrcpy(workgroup,lp+1); 740 } 741 } else if(!strcmp(opts, "passwd") || 742 !strcmp(opts, "password")) { 743 pstrcpy(password,opteq+1); 744 got_pass = True; 745 memset(opteq+1,'X',strlen(password)); 746 } else if(!strcmp(opts, "credentials")) { 747 pstrcpy(credentials,opteq+1); 748 } else if(!strcmp(opts, "netbiosname")) { 749 pstrcpy(my_netbios_name,opteq+1); 750 } else if(!strcmp(opts, "uid")) { 751 mount_uid = nametouid(opteq+1); 752 } else if(!strcmp(opts, "gid")) { 753 mount_gid = nametogid(opteq+1); 754 } else if(!strcmp(opts, "port")) { 755 smb_port = val; 756 } else if(!strcmp(opts, "fmask")) { 757 mount_fmask = strtol(opteq+1, NULL, 8); 758 } else if(!strcmp(opts, "dmask")) { 759 mount_dmask = strtol(opteq+1, NULL, 8); 760 } else if(!strcmp(opts, "debug")) { 761 DEBUGLEVEL = val; 762 } else if(!strcmp(opts, "ip")) { 763 dest_ip = *interpret_addr2(opteq+1); 764 if (zero_ip(dest_ip)) { 765 fprintf(stderr,"Can't resolve address %s\n", opteq+1); 766 exit(1); 767 } 768 have_ip = True; 769 } else if(!strcmp(opts, "workgroup")) { 770 pstrcpy(workgroup,opteq+1); 771 } else if(!strcmp(opts, "sockopt")) { 772 pstrcpy(user_socket_options,opteq+1); 773 } else if(!strcmp(opts, "scope")) { 774 pstrcpy(global_scope,opteq+1); 775 } else { 776 slprintf(p, sizeof(pstring) - (p - options) - 1, "%s=%s,", opts, opteq+1); 777 p += strlen(p); 778 } 779 } else { 780 val = 1; 781 if(!strcmp(opts, "nocaps")) { 782 fprintf(stderr, "Unhandled option: %s\n", opteq+1); 783 exit(1); 784 } else if(!strcmp(opts, "guest")) { 785 *password = '\0'; 786 got_pass = True; 787 } else if(!strcmp(opts, "rw")) { 788 mount_ro = 0; 789 } else if(!strcmp(opts, "ro")) { 790 mount_ro = 1; 791 } else { 792 strncpy(p, opts, sizeof(pstring) - (p - options) - 1); 793 p += strlen(opts); 794 *p++ = ','; 795 *p = 0; 796 } 797 } 798 } 799 800 if (!*service) { 801 usage(); 802 exit(1); 803 } 804 805 if (p != options) { 806 *(p-1) = 0; /* remove trailing , */ 807 DEBUG(3,("passthrough options '%s'\n", options)); 808 } 809} 810 811/**************************************************************************** 812 main program 813****************************************************************************/ 814 int main(int argc,char *argv[]) 815{ 816 extern char *optarg; 817 extern int optind; 818 static pstring servicesf = CONFIGFILE; 819 char *p; 820 821 DEBUGLEVEL = 1; 822 823 /* here we are interactive, even if run from autofs */ 824 setup_logging("mount.smbfs",True); 825 826 TimeInit(); 827 charset_initialise(); 828 829 in_client = True; /* Make sure that we tell lp_load we are */ 830 831 if (getenv("USER")) { 832 pstrcpy(username,getenv("USER")); 833 834 if ((p=strchr(username,'%'))) { 835 *p = 0; 836 pstrcpy(password,p+1); 837 got_pass = True; 838 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password)); 839 } 840 strupper(username); 841 } 842 843 if (getenv("PASSWD")) { 844 pstrcpy(password,getenv("PASSWD")); 845 got_pass = True; 846 } 847 848 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { 849 get_password_file(); 850 got_pass = True; 851 } 852 853 if (*username == 0 && getenv("LOGNAME")) { 854 pstrcpy(username,getenv("LOGNAME")); 855 } 856 857 if (!lp_load(servicesf,True,False,False)) { 858 fprintf(stderr, "Can't load %s - run testparm to debug it\n", 859 servicesf); 860 } 861 862 parse_mount_smb(argc, argv); 863 864 if (*credentials != 0) { 865 read_credentials_file(credentials); 866 } 867 868 DEBUG(3,("mount.smbfs started (version %s)\n", VERSION)); 869 870 codepage_initialise(lp_client_code_page()); 871 872 if (*workgroup == 0) { 873 pstrcpy(workgroup,lp_workgroup()); 874 } 875 876 load_interfaces(); 877 if (!*my_netbios_name) { 878 pstrcpy(my_netbios_name, myhostname()); 879 } 880 strupper(my_netbios_name); 881 882 init_mount(); 883 return 0; 884} 885