From 6760e69a68571e01ee57b959193a56278962a23c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Oct 1998 09:42:51 +0000 Subject: added support for printing via smbwrapper You can print using "cp filename /smb/SERVER/PRINTER/jobname" You can list the current printqueue using ls (This used to be commit 080fb61b69620e26e8122705383dc2bd0468a519) --- source3/include/client.h | 15 ++++++- source3/include/proto.h | 7 +++ source3/lib/util.c | 12 ++++- source3/libsmb/clientgen.c | 100 +++++++++++++++++++++++++++++++++++++++++ source3/smbd/trans2.c | 14 +++--- source3/smbwrapper/smbw.c | 3 +- source3/smbwrapper/smbw_dir.c | 36 +++++++++++++-- source3/smbwrapper/smbw_stat.c | 46 +++++++++++++++++-- 8 files changed, 214 insertions(+), 19 deletions(-) (limited to 'source3') diff --git a/source3/include/client.h b/source3/include/client.h index 79fb96dad2..495780cbaa 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -25,8 +25,9 @@ #define _CLIENT_H /* the client asks for a smaller buffer to save ram and also to get more - overlap on the wire */ -#define CLI_BUFFER_SIZE (0x4000) + overlap on the wire. This size gives us a nice read/write size, which + will be a multiple of the page size on almost any system */ +#define CLI_BUFFER_SIZE (0x4400) /* * These definitions depend on smb.h @@ -45,6 +46,16 @@ typedef struct file_info pstring name; } file_info; +struct print_job_info +{ + uint16 id; + uint16 priority; + size_t size; + fstring user; + fstring name; + time_t t; +}; + struct pwd_info { BOOL null_pwd; diff --git a/source3/include/proto.h b/source3/include/proto.h index 78863b5984..29803cdbbc 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -321,6 +321,7 @@ struct hostent *Get_Hostbyname(char *name); BOOL process_exists(int pid); char *uidtoname(uid_t uid); char *gidtoname(gid_t gid); +uid_t nametouid(const char *name); void smb_panic(char *why); char *readdirname(void *p); BOOL is_in_path(char *name, name_compare_entry *namelist); @@ -417,6 +418,8 @@ BOOL cli_establish_connection(struct cli_state *cli, struct nmb_name *calling, struct nmb_name *called, char *service, char *service_type, BOOL do_shutdown, BOOL do_tcon); +int cli_print_queue(struct cli_state *cli, + void (*fn)(struct print_job_info *)); /*The following definitions come from libsmb/credentials.c */ @@ -2294,6 +2297,8 @@ int smbw_utime(const char *fname, void *buf); int smbw_chown(const char *fname, uid_t owner, gid_t group); int smbw_chmod(const char *fname, mode_t newmode); off_t smbw_lseek(int fd, off_t offset, int whence); +int smbw_dup(int fd); +int smbw_dup2(int fd, int fd2); /*The following definitions come from smbwrapper/smbw_dir.c */ @@ -2321,6 +2326,8 @@ void smbw_setup_stat(struct stat *st, char *fname, size_t size, int mode); BOOL smbw_getatr(struct smbw_server *srv, char *path, uint32 *mode, size_t *size, time_t *c_time, time_t *a_time, time_t *m_time); +int smbw_stat_printjob(struct smbw_server *srv,char *path, + size_t *size, time_t *m_time); int smbw_fstat(int fd, struct stat *st); int smbw_stat(const char *fname, struct stat *st); diff --git a/source3/lib/util.c b/source3/lib/util.c index 313021abb8..ccbaebf4ea 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -4044,7 +4044,6 @@ BOOL process_exists(int pid) /******************************************************************* turn a uid into a user name ********************************************************************/ - char *uidtoname(uid_t uid) { static char name[40]; @@ -4054,6 +4053,7 @@ char *uidtoname(uid_t uid) return(name); } + /******************************************************************* turn a gid into a group name ********************************************************************/ @@ -4067,6 +4067,16 @@ char *gidtoname(gid_t gid) return(name); } +/******************************************************************* +turn a user name into a uid +********************************************************************/ +uid_t nametouid(const char *name) +{ + struct passwd *pass = getpwnam(name); + if (pass) return(pass->pw_uid); + return (uid_t)-1; +} + /******************************************************************* something really nasty happened - panic! ********************************************************************/ diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index e871bd7d9d..0e01370f5d 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -137,6 +137,29 @@ static void cli_setup_packet(struct cli_state *cli) } +/***************************************************************************** + 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; + + if (offset >= rdrcnt) { + DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>", + datap, converter, rdrcnt)); + return ""; + } else { + return &rdata[offset]; + } + } +} + /**************************************************************************** send a SMB trans or trans2 request ****************************************************************************/ @@ -739,6 +762,8 @@ BOOL cli_send_tconX(struct cli_state *cli, bzero(cli->outbuf,smb_size); bzero(cli->inbuf,smb_size); + fstrcpy(cli->share, share); + if (cli->sec_mode & 1) { passlen = 1; pass = ""; @@ -779,6 +804,8 @@ BOOL cli_send_tconX(struct cli_state *cli, return False; } + fstrcpy(cli->dev, smb_buf(cli->inbuf)); + if (cli->protocol >= PROTOCOL_NT1 && smb_buflen(cli->inbuf) == 3) { /* almost certainly win95 - enable bug fixes */ @@ -2466,3 +2493,76 @@ BOOL cli_establish_connection(struct cli_state *cli, return True; } + + + +/**************************************************************************** +call fn() on each entry in a print queue +****************************************************************************/ +int cli_print_queue(struct cli_state *cli, + void (*fn)(struct print_job_info *)) +{ + char *rparam = NULL; + char *rdata = NULL; + char *p; + int rdrcnt, rprcnt; + pstring param; + int result_code=0; + int i = -1; + + bzero(param,sizeof(param)); + + p = param; + SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */ + p += 2; + pstrcpy(p,"zWrLeh"); /* parameter description? */ + p = skip_string(p,1); + pstrcpy(p,"WWzWWDDzz"); /* returned data format */ + p = skip_string(p,1); + pstrcpy(p,cli->share); /* 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; + pstrcpy(p,""); /* subformat */ + p = skip_string(p,1); + + DEBUG(4,("doing cli_print_queue for %s\n", cli->share)); + + if (cli_api(cli, + param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ + NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */ + &rparam, &rprcnt, /* return params, length */ + &rdata, &rdrcnt)) { /* return data, length */ + int converter; + result_code = SVAL(rparam,0); + converter = SVAL(rparam,2); /* conversion factor */ + + if (result_code == 0) { + struct print_job_info job; + + p = rdata; + + for (i = 0; i < SVAL(rparam,4); ++i) { + job.id = SVAL(p,0); + job.priority = SVAL(p,2); + fstrcpy(job.user, + fix_char_ptr(SVAL(p,4), converter, + rdata, rdrcnt)); + job.t = make_unix_date3(p + 12); + job.size = IVAL(p,16); + fstrcpy(job.name,fix_char_ptr(SVAL(p,24), + converter, + rdata, rdrcnt)); + fn(&job); + p += 28; + } + } + } + + /* If any parameters or data were returned, free the storage. */ + if(rparam) free(rparam); + if(rdata) free(rdata); + + return i; +} diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6fd0272a0a..6d2f61f5b9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -249,7 +249,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) { close_file(fsp,False); - return(ERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } size = sbuf.st_size; @@ -681,7 +681,7 @@ static int call_trans2findfirst(connection_struct *conn, } #endif - return(ERROR(ERRDOS,ERRbadpath)); + return(UNIXERROR(ERRDOS,ERRbadpath)); } p = strrchr(directory,'/'); @@ -707,7 +707,7 @@ static int call_trans2findfirst(connection_struct *conn, dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid)); if (dptr_num < 0) - return(ERROR(ERRDOS,ERRbadfile)); + return(UNIXERROR(ERRDOS,ERRbadfile)); /* Convert the formatted mask. */ mask_convert(mask); @@ -1475,7 +1475,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if(sys_fstat(fd,&st)!=0) { DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); - return(ERROR(ERRDOS,ERRbadpath)); + return(UNIXERROR(ERRDOS,ERRbadpath)); } } else { /* set path info */ @@ -1639,7 +1639,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, { if(file_utime(conn, fname, &tvs)!=0) { - return(ERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } } @@ -1647,7 +1647,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL)) { DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); - return(ERROR(ERRDOS,ERRnoaccess)); + return(UNIXERROR(ERRDOS,ERRnoaccess)); } if(size != st.st_size) @@ -1657,7 +1657,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fd = dos_open(fname,O_RDWR,0); if (fd == -1) { - return(ERROR(ERRDOS,ERRbadpath)); + return(UNIXERROR(ERRDOS,ERRbadpath)); } set_filelen(fd, size); close(fd); diff --git a/source3/smbwrapper/smbw.c b/source3/smbwrapper/smbw.c index 74a40a2451..3a2cbcf5ac 100644 --- a/source3/smbwrapper/smbw.c +++ b/source3/smbwrapper/smbw.c @@ -390,8 +390,7 @@ struct smbw_server *smbw_server(char *server, char *share) return NULL; } - if (!cli_send_tconX(&c, share, - strstr(share,"IPC$")?"IPC":"A:", + if (!cli_send_tconX(&c, share, "?????", password, strlen(password)+1)) { errno = smbw_errno(&c); cli_shutdown(&c); diff --git a/source3/smbwrapper/smbw_dir.c b/source3/smbwrapper/smbw_dir.c index a127048793..3fdaebec5a 100644 --- a/source3/smbwrapper/smbw_dir.c +++ b/source3/smbwrapper/smbw_dir.c @@ -112,6 +112,28 @@ static void smbw_share_add(const char *share, uint32 type, const char *comment) } +/***************************************************** +add a entry to a directory listing +*******************************************************/ +static void smbw_printjob_add(struct print_job_info *job) +{ + struct file_info finfo; + + ZERO_STRUCT(finfo); + + pstrcpy(finfo.name, job->name); + finfo.mode = aRONLY | aDIR; + finfo.mtime = job->t; + finfo.atime = job->t; + finfo.ctime = job->t; + finfo.uid = nametouid(job->user); + finfo.mode = aRONLY; + finfo.size = job->size; + + smbw_dir_add(&finfo); +} + + /***************************************************** open a directory on the server *******************************************************/ @@ -159,15 +181,20 @@ int smbw_dir_open(const char *fname) slprintf(mask, sizeof(mask)-1, "%s\\*", path); string_sub(mask,"\\\\","\\"); - if (strcmp(share,"IPC$") == 0) { + if (strcmp(srv->cli.dev,"IPC") == 0) { DEBUG(4,("doing NetShareEnum\n")); - if (cli_RNetShareEnum(&srv->cli, smbw_share_add) <= 0) { + if (cli_RNetShareEnum(&srv->cli, smbw_share_add) < 0) { + errno = smbw_errno(&srv->cli); + goto failed; + } + } else if (strncmp(srv->cli.dev,"LPT",3) == 0) { + if (cli_print_queue(&srv->cli, smbw_printjob_add) < 0) { errno = smbw_errno(&srv->cli); goto failed; } } else { if (cli_list(&srv->cli, mask, aHIDDEN|aSYSTEM|aDIR, - smbw_dir_add) <= 0) { + smbw_dir_add) < 0) { errno = smbw_errno(&srv->cli); goto failed; } @@ -344,7 +371,8 @@ int smbw_chdir(const char *name) goto failed; } - if (strcmp(share,"IPC$") && + if (strncmp(srv->cli.dev,"IPC",3) && + strncmp(srv->cli.dev,"LPT",3) && !smbw_getatr(srv, path, &mode, NULL, NULL, NULL, NULL)) { errno = smbw_errno(&srv->cli); diff --git a/source3/smbwrapper/smbw_stat.c b/source3/smbwrapper/smbw_stat.c index ae8671c591..69ca38a2ae 100644 --- a/source3/smbwrapper/smbw_stat.c +++ b/source3/smbwrapper/smbw_stat.c @@ -74,6 +74,38 @@ BOOL smbw_getatr(struct smbw_server *srv, char *path, return False; } + +static struct print_job_info printjob; + +/***************************************************** +gather info from a printjob listing +*******************************************************/ +static void smbw_printjob_stat(struct print_job_info *job) +{ + if (strcmp(job->name, printjob.name) == 0) { + printjob = *job; + } +} + +/***************************************************** +stat a printjob +*******************************************************/ +int smbw_stat_printjob(struct smbw_server *srv,char *path, + size_t *size, time_t *m_time) +{ + if (path[0] == '\\') path++; + + ZERO_STRUCT(printjob); + + fstrcpy(printjob.name, path); + cli_print_queue(&srv->cli, smbw_printjob_stat); + + *size = printjob.size; + *m_time = printjob.t; + return 0; +} + + /***************************************************** a wrapper for fstat() *******************************************************/ @@ -151,8 +183,16 @@ int smbw_stat(const char *fname, struct stat *st) goto failed; } - if (strcmp(share,"IPC$") == 0) { + if (strncmp(srv->cli.dev,"IPC",3) == 0) { mode = aDIR | aRONLY; + } else if (strncmp(srv->cli.dev,"LPT",3) == 0) { + if (strcmp(path,"\\") == 0) { + mode = aDIR | aRONLY; + } else { + mode = aRONLY; + smbw_stat_printjob(srv, path, &size, &m_time); + c_time = a_time = m_time; + } } else { if (!smbw_getatr(srv, path, &mode, &size, &c_time, &a_time, &m_time)) { @@ -163,8 +203,8 @@ int smbw_stat(const char *fname, struct stat *st) smbw_setup_stat(st, path, size, mode); - st->st_atime = time(NULL); - st->st_ctime = m_time; + st->st_atime = a_time; + st->st_ctime = c_time; st->st_mtime = m_time; st->st_dev = srv->dev; -- cgit