diff options
Diffstat (limited to 'source/client/client.c')
-rw-r--r-- | source/client/client.c | 2339 |
1 files changed, 867 insertions, 1472 deletions
diff --git a/source/client/client.c b/source/client/client.c index 504cb5a0bb4..68cd930cf93 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. SMB client - Copyright (C) Andrew Tridgell 1994-1995 + Copyright (C) Andrew Tridgell 1994-1997 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,7 +24,6 @@ #endif #include "includes.h" -#include "nameserv.h" #ifndef REGISTER #define REGISTER 0 @@ -32,20 +31,21 @@ pstring cur_dir = "\\"; pstring cd_path = ""; -pstring service=""; -pstring desthost=""; -pstring myname = ""; -pstring password = ""; -pstring username=""; -pstring workgroup=WORKGROUP; -BOOL got_pass = False; -BOOL connect_as_printer = False; -BOOL connect_as_ipc = False; -extern struct in_addr bcast_ip; -static BOOL got_bcast=False; +extern pstring service; +extern pstring desthost; +extern pstring myname; +extern pstring myhostname; +extern pstring password; +extern pstring username; +extern pstring workgroup; +char *cmdstr=""; +extern BOOL got_pass; +extern BOOL connect_as_printer; +extern BOOL connect_as_ipc; +extern struct in_addr ipzero; char cryptkey[8]; -BOOL doencrypt=False; +extern BOOL doencrypt; extern pstring user_socket_options; @@ -56,43 +56,43 @@ extern pstring user_socket_options; /* value for unused fid field in trans2 secondary request */ #define FID_UNUSED (0xFFFF) -int name_type = 0x20; +extern int name_type; -int max_protocol = PROTOCOL_NT1; +extern int max_protocol; time_t newer_than = 0; int archive_level = 0; -extern struct in_addr myip; - extern pstring debugf; extern int DEBUGLEVEL; BOOL translation = False; +extern int cnum; +extern int mid; +extern int pid; +extern int tid; +extern int gid; +extern int uid; + +extern BOOL have_ip; +extern int max_xmit; + +static int interpret_long_filename(int level,char *p,file_info *finfo); +static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir); +static int interpret_short_filename(char *p,file_info *finfo); +static BOOL do_this_one(file_info *finfo); + /* clitar bits insert */ -extern void cmd_tar(); -extern void cmd_block(); -extern void cmd_tarmode(); -extern void cmd_setmode(); extern int blocksize; extern BOOL tar_inc; extern BOOL tar_reset; -extern int process_tar(); -extern int tar_parseargs(); /* clitar bits end */ -int cnum = 0; -int pid = 0; -int gid = 0; -int uid = 0; -int mid = 0; int myumask = 0755; -int max_xmit = BUFFER_SIZE; - extern pstring scope; BOOL prompt = True; @@ -102,8 +102,6 @@ int printmode = 1; BOOL recurse = False; BOOL lowercase = False; -BOOL have_ip = False; - struct in_addr dest_ip; #define SEPARATORS " \t\n\r" @@ -112,8 +110,8 @@ BOOL abort_mget = True; extern int Protocol; -BOOL readbraw_supported = False; -BOOL writebraw_supported = False; +extern BOOL readbraw_supported ; +extern BOOL writebraw_supported; pstring fileselection = ""; @@ -125,17 +123,15 @@ int get_total_time_ms = 0; int put_total_size = 0; int put_total_time_ms = 0; +/* totals globals */ +int dir_total = 0; extern int Client; #define USENMB -#ifdef KANJI extern int coding_system; -#define CNV_LANG(s) (coding_system == DOSV_CODE?s:dos_to_unix(s, False)) -#define CNV_INPUT(s) (coding_system == DOSV_CODE?s:unix_to_dos(s, True)) -static BOOL -setup_term_code (char *code) +static BOOL setup_term_code (char *code) { int new; new = interpret_coding_system (code, UNKNOWN_CODE); @@ -145,38 +141,25 @@ setup_term_code (char *code) } return False; } -#else #define CNV_LANG(s) dos2unix_format(s,False) #define CNV_INPUT(s) unix2dos_format(s,True) -#endif - -static void send_logout(void ); -BOOL reopen_connection(char *inbuf,char *outbuf); -static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir); -static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir); -static BOOL call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt, - int *rprcnt,int *rdrcnt,char *param,char *data, - char **rparam,char **rdata); -static BOOL send_trans_request(char *outbuf,int trans, - char *name,int fid,int flags, - char *data,char *param,uint16 *setup, - int ldata,int lparam,int lsetup, - int mdata,int mparam,int msetup); - /**************************************************************************** -setup basics in a outgoing packet +send an SMBclose on an SMB file handle ****************************************************************************/ -void setup_pkt(char *outbuf) +void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num) { - SSVAL(outbuf,smb_pid,pid); - SSVAL(outbuf,smb_uid,uid); - SSVAL(outbuf,smb_mid,mid); - if (Protocol > PROTOCOL_CORE) - { - SCVAL(outbuf,smb_flg,0x8); - SSVAL(outbuf,smb_flg2,0x1); - } + bzero(outbuf,smb_size); + set_message(outbuf,3,0,True); + + CVAL (outbuf,smb_com) = SMBclose; + SSVAL(outbuf,smb_tid,c_num); + cli_setup_pkt(outbuf); + SSVAL (outbuf,smb_vwv0, f_num); + SIVALS(outbuf,smb_vwv1, -1); + + send_smb(clnt_fd, outbuf); + receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT); } /**************************************************************************** @@ -234,7 +217,8 @@ static int readfile(char *b, int size, int n, FILE *f) n++; } - b[i++] = c; + if(i < n) + b[i++] = c; } return(i); @@ -275,12 +259,24 @@ static BOOL chkpath(char *path,BOOL report) set_message(outbuf,0,4 + strlen(path2),True); SCVAL(outbuf,smb_com,SMBchkpth); SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); p = smb_buf(outbuf); *p++ = 4; strcpy(p,path2); +#if 0 + { + /* this little bit of code can be used to extract NT error codes. + Just feed a bunch of "cd foo" commands to smbclient then watch + in netmon (tridge) */ + static int code=0; + SIVAL(outbuf, smb_rcls, code | 0xC0000000); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14)); + code++; + } +#endif + send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); @@ -403,7 +399,7 @@ static void do_dskattr(void) set_message(outbuf,0,0,True); CVAL(outbuf,smb_com) = SMBdskattr; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); @@ -477,209 +473,188 @@ static void cmd_cd(char *inbuf,char *outbuf) ****************************************************************************/ static void display_finfo(file_info *finfo) { - time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */ - DEBUG(0,(" %-30s%7.7s%10d %s", - CNV_LANG(finfo->name), + if (do_this_one(finfo)) { + time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */ + DEBUG(0,(" %-30s%7.7s%10d %s", + CNV_LANG(finfo->name), attrib_string(finfo->mode), finfo->size, - asctime(LocalTime(&t,GMT_TO_LOCAL)))); + asctime(LocalTime(&t)))); + dir_total += finfo->size; + } } + /**************************************************************************** - do a directory listing, calling fn on each file found + do a directory listing, calling fn on each file found. Use the TRANSACT2 + call for long filenames ****************************************************************************/ -void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir) -{ - DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir))); - if (Protocol >= PROTOCOL_LANMAN2) - { - if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0) - return; - } - - expand_mask(Mask,False); - do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir); - return; -} - -/******************************************************************* - decide if a file should be operated on - ********************************************************************/ -static BOOL do_this_one(file_info *finfo) +static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir) { - if (finfo->mode & aDIR) return(True); - - if (newer_than && finfo->mtime < newer_than) - return(False); - - if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH)) - return(False); - - return(True); -} + int max_matches = 512; + int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */ + char *p; + pstring mask; + file_info finfo; + int i; + char *dirlist = NULL; + int dirlist_len = 0; + int total_received = 0; + BOOL First = True; + char *resp_data=NULL; + char *resp_param=NULL; + int resp_data_len = 0; + int resp_param_len=0; -/**************************************************************************** -interpret a short filename structure -The length of the structure is returned -****************************************************************************/ -static int interpret_short_filename(char *p,file_info *finfo) -{ - finfo->mode = CVAL(p,21); + int ff_resume_key = 0; + int ff_searchcount=0; + int ff_eos=0; + int ff_lastname=0; + int ff_dir_handle=0; + int loop_count = 0; - /* this date is converted to GMT by make_unix_date */ - finfo->ctime = make_unix_date(p+22); - finfo->mtime = finfo->atime = finfo->ctime; - finfo->size = IVAL(p,26); - strcpy(finfo->name,p+30); - - return(DIR_STRUCT_SIZE); -} + uint16 setup; + pstring param; -/**************************************************************************** -interpret a long filename structure - this is mostly guesses at the moment -The length of the structure is returned -The structure of a long filename depends on the info level. 260 is used -by NT and 2 is used by OS/2 -****************************************************************************/ -static int interpret_long_filename(int level,char *p,file_info *finfo) -{ - if (finfo) - memcpy(finfo,&def_finfo,sizeof(*finfo)); + strcpy(mask,Mask); - switch (level) + while (ff_eos == 0) { - case 1: /* OS/2 understands this */ - if (finfo) + loop_count++; + if (loop_count > 200) { - /* these dates are converted to GMT by make_unix_date */ - finfo->ctime = make_unix_date2(p+4); - finfo->atime = make_unix_date2(p+8); - finfo->mtime = make_unix_date2(p+12); - finfo->size = IVAL(p,16); - finfo->mode = CVAL(p,24); - strcpy(finfo->name,p+27); + DEBUG(0,("Error: Looping in FIND_NEXT??\n")); + break; } - return(28 + CVAL(p,26)); - case 2: /* this is what OS/2 uses mostly */ - if (finfo) + if (First) { - /* these dates are converted to GMT by make_unix_date */ - finfo->ctime = make_unix_date2(p+4); - finfo->atime = make_unix_date2(p+8); - finfo->mtime = make_unix_date2(p+12); - finfo->size = IVAL(p,16); - finfo->mode = CVAL(p,24); - strcpy(finfo->name,p+31); + setup = TRANSACT2_FINDFIRST; + SSVAL(param,0,attribute); /* attribute */ + SSVAL(param,2,max_matches); /* max count */ + SSVAL(param,4,8+4+2); /* resume required + close on end + continue */ + SSVAL(param,6,info_level); + SIVAL(param,8,0); + strcpy(param+12,mask); } - return(32 + CVAL(p,30)); - - /* levels 3 and 4 are untested */ - case 3: - if (finfo) + else { - /* these dates are probably like the other ones */ - finfo->ctime = make_unix_date2(p+8); - finfo->atime = make_unix_date2(p+12); - finfo->mtime = make_unix_date2(p+16); - finfo->size = IVAL(p,20); - finfo->mode = CVAL(p,28); - strcpy(finfo->name,p+33); + setup = TRANSACT2_FINDNEXT; + SSVAL(param,0,ff_dir_handle); + SSVAL(param,2,max_matches); /* max count */ + SSVAL(param,4,info_level); + SIVAL(param,6,ff_resume_key); /* ff_resume_key */ + SSVAL(param,10,8+4+2); /* resume required + close on end + continue */ + strcpy(param+12,mask); + + DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", + ff_dir_handle,ff_resume_key,ff_lastname,mask)); } - return(SVAL(p,4)+4); + /* ??? original code added 1 pad byte after param */ - case 4: - if (finfo) + cli_send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0, + NULL,param,&setup, + 0,12+strlen(mask)+1,1, + BUFFER_SIZE,10,0); + + if (!cli_receive_trans_response(inbuf,SMBtrans2, + &resp_data_len,&resp_param_len, + &resp_data,&resp_param)) { - /* these dates are probably like the other ones */ - finfo->ctime = make_unix_date2(p+8); - finfo->atime = make_unix_date2(p+12); - finfo->mtime = make_unix_date2(p+16); - finfo->size = IVAL(p,20); - finfo->mode = CVAL(p,28); - strcpy(finfo->name,p+37); + DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf))); + break; } - return(SVAL(p,4)+4); - case 260: /* NT uses this, but also accepts 2 */ - if (finfo) + /* parse out some important return info */ + p = resp_param; + if (First) { - int ret = SVAL(p,0); - int namelen; - p += 4; /* next entry offset */ - p += 4; /* fileindex */ + ff_dir_handle = SVAL(p,0); + ff_searchcount = SVAL(p,2); + ff_eos = SVAL(p,4); + ff_lastname = SVAL(p,8); + } + else + { + ff_searchcount = SVAL(p,0); + ff_eos = SVAL(p,2); + ff_lastname = SVAL(p,6); + } - /* these dates appear to arrive in a weird way. It seems to - be localtime plus the serverzone given in the initial - connect. This is GMT when DST is not in effect and one - hour from GMT otherwise. Can this really be right?? + if (ff_searchcount == 0) + break; - I suppose this could be called kludge-GMT. Is is the GMT - you get by using the current DST setting on a different - localtime. It will be cheap to calculate, I suppose, as - no DST tables will be needed */ + /* point to the data bytes */ + p = resp_data; - finfo->ctime = interpret_long_date(p); p += 8; - finfo->atime = interpret_long_date(p); p += 8; - finfo->mtime = interpret_long_date(p); p += 8; p += 8; - finfo->size = IVAL(p,0); p += 8; - p += 8; /* alloc size */ - finfo->mode = CVAL(p,0); p += 4; - namelen = IVAL(p,0); p += 4; - p += 4; /* EA size */ - p += 2; /* short name len? */ - p += 24; /* short name? */ - StrnCpy(finfo->name,p,namelen); - return(ret); + /* we might need the lastname for continuations */ + if (ff_lastname > 0) + { + switch(info_level) + { + case 260: + ff_resume_key =0; + StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname); + /* strcpy(mask,p+ff_lastname+94); */ + break; + case 1: + strcpy(mask,p + ff_lastname + 1); + ff_resume_key = 0; + break; + } } - return(SVAL(p,0)); - } - - DEBUG(1,("Unknown long filename format %d\n",level)); - return(SVAL(p,0)); -} + else + strcpy(mask,""); + + /* and add them to the dirlist pool */ + dirlist = Realloc(dirlist,dirlist_len + resp_data_len); + if (!dirlist) + { + DEBUG(0,("Failed to expand dirlist\n")); + break; + } + /* put in a length for the last entry, to ensure we can chain entries + into the next packet */ + { + char *p2; + for (p2=p,i=0;i<(ff_searchcount-1);i++) + p2 += interpret_long_filename(info_level,p2,NULL); + SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p)); + } + /* grab the data for later use */ + memcpy(dirlist+dirlist_len,p,resp_data_len); + dirlist_len += resp_data_len; -/**************************************************************************** - act on the files in a dir listing - ****************************************************************************/ -static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir) -{ + total_received += ff_searchcount; - if (!((finfo->mode & aDIR) == 0 && *fileselection && - !mask_match(finfo->name,fileselection,False,False)) && - !(recurse_dir && (strequal(finfo->name,".") || - strequal(finfo->name,"..")))) - { - if (recurse_dir && (finfo->mode & aDIR)) - { - pstring mask2; - pstring sav_dir; - strcpy(sav_dir,cur_dir); - strcat(cur_dir,finfo->name); - strcat(cur_dir,"\\"); - strcpy(mask2,cur_dir); + if (resp_data) free(resp_data); resp_data = NULL; + if (resp_param) free(resp_param); resp_param = NULL; - if (!fn) - DEBUG(0,("\n%s\n",CNV_LANG(cur_dir))); + DEBUG(3,("received %d entries (eos=%d resume=%d)\n", + ff_searchcount,ff_eos,ff_resume_key)); - strcat(mask2,"*"); + First = False; + } - if (longdir) - do_long_dir(inbuf,outbuf,mask2,attribute,fn,True); - else - do_dir(inbuf,outbuf,mask2,attribute,fn,True); + if (!fn) + for (p=dirlist,i=0;i<total_received;i++) + { + p += interpret_long_filename(info_level,p,&finfo); + display_finfo(&finfo); + } - strcpy(cur_dir,sav_dir); - } - else - { - if (fn && do_this_one(finfo)) - fn(finfo); - } + for (p=dirlist,i=0;i<total_received;i++) + { + p += interpret_long_filename(info_level,p,&finfo); + dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True); } + + /* free up the dirlist buffer */ + if (dirlist) free(dirlist); + return(total_received); } @@ -721,7 +696,7 @@ static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void ( CVAL(outbuf,smb_com) = SMBsearch; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,num_asked); SSVAL(outbuf,smb_vwv1,attribute); @@ -782,7 +757,7 @@ static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void ( CVAL(outbuf,smb_com) = SMBfclose; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); p = smb_buf(outbuf); *p++ = 4; @@ -796,7 +771,7 @@ static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void ( memcpy(p,status,21); send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT,False); + receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf))); @@ -820,249 +795,231 @@ static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void ( return(num_received); } + + /**************************************************************************** - receive a SMB trans or trans2 response allocating the necessary memory + do a directory listing, calling fn on each file found ****************************************************************************/ -static BOOL receive_trans_response(char *inbuf,int trans, - int *data_len,int *param_len, - char **data,char **param) +void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir) { - int total_data=0; - int total_param=0; - int this_data,this_param; + DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir))); + if (Protocol >= PROTOCOL_LANMAN2) + { + if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0) + return; + } - *data_len = *param_len = 0; + expand_mask(Mask,False); + do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir); + return; +} - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - show_msg(inbuf); +/******************************************************************* + decide if a file should be operated on + ********************************************************************/ +static BOOL do_this_one(file_info *finfo) +{ + if (finfo->mode & aDIR) return(True); - /* sanity check */ - if (CVAL(inbuf,smb_com) != trans) - { - DEBUG(0,("Expected %s response, got command 0x%02x\n", - trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com))); - return(False); - } - if (CVAL(inbuf,smb_rcls) != 0) + if (newer_than && finfo->mtime < newer_than) return(False); - /* parse out the lengths */ - total_data = SVAL(inbuf,smb_tdrcnt); - total_param = SVAL(inbuf,smb_tprcnt); + if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH)) + return(False); - /* allocate it */ - *data = Realloc(*data,total_data); - *param = Realloc(*param,total_param); + return(True); +} - while (1) - { - this_data = SVAL(inbuf,smb_drcnt); - this_param = SVAL(inbuf,smb_prcnt); - if (this_data) - memcpy(*data + SVAL(inbuf,smb_drdisp), - smb_base(inbuf) + SVAL(inbuf,smb_droff), - this_data); - if (this_param) - memcpy(*param + SVAL(inbuf,smb_prdisp), - smb_base(inbuf) + SVAL(inbuf,smb_proff), - this_param); - *data_len += this_data; - *param_len += this_param; - - /* parse out the total lengths again - they can shrink! */ - total_data = SVAL(inbuf,smb_tdrcnt); - total_param = SVAL(inbuf,smb_tprcnt); - - if (total_data <= *data_len && total_param <= *param_len) - break; - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - show_msg(inbuf); +/***************************************************************************** + Convert a character pointer in a cli_call_api() response to a form we can use. + This function contains code to prevent core dumps if the server returns + invalid data. +*****************************************************************************/ +static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt) +{ +if( datap == 0 ) /* turn NULL pointers */ + { /* into zero length strings */ + return ""; + } +else + { + unsigned int offset = datap - converter; - /* sanity check */ - if (CVAL(inbuf,smb_com) != trans) - { - DEBUG(0,("Expected %s response, got command 0x%02x\n", - trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com))); - return(False); - } - if (CVAL(inbuf,smb_rcls) != 0) - return(False); + if( offset >= rdrcnt ) + { + DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%lu, rdrcnt=%d>", datap, converter, (unsigned long)rdata, rdrcnt)); + return "<ERROR>"; } - - return(True); + else + { + return &rdata[offset]; + } + } } /**************************************************************************** - do a directory listing, calling fn on each file found. Use the TRANSACT2 - call for long filenames - ****************************************************************************/ -static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir) +interpret a short filename structure +The length of the structure is returned +****************************************************************************/ +static int interpret_short_filename(char *p,file_info *finfo) { - int max_matches = 512; - int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */ - char *p; - pstring mask; - file_info finfo; - int i; - char *dirlist = NULL; - int dirlist_len = 0; - int total_received = 0; - BOOL First = True; - char *resp_data=NULL; - char *resp_param=NULL; - int resp_data_len = 0; - int resp_param_len=0; - - int ff_resume_key = 0; - int ff_searchcount=0; - int ff_eos=0; - int ff_lastname=0; - int ff_dir_handle=0; - int loop_count = 0; + finfo->mode = CVAL(p,21); - uint16 setup; - pstring param; + /* this date is converted to GMT by make_unix_date */ + finfo->ctime = make_unix_date(p+22); + finfo->mtime = finfo->atime = finfo->ctime; + finfo->size = IVAL(p,26); + strcpy(finfo->name,p+30); + + return(DIR_STRUCT_SIZE); +} - strcpy(mask,Mask); +/**************************************************************************** +interpret a long filename structure - this is mostly guesses at the moment +The length of the structure is returned +The structure of a long filename depends on the info level. 260 is used +by NT and 2 is used by OS/2 +****************************************************************************/ +static int interpret_long_filename(int level,char *p,file_info *finfo) +{ + if (finfo) + memcpy(finfo,&def_finfo,sizeof(*finfo)); - while (ff_eos == 0) + switch (level) { - loop_count++; - if (loop_count > 200) + case 1: /* OS/2 understands this */ + if (finfo) { - DEBUG(0,("ERROR: Looping in FIND_NEXT??\n")); - break; + /* these dates are converted to GMT by make_unix_date */ + finfo->ctime = make_unix_date2(p+4); + finfo->atime = make_unix_date2(p+8); + finfo->mtime = make_unix_date2(p+12); + finfo->size = IVAL(p,16); + finfo->mode = CVAL(p,24); + strcpy(finfo->name,p+27); } + return(28 + CVAL(p,26)); - if (First) - { - setup = TRANSACT2_FINDFIRST; - SSVAL(param,0,attribute); /* attribute */ - SSVAL(param,2,max_matches); /* max count */ - SSVAL(param,4,8+4+2); /* resume required + close on end + continue */ - SSVAL(param,6,info_level); - SIVAL(param,8,0); - strcpy(param+12,mask); - } - else + case 2: /* this is what OS/2 uses mostly */ + if (finfo) { - setup = TRANSACT2_FINDNEXT; - SSVAL(param,0,ff_dir_handle); - SSVAL(param,2,max_matches); /* max count */ - SSVAL(param,4,info_level); - SIVAL(param,6,ff_resume_key); /* ff_resume_key */ - SSVAL(param,10,8+4+2); /* resume required + close on end + continue */ - strcpy(param+12,mask); - - DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", - ff_dir_handle,ff_resume_key,ff_lastname,mask)); + /* these dates are converted to GMT by make_unix_date */ + finfo->ctime = make_unix_date2(p+4); + finfo->atime = make_unix_date2(p+8); + finfo->mtime = make_unix_date2(p+12); + finfo->size = IVAL(p,16); + finfo->mode = CVAL(p,24); + strcpy(finfo->name,p+31); } - /* ??? original code added 1 pad byte after param */ - - send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0, - NULL,param,&setup, - 0,12+strlen(mask)+1,1, - BUFFER_SIZE,10,0); + return(32 + CVAL(p,30)); - if (!receive_trans_response(inbuf,SMBtrans2, - &resp_data_len,&resp_param_len, - &resp_data,&resp_param)) + /* levels 3 and 4 are untested */ + case 3: + if (finfo) { - DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf))); - break; + /* these dates are probably like the other ones */ + finfo->ctime = make_unix_date2(p+8); + finfo->atime = make_unix_date2(p+12); + finfo->mtime = make_unix_date2(p+16); + finfo->size = IVAL(p,20); + finfo->mode = CVAL(p,28); + strcpy(finfo->name,p+33); } + return(SVAL(p,4)+4); - /* parse out some important return info */ - p = resp_param; - if (First) + case 4: + if (finfo) { - ff_dir_handle = SVAL(p,0); - ff_searchcount = SVAL(p,2); - ff_eos = SVAL(p,4); - ff_lastname = SVAL(p,8); + /* these dates are probably like the other ones */ + finfo->ctime = make_unix_date2(p+8); + finfo->atime = make_unix_date2(p+12); + finfo->mtime = make_unix_date2(p+16); + finfo->size = IVAL(p,20); + finfo->mode = CVAL(p,28); + strcpy(finfo->name,p+37); } - else + return(SVAL(p,4)+4); + + case 260: /* NT uses this, but also accepts 2 */ + if (finfo) { - ff_searchcount = SVAL(p,0); - ff_eos = SVAL(p,2); - ff_lastname = SVAL(p,6); - } + int ret = SVAL(p,0); + int namelen; + p += 4; /* next entry offset */ + p += 4; /* fileindex */ - if (ff_searchcount == 0) - break; + /* these dates appear to arrive in a weird way. It seems to + be localtime plus the serverzone given in the initial + connect. This is GMT when DST is not in effect and one + hour from GMT otherwise. Can this really be right?? - /* point to the data bytes */ - p = resp_data; + I suppose this could be called kludge-GMT. Is is the GMT + you get by using the current DST setting on a different + localtime. It will be cheap to calculate, I suppose, as + no DST tables will be needed */ - /* we might need the lastname for continuations */ - if (ff_lastname > 0) - { - switch(info_level) - { - case 260: - ff_resume_key =0; - StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname); - /* strcpy(mask,p+ff_lastname+94); */ - break; - case 1: - strcpy(mask,p + ff_lastname + 1); - ff_resume_key = 0; - break; - } + finfo->ctime = interpret_long_date(p); p += 8; + finfo->atime = interpret_long_date(p); p += 8; + finfo->mtime = interpret_long_date(p); p += 8; p += 8; + finfo->size = IVAL(p,0); p += 8; + p += 8; /* alloc size */ + finfo->mode = CVAL(p,0); p += 4; + namelen = IVAL(p,0); p += 4; + p += 4; /* EA size */ + p += 2; /* short name len? */ + p += 24; /* short name? */ + StrnCpy(finfo->name,p,namelen); + return(ret); } - else - strcpy(mask,""); - - /* and add them to the dirlist pool */ - dirlist = Realloc(dirlist,dirlist_len + resp_data_len); + return(SVAL(p,0)); + } - if (!dirlist) - { - DEBUG(0,("Failed to expand dirlist\n")); - break; - } + DEBUG(1,("Unknown long filename format %d\n",level)); + return(SVAL(p,0)); +} - /* put in a length for the last entry, to ensure we can chain entries - into the next packet */ - { - char *p2; - for (p2=p,i=0;i<(ff_searchcount-1);i++) - p2 += interpret_long_filename(info_level,p2,NULL); - SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p)); - } - /* grab the data for later use */ - memcpy(dirlist+dirlist_len,p,resp_data_len); - dirlist_len += resp_data_len; - total_received += ff_searchcount; - if (resp_data) free(resp_data); resp_data = NULL; - if (resp_param) free(resp_param); resp_param = NULL; +/**************************************************************************** + act on the files in a dir listing + ****************************************************************************/ +static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir) +{ - DEBUG(3,("received %d entries (eos=%d resume=%d)\n", - ff_searchcount,ff_eos,ff_resume_key)); + if (!((finfo->mode & aDIR) == 0 && *fileselection && + !mask_match(finfo->name,fileselection,False,False)) && + !(recurse_dir && (strequal(finfo->name,".") || + strequal(finfo->name,"..")))) + { + if (recurse_dir && (finfo->mode & aDIR)) + { + pstring mask2; + pstring sav_dir; + strcpy(sav_dir,cur_dir); + strcat(cur_dir,finfo->name); + strcat(cur_dir,"\\"); + strcpy(mask2,cur_dir); - First = False; - } + if (!fn) + DEBUG(0,("\n%s\n",CNV_LANG(cur_dir))); - if (!fn) - for (p=dirlist,i=0;i<total_received;i++) - { - p += interpret_long_filename(info_level,p,&finfo); - display_finfo(&finfo); - } + strcat(mask2,"*"); - for (p=dirlist,i=0;i<total_received;i++) - { - p += interpret_long_filename(info_level,p,&finfo); - dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True); - } + if (longdir) + do_long_dir(inbuf,outbuf,mask2,attribute,fn,True); + else + do_dir(inbuf,outbuf,mask2,attribute,fn,True); - /* free up the dirlist buffer */ - if (dirlist) free(dirlist); - return(total_received); + strcpy(cur_dir,sav_dir); + } + else + { + if (fn && do_this_one(finfo)) + fn(finfo); + } + } } @@ -1076,6 +1033,7 @@ static void cmd_dir(char *inbuf,char *outbuf) fstring buf; char *p=buf; + dir_total = 0; strcpy(mask,cur_dir); if(mask[strlen(mask)-1]!='\\') strcat(mask,"\\"); @@ -1094,6 +1052,8 @@ static void cmd_dir(char *inbuf,char *outbuf) do_dir(inbuf,outbuf,mask,attribute,NULL,recurse); do_dskattr(); + + DEBUG(3, ("Total bytes listed: %d\n", dir_total)); } @@ -1140,7 +1100,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1) CVAL(outbuf,smb_com) = SMBopenX; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,0xFF); SSVAL(outbuf,smb_vwv2,1); @@ -1148,6 +1108,8 @@ static void do_get(char *rname,char *lname,file_info *finfo1) SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN); SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN); SSVAL(outbuf,smb_vwv8,1); + SSVAL(outbuf,smb_vwv11,0xffff); + SSVAL(outbuf,smb_vwv12,0xffff); p = smb_buf(outbuf); strcpy(p,rname); @@ -1191,7 +1153,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1) { if (CVAL(inbuf,smb_rcls) == ERRSRV && SVAL(inbuf,smb_err) == ERRnoresource && - reopen_connection(inbuf,outbuf)) + cli_reopen_connection(inbuf,outbuf)) { do_get(rname,lname,finfo1); return; @@ -1281,7 +1243,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1) set_message(outbuf,10,0,True); CVAL(outbuf,smb_com) = SMBreadX; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); if (close_done) { @@ -1345,7 +1307,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1) set_message(outbuf,8,0,True); CVAL(outbuf,smb_com) = SMBreadbraw; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,fnum); SIVAL(outbuf,smb_vwv1,nread); SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size)); @@ -1397,7 +1359,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1) set_message(outbuf,5,0,True); CVAL(outbuf,smb_com) = SMBread; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,fnum); SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread)); @@ -1439,17 +1401,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1) if (!close_done) { - bzero(outbuf,smb_size); - set_message(outbuf,3,0,True); - CVAL(outbuf,smb_com) = SMBclose; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - SIVALS(outbuf,smb_vwv1,-1); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); + cli_smb_close(inbuf, outbuf, Client, cnum, fnum); if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0) { @@ -1469,7 +1421,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1) set_message(outbuf,8,strlen(rname)+4,True); CVAL(outbuf,smb_com) = SMBsetatr; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH)); SIVALS(outbuf,smb_vwv1,0); p = smb_buf(outbuf); @@ -1493,7 +1445,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1) get_total_time_ms += this_time; get_total_size += finfo.size; - DEBUG(2,("(%g kb/s) (average %g kb/s)\n", + DEBUG(1,("(%g kb/s) (average %g kb/s)\n", finfo.size / (1.024*this_time + 1.0e-4), get_total_size / (1.024*get_total_time_ms))); } @@ -1623,7 +1575,7 @@ static void cmd_more(void) strcpy(rname,cur_dir); strcat(rname,"\\"); - sprintf(tmpname,"/tmp/smbmore.%d",getpid()); + sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid()); strcpy(lname,tmpname); if (!next_token(NULL,rname+strlen(rname),NULL)) { @@ -1704,7 +1656,7 @@ static BOOL do_mkdir(char *name) CVAL(outbuf,smb_com) = SMBmkdir; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); p = smb_buf(outbuf); @@ -1786,7 +1738,7 @@ static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n) CVAL(outbuf,smb_com) = SMBwritebraw; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,fnum); SSVAL(outbuf,smb_vwv1,n); @@ -1828,7 +1780,7 @@ static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n) CVAL(outbuf,smb_com) = SMBwrite; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,fnum); SSVAL(outbuf,smb_vwv1,n); @@ -1885,7 +1837,7 @@ static void do_put(char *rname,char *lname,file_info *finfo) CVAL(outbuf,smb_com) = SMBcreate; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,finfo->mode); put_dos_date3(outbuf,smb_vwv1,finfo->mtime); @@ -1961,7 +1913,7 @@ static void do_put(char *rname,char *lname,file_info *finfo) set_message(outbuf,3,0,True); CVAL(outbuf,smb_com) = SMBclose; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,fnum); put_dos_date3(outbuf,smb_vwv1,close_time); @@ -1994,7 +1946,7 @@ static void do_put(char *rname,char *lname,file_info *finfo) put_total_time_ms += this_time; put_total_size += finfo->size; - DEBUG(2,("(%g kb/s) (average %g kb/s)\n", + DEBUG(1,("(%g kb/s) (average %g kb/s)\n", finfo->size / (1.024*this_time + 1.0e-4), put_total_size / (1.024*put_total_time_ms))); } @@ -2097,7 +2049,7 @@ static void cmd_mput(void) pstring tmpname; FILE *f; - sprintf(tmpname,"/tmp/ls.smb.%d",(int)getpid()); + sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid()); if (recurse) sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname); else @@ -2131,13 +2083,12 @@ static void cmd_mput(void) strcpy(rname,cur_dir); strcat(rname,lname); - if (!do_mkdir(rname)) - { - strcat(lname,"/"); - if (!seek_list(f,lname)) - break; - goto again1; - } + if (!chkpath(rname,False) && !do_mkdir(rname)) { + strcat(lname,"/"); + if (!seek_list(f,lname)) + break; + goto again1; + } continue; } @@ -2178,7 +2129,7 @@ static void do_cancel(int job) bzero(param,sizeof(param)); p = param; - SSVAL(p,0,81); /* api number */ + SSVAL(p,0,81); /* DosPrintJobDel() */ p += 2; strcpy(p,"W"); p = skip_string(p,1); @@ -2187,10 +2138,10 @@ static void do_cancel(int job) SSVAL(p,0,job); p += 2; - if (call_api(PTR_DIFF(p,param),0, - 6,1000, + if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param),0, 0, + 6, 1000, &rprcnt,&rdrcnt, - param,NULL, + param,NULL, NULL, &rparam,&rdata)) { int res = SVAL(rparam,0); @@ -2261,12 +2212,12 @@ static void cmd_stat(char *inbuf,char *outbuf) strcpy(p,cur_dir); strcat(p,buf); - send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0, + cli_send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0, NULL,param,&setup, 0,6 + strlen(p)+1,1, BUFFER_SIZE,2,0); - receive_trans_response(inbuf,SMBtrans2, + cli_receive_trans_response(inbuf,SMBtrans2, &resp_data_len,&resp_param_len, &resp_data,&resp_param); @@ -2324,7 +2275,7 @@ static void cmd_print(char *inbuf,char *outbuf ) CVAL(outbuf,smb_com) = SMBsplopen; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,0); SSVAL(outbuf,smb_vwv1,printmode); @@ -2380,7 +2331,7 @@ static void cmd_print(char *inbuf,char *outbuf ) CVAL(outbuf,smb_com) = SMBsplwr; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,fnum); SSVAL(outbuf,smb_vwv1,n+3); @@ -2405,7 +2356,7 @@ static void cmd_print(char *inbuf,char *outbuf ) set_message(outbuf,1,0,True); CVAL(outbuf,smb_com) = SMBsplclose; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,fnum); @@ -2425,7 +2376,8 @@ static void cmd_print(char *inbuf,char *outbuf ) } /**************************************************************************** -print a file +show a print queue - this is deprecated as it uses the old smb that +has limited support - the correct call is the cmd_p_queue_4() after this. ****************************************************************************/ static void cmd_queue(char *inbuf,char *outbuf ) { @@ -2437,7 +2389,7 @@ static void cmd_queue(char *inbuf,char *outbuf ) CVAL(outbuf,smb_com) = SMBsplretq; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */ SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */ @@ -2487,6 +2439,222 @@ static void cmd_queue(char *inbuf,char *outbuf ) /**************************************************************************** +show information about a print queue +****************************************************************************/ +static void cmd_p_queue_4(char *inbuf,char *outbuf ) +{ + char *rparam = NULL; + char *rdata = NULL; + char *p; + int rdrcnt, rprcnt; + pstring param; + int result_code=0; + + if (!connect_as_printer) + { + DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n")); + DEBUG(0,("Trying to print without -P may fail\n")); + } + + bzero(param,sizeof(param)); + + p = param; + SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */ + p += 2; + strcpy(p,"zWrLeh"); /* parameter description? */ + p = skip_string(p,1); + strcpy(p,"WWzWWDDzz"); /* returned data format */ + p = skip_string(p,1); + strcpy(p,strrchr(service,'\\')+1); /* name of queue */ + p = skip_string(p,1); + SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */ + SSVAL(p,2,1000); /* size of bytes of returned data buffer */ + p += 4; + strcpy(p,""); /* subformat */ + p = skip_string(p,1); + + DEBUG(1,("Calling DosPrintJobEnum()...\n")); + if( cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param), 0, + 10, 0, 4096, + &rprcnt, &rdrcnt, + param, NULL, NULL, + &rparam, &rdata) ) + { + int converter; + result_code = SVAL(rparam,0); + converter = SVAL(rparam,2); /* conversion factor */ + + DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) )); + + if (result_code == 0) /* if no error, */ + { + int i; + uint16 JobId; + uint16 Priority; + uint32 Size; + char *UserName; + char *JobName; + char *JobTimeStr; + time_t JobTime; + char PrinterName[20]; + + strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */ + strlower(PrinterName); /* in lower case */ + + p = rdata; /* received data */ + for( i = 0; i < SVAL(rparam,4); ++i) + { + JobId = SVAL(p,0); + Priority = SVAL(p,2); + UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt); + strlower(UserName); + Priority = SVAL(p,2); + JobTime = make_unix_date3( p + 12); + JobTimeStr = asctime(LocalTime( &JobTime)); + Size = IVAL(p,16); + JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt); + + + printf("%s-%u %s priority %u %s %s %u bytes\n", + PrinterName, JobId, UserName, + Priority, JobTimeStr, JobName, Size); + +#if 0 /* DEBUG code */ + printf("Job Id: \"%u\"\n", SVAL(p,0)); + printf("Priority: \"%u\"\n", SVAL(p,2)); + + printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) ); + printf("Position: \"%u\"\n", SVAL(p,8)); + printf("Status: \"%u\"\n", SVAL(p,10)); + + JobTime = make_unix_date3( p + 12); + printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime))); + printf("date: \"%u\"\n", SVAL(p,12)); + + printf("Size: \"%u\"\n", SVAL(p,16)); + printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) ); + printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) ); +#endif /* DEBUG CODE */ + p += 28; + } + } + } + else /* cli_call_api() failed */ + { + printf("Failed, error = %d\n", result_code); + } + + /* If any parameters or data were returned, free the storage. */ + if(rparam) free(rparam); + if(rdata) free(rdata); + + return; +} + +/**************************************************************************** +show information about a print queue +****************************************************************************/ +static void cmd_qinfo(char *inbuf,char *outbuf ) +{ + char *rparam = NULL; + char *rdata = NULL; + char *p; + int rdrcnt, rprcnt; + pstring param; + int result_code=0; + + bzero(param,sizeof(param)); + + p = param; + SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */ + p += 2; + strcpy(p,"zWrLh"); /* parameter description? */ + p = skip_string(p,1); + strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */ + p = skip_string(p,1); + strcpy(p,strrchr(service,'\\')+1); /* name of queue */ + p = skip_string(p,1); + SSVAL(p,0,3); /* API function level 3, just queue info, no job info */ + SSVAL(p,2,1000); /* size of bytes of returned data buffer */ + p += 4; + strcpy(p,""); /* subformat */ + p = skip_string(p,1); + + DEBUG(1,("Calling DosPrintQueueGetInfo()...\n")); + if( cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param), 0, 0, + 10, 4096, + &rprcnt, &rdrcnt, + param, NULL, NULL, + &rparam, &rdata) ) + { + int converter; + result_code = SVAL(rparam,0); + converter = SVAL(rparam,2); /* conversion factor */ + + DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) )); + + if (result_code == 0) /* if no error, */ + { + p = rdata; /* received data */ + + printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) ); + printf("Priority: %u\n", SVAL(p,4) ); + printf("Start time: %u\n", SVAL(p,6) ); + printf("Until time: %u\n", SVAL(p,8) ); + printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) ); + printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) ); + printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) ); + printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) ); + printf("Status: %u\n", SVAL(p,28) ); + printf("Jobs: %u\n", SVAL(p,30) ); + printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) ); + printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) ); + + /* Dump the driver data */ + { + int count, x, y, c; + char *ddptr; + + ddptr = rdata + SVAL(p,40) - converter; + if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);} + printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) ); + + for(x=8; x < count; x+=16) + { + for(y=0; y < 16; y++) + { + if( (x+y) < count ) + printf("%2.2X ", CVAL(ddptr,(x+y)) ); + else + fputs(" ", stdout); + } + for(y=0; y < 16 && (x+y) < count; y++) + { + c = CVAL(ddptr,(x+y)); + if(isprint(c)) + fputc(c, stdout); + else + fputc('.', stdout); + } + fputc('\n', stdout); + } + } + + } + } + else /* cli_call_api() failed */ + { + printf("Failed, error = %d\n", result_code); + } + + /* If any parameters or data were returned, free the storage. */ + if(rparam) free(rparam); + if(rdata) free(rdata); + + return; +} + +/**************************************************************************** delete some files ****************************************************************************/ static void do_del(file_info *finfo) @@ -2515,7 +2683,7 @@ static void do_del(file_info *finfo) CVAL(outbuf,smb_com) = SMBunlink; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,0); @@ -2581,7 +2749,7 @@ static void cmd_rmdir(char *inbuf,char *outbuf ) CVAL(outbuf,smb_com) = SMBrmdir; SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); p = smb_buf(outbuf); @@ -2625,7 +2793,7 @@ static void cmd_rename(char *inbuf,char *outbuf ) CVAL(outbuf,smb_com) = SMBmv; SSVAL(outbuf,smb_tid,cnum); SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM); - setup_pkt(outbuf); + cli_setup_pkt(outbuf); p = smb_buf(outbuf); *p++ = 4; @@ -2670,7 +2838,7 @@ static void cmd_newer(void) { newer_than = sbuf.st_mtime; DEBUG(1,("Getting files newer than %s", - asctime(LocalTime(&newer_than,GMT_TO_LOCAL)))); + asctime(LocalTime(&newer_than)))); } else newer_than = 0; @@ -2776,649 +2944,18 @@ static void cmd_lcd(void) /**************************************************************************** -send a session request -****************************************************************************/ -static BOOL send_session_request(char *inbuf,char *outbuf) -{ - fstring dest; - char *p; - int len = 4; - /* send a session request (RFC 8002) */ - - strcpy(dest,desthost); - p = strchr(dest,'.'); - if (p) *p = 0; - - /* put in the destination name */ - p = outbuf+len; - name_mangle(dest,p,name_type); - len += name_len(p); - - /* and my name */ - p = outbuf+len; - name_mangle(myname,p,0); - len += name_len(p); - - /* setup the packet length */ - _smb_setlen(outbuf,len); - CVAL(outbuf,0) = 0x81; - - send_smb(Client,outbuf); - DEBUG(5,("Sent session request\n")); - - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */ - { - /* For information, here is the response structure. - * We do the byte-twiddling to for portability. - struct RetargetResponse{ - unsigned char type; - unsigned char flags; - int16 length; - int32 ip_addr; - int16 port; - }; - */ - extern int Client; - int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9); - /* SESSION RETARGET */ - putip((char *)&dest_ip,inbuf+4); - - close_sockets(); - Client = open_socket_out(SOCK_STREAM, &dest_ip, port); - if (Client == -1) - return False; - - DEBUG(3,("Retargeted\n")); - - set_socket_options(Client,user_socket_options); - - /* Try again */ - return send_session_request(inbuf,outbuf); - } /* C. Hoch 9/14/95 End */ - - - if (CVAL(inbuf,0) != 0x82) - { - int ecode = CVAL(inbuf,4); - DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n", - CVAL(inbuf,0),ecode,myname,desthost)); - switch (ecode) - { - case 0x80: - DEBUG(0,("Not listening on called name\n")); - DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost)); - DEBUG(0,("You may find the -I option useful for this\n")); - break; - case 0x81: - DEBUG(0,("Not listening for calling name\n")); - DEBUG(0,("Try to connect as another name (instead of %s)\n",myname)); - DEBUG(0,("You may find the -n option useful for this\n")); - break; - case 0x82: - DEBUG(0,("Called name not present\n")); - DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost)); - DEBUG(0,("You may find the -I option useful for this\n")); - break; - case 0x83: - DEBUG(0,("Called name present, but insufficient resources\n")); - DEBUG(0,("Perhaps you should try again later?\n")); - break; - default: - DEBUG(0,("Unspecified error 0x%X\n",ecode)); - DEBUG(0,("Your server software is being unfriendly\n")); - break; - } - return(False); - } - return(True); -} - - -/**************************************************************************** -send a login command -****************************************************************************/ -static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup) -{ - BOOL was_null = (!inbuf && !outbuf); - int sesskey=0; - time_t servertime = 0; - extern int serverzone; - int sec_mode=0; - int crypt_len; - int max_vcs=0; - struct { - int prot; - char *name; - } - prots[] = - { - {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"}, - {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"}, - {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"}, - {PROTOCOL_LANMAN1,"LANMAN1.0"}, - {PROTOCOL_LANMAN2,"LM1.2X002"}, - {PROTOCOL_LANMAN2,"Samba"}, - {PROTOCOL_NT1,"NT LM 0.12"}, - {PROTOCOL_NT1,"NT LANMAN 1.0"}, - {-1,NULL} - }; - char *pass = NULL; - pstring dev; - char *p; - int numprots; - - if (was_null) - { - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - } - -#if AJT - if (strstr(service,"IPC$")) connect_as_ipc = True; -#endif - - strcpy(dev,"A:"); - if (connect_as_printer) - strcpy(dev,"LPT1:"); - if (connect_as_ipc) - strcpy(dev,"IPC"); - - - if (start_session && !send_session_request(inbuf,outbuf)) - { - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - bzero(outbuf,smb_size); - - /* setup the protocol strings */ - { - int plength; - - for (plength=0,numprots=0; - prots[numprots].name && prots[numprots].prot<=max_protocol; - numprots++) - plength += strlen(prots[numprots].name)+2; - - set_message(outbuf,0,plength,True); - - p = smb_buf(outbuf); - for (numprots=0; - prots[numprots].name && prots[numprots].prot<=max_protocol; - numprots++) - { - *p++ = 2; - strcpy(p,prots[numprots].name); - p += strlen(p) + 1; - } - } - - CVAL(outbuf,smb_com) = SMBnegprot; - setup_pkt(outbuf); - - CVAL(smb_buf(outbuf),0) = 2; - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - show_msg(inbuf); - - if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots)) - { - DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n", - myname,desthost,smb_errstr(inbuf))); - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - Protocol = prots[SVAL(inbuf,smb_vwv0)].prot; - - - if (Protocol < PROTOCOL_NT1) { - sec_mode = SVAL(inbuf,smb_vwv1); - max_xmit = SVAL(inbuf,smb_vwv2); - sesskey = IVAL(inbuf,smb_vwv6); - serverzone = SVALS(inbuf,smb_vwv10)*60; - /* this time is converted to GMT by make_unix_date */ - servertime = make_unix_date(inbuf+smb_vwv8); - if (Protocol >= PROTOCOL_COREPLUS) { - readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0); - writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0); - } - crypt_len = smb_buflen(inbuf); - memcpy(cryptkey,smb_buf(inbuf),8); - DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3))); - max_vcs = SVAL(inbuf,smb_vwv4); - DEBUG(3,("max vcs %d\n",max_vcs)); - DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5))); - } else { - /* NT protocol */ - sec_mode = CVAL(inbuf,smb_vwv1); - max_xmit = IVAL(inbuf,smb_vwv3+1); - sesskey = IVAL(inbuf,smb_vwv7+1); - serverzone = SVALS(inbuf,smb_vwv15+1)*60; - /* this time arrives in real GMT */ - servertime = interpret_long_date(inbuf+smb_vwv11+1); - crypt_len = CVAL(inbuf,smb_vwv16+1); - memcpy(cryptkey,smb_buf(inbuf),8); - if (IVAL(inbuf,smb_vwv9+1) & 1) - readbraw_supported = writebraw_supported = True; - DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1))); - max_vcs = SVAL(inbuf,smb_vwv2+1); - DEBUG(3,("max vcs %d\n",max_vcs)); - DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1))); - DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1))); - } - - DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1))); - DEBUG(3,("max xmt %d\n",max_xmit)); - DEBUG(3,("Got %d byte crypt key\n",crypt_len)); - DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name)); - - doencrypt = ((sec_mode & 2) != 0); - - if (servertime) { - static BOOL done_time = False; - if (!done_time) { - DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n", - asctime(LocalTime(&servertime,GMT_TO_LOCAL)), - -(double)(serverzone/3600.0))); - done_time = True; - } - } - - get_pass: - - if (got_pass) - pass = password; - else - pass = (char *)getpass("Password: "); - - if (Protocol >= PROTOCOL_LANMAN1 && use_setup) - { - fstring pword; - int passlen = strlen(pass)+1; - strcpy(pword,pass); - -#ifdef SMB_PASSWD - if (doencrypt && *pass) { - DEBUG(3,("Using encrypted passwords\n")); - passlen = 24; - SMBencrypt(pass,cryptkey,pword); - } -#else - doencrypt = False; -#endif - - /* if in share level security then don't send a password now */ - if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;} - - /* send a session setup command */ - bzero(outbuf,smb_size); - - if (Protocol < PROTOCOL_NT1) { - set_message(outbuf,10,1 + strlen(username) + passlen,True); - CVAL(outbuf,smb_com) = SMBsesssetupX; - setup_pkt(outbuf); - - CVAL(outbuf,smb_vwv0) = 0xFF; - SSVAL(outbuf,smb_vwv2,max_xmit); - SSVAL(outbuf,smb_vwv3,2); - SSVAL(outbuf,smb_vwv4,max_vcs-1); - SIVAL(outbuf,smb_vwv5,sesskey); - SSVAL(outbuf,smb_vwv7,passlen); - p = smb_buf(outbuf); - memcpy(p,pword,passlen); - p += passlen; - strcpy(p,username); - } else { - if (!doencrypt) passlen--; - /* for Win95 */ - set_message(outbuf,13,0,True); - CVAL(outbuf,smb_com) = SMBsesssetupX; - setup_pkt(outbuf); - - CVAL(outbuf,smb_vwv0) = 0xFF; - SSVAL(outbuf,smb_vwv2,BUFFER_SIZE); - SSVAL(outbuf,smb_vwv3,2); - SSVAL(outbuf,smb_vwv4,getpid()); - SIVAL(outbuf,smb_vwv5,sesskey); - SSVAL(outbuf,smb_vwv7,passlen); - SSVAL(outbuf,smb_vwv8,0); - p = smb_buf(outbuf); - memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7); - strcpy(p,username);p = skip_string(p,1); - strcpy(p,workgroup);p = skip_string(p,1); - strcpy(p,"Unix");p = skip_string(p,1); - strcpy(p,"Samba");p = skip_string(p,1); - set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False); - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - show_msg(inbuf); - - if (CVAL(inbuf,smb_rcls) != 0) - { - if (! *pass && - ((CVAL(inbuf,smb_rcls) == ERRDOS && - SVAL(inbuf,smb_err) == ERRnoaccess) || - (CVAL(inbuf,smb_rcls) == ERRSRV && - SVAL(inbuf,smb_err) == ERRbadpw))) - { - got_pass = False; - DEBUG(3,("resending login\n")); - goto get_pass; - } - - DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n", - username,myname,desthost,smb_errstr(inbuf))); - DEBUG(0,("You might find the -U, -W or -n options useful\n")); - DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n")); - DEBUG(0,("Some servers also insist on uppercase-only passwords\n")); - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - if (Protocol >= PROTOCOL_NT1) { - char *domain,*os,*lanman; - p = smb_buf(inbuf); - os = p; - lanman = skip_string(os,1); - domain = skip_string(lanman,1); - if (*domain || *os || *lanman) - DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman)); - } - - /* use the returned uid from now on */ - if (SVAL(inbuf,smb_uid) != uid) - DEBUG(3,("Server gave us a UID of %d. We gave %d\n", - SVAL(inbuf,smb_uid),uid)); - uid = SVAL(inbuf,smb_uid); - } - - /* now we've got a connection - send a tcon message */ - bzero(outbuf,smb_size); - - if (strncmp(service,"\\\\",2) != 0) - { - DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n")); - DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n")); - } - - - again2: - - { - int passlen = strlen(pass)+1; - fstring pword; - strcpy(pword,pass); - -#ifdef SMB_PASSWD - if (doencrypt && *pass) { - passlen=24; - SMBencrypt(pass,cryptkey,pword); - } -#endif - - /* if in user level security then don't send a password now */ - if ((sec_mode & 1)) { - strcpy(pword, ""); passlen=1; - } - - set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True); - CVAL(outbuf,smb_com) = SMBtconX; - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv3,passlen); - - p = smb_buf(outbuf); - memcpy(p,pword,passlen); - p += passlen; - strcpy(p,service); - p = skip_string(p,1); - strcpy(p,dev); - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - /* trying again with a blank password */ - if (CVAL(inbuf,smb_rcls) != 0 && - (int)strlen(pass) > 0 && - !doencrypt && - Protocol >= PROTOCOL_LANMAN1) - { - DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf))); - strcpy(pass,""); - goto again2; - } - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf))); - DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n")); - DEBUG(0,("Some servers insist that these be in uppercase\n")); - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - - max_xmit = MIN(max_xmit,BUFFER_SIZE-4); - if (max_xmit <= 0) - max_xmit = BUFFER_SIZE - 4; - - cnum = SVAL(inbuf,smb_tid); - - DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit)); - - if (was_null) - { - free(inbuf); - free(outbuf); - } - return True; -} - - -/**************************************************************************** -send a logout command -****************************************************************************/ -static void send_logout(void ) -{ - pstring inbuf,outbuf; - - bzero(outbuf,smb_size); - set_message(outbuf,0,0,True); - CVAL(outbuf,smb_com) = SMBtdis; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,SHORT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf))); - } - - -#ifdef STATS - stats_report(); -#endif - exit(0); -} - - - -/**************************************************************************** -call a remote api -****************************************************************************/ -static BOOL call_api(int prcnt,int drcnt, - int mprcnt,int mdrcnt, - int *rprcnt,int *rdrcnt, - char *param,char *data, - char **rparam,char **rdata) -{ - static char *inbuf=NULL; - static char *outbuf=NULL; - - if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0, - data,param,NULL, - drcnt,prcnt,0, - mdrcnt,mprcnt,0); - - return (receive_trans_response(inbuf,SMBtrans, - rdrcnt,rprcnt, - rdata,rparam)); -} - -/**************************************************************************** - send a SMB trans or trans2 request - ****************************************************************************/ -static BOOL send_trans_request(char *outbuf,int trans, - char *name,int fid,int flags, - char *data,char *param,uint16 *setup, - int ldata,int lparam,int lsetup, - int mdata,int mparam,int msetup) -{ - int i; - int this_ldata,this_lparam; - int tot_data=0,tot_param=0; - char *outdata,*outparam; - pstring inbuf; - char *p; - - this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */ - this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam)); - - bzero(outbuf,smb_size); - set_message(outbuf,14+lsetup,0,True); - CVAL(outbuf,smb_com) = trans; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3); - outdata = outparam+this_lparam; - - /* primary request */ - SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */ - SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */ - SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */ - SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */ - SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */ - SSVAL(outbuf,smb_flags,flags); /* flags */ - SIVAL(outbuf,smb_timeout,0); /* timeout */ - SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */ - SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */ - SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */ - SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */ - SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */ - for (i=0;i<lsetup;i++) /* setup[] */ - SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]); - p = smb_buf(outbuf); - if (trans==SMBtrans) - strcpy(p,name); /* name[] */ - else - { - *p++ = 0; /* put in a null smb_name */ - *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */ - } - if (this_lparam) /* param[] */ - memcpy(outparam,param,this_lparam); - if (this_ldata) /* data[] */ - memcpy(outdata,data,this_ldata); - set_message(outbuf,14+lsetup, /* wcnt, bcc */ - PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False); - - show_msg(outbuf); - send_smb(Client,outbuf); - - if (this_ldata < ldata || this_lparam < lparam) - { - /* receive interim response */ - if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s request failed (%s)\n", - trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf))); - return(False); - } - - tot_data = this_ldata; - tot_param = this_lparam; - - while (tot_data < ldata || tot_param < lparam) - { - this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */ - this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam)); - - set_message(outbuf,trans==SMBtrans?8:9,0,True); - CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2; - - outparam = smb_buf(outbuf); - outdata = outparam+this_lparam; - - /* secondary request */ - SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */ - SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */ - SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */ - SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */ - SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */ - SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */ - SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */ - SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */ - if (trans==SMBtrans2) - SSVAL(outbuf,smb_sfid,fid); /* fid */ - if (this_lparam) /* param[] */ - memcpy(outparam,param,this_lparam); - if (this_ldata) /* data[] */ - memcpy(outdata,data,this_ldata); - set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */ - PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False); - - show_msg(outbuf); - send_smb(Client,outbuf); - - tot_data += this_ldata; - tot_param += this_lparam; - } - } - - return(True); -} - -/**************************************************************************** try and browse available connections on a host ****************************************************************************/ static BOOL browse_host(BOOL sort) { #ifdef NOSTRCASECMP +/* If strcasecmp is already defined, remove it. */ +#ifdef strcasecmp +#undef strcasecmp +#endif /* strcasecmp */ #define strcasecmp StrCaseCmp -#endif +#endif /* NOSTRCASECMP */ + extern int strcasecmp(); char *rparam = NULL; @@ -3440,10 +2977,10 @@ static BOOL browse_host(BOOL sort) SSVAL(p,2,BUFFER_SIZE); p += 4; - if (call_api(PTR_DIFF(p,param),0, - 1024,BUFFER_SIZE, + if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param),0, 0, + 1024, BUFFER_SIZE, &rprcnt,&rdrcnt, - param,NULL, + param,NULL, NULL, &rparam,&rdata)) { int res = SVAL(rparam,0); @@ -3522,7 +3059,7 @@ static void server_info() bzero(param,sizeof(param)); p = param; - SSVAL(p,0,63); /* api number */ + SSVAL(p,0,63); /* NetServerGetInfo()? */ p += 2; strcpy(p,"WrLh"); p = skip_string(p,1); @@ -3532,10 +3069,10 @@ static void server_info() SSVAL(p,2,1000); p += 6; - if (call_api(PTR_DIFF(p,param),0, - 6,1000, + if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p,param),0, 0, + 6, 1000, &rprcnt,&rdrcnt, - param,NULL, + param,NULL, NULL, &rparam,&rdata)) { int res = SVAL(rparam,0); @@ -3563,39 +3100,54 @@ static void server_info() /**************************************************************************** try and browse available connections on a host ****************************************************************************/ -static BOOL list_servers() +static BOOL list_servers(char *wk_grp) { char *rparam = NULL; char *rdata = NULL; int rdrcnt,rprcnt; - char *p; + char *p,*svtype_p; pstring param; int uLevel = 1; int count = 0; + BOOL ok = False; + BOOL generic_request = False; + + + if (strequal(wk_grp,"WORKGROUP")) { + /* we won't specify a workgroup */ + generic_request = True; + } /* now send a SMBtrans command with api ServerEnum? */ p = param; SSVAL(p,0,0x68); /* api number */ p += 2; - strcpy(p,"WrLehDO"); + + strcpy(p,generic_request?"WrLehDO":"WrLehDz"); p = skip_string(p,1); strcpy(p,"B16BBDz"); -#if 0 - strcpy(p,getenv("XX_STR2")); -#endif p = skip_string(p,1); SSVAL(p,0,uLevel); - SSVAL(p,2,0x2000); /* buf length */ + SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */ p += 4; - SIVAL(p,0,SV_TYPE_ALL); + svtype_p = p; + p += 4; - if (call_api(PTR_DIFF(p+4,param),0, - 8,10000, + if (!generic_request) { + strcpy(p, wk_grp); + p = skip_string(p,1); + } + + /* first ask for a list of servers in this workgroup */ + SIVAL(svtype_p,0,SV_TYPE_ALL); + + if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p+4,param),0, 0, + 8, BUFFER_SIZE - SAFETY_MARGIN, &rprcnt,&rdrcnt, - param,NULL, + param,NULL, NULL, &rparam,&rdata)) { int res = SVAL(rparam,0); @@ -3618,7 +3170,8 @@ static BOOL list_servers() printf("\t%-16.16s %s\n", sname, comment_offset?rdata+comment_offset-converter:""); - + + ok=True; p2 += 26; } } @@ -3627,12 +3180,13 @@ static BOOL list_servers() if (rparam) {free(rparam); rparam = NULL;} if (rdata) {free(rdata); rdata = NULL;} - SIVAL(p,0,SV_TYPE_DOMAIN_ENUM); + /* now ask for a list of workgroups */ + SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM); - if (call_api(PTR_DIFF(p+4,param),0, - 8,10000, + if (cli_call_api(PIPE_LANMAN, PTR_DIFF(p+4,param),0, 0, + 8, BUFFER_SIZE - SAFETY_MARGIN, &rprcnt,&rdrcnt, - param,NULL, + param,NULL, NULL, &rparam,&rdata)) { int res = SVAL(rparam,0); @@ -3656,6 +3210,7 @@ static BOOL list_servers() sname, comment_offset?rdata+comment_offset-converter:""); + ok=True; p2 += 26; } } @@ -3664,14 +3219,10 @@ static BOOL list_servers() if (rparam) free(rparam); if (rdata) free(rdata); - return(count>0); + return(ok); } - - -void cmd_help(); - /* This defines the commands supported by this client */ struct { @@ -3698,6 +3249,7 @@ struct {"md",cmd_mkdir,"<directory> make a directory"}, {"rmdir",cmd_rmdir,"<directory> remove a directory"}, {"rd",cmd_rmdir,"<directory> remove a directory"}, + {"pq",cmd_p_queue_4,"enumerate the print queue"}, {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"}, {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"}, {"translate",cmd_translate,"toggle text translation for printing"}, @@ -3705,11 +3257,12 @@ struct {"print",cmd_print,"<file name> print a file"}, {"printmode",cmd_printmode,"<graphics or text> set the print mode"}, {"queue",cmd_queue,"show the print queue"}, + {"qinfo",cmd_qinfo,"show print queue information"}, {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"}, {"stat",cmd_stat,"<file> get info on a file (experimental!)"}, - {"quit",send_logout,"logoff the server"}, - {"q",send_logout,"logoff the server"}, - {"exit",send_logout,"logoff the server"}, + {"quit",cli_send_logout,"logoff the server"}, + {"q",cli_send_logout,"logoff the server"}, + {"exit",cli_send_logout,"logoff the server"}, {"newer",cmd_newer,"<file> only mget files newer than the specified local file"}, {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit"}, {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" }, @@ -3783,92 +3336,6 @@ void cmd_help(void) } /**************************************************************************** -open the client sockets -****************************************************************************/ -static BOOL open_sockets(int port ) -{ - static int last_port; - char *host; - pstring service2; - extern int Client; -#ifdef USENMB - BOOL failed = True; -#endif - - if (port == 0) port=last_port; - last_port=port; - - strupper(service); - - if (*desthost) - { - host = desthost; - } - else - { - strcpy(service2,service); - host = strtok(service2,"\\/"); - if (!host) { - DEBUG(0,("Badly formed host name\n")); - return(False); - } - strcpy(desthost,host); - } - - DEBUG(3,("Opening sockets\n")); - - if (*myname == 0) - { - get_myname(myname,NULL); - strupper(myname); - } - - if (!have_ip) - { - struct hostent *hp; - - if ((hp = Get_Hostbyname(host))) { - putip((char *)&dest_ip,(char *)hp->h_addr); - failed = False; - } else { -#ifdef USENMB - /* Try and resolve the name with the netbios server */ - int bcast; - pstring hs; - struct in_addr ip1, ip2; - - if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3)) != -1) { - set_socket_options (bcast, "SO_BROADCAST"); - - if (!got_bcast && get_myname(hs, &ip1)) { - get_broadcast(&ip1, &bcast_ip, &ip2); - } - - if (name_query(bcast, host, 0x20, True, True, bcast_ip, &dest_ip,0)){ - failed = False; - } - close (bcast); - } -#endif - if (failed) { - DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host)); - return False; - } - } - } - - Client = open_socket_out(SOCK_STREAM, &dest_ip, port); - if (Client == -1) - return False; - - DEBUG(3,("Connected\n")); - - set_socket_options(Client,user_socket_options); - - return True; -} - -/**************************************************************************** wait for keyboard activity, swallowing network packets ****************************************************************************/ #ifdef CLIX @@ -3907,13 +3374,11 @@ static void wait_keyboard(char *buffer) #else { char ch; - int f_flags; int readret; - - f_flags = fcntl(fileno(stdin), F_GETFL, 0); - fcntl( fileno(stdin), F_SETFL, f_flags | O_NONBLOCK); + + set_blocking(fileno(stdin), False); readret = read_data( fileno(stdin), &ch, 1); - fcntl(fileno(stdin), F_SETFL, f_flags); + set_blocking(fileno(stdin), True); if (readret == -1) { if (errno != EAGAIN) @@ -3946,39 +3411,13 @@ static void wait_keyboard(char *buffer) /**************************************************************************** -close and open the connection again -****************************************************************************/ -BOOL reopen_connection(char *inbuf,char *outbuf) -{ - static int open_count=0; - - open_count++; - - if (open_count>5) return(False); - - DEBUG(1,("Trying to re-open connection\n")); - - set_message(outbuf,0,0,True); - SCVAL(outbuf,smb_com,SMBtdis); - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,SHORT_TIMEOUT); - - close_sockets(); - if (!open_sockets(0)) return(False); - - return(send_login(inbuf,outbuf,True,True)); -} - -/**************************************************************************** process commands from the client ****************************************************************************/ -BOOL process(char *base_directory) +static BOOL process(char *base_directory) { extern FILE *dbf; pstring line; + char *cmd; char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); @@ -3988,12 +3427,49 @@ BOOL process(char *base_directory) bzero(OutBuffer,smb_size); - if (!send_login(InBuffer,OutBuffer,True,True)) + if (!cli_send_login(InBuffer,OutBuffer,True,True)) return(False); if (*base_directory) do_cd(base_directory); - while (!feof(stdin)) + cmd = cmdstr; + if (cmd[0] != '\0') while (cmd[0] != '\0') + { + char *p; + fstring tok; + int i; + + if ((p = strchr(cmd, ';')) == 0) + { + strncpy(line, cmd, 999); + line[1000] = '\0'; + cmd += strlen(cmd); + } + else + { + if (p - cmd > 999) p = cmd + 999; + strncpy(line, cmd, p - cmd); + line[p - cmd] = '\0'; + cmd = p + 1; + } + + /* input language code to internal one */ + CNV_INPUT (line); + + /* and get the first part of the command */ + { + char *ptr = line; + if (!next_token(&ptr,tok,NULL)) continue; + } + + if ((i = process_tok(tok)) >= 0) + commands[i].fn(InBuffer,OutBuffer); + else if (i == -2) + DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok))); + else + DEBUG(0,("%s: command not found\n",CNV_LANG(tok))); + } + else while (!feof(stdin)) { fstring tok; int i; @@ -4001,7 +3477,7 @@ BOOL process(char *base_directory) bzero(OutBuffer,smb_size); /* display a prompt */ - DEBUG(1,("smb: %s> ", CNV_LANG(cur_dir))); + DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir))); fflush(dbf); #ifdef CLIX @@ -4045,23 +3521,18 @@ BOOL process(char *base_directory) DEBUG(0,("%s: command not found\n",CNV_LANG(tok))); } - send_logout(); + cli_send_logout(); return(True); } - /**************************************************************************** usage on the program ****************************************************************************/ -void usage(char *pname) +static void usage(char *pname) { DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ", pname)); -#ifdef KANJI - DEBUG(0,("[-t termcode] ")); -#endif /* KANJI */ - DEBUG(0,("\nVersion %s\n",VERSION)); DEBUG(0,("\t-p port listen on the specified port\n")); DEBUG(0,("\t-d debuglevel set the debuglevel\n")); @@ -4076,31 +3547,38 @@ void usage(char *pname) DEBUG(0,("\t-E write messages to stderr instead of stdout\n")); DEBUG(0,("\t-U username set the network username\n")); DEBUG(0,("\t-W workgroup set the workgroup name\n")); -#ifdef KANJI + DEBUG(0,("\t-c command string execute semicolon separated commands\n")); DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n")); -#endif /* KANJI */ DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n")); DEBUG(0,("\t-D directory start from directory\n")); DEBUG(0,("\n")); } - - /**************************************************************************** main program ****************************************************************************/ -int main(int argc,char *argv[]) + int main(int argc,char *argv[]) { fstring base_directory; char *pname = argv[0]; - int port = 139; + int port = SMB_PORT; int opt; extern FILE *dbf; extern char *optarg; extern int optind; pstring query_host; BOOL message = False; + BOOL nt_domain_logon = False; extern char tar_type; + static pstring servicesf = CONFIGFILE; + pstring term_code; + char *p; + +#ifdef KANJI + strcpy(term_code, KANJI); +#else /* KANJI */ + *term_code = 0; +#endif /* KANJI */ *query_host = 0; *base_directory = 0; @@ -4120,10 +3598,27 @@ int main(int argc,char *argv[]) umask(myumask); if (getenv("USER")) + { + strcpy(username,getenv("USER")); + + /* modification to support userid%passwd syntax in the USER var + 25.Aug.97, jdblair@uab.edu */ + + if ((p=strchr(username,'%'))) { - strcpy(username,getenv("USER")); - strupper(username); + *p = 0; + strcpy(password,p+1); + got_pass = True; + memset(strchr(getenv("USER"),'%')+1,'X',strlen(password)); } + strupper(username); + } + + /* modification to support PASSWD environmental var + 25.Aug.97, jdblair@uab.edu */ + + if (getenv("PASSWD")) + strcpy(password,getenv("PASSWD")); if (*username == 0 && getenv("LOGNAME")) { @@ -4141,6 +3636,8 @@ int main(int argc,char *argv[]) { strcpy(service,argv[1]); + /* Convert any '/' characters in the service name to '\' characters */ + string_replace( service, '/','\\'); argc--; argv++; @@ -4170,12 +3667,8 @@ int main(int argc,char *argv[]) } } -#ifdef KANJI - setup_term_code (KANJI); - while ((opt = getopt (argc, argv, "B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:")) != EOF) -#else - while ((opt = getopt (argc, argv, "B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:m:W:T:D:")) != EOF) -#endif /* KANJI */ + while ((opt = + getopt(argc, argv,"s:B:O:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF) switch (opt) { case 'm': @@ -4184,15 +3677,19 @@ int main(int argc,char *argv[]) case 'O': strcpy(user_socket_options,optarg); break; + case 'S': + strcpy(desthost,optarg); + strupper(desthost); + nt_domain_logon = True; + break; case 'M': - name_type = 3; + name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */ strcpy(desthost,optarg); strupper(desthost); message = True; break; case 'B': - bcast_ip = *interpret_addr2(optarg); - got_bcast = True; + iface_set_default(NULL,optarg,NULL); break; case 'D': strcpy(base_directory,optarg); @@ -4212,12 +3709,12 @@ int main(int argc,char *argv[]) break; case 'U': { - char *p; + char *lp; strcpy(username,optarg); - if ((p=strchr(username,'%'))) + if ((lp=strchr(username,'%'))) { - *p = 0; - strcpy(password,p+1); + *lp = 0; + strcpy(password,lp+1); got_pass = True; memset(strchr(optarg,'%')+1,'X',strlen(password)); } @@ -4258,19 +3755,20 @@ int main(int argc,char *argv[]) case 'p': port = atoi(optarg); break; + case 'c': + cmdstr = optarg; + got_pass = True; + break; case 'h': usage(pname); exit(0); break; -#ifdef KANJI + case 's': + strcpy(servicesf, optarg); + break; case 't': - if (!setup_term_code (optarg)) { - DEBUG(0, ("%s: unknown terminal code name\n", optarg)); - usage (pname); - exit (1); - } + strcpy(term_code, optarg); break; -#endif /* KANJI */ default: usage(pname); exit(1); @@ -4285,13 +3783,38 @@ int main(int argc,char *argv[]) DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION)); - get_myname(*myname?NULL:myname,&myip); + if(!get_myname(myhostname,NULL)) + { + DEBUG(0,("Failed to get my hostname.\n")); + } + + if (!lp_load(servicesf,True)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); + } + + codepage_initialise(lp_client_code_page()); + + if(lp_client_code_page() == KANJI_CODEPAGE) + { + if (!setup_term_code (term_code)) + { + DEBUG(0, ("%s: unknown terminal code name\n", optarg)); + usage (pname); + exit (1); + } + } + + if (*workgroup == 0) + strcpy(workgroup,lp_workgroup()); + + load_interfaces(); + get_myname((*myname)?NULL:myname,NULL); strupper(myname); if (tar_type) { recurse=True; - if (open_sockets(port)) { + if (cli_open_sockets(port)) { char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); int ret; @@ -4300,32 +3823,32 @@ int main(int argc,char *argv[]) return(1); bzero(OutBuffer,smb_size); - if (!send_login(InBuffer,OutBuffer,True,True)) + if (!cli_send_login(InBuffer,OutBuffer,True,True)) return(False); if (*base_directory) do_cd(base_directory); ret=process_tar(InBuffer, OutBuffer); - send_logout(); + cli_send_logout(); close_sockets(); return(ret); } else return(1); } - if (*query_host) + if (*query_host && !nt_domain_logon) { int ret = 0; sprintf(service,"\\\\%s\\IPC$",query_host); strupper(service); connect_as_ipc = True; - if (open_sockets(port)) + if (cli_open_sockets(port)) { #if 0 *username = 0; #endif - if (!send_login(NULL,NULL,True,True)) + if (!cli_send_login(NULL,NULL,True,True)) return(1); server_info(); @@ -4333,12 +3856,12 @@ int main(int argc,char *argv[]) sleep(1); browse_host(True); } - if (!list_servers()) { + if (!list_servers(workgroup)) { sleep(1); - list_servers(); + list_servers(workgroup); } - send_logout(); + cli_send_logout(); close_sockets(); } @@ -4348,11 +3871,11 @@ int main(int argc,char *argv[]) if (message) { int ret = 0; - if (open_sockets(port)) + if (cli_open_sockets(port)) { pstring inbuf,outbuf; bzero(outbuf,smb_size); - if (!send_session_request(inbuf,outbuf)) + if (!cli_send_session_request(inbuf,outbuf)) return(1); send_message(inbuf,outbuf); @@ -4363,7 +3886,32 @@ int main(int argc,char *argv[]) return(ret); } - if (open_sockets(port)) +#ifdef NTDOMAIN + + if (nt_domain_logon) + { + int ret = 0; + sprintf(service,"\\\\%s\\IPC$",query_host); + strupper(service); + connect_as_ipc = True; + + DEBUG(5,("NT Domain Logon. Service: %s\n", service)); + + if (cli_open_sockets(port)) + { + if (!cli_send_login(NULL,NULL,True,True)) return(1); + + do_nt_login(desthost, myhostname, Client, cnum); + + cli_send_logout(); + close_sockets(); + } + + return(ret); + } +#endif + + if (cli_open_sockets(port)) { if (!process(base_directory)) { @@ -4379,156 +3927,3 @@ int main(int argc,char *argv[]) } -/* error code stuff - put together by Merik Karman - merik@blackadder.dsh.oz.au */ - -typedef struct -{ - char *name; - int code; - char *message; -} err_code_struct; - -/* Dos Error Messages */ -err_code_struct dos_msgs[] = { - {"ERRbadfunc",1,"Invalid function."}, - {"ERRbadfile",2,"File not found."}, - {"ERRbadpath",3,"Directory invalid."}, - {"ERRnofids",4,"No file descriptors available"}, - {"ERRnoaccess",5,"Access denied."}, - {"ERRbadfid",6,"Invalid file handle."}, - {"ERRbadmcb",7,"Memory control blocks destroyed."}, - {"ERRnomem",8,"Insufficient server memory to perform the requested function."}, - {"ERRbadmem",9,"Invalid memory block address."}, - {"ERRbadenv",10,"Invalid environment."}, - {"ERRbadformat",11,"Invalid format."}, - {"ERRbadaccess",12,"Invalid open mode."}, - {"ERRbaddata",13,"Invalid data."}, - {"ERR",14,"reserved."}, - {"ERRbaddrive",15,"Invalid drive specified."}, - {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."}, - {"ERRdiffdevice",17,"Not same device."}, - {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."}, - {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."}, - {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, - {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."}, - {"ERRbadpipe",230,"Pipe invalid."}, - {"ERRpipebusy",231,"All instances of the requested pipe are busy."}, - {"ERRpipeclosing",232,"Pipe close in progress."}, - {"ERRnotconnected",233,"No process on other end of pipe."}, - {"ERRmoredata",234,"There is more data to be returned."}, - {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"}, - {NULL,-1,NULL}}; - -/* Server Error Messages */ -err_code_struct server_msgs[] = { - {"ERRerror",1,"Non-specific error code."}, - {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."}, - {"ERRbadtype",3,"reserved."}, - {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."}, - {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."}, - {"ERRinvnetname",6,"Invalid network name in tree connect."}, - {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."}, - {"ERRqfull",49,"Print queue full (files) -- returned by open print file."}, - {"ERRqtoobig",50,"Print queue full -- no space."}, - {"ERRqeof",51,"EOF on print queue dump."}, - {"ERRinvpfid",52,"Invalid print file FID."}, - {"ERRsmbcmd",64,"The server did not recognize the command received."}, - {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."}, - {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."}, - {"ERRreserved",68,"reserved."}, - {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."}, - {"ERRreserved",70,"reserved."}, - {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."}, - {"ERRpaused",81,"Server is paused."}, - {"ERRmsgoff",82,"Not receiving messages."}, - {"ERRnoroom",83,"No room to buffer message."}, - {"ERRrmuns",87,"Too many remote user names."}, - {"ERRtimeout",88,"Operation timed out."}, - {"ERRnoresource",89,"No resources currently available for request."}, - {"ERRtoomanyuids",90,"Too many UIDs active on this session."}, - {"ERRbaduid",91,"The UID is not known as a valid ID on this session."}, - {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."}, - {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."}, - {"ERRcontmpx",252,"Continue in MPX mode."}, - {"ERRreserved",253,"reserved."}, - {"ERRreserved",254,"reserved."}, - {"ERRnosupport",0xFFFF,"Function not supported."}, - {NULL,-1,NULL}}; - -/* Hard Error Messages */ -err_code_struct hard_msgs[] = { - {"ERRnowrite",19,"Attempt to write on write-protected diskette."}, - {"ERRbadunit",20,"Unknown unit."}, - {"ERRnotready",21,"Drive not ready."}, - {"ERRbadcmd",22,"Unknown command."}, - {"ERRdata",23,"Data error (CRC)."}, - {"ERRbadreq",24,"Bad request structure length."}, - {"ERRseek",25 ,"Seek error."}, - {"ERRbadmedia",26,"Unknown media type."}, - {"ERRbadsector",27,"Sector not found."}, - {"ERRnopaper",28,"Printer out of paper."}, - {"ERRwrite",29,"Write fault."}, - {"ERRread",30,"Read fault."}, - {"ERRgeneral",31,"General failure."}, - {"ERRbadshare",32,"A open conflicts with an existing open."}, - {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, - {"ERRwrongdisk",34,"The wrong disk was found in a drive."}, - {"ERRFCBUnavail",35,"No FCBs are available to process request."}, - {"ERRsharebufexc",36,"A sharing buffer has been exceeded."}, - {NULL,-1,NULL}}; - - -struct -{ - int code; - char *class; - err_code_struct *err_msgs; -} err_classes[] = { - {0,"SUCCESS",NULL}, - {0x01,"ERRDOS",dos_msgs}, - {0x02,"ERRSRV",server_msgs}, - {0x03,"ERRHRD",hard_msgs}, - {0x04,"ERRXOS",NULL}, - {0xE1,"ERRRMX1",NULL}, - {0xE2,"ERRRMX2",NULL}, - {0xE3,"ERRRMX3",NULL}, - {0xFF,"ERRCMD",NULL}, - {-1,NULL,NULL}}; - - -/**************************************************************************** -return a SMB error string from a SMB buffer -****************************************************************************/ -char *smb_errstr(char *inbuf) -{ - static pstring ret; - int class = CVAL(inbuf,smb_rcls); - int num = SVAL(inbuf,smb_err); - int i,j; - - for (i=0;err_classes[i].class;i++) - if (err_classes[i].code == class) - { - if (err_classes[i].err_msgs) - { - err_code_struct *err = err_classes[i].err_msgs; - for (j=0;err[j].name;j++) - if (num == err[j].code) - { - if (DEBUGLEVEL > 0) - sprintf(ret,"%s - %s (%s)",err_classes[i].class, - err[j].name,err[j].message); - else - sprintf(ret,"%s - %s",err_classes[i].class,err[j].name); - return ret; - } - } - - sprintf(ret,"%s - %d",err_classes[i].class,num); - return ret; - } - - sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num); - return(ret); -} |