1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-13 13:18:06 +03:00

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 commit is contained in:
Andrew Tridgell 0001-01-01 00:00:00 +00:00
parent c5210cb0ff
commit 080fb61b69
8 changed files with 214 additions and 19 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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!
********************************************************************/

View File

@ -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 "<ERROR>";
} 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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;