2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1997
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.
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.
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.
27 #include <linux/smb_fs.h>
28 static struct smb_conn_opt conn_options;
34 pstring cur_dir = "\\";
36 extern pstring service;
37 extern pstring desthost;
38 extern pstring myname;
39 extern pstring myhostname;
40 extern pstring password;
41 extern pstring username;
42 extern pstring workgroup;
45 extern BOOL connect_as_printer;
46 extern BOOL connect_as_ipc;
47 extern struct in_addr ipzero;
49 extern BOOL doencrypt;
51 extern pstring user_socket_options;
53 /* 30 second timeout on most commands */
54 #define CLIENT_TIMEOUT (30*1000)
55 #define SHORT_TIMEOUT (5*1000)
57 /* value for unused fid field in trans2 secondary request */
58 #define FID_UNUSED (0xFFFF)
62 extern int max_protocol;
65 time_t newer_than = 0;
66 int archive_level = 0;
68 extern pstring debugf;
69 extern int DEBUGLEVEL;
71 BOOL translation = False;
83 /* clitar bits insert */
86 extern BOOL tar_reset;
99 BOOL lowercase = False;
101 struct in_addr dest_ip;
103 #define SEPARATORS " \t\n\r"
105 BOOL abort_mget = True;
109 extern BOOL readbraw_supported ;
110 extern BOOL writebraw_supported;
112 pstring fileselection = "";
114 extern file_info def_finfo;
117 int get_total_size = 0;
118 int get_total_time_ms = 0;
119 int put_total_size = 0;
120 int put_total_time_ms = 0;
129 static BOOL setup_term_code(char *code)
131 interpret_coding_system(code);
134 #define CNV_LANG(s) dos2unix_format(s,False)
135 #define CNV_INPUT(s) unix2dos_format(s,True)
137 /****************************************************************************
138 check for existance of a dir
139 ****************************************************************************/
140 static BOOL chkpath(char *path,BOOL report)
143 pstring inbuf,outbuf;
147 trim_string(path2,NULL,"\\");
148 if (!*path2) *path2 = '\\';
150 bzero(outbuf,smb_size);
151 set_message(outbuf,0,4 + strlen(path2),True);
152 SCVAL(outbuf,smb_com,SMBchkpth);
153 SSVAL(outbuf,smb_tid,cnum);
154 cli_setup_pkt(outbuf);
162 /* this little bit of code can be used to extract NT error codes.
163 Just feed a bunch of "cd foo" commands to smbclient then watch
164 in netmon (tridge) */
166 SIVAL(outbuf, smb_rcls, code | 0xC0000000);
167 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
172 send_smb(Client,outbuf);
173 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
175 if (report && CVAL(inbuf,smb_rcls) != 0)
176 DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
178 return(CVAL(inbuf,smb_rcls) == 0);
182 /* #define SMBFS_DEBUG 1 */
188 if ((i = fork()) < 0)
190 DEBUG(0, ("could not fork\n"));
194 /* parent simply exits */
202 close_our_files(void)
205 for (i = 0; i < NR_OPEN; i++) {
220 * Send a login and store the connection options. This is a separate
221 * function to keep clientutil.c independent of linux kernel changes.
223 static BOOL mount_send_login(char *inbuf, char *outbuf)
225 struct connection_options opt;
226 int res = cli_send_login(inbuf, outbuf, True, True, &opt);
231 conn_options.protocol = opt.protocol;
232 conn_options.case_handling = CASE_LOWER;
233 conn_options.max_xmit = opt.max_xmit;
234 conn_options.server_uid = opt.server_uid;
235 conn_options.tid = opt.tid;
236 conn_options.secmode = opt.sec_mode;
237 conn_options.maxmux = opt.max_mux;
238 conn_options.maxvcs = opt.max_vcs;
239 conn_options.rawmode = opt.rawmode;
240 conn_options.sesskey = opt.sesskey;
241 conn_options.maxraw = opt.maxraw;
242 conn_options.capabilities = opt.capabilities;
243 conn_options.serverzone = opt.serverzone;
249 * Call the smbfs ioctl to install a connection socket,
250 * then wait for a signal to reconnect. Note that we do
251 * not exit after open_sockets() or send_login() errors,
252 * as the smbfs mount would then have no way to recover.
255 send_fs_socket(char *mount_point, char *inbuf, char *outbuf)
257 int fd, closed = 0, res = 1;
261 if ((fd = open(mount_point, O_RDONLY)) < 0)
264 printf("smbclient: can't open %s\n", mount_point);
270 * Call the ioctl even if we couldn't get a socket ...
271 * there's no point in making smbfs wait for a timeout.
273 conn_options.fd = -1;
275 conn_options.fd = Client;
276 res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options);
280 printf("smbclient: ioctl failed, res=%d\n",res);
287 * Close all open files if we haven't done so yet.
298 * Wait for a signal from smbfs ...
300 signal(SIGUSR1, &usr1_handler);
303 printf("smbclient: got signal, getting new socket\n");
306 res = mount_send_login(inbuf,outbuf);
310 printf("smbclient: login failed\n");
315 printf("smbclient: exit\n");
320 /****************************************************************************
322 ****************************************************************************/
323 static void cmd_mount(char *inbuf,char *outbuf)
326 char mount_point[MAXPATHLEN+1];
327 pstring mount_command;
331 if (!next_token(NULL, mpoint, NULL))
333 DEBUG(0,("You must supply a mount point\n"));
337 memset(mount_point, 0, sizeof(mount_point));
339 if (realpath(mpoint, mount_point) == NULL)
341 DEBUG(0, ("Could not resolve mount point\n"));
345 sprintf(mount_command, "smbmnt %s", mount_point);
347 while(next_token(NULL, buf, NULL))
349 strcat(mount_command, " ");
350 strcat(mount_command, buf);
353 DEBUG(3,("mount command: %s\n", mount_command));
356 * Create the background process before trying the mount.
357 * (We delay closing files to allow diagnostic messages.)
361 /* The parent has exited here, the child handles the connection: */
362 if ((retval = system(mount_command)) != 0)
364 DEBUG(0,("mount failed\n"));
367 send_fs_socket(mount_point, inbuf, outbuf);
374 /* This defines the commands supported by this client */
382 {"mount", cmd_mount, "<mount-point options> mount an smbfs file system"},
387 /*******************************************************************
388 lookup a command string in the list of commands, including
390 ******************************************************************/
391 static int process_tok(fstring tok)
393 int i = 0, matches = 0;
395 int tok_len = strlen(tok);
397 while (commands[i].fn != NULL)
399 if (strequal(commands[i].name,tok))
405 else if (strnequal(commands[i].name, tok, tok_len))
415 else if (matches == 1)
421 /****************************************************************************
423 ****************************************************************************/
429 if (next_token(NULL,buf,NULL))
431 if ((i = process_tok(buf)) >= 0)
432 DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));
435 while (commands[i].description)
437 for (j=0; commands[i].description && (j<5); j++) {
438 DEBUG(0,("%-15s",commands[i].name));
445 /****************************************************************************
446 wait for keyboard activity, swallowing network packets
447 ****************************************************************************/
449 static char wait_keyboard(char *buffer)
451 static void wait_keyboard(char *buffer)
456 struct timeval timeout;
468 FD_SET(fileno(stdin),&fds);
476 selrtn = sys_select(&fds,&timeout);
479 if (FD_ISSET(fileno(stdin),&fds))
486 set_blocking(fileno(stdin), False);
487 readret = read_data( fileno(stdin), &ch, 1);
488 set_blocking(fileno(stdin), True);
493 /* should crash here */
494 DEBUG(1,("readchar stdin failed\n"));
497 else if (readret != 0)
504 /* We deliberately use receive_smb instead of
505 client_receive_smb as we want to receive
506 session keepalives and then drop them here.
508 if (FD_ISSET(Client,&fds))
509 receive_smb(Client,buffer,0);
525 /****************************************************************************
526 process commands from the client
527 ****************************************************************************/
528 static BOOL process(char *base_directory)
534 char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
535 char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
537 if ((InBuffer == NULL) || (OutBuffer == NULL))
540 bzero(OutBuffer,smb_size);
542 if (!mount_send_login(InBuffer,OutBuffer))
546 if (cmd[0] != '\0') while (cmd[0] != '\0')
552 if ((p = strchr(cmd, ';')) == 0)
554 strncpy(line, cmd, 999);
560 if (p - cmd > 999) p = cmd + 999;
561 strncpy(line, cmd, p - cmd);
562 line[p - cmd] = '\0';
566 /* input language code to internal one */
569 /* and get the first part of the command */
572 if (!next_token(&ptr,tok,NULL)) continue;
575 if ((i = process_tok(tok)) >= 0)
576 commands[i].fn(InBuffer,OutBuffer);
578 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
580 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
582 else while (!feof(stdin))
587 bzero(OutBuffer,smb_size);
589 /* display a prompt */
590 DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir)));
594 line[0] = wait_keyboard(InBuffer);
595 /* this might not be such a good idea... */
599 wait_keyboard(InBuffer);
602 /* and get a response */
604 fgets( &line[1],999, stdin);
606 if (!fgets(line,1000,stdin))
610 /* input language code to internal one */
613 /* special case - first char is ! */
620 /* and get the first part of the command */
623 if (!next_token(&ptr,tok,NULL)) continue;
626 if ((i = process_tok(tok)) >= 0)
627 commands[i].fn(InBuffer,OutBuffer);
629 DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
631 DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
638 /****************************************************************************
640 ****************************************************************************/
641 static void usage(char *pname)
643 DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
646 DEBUG(0,("\nVersion %s\n",VERSION));
647 DEBUG(0,("\t-p port connect to the specified port\n"));
648 DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
649 DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
650 DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
651 DEBUG(0,("\t-N don't ask for a password\n"));
652 DEBUG(0,("\t-P connect to service as a printer\n"));
653 DEBUG(0,("\t-M host send a winpopup message to the host\n"));
654 DEBUG(0,("\t-m max protocol set the max protocol level\n"));
655 DEBUG(0,("\t-L host get a list of shares available on a host\n"));
656 DEBUG(0,("\t-I dest IP use this IP to connect to\n"));
657 DEBUG(0,("\t-E write messages to stderr instead of stdout\n"));
658 DEBUG(0,("\t-U username set the network username\n"));
659 DEBUG(0,("\t-W workgroup set the workgroup name\n"));
660 DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
661 DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
662 DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
663 DEBUG(0,("\t-D directory start from directory\n"));
667 /****************************************************************************
669 ****************************************************************************/
670 int main(int argc,char *argv[])
672 fstring base_directory;
673 char *pname = argv[0];
680 BOOL nt_domain_logon = False;
681 static pstring servicesf = CONFIGFILE;
686 strcpy(term_code, KANJI);
696 setup_logging(pname,True);
699 charset_initialise();
710 strcpy(username,getenv("USER"));
712 /* modification to support userid%passwd syntax in the USER var
713 25.Aug.97, jdblair@uab.edu */
715 if ((p=strchr(username,'%')))
718 strcpy(password,p+1);
720 memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
725 /* modification to support PASSWD environmental var
726 25.Aug.97, jdblair@uab.edu */
728 if (getenv("PASSWD"))
729 strcpy(password,getenv("PASSWD"));
731 if (*username == 0 && getenv("LOGNAME"))
733 strcpy(username,getenv("LOGNAME"));
746 strcpy(service,argv[1]);
747 /* Convert any '/' characters in the service name to '\' characters */
748 string_replace( service, '/','\\');
752 if (count_chars(service,'\\') < 3)
755 printf("\n%s: Not enough '\\' characters in service\n",service);
760 if (count_chars(service,'\\') > 3)
763 printf("\n%s: Too many '\\' characters in service\n",service);
768 if (argc > 1 && (*argv[1] != '-'))
771 strcpy(password,argv[1]);
772 memset(argv[1],'X',strlen(argv[1]));
779 getopt(argc, argv,"s:B:O:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
783 max_protocol = interpret_protocol(optarg,max_protocol);
786 strcpy(user_socket_options,optarg);
789 strcpy(desthost,optarg);
791 nt_domain_logon = True;
794 iface_set_default(NULL,optarg,NULL);
797 strcpy(base_directory,optarg);
800 strcpy(scope,optarg);
805 strcpy(username,optarg);
806 if ((lp=strchr(username,'%')))
809 strcpy(password,lp+1);
811 memset(strchr(optarg,'%')+1,'X',strlen(password));
817 strcpy(workgroup,optarg);
824 dest_ip = *interpret_addr2(optarg);
825 if (zero_ip(dest_ip)) exit(1);
830 strcpy(myname,optarg);
839 DEBUGLEVEL = atoi(optarg);
842 sprintf(debugf,"%s.client",optarg);
856 strcpy(servicesf, optarg);
859 strcpy(term_code, optarg);
866 if (!*query_host && !*service)
873 DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
875 if(!get_myname(myhostname,NULL))
877 DEBUG(0,("Failed to get my hostname.\n"));
880 if (!lp_load(servicesf,True)) {
881 fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
884 codepage_initialise(lp_client_code_page());
886 if(lp_client_code_page() == KANJI_CODEPAGE)
888 if (!setup_term_code (term_code))
890 DEBUG(0, ("%s: unknown terminal code name\n", optarg));
897 strcpy(workgroup,lp_workgroup());
900 get_myname((*myname)?NULL:myname,NULL);
908 sprintf(service,"\\\\%s\\IPC$",query_host);
910 connect_as_ipc = True;
912 DEBUG(5,("NT Domain Logon. Service: %s\n", service));
914 if (cli_open_sockets(port))
916 if (!cli_send_login(NULL,NULL,True,True,NULL)) return(1);
918 do_nt_login(desthost, myhostname, Client, cnum);
928 if (cli_open_sockets(port))
930 if (!process(base_directory))