home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / samba-1.9.18p7.tar.gz / samba-1.9.18p7.tar / samba-1.9.18p7 / source / smbmount.c < prev    next >
C/C++ Source or Header  |  1998-05-12  |  20KB  |  925 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    SMB client
  5.    Copyright (C) Andrew Tridgell 1994-1998
  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. #ifdef SYSLOG
  23. #undef SYSLOG
  24. #endif
  25.  
  26. #include <linux/version.h>
  27. #define LVERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch))
  28. #if LINUX_VERSION_CODE < LVERSION(2,1,70)
  29. #error this code will only compile on versions of linux after 2.1.70
  30. #endif
  31.  
  32. #include "includes.h"
  33. #include <linux/smb_fs.h>
  34. static struct smb_conn_opt conn_options;
  35.  
  36. #ifndef REGISTER
  37. #define REGISTER 0
  38. #endif
  39.  
  40. /* Uncomment this to allow debug the smbmount daemon */
  41. #define SMBFS_DEBUG 1
  42.  
  43. pstring cur_dir = "\\";
  44. pstring cd_path = "";
  45. extern pstring service;
  46. extern pstring desthost;
  47. extern pstring myname;
  48. extern pstring myhostname;
  49. extern pstring password;
  50. extern pstring username;
  51. extern pstring workgroup;
  52. char *cmdstr="";
  53. extern BOOL got_pass;
  54. extern BOOL connect_as_printer;
  55. extern BOOL connect_as_ipc;
  56. extern struct in_addr ipzero;
  57.  
  58. extern BOOL doencrypt;
  59.  
  60. extern pstring user_socket_options;
  61.  
  62. /* 30 second timeout on most commands */
  63. #define CLIENT_TIMEOUT (30*1000)
  64. #define SHORT_TIMEOUT (5*1000)
  65.  
  66. /* value for unused fid field in trans2 secondary request */
  67. #define FID_UNUSED (0xFFFF)
  68.  
  69. extern int name_type;
  70.  
  71. extern int max_protocol;
  72. int port = SMB_PORT;
  73.  
  74.  
  75. time_t newer_than = 0;
  76. int archive_level = 0;
  77.  
  78. extern pstring debugf;
  79. extern int DEBUGLEVEL;
  80.  
  81. BOOL translation = False;
  82.  
  83. extern int cnum;
  84. extern int mid;
  85. extern int pid;
  86. extern int tid;
  87. extern int gid;
  88. extern int uid;
  89.  
  90. extern BOOL have_ip;
  91. extern int max_xmit;
  92.  
  93. /* clitar bits insert */
  94. extern int blocksize;
  95. extern BOOL tar_inc;
  96. extern BOOL tar_reset;
  97. /* clitar bits end */
  98.  
  99.  
  100. int myumask = 0755;
  101.  
  102. extern pstring scope;
  103.  
  104. BOOL prompt = True;
  105.  
  106. int printmode = 1;
  107.  
  108. BOOL recurse = False;
  109. BOOL lowercase = False;
  110.  
  111. struct in_addr dest_ip;
  112.  
  113. #define SEPARATORS " \t\n\r"
  114.  
  115. BOOL abort_mget = True;
  116.  
  117. extern int Protocol;
  118.  
  119. extern BOOL readbraw_supported ;
  120. extern BOOL writebraw_supported;
  121.  
  122. pstring fileselection = "";
  123.  
  124. extern file_info def_finfo;
  125.  
  126. /* timing globals */
  127. int get_total_size = 0;
  128. int get_total_time_ms = 0;
  129. int put_total_size = 0;
  130. int put_total_time_ms = 0;
  131.  
  132. /* totals globals */
  133. int dir_total = 0;
  134.  
  135. extern int Client;
  136.  
  137. #define USENMB
  138.  
  139. #define CNV_LANG(s) dos_to_unix(s,False)
  140. #define CNV_INPUT(s) unix_to_dos(s,True)
  141.  
  142. /****************************************************************************
  143. check for existance of a dir
  144. ****************************************************************************/
  145. static BOOL chkpath(char *path,BOOL report)
  146. {
  147.   pstring path2;
  148.   pstring inbuf,outbuf;
  149.   char *p;
  150.  
  151.   pstrcpy(path2,path);
  152.   trim_string(path2,NULL,"\\");
  153.   if (!*path2) *path2 = '\\';
  154.  
  155.   bzero(outbuf,smb_size);
  156.   set_message(outbuf,0,4 + strlen(path2),True);
  157.   SCVAL(outbuf,smb_com,SMBchkpth);
  158.   SSVAL(outbuf,smb_tid,cnum);
  159.   cli_setup_pkt(outbuf);
  160.  
  161.   p = smb_buf(outbuf);
  162.   *p++ = 4;
  163.   pstrcpy(p,path2);
  164.  
  165. #if 0
  166.   {
  167.       /* this little bit of code can be used to extract NT error codes.
  168.          Just feed a bunch of "cd foo" commands to smbclient then watch
  169.          in netmon (tridge) */
  170.       static int code=0;
  171.       SIVAL(outbuf, smb_rcls, code | 0xC0000000);
  172.       SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
  173.       code++;
  174.   }
  175. #endif
  176.  
  177.   send_smb(Client,outbuf);
  178.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  179.  
  180.   if (report && CVAL(inbuf,smb_rcls) != 0)
  181.     DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
  182.  
  183.   return(CVAL(inbuf,smb_rcls) == 0);
  184. }
  185.  
  186. static void
  187. daemonize(void)
  188. {
  189.     int i;
  190.     if ((i = fork()) < 0)
  191.     {
  192.         DEBUG(0, ("could not fork\n"));
  193.     }
  194.     if (i > 0)
  195.     {
  196.         /* parent simply exits */
  197.         exit(0);
  198.     }
  199.     setsid();
  200.     chdir("/");
  201. }
  202.  
  203. static void
  204. close_our_files(void)
  205. {
  206.     int i;
  207.     for (i = 0; i < NR_OPEN; i++) {
  208.         if (i == Client) {
  209.             continue;
  210.         }
  211.         close(i);
  212.     }
  213. }
  214.  
  215. static void
  216. usr1_handler(int x)
  217. {
  218.     return;
  219. }
  220.  
  221. /*
  222.  * Send a login and store the connection options. This is a separate
  223.  * function to keep clientutil.c independent of linux kernel changes.
  224.  */
  225. static BOOL mount_send_login(char *inbuf, char *outbuf)
  226. {
  227.   struct connection_options opt;
  228.   int res = cli_send_login(inbuf, outbuf, True, True, &opt);
  229.  
  230.   if (!res)
  231.     return res;
  232.  
  233.   conn_options.protocol = opt.protocol;
  234.   conn_options.case_handling = CASE_LOWER;
  235.   conn_options.max_xmit = opt.max_xmit;
  236.   conn_options.server_uid = opt.server_uid;
  237.   conn_options.tid = opt.tid;
  238.   conn_options.secmode = opt.sec_mode;
  239.   conn_options.maxmux = opt.max_mux;
  240.   conn_options.maxvcs = opt.max_vcs;
  241.   conn_options.rawmode = opt.rawmode;
  242.   conn_options.sesskey = opt.sesskey;
  243.   conn_options.maxraw = opt.maxraw;
  244.   conn_options.capabilities = opt.capabilities;
  245.   conn_options.serverzone = opt.serverzone;
  246.  
  247.   return True;
  248. }
  249.  
  250. /*
  251.  * Call the smbfs ioctl to install a connection socket,
  252.  * then wait for a signal to reconnect. Note that we do
  253.  * not exit after open_sockets() or send_login() errors,
  254.  * as the smbfs mount would then have no way to recover.
  255.  */
  256. static void
  257. send_fs_socket(char *mount_point, char *inbuf, char *outbuf)
  258. {
  259.     int fd, closed = 0, res = 1;
  260.  
  261.     while (1)
  262.     {
  263.         if ((fd = open(mount_point, O_RDONLY)) < 0)
  264.         {
  265.             DEBUG(0, ("smbmount: can't open %s\n", mount_point));
  266.             break;
  267.         }        
  268.  
  269.         /*
  270.          * Call the ioctl even if we couldn't get a socket ...
  271.          * there's no point in making smbfs wait for a timeout.
  272.          */
  273.         conn_options.fd = -1;
  274.         if (res)
  275.             conn_options.fd = Client;
  276.         res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options);
  277.         if (res != 0)
  278.         {
  279.             DEBUG(0, ("smbmount: ioctl failed, res=%d\n", res));
  280.         }
  281.  
  282.         close_sockets();
  283.         close(fd);
  284.         /*
  285.          * Close all open files if we haven't done so yet.
  286.          */
  287. #ifndef SMBFS_DEBUG
  288.         if (!closed)
  289.         {
  290.             closed = 1;
  291.             close_our_files();
  292.         }
  293. #endif
  294.  
  295.         /*
  296.          * Wait for a signal from smbfs ...
  297.          */
  298.         signal(SIGUSR1, &usr1_handler);
  299.         pause();
  300.         DEBUG(0, ("smbmount: got signal, getting new socket\n"));
  301.  
  302.         res = cli_open_sockets(port);
  303.         if (!res)
  304.         {
  305.             DEBUG(0, ("smbmount: can't open sockets\n"));
  306.             continue;
  307.         }
  308.  
  309.         res = mount_send_login(inbuf, outbuf);
  310.         if (!res)
  311.         {
  312.             DEBUG(0, ("smbmount: login failed\n"));
  313.         }
  314.     }
  315.     DEBUG(0, ("smbmount: exit\n"));
  316.     exit(1);
  317. }
  318.  
  319. /****************************************************************************
  320. mount smbfs
  321. ****************************************************************************/
  322. static void cmd_mount(char *inbuf,char *outbuf)
  323. {
  324.     pstring mpoint;
  325.     pstring share_name;
  326.     pstring mount_command;
  327.     fstring buf;
  328.     int retval;
  329.     char mount_point[MAXPATHLEN+1];
  330.  
  331.     if (!next_token(NULL, mpoint, NULL))
  332.     {
  333.         DEBUG(0,("You must supply a mount point\n"));
  334.         return;
  335.     }
  336.  
  337.     memset(mount_point, 0, sizeof(mount_point));
  338.  
  339.     if (realpath(mpoint, mount_point) == NULL)
  340.     {
  341.         DEBUG(0, ("Could not resolve mount point\n"));
  342.         return;
  343.     }
  344.  
  345.     /*
  346.      * Build the service name to report on the Unix side,
  347.      * converting '\' to '/' and ' ' to '_'.
  348.      */
  349.     pstrcpy(share_name, service);  
  350.     string_replace(share_name, '\\', '/');
  351.     string_replace(share_name, ' ', '_');
  352.  
  353.     slprintf(mount_command, sizeof(mount_command)-1,"smbmnt %s -s %s", mount_point, share_name);
  354.  
  355.     while(next_token(NULL, buf, NULL))
  356.     {
  357.         pstrcat(mount_command, " ");
  358.         pstrcat(mount_command, buf);
  359.     }
  360.  
  361.     DEBUG(3, ("mount command: %s\n", mount_command));
  362.  
  363.     /*
  364.      * Create the background process before trying the mount.
  365.      * (We delay closing files to allow diagnostic messages.)
  366.      */
  367.     daemonize();
  368.  
  369.     /* The parent has exited here, the child handles the connection: */
  370.     if ((retval = system(mount_command)) != 0)
  371.     {
  372.         DEBUG(0,("mount failed\n"));
  373.         exit(1);
  374.     }
  375.     send_fs_socket(mount_point, inbuf, outbuf);
  376. }    
  377.  
  378.  
  379. /* This defines the commands supported by this client */
  380. struct
  381. {
  382.   char *name;
  383.   void (*fn)();
  384.   char *description;
  385. } commands[] = 
  386. {
  387.   {"mount", cmd_mount, "<mount-point options> mount an smbfs file system"},
  388.   {"",NULL,NULL}
  389. };
  390.  
  391.  
  392. /*******************************************************************
  393.   lookup a command string in the list of commands, including 
  394.   abbreviations
  395.   ******************************************************************/
  396. static int process_tok(fstring tok)
  397. {
  398.   int i = 0, matches = 0;
  399.   int cmd=0;
  400.   int tok_len = strlen(tok);
  401.   
  402.   while (commands[i].fn != NULL)
  403.     {
  404.       if (strequal(commands[i].name,tok))
  405.     {
  406.       matches = 1;
  407.       cmd = i;
  408.       break;
  409.     }
  410.       else if (strnequal(commands[i].name, tok, tok_len))
  411.     {
  412.       matches++;
  413.       cmd = i;
  414.     }
  415.       i++;
  416.     }
  417.   
  418.   if (matches == 0)
  419.     return(-1);
  420.   else if (matches == 1)
  421.     return(cmd);
  422.   else
  423.     return(-2);
  424. }
  425.  
  426. /****************************************************************************
  427. help
  428. ****************************************************************************/
  429. void cmd_help(char *dum_in, char *dum_out)
  430. {
  431.   int i=0,j;
  432.   fstring buf;
  433.  
  434.   if (next_token(NULL,buf,NULL))
  435.     {
  436.       if ((i = process_tok(buf)) >= 0)
  437.     DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));            
  438.     }
  439.   else
  440.     while (commands[i].description)
  441.       {
  442.     for (j=0; commands[i].description && (j<5); j++) {
  443.       DEBUG(0,("%-15s",commands[i].name));
  444.       i++;
  445.     }
  446.     DEBUG(0,("\n"));
  447.       }
  448. }
  449.  
  450. /****************************************************************************
  451. wait for keyboard activity, swallowing network packets
  452. ****************************************************************************/
  453. #ifdef CLIX
  454. static char wait_keyboard(char *buffer)
  455. #else
  456. static void wait_keyboard(char *buffer)
  457. #endif
  458. {
  459.   fd_set fds;
  460.   int selrtn;
  461.   struct timeval timeout;
  462.   
  463. #ifdef CLIX
  464.   int delay = 0;
  465. #endif
  466.   
  467.   while (1) 
  468.     {
  469.       extern int Client;
  470.       FD_ZERO(&fds);
  471.       FD_SET(Client,&fds);
  472. #ifndef CLIX
  473.       FD_SET(fileno(stdin),&fds);
  474. #endif
  475.  
  476.       timeout.tv_sec = 20;
  477.       timeout.tv_usec = 0;
  478. #ifdef CLIX
  479.       timeout.tv_sec = 0;
  480. #endif
  481.       selrtn = sys_select(&fds,&timeout);
  482.       
  483. #ifndef CLIX
  484.       if (FD_ISSET(fileno(stdin),&fds))
  485.       return;
  486. #else
  487.       {
  488.     char ch;
  489.     int readret;
  490.  
  491.     set_blocking(fileno(stdin), False);    
  492.     readret = read_data( fileno(stdin), &ch, 1);
  493.     set_blocking(fileno(stdin), True);
  494.     if (readret == -1)
  495.       {
  496.         if (errno != EAGAIN)
  497.           {
  498.         /* should crash here */
  499.         DEBUG(1,("readchar stdin failed\n"));
  500.           }
  501.       }
  502.     else if (readret != 0)
  503.       {
  504.         return ch;
  505.       }
  506.       }
  507. #endif
  508.  
  509.       /* We deliberately use receive_smb instead of
  510.          client_receive_smb as we want to receive
  511.          session keepalives and then drop them here.
  512.        */
  513.       if (FD_ISSET(Client,&fds))
  514.       receive_smb(Client,buffer,0);
  515.       
  516. #ifdef CLIX
  517.       delay++;
  518.       if (delay > 100000)
  519.     {
  520.       delay = 0;
  521.       chkpath("\\",False);
  522.     }
  523. #else
  524.       chkpath("\\",False);
  525. #endif
  526.     }  
  527. }
  528.  
  529.  
  530. /****************************************************************************
  531.   process commands from the client
  532. ****************************************************************************/
  533. static BOOL process(char *base_directory)
  534. {
  535.   extern FILE *dbf;
  536.   pstring line;
  537.   char *cmd;
  538.  
  539.   char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  540.   char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  541.  
  542.   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
  543.     return(False);
  544.   
  545.   bzero(OutBuffer,smb_size);
  546.  
  547.   if (!mount_send_login(InBuffer,OutBuffer))
  548.     return(False);
  549.  
  550.   cmd = cmdstr;
  551.   if (cmd[0] != '\0') while (cmd[0] != '\0')
  552.     {
  553.       char *p;
  554.       fstring tok;
  555.       int i;
  556.  
  557.       if ((p = strchr(cmd, ';')) == 0)
  558.     {
  559.       strncpy(line, cmd, 999);
  560.       line[1000] = '\0';
  561.       cmd += strlen(cmd);
  562.     }
  563.       else
  564.     {
  565.       if (p - cmd > 999) p = cmd + 999;
  566.       strncpy(line, cmd, p - cmd);
  567.       line[p - cmd] = '\0';
  568.       cmd = p + 1;
  569.     }
  570.  
  571.       /* input language code to internal one */
  572.       CNV_INPUT (line);
  573.       
  574.       /* and get the first part of the command */
  575.       {
  576.     char *ptr = line;
  577.     if (!next_token(&ptr,tok,NULL)) continue;
  578.       }
  579.  
  580.       if ((i = process_tok(tok)) >= 0)
  581.     commands[i].fn(InBuffer,OutBuffer);
  582.       else if (i == -2)
  583.     DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
  584.       else
  585.     DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
  586.     }
  587.   else while (!feof(stdin))
  588.     {
  589.       fstring tok;
  590.       int i;
  591.  
  592.       bzero(OutBuffer,smb_size);
  593.  
  594.       /* display a prompt */
  595.       DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
  596.       fflush(dbf);
  597.  
  598. #ifdef CLIX
  599.       line[0] = wait_keyboard(InBuffer);
  600.       /* this might not be such a good idea... */
  601.       if ( line[0] == EOF)
  602.     break;
  603. #else
  604.       wait_keyboard(InBuffer);
  605. #endif
  606.   
  607.       /* and get a response */
  608. #ifdef CLIX
  609.       fgets( &line[1],999, stdin);
  610. #else
  611.       if (!fgets(line,1000,stdin))
  612.     break;
  613. #endif
  614.  
  615.       /* input language code to internal one */
  616.       CNV_INPUT (line);
  617.  
  618.       /* special case - first char is ! */
  619.       if (*line == '!')
  620.     {
  621.       system(line + 1);
  622.       continue;
  623.     }
  624.       
  625.       /* and get the first part of the command */
  626.       {
  627.     char *ptr = line;
  628.     if (!next_token(&ptr,tok,NULL)) continue;
  629.       }
  630.  
  631.       if ((i = process_tok(tok)) >= 0)
  632.     commands[i].fn(InBuffer,OutBuffer);
  633.       else if (i == -2)
  634.     DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
  635.       else
  636.     DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
  637.     }
  638.   
  639.   cli_send_logout(InBuffer,OutBuffer);
  640.   return(True);
  641. }
  642.  
  643. /****************************************************************************
  644. usage on the program
  645. ****************************************************************************/
  646. static void usage(char *pname)
  647. {
  648.   DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
  649.        pname));
  650.  
  651.   DEBUG(0,("\nVersion %s\n",VERSION));
  652.   DEBUG(0,("\t-p port               connect to the specified port\n"));
  653.   DEBUG(0,("\t-d debuglevel         set the debuglevel\n"));
  654.   DEBUG(0,("\t-l log basename.      Basename for log/debug files\n"));
  655.   DEBUG(0,("\t-n netbios name.      Use this name as my netbios name\n"));
  656.   DEBUG(0,("\t-N                    don't ask for a password\n"));
  657.   DEBUG(0,("\t-m max protocol       set the max protocol level\n"));
  658.   DEBUG(0,("\t-I dest IP            use this IP to connect to\n"));
  659.   DEBUG(0,("\t-E                    write messages to stderr instead of stdout\n"));
  660.   DEBUG(0,("\t-U username           set the network username\n"));
  661.   DEBUG(0,("\t-W workgroup          set the workgroup name\n"));
  662.   DEBUG(0,("\t-c command string     execute semicolon separated commands\n"));
  663.   DEBUG(0,("\t-t terminal code      terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
  664.   DEBUG(0,("\t-D directory          start from directory\n"));
  665.   DEBUG(0,("\n"));
  666. }
  667.  
  668. /****************************************************************************
  669.   main program
  670. ****************************************************************************/
  671.  int main(int argc,char *argv[])
  672. {
  673.   fstring base_directory;
  674.   char *pname = argv[0];
  675.   int opt;
  676.   extern FILE *dbf;
  677.   extern char *optarg;
  678.   extern int optind;
  679.   pstring query_host;
  680.   BOOL nt_domain_logon = False;
  681.   static pstring servicesf = CONFIGFILE;
  682.   pstring term_code;
  683.   char *p;
  684.  
  685. #ifdef KANJI
  686.   pstrcpy(term_code, KANJI);
  687. #else /* KANJI */
  688.   *term_code = 0;
  689. #endif /* KANJI */
  690.  
  691.   *query_host = 0;
  692.   *base_directory = 0;
  693.  
  694.   DEBUGLEVEL = 2;
  695.  
  696.   setup_logging(pname,True);
  697.  
  698.   TimeInit();
  699.   charset_initialise();
  700.  
  701.   pid = getpid();
  702.   uid = getuid();
  703.   gid = getgid();
  704.   mid = pid + 100;
  705.   myumask = umask(0);
  706.   umask(myumask);
  707.  
  708.   if (getenv("USER"))
  709.   {
  710.     pstrcpy(username,getenv("USER"));
  711.  
  712.     /* modification to support userid%passwd syntax in the USER var
  713.        25.Aug.97, jdblair@uab.edu */
  714.  
  715.     if ((p=strchr(username,'%')))
  716.     {
  717.       *p = 0;
  718.       pstrcpy(password,p+1);
  719.       got_pass = True;
  720.       memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
  721.     }
  722.     strupper(username);
  723.   }
  724.  
  725.  /* modification to support PASSWD environmental var
  726.   25.Aug.97, jdblair@uab.edu */
  727.  
  728.   if (getenv("PASSWD"))
  729.     pstrcpy(password,getenv("PASSWD"));
  730.  
  731.   if (*username == 0 && getenv("LOGNAME"))
  732.     {
  733.       pstrcpy(username,getenv("LOGNAME"));
  734.       strupper(username);
  735.     }
  736.  
  737.   if (argc < 2)
  738.     {
  739.       usage(pname);
  740.       exit(1);
  741.     }
  742.   
  743.   if (*argv[1] != '-')
  744.     {
  745.  
  746.       pstrcpy(service, argv[1]);  
  747.       /* Convert any '/' characters in the service name to '\' characters */
  748.       string_replace( service, '/','\\');
  749.       argc--;
  750.       argv++;
  751.  
  752.       if (count_chars(service,'\\') < 3)
  753.     {
  754.       usage(pname);
  755.       printf("\n%s: Not enough '\\' characters in service\n",service);
  756.       exit(1);
  757.     }
  758.  
  759.       if (argc > 1 && (*argv[1] != '-'))
  760.     {
  761.       got_pass = True;
  762.       pstrcpy(password,argv[1]);  
  763.       memset(argv[1],'X',strlen(argv[1]));
  764.       argc--;
  765.       argv++;
  766.     }
  767.     }
  768.  
  769.   while ((opt = 
  770.       getopt(argc, argv,"s:B:O:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
  771.     switch (opt)
  772.       {
  773.       case 'm':
  774.     max_protocol = interpret_protocol(optarg,max_protocol);
  775.     break;
  776.       case 'O':
  777.     pstrcpy(user_socket_options,optarg);
  778.     break;    
  779.       case 'S':
  780.     pstrcpy(desthost,optarg);
  781.     strupper(desthost);
  782.     nt_domain_logon = True;
  783.     break;
  784.       case 'B':
  785.     iface_set_default(NULL,optarg,NULL);
  786.     break;
  787.       case 'D':
  788.     pstrcpy(base_directory,optarg);
  789.     break;
  790.       case 'i':
  791.     pstrcpy(scope,optarg);
  792.     break;
  793.       case 'U':
  794.     {
  795.       char *lp;
  796.     pstrcpy(username,optarg);
  797.     if ((lp=strchr(username,'%')))
  798.       {
  799.         *lp = 0;
  800.         pstrcpy(password,lp+1);
  801.         got_pass = True;
  802.         memset(strchr(optarg,'%')+1,'X',strlen(password));
  803.       }
  804.     }
  805.         
  806.     break;
  807.       case 'W':
  808.     pstrcpy(workgroup,optarg);
  809.     break;
  810.       case 'E':
  811.     dbf = stderr;
  812.     break;
  813.       case 'I':
  814.     {
  815.       dest_ip = *interpret_addr2(optarg);
  816.       if (zero_ip(dest_ip)) exit(1);
  817.       have_ip = True;
  818.     }
  819.     break;
  820.       case 'n':
  821.     pstrcpy(myname,optarg);
  822.     break;
  823.       case 'N':
  824.     got_pass = True;
  825.     break;
  826.       case 'd':
  827.     if (*optarg == 'A')
  828.       DEBUGLEVEL = 10000;
  829.     else
  830.       DEBUGLEVEL = atoi(optarg);
  831.     break;
  832.       case 'l':
  833.     slprintf(debugf,sizeof(debugf)-1,"%s.client",optarg);
  834.     break;
  835.       case 'p':
  836.     port = atoi(optarg);
  837.     break;
  838.       case 'c':
  839.     cmdstr = optarg;
  840.     got_pass = True;
  841.     break;
  842.       case 'h':
  843.     usage(pname);
  844.     exit(0);
  845.     break;
  846.       case 's':
  847.     pstrcpy(servicesf, optarg);
  848.     break;
  849.       case 't':
  850.         pstrcpy(term_code, optarg);
  851.     break;
  852.       default:
  853.     usage(pname);
  854.     exit(1);
  855.       }
  856.  
  857.   if (!*query_host && !*service)
  858.     {
  859.       usage(pname);
  860.       exit(1);
  861.     }
  862.  
  863.  
  864.   DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
  865.  
  866.   if(!get_myname(myhostname,NULL))
  867.   {
  868.     DEBUG(0,("Failed to get my hostname.\n"));
  869.   }
  870.  
  871.   if (!lp_load(servicesf,True)) {
  872.     fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
  873.   }
  874.  
  875.   codepage_initialise(lp_client_code_page());
  876.  
  877.   interpret_coding_system(term_code);
  878.  
  879.   if (*workgroup == 0)
  880.     pstrcpy(workgroup,lp_workgroup());
  881.  
  882.   load_interfaces();
  883.   get_myname((*myname)?NULL:myname,NULL);  
  884.   strupper(myname);
  885.  
  886. #ifdef NTDOMAIN
  887.  
  888.     if (nt_domain_logon)
  889.     {
  890.         int ret = 0;
  891.         slprintf(service,sizeof(service), "\\\\%s\\IPC$",query_host);
  892.         strupper(service);
  893.         connect_as_ipc = True;
  894.  
  895.         DEBUG(5,("NT Domain Logon.  Service: %s\n", service));
  896.  
  897.         if (cli_open_sockets(port))
  898.         {
  899.             if (!cli_send_login(NULL,NULL,True,True,NULL)) return(1);
  900.  
  901.             do_nt_login(desthost, myhostname, Client, cnum);
  902.  
  903.             cli_send_logout();
  904.             close_sockets();
  905.         }
  906.  
  907.         return(ret);
  908.     }
  909. #endif 
  910.  
  911.   if (cli_open_sockets(port))
  912.     {
  913.       if (!process(base_directory))
  914.     {
  915.       close_sockets();
  916.       return(1);
  917.     }
  918.       close_sockets();
  919.     }
  920.   else
  921.     return(1);
  922.  
  923.   return(0);
  924. }
  925.