diff options
Diffstat (limited to 'source4/printing')
-rw-r--r-- | source4/printing/config.m4 | 16 | ||||
-rw-r--r-- | source4/printing/load.c | 73 | ||||
-rw-r--r-- | source4/printing/lpq_parse.c | 1099 | ||||
-rw-r--r-- | source4/printing/notify.c | 526 | ||||
-rw-r--r-- | source4/printing/pcap.c | 413 | ||||
-rw-r--r-- | source4/printing/print_cups.c | 1293 | ||||
-rw-r--r-- | source4/printing/print_generic.c | 245 | ||||
-rw-r--r-- | source4/printing/print_svid.c | 144 | ||||
-rw-r--r-- | source4/printing/printfsp.c | 120 | ||||
-rw-r--r-- | source4/printing/printing.c | 2128 | ||||
-rw-r--r-- | source4/printing/printing_db.c | 204 |
11 files changed, 0 insertions, 6261 deletions
diff --git a/source4/printing/config.m4 b/source4/printing/config.m4 deleted file mode 100644 index ad5e4844e5..0000000000 --- a/source4/printing/config.m4 +++ /dev/null @@ -1,16 +0,0 @@ -############################################ -# for cups support we need libcups, and a handful of header files - -AC_ARG_ENABLE(cups, -[ --enable-cups Turn on CUPS support (default=auto)]) - -if test x$enable_cups != xno; then - AC_PATH_PROG(CUPS_CONFIG, cups-config) - - if test "x$CUPS_CONFIG" != x; then - AC_DEFINE(HAVE_CUPS,1,[Whether we have CUPS]) - CFLAGS="$CFLAGS `$CUPS_CONFIG --cflags`" - LDFLAGS="$LDFLAGS `$CUPS_CONFIG --ldflags`" - PRINTLIBS="$PRINTLIBS `$CUPS_CONFIG --libs`" - fi -fi diff --git a/source4/printing/load.c b/source4/printing/load.c deleted file mode 100644 index cd90cbb6f3..0000000000 --- a/source4/printing/load.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - Unix SMB/CIFS implementation. - load printer lists - Copyright (C) Andrew Tridgell 1992-2000 - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - - -/*************************************************************************** -auto-load printer services -***************************************************************************/ -void add_all_printers(void) -{ - int printers = lp_servicenumber(PRINTERS_NAME); - - if (printers < 0) return; - - pcap_printer_fn(lp_add_one_printer); -} - -/*************************************************************************** -auto-load some homes and printer services -***************************************************************************/ -static void add_auto_printers(void) -{ - const char *p; - int printers; - char *str = strdup(lp_auto_services()); - - if (!str) return; - - printers = lp_servicenumber(PRINTERS_NAME); - - if (printers < 0) { - SAFE_FREE(str); - return; - } - - for (p=strtok(str,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) { - if (lp_servicenumber(p) >= 0) continue; - - if (pcap_printername_ok(p,NULL)) { - lp_add_printer(p,printers); - } - } - - SAFE_FREE(str); -} - -/*************************************************************************** -load automatic printer services -***************************************************************************/ -void load_printers(void) -{ - add_auto_printers(); - if (lp_load_printers()) - add_all_printers(); -} diff --git a/source4/printing/lpq_parse.c b/source4/printing/lpq_parse.c deleted file mode 100644 index 4b91b8ac9a..0000000000 --- a/source4/printing/lpq_parse.c +++ /dev/null @@ -1,1099 +0,0 @@ -/* - Unix SMB/CIFS implementation. - lpq parsing routines - Copyright (C) Andrew Tridgell 2000 - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -static const char *Months[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err"}; - - -/******************************************************************* -process time fields -********************************************************************/ -static time_t EntryTime(fstring tok[], int ptr, int count, int minimum) -{ - time_t jobtime,jobtime1; - - jobtime = time(NULL); /* default case: take current time */ - if (count >= minimum) { - struct tm *t; - int i, day, hour, min, sec; - char *c; - - for (i=0; i<13; i++) if (!strncmp(tok[ptr], Months[i],3)) break; /* Find month */ - if (i<12) { - t = localtime(&jobtime); - day = atoi(tok[ptr+1]); - c=(char *)(tok[ptr+2]); - *(c+2)=0; - hour = atoi(c); - *(c+5)=0; - min = atoi(c+3); - if(*(c+6) != 0)sec = atoi(c+6); - else sec=0; - - if ((t->tm_mon < i)|| - ((t->tm_mon == i)&& - ((t->tm_mday < day)|| - ((t->tm_mday == day)&& - (t->tm_hour*60+t->tm_min < hour*60+min))))) - t->tm_year--; /* last year's print job */ - - t->tm_mon = i; - t->tm_mday = day; - t->tm_hour = hour; - t->tm_min = min; - t->tm_sec = sec; - jobtime1 = mktime(t); - if (jobtime1 != (time_t)-1) - jobtime = jobtime1; - } - } - return jobtime; -} - - -/**************************************************************************** -parse a lpq line - -here is an example of lpq output under bsd - -Warning: no daemon present -Rank Owner Job Files Total Size -1st tridge 148 README 8096 bytes - -here is an example of lpq output under osf/1 - -Warning: no daemon present -Rank Pri Owner Job Files Total Size -1st 0 tridge 148 README 8096 bytes - - -<allan@umich.edu> June 30, 1998. -Modified to handle file names with spaces, like the parse_lpq_lprng code -further below. -****************************************************************************/ -static BOOL parse_lpq_bsd(char *line,print_queue_struct *buf,BOOL first) -{ -#ifdef OSF1 -#define RANKTOK 0 -#define PRIOTOK 1 -#define USERTOK 2 -#define JOBTOK 3 -#define FILETOK 4 -#define TOTALTOK (count - 2) -#define NTOK 6 -#define MAXTOK 128 -#else /* OSF1 */ -#define RANKTOK 0 -#define USERTOK 1 -#define JOBTOK 2 -#define FILETOK 3 -#define TOTALTOK (count - 2) -#define NTOK 5 -#define MAXTOK 128 -#endif /* OSF1 */ - - char *tok[MAXTOK]; - int count = 0; - pstring line2; - - pstrcpy(line2,line); - -#ifdef OSF1 - { - size_t length; - length = strlen(line2); - if (line2[length-3] == ':') - return(False); - } -#endif /* OSF1 */ - - /* FIXME: Use next_token rather than strtok! */ - tok[0] = strtok(line2," \t"); - count++; - - while (((tok[count] = strtok(NULL," \t")) != NULL) && (count < MAXTOK)) { - count++; - } - - /* we must get at least NTOK tokens */ - if (count < NTOK) - return(False); - - /* the Job and Total columns must be integer */ - if (!isdigit((int)*tok[JOBTOK]) || !isdigit((int)*tok[TOTALTOK])) return(False); - - buf->job = atoi(tok[JOBTOK]); - buf->size = atoi(tok[TOTALTOK]); - buf->status = strequal(tok[RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED; - buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[USERTOK],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[FILETOK],sizeof(buf->fs_file)-1); - - if ((FILETOK + 1) != TOTALTOK) { - int i; - - for (i = (FILETOK + 1); i < TOTALTOK; i++) { - /* FIXME: Using fstrcat rather than other means is a bit - * inefficient; this might be a problem for enormous queues with - * many fields. */ - fstrcat(buf->fs_file, " "); - fstrcat(buf->fs_file, tok[i]); - } - /* Ensure null termination. */ - fstrterminate(buf->fs_file); - } - -#ifdef PRIOTOK - buf->priority = atoi(tok[PRIOTOK]); -#else - buf->priority = 1; -#endif - return(True); -} - -/* -<magnus@hum.auc.dk> -LPRng_time modifies the current date by inserting the hour and minute from -the lpq output. The lpq time looks like "23:15:07" - -<allan@umich.edu> June 30, 1998. -Modified to work with the re-written parse_lpq_lprng routine. - -<J.P.M.v.Itegem@tue.nl> Dec 17,1999 -Modified to work with lprng 3.16 -With lprng 3.16 The lpq time looks like - "23:15:07" - "23:15:07.100" - "1999-12-16-23:15:07" - "1999-12-16-23:15:07.100" - -*/ -static time_t LPRng_time(char *time_string) -{ - time_t jobtime; - struct tm t; - - jobtime = time(NULL); /* default case: take current time */ - t = *localtime(&jobtime); - - if ( atoi(time_string) < 24 ){ - t.tm_hour = atoi(time_string); - t.tm_min = atoi(time_string+3); - t.tm_sec = atoi(time_string+6); - } else { - t.tm_year = atoi(time_string)-1900; - t.tm_mon = atoi(time_string+5)-1; - t.tm_mday = atoi(time_string+8); - t.tm_hour = atoi(time_string+11); - t.tm_min = atoi(time_string+14); - t.tm_sec = atoi(time_string+17); - } - jobtime = mktime(&t); - - return jobtime; -} - - -/**************************************************************************** - parse a lprng lpq line - <allan@umich.edu> June 30, 1998. - Re-wrote this to handle file names with spaces, multiple file names on one - lpq line, etc; -****************************************************************************/ -static BOOL parse_lpq_lprng(char *line,print_queue_struct *buf,BOOL first) -{ -#define LPRNG_RANKTOK 0 -#define LPRNG_USERTOK 1 -#define LPRNG_PRIOTOK 2 -#define LPRNG_JOBTOK 3 -#define LPRNG_FILETOK 4 -#define LPRNG_TOTALTOK (num_tok - 2) -#define LPRNG_TIMETOK (num_tok - 1) -#define LPRNG_NTOK 7 -#define LPRNG_MAXTOK 128 /* PFMA just to keep us from running away. */ - - fstring tokarr[LPRNG_MAXTOK]; - const char *cptr; - char *ptr; - int num_tok = 0; - - cptr = line; - while(next_token( &cptr, tokarr[num_tok], " \t", sizeof(fstring)) && (num_tok < LPRNG_MAXTOK)) - num_tok++; - - /* We must get at least LPRNG_NTOK tokens. */ - if (num_tok < LPRNG_NTOK) { - return(False); - } - - if (!isdigit((int)*tokarr[LPRNG_JOBTOK]) || !isdigit((int)*tokarr[LPRNG_TOTALTOK])) { - return(False); - } - - buf->job = atoi(tokarr[LPRNG_JOBTOK]); - buf->size = atoi(tokarr[LPRNG_TOTALTOK]); - - if (strequal(tokarr[LPRNG_RANKTOK],"active")) { - buf->status = LPQ_PRINTING; - } else if (strequal(tokarr[LPRNG_RANKTOK],"done")) { - buf->status = LPQ_PRINTED; - } else if (isdigit((int)*tokarr[LPRNG_RANKTOK])) { - buf->status = LPQ_QUEUED; - } else { - buf->status = LPQ_PAUSED; - } - - buf->priority = *tokarr[LPRNG_PRIOTOK] -'A'; - - buf->time = LPRng_time(tokarr[LPRNG_TIMETOK]); - - StrnCpy(buf->fs_user,tokarr[LPRNG_USERTOK],sizeof(buf->fs_user)-1); - - /* The '@hostname' prevents windows from displaying the printing icon - * for the current user on the taskbar. Plop in a null. - */ - - if ((ptr = strchr_m(buf->fs_user,'@')) != NULL) { - *ptr = '\0'; - } - - StrnCpy(buf->fs_file,tokarr[LPRNG_FILETOK],sizeof(buf->fs_file)-1); - - if ((LPRNG_FILETOK + 1) != LPRNG_TOTALTOK) { - int i; - - for (i = (LPRNG_FILETOK + 1); i < LPRNG_TOTALTOK; i++) { - /* FIXME: Using fstrcat rather than other means is a bit - * inefficient; this might be a problem for enormous queues with - * many fields. */ - fstrcat(buf->fs_file, " "); - fstrcat(buf->fs_file, tokarr[i]); - } - /* Ensure null termination. */ - fstrterminate(buf->fs_file); - } - - return(True); -} - - - -/******************************************************************* -parse lpq on an aix system - -Queue Dev Status Job Files User PP % Blks Cp Rnk -------- ----- --------- --- ------------------ ---------- ---- -- ----- --- --- -lazer lazer READY -lazer lazer RUNNING 537 6297doc.A kvintus@IE 0 10 2445 1 1 - QUEUED 538 C.ps root@IEDVB 124 1 2 - QUEUED 539 E.ps root@IEDVB 28 1 3 - QUEUED 540 L.ps root@IEDVB 172 1 4 - QUEUED 541 P.ps root@IEDVB 22 1 5 -********************************************************************/ -static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first) -{ - fstring tok[11]; - int count=0; - const char *cline = line; - - /* handle the case of "(standard input)" as a filename */ - string_sub(line,"standard input","STDIN",0); - all_string_sub(line,"(","\"",0); - all_string_sub(line,")","\"",0); - - for (count=0; - count<10 && - next_token(&cline,tok[count],NULL, sizeof(tok[count])); - count++) ; - - /* we must get 6 tokens */ - if (count < 10) - { - if ((count == 7) && ((strcmp(tok[0],"QUEUED") == 0) || (strcmp(tok[0],"HELD") == 0))) - { - /* the 2nd and 5th columns must be integer */ - if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4])) return(False); - buf->size = atoi(tok[4]) * 1024; - /* if the fname contains a space then use STDIN */ - if (strchr_m(tok[2],' ')) - fstrcpy(tok[2],"STDIN"); - - /* only take the last part of the filename */ - { - fstring tmp; - char *p = strrchr_m(tok[2],'/'); - if (p) - { - fstrcpy(tmp,p+1); - fstrcpy(tok[2],tmp); - } - } - - - buf->job = atoi(tok[1]); - buf->status = strequal(tok[0],"HELD")?LPQ_PAUSED:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[3],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[2],sizeof(buf->fs_file)-1); - } - else - { - DEBUG(6,("parse_lpq_aix count=%d\n", count)); - return(False); - } - } - else - { - /* the 4th and 9th columns must be integer */ - if (!isdigit((int)*tok[3]) || !isdigit((int)*tok[8])) return(False); - buf->size = atoi(tok[8]) * 1024; - /* if the fname contains a space then use STDIN */ - if (strchr_m(tok[4],' ')) - fstrcpy(tok[4],"STDIN"); - - /* only take the last part of the filename */ - { - fstring tmp; - char *p = strrchr_m(tok[4],'/'); - if (p) - { - fstrcpy(tmp,p+1); - fstrcpy(tok[4],tmp); - } - } - - - buf->job = atoi(tok[3]); - buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[5],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[4],sizeof(buf->fs_file)-1); - } - - - return(True); -} - - -/**************************************************************************** -parse a lpq line -here is an example of lpq output under hpux; note there's no space after -o ! -$> lpstat -oljplus -ljplus-2153 user priority 0 Jan 19 08:14 on ljplus - util.c 125697 bytes - server.c 110712 bytes -ljplus-2154 user priority 0 Jan 19 08:14 from client - (standard input) 7551 bytes -****************************************************************************/ -static BOOL parse_lpq_hpux(char *line, print_queue_struct *buf, BOOL first) -{ - /* must read two lines to process, therefore keep some values static */ - static BOOL header_line_ok=False, base_prio_reset=False; - static fstring jobuser; - static int jobid; - static int jobprio; - static time_t jobtime; - static int jobstat=LPQ_QUEUED; - /* to store minimum priority to print, lpstat command should be invoked - with -p option first, to work */ - static int base_prio; - int count; - char htab = '\011'; - const char *cline = line; - fstring tok[12]; - - /* If a line begins with a horizontal TAB, it is a subline type */ - - if (line[0] == htab) { /* subline */ - /* check if it contains the base priority */ - if (!strncmp(line,"\tfence priority : ",18)) { - base_prio=atoi(&line[18]); - DEBUG(4, ("fence priority set at %d\n", base_prio)); - } - if (!header_line_ok) return (False); /* incorrect header line */ - /* handle the case of "(standard input)" as a filename */ - string_sub(line,"standard input","STDIN",0); - all_string_sub(line,"(","\"",0); - all_string_sub(line,")","\"",0); - - for (count=0; count<2 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) ; - /* we must get 2 tokens */ - if (count < 2) return(False); - - /* the 2nd column must be integer */ - if (!isdigit((int)*tok[1])) return(False); - - /* if the fname contains a space then use STDIN */ - if (strchr_m(tok[0],' ')) - fstrcpy(tok[0],"STDIN"); - - buf->size = atoi(tok[1]); - StrnCpy(buf->fs_file,tok[0],sizeof(buf->fs_file)-1); - - /* fill things from header line */ - buf->time = jobtime; - buf->job = jobid; - buf->status = jobstat; - buf->priority = jobprio; - StrnCpy(buf->fs_user,jobuser,sizeof(buf->fs_user)-1); - - return(True); - } - else { /* header line */ - header_line_ok=False; /* reset it */ - if (first) { - if (!base_prio_reset) { - base_prio=0; /* reset it */ - base_prio_reset=True; - } - } - else if (base_prio) base_prio_reset=False; - - /* handle the dash in the job id */ - string_sub(line,"-"," ",0); - - for (count=0; count<12 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) ; - - /* we must get 8 tokens */ - if (count < 8) return(False); - - /* first token must be printer name (cannot check ?) */ - /* the 2nd, 5th & 7th column must be integer */ - if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4]) || !isdigit((int)*tok[6])) return(False); - jobid = atoi(tok[1]); - StrnCpy(jobuser,tok[2],sizeof(buf->fs_user)-1); - jobprio = atoi(tok[4]); - - /* process time */ - jobtime=EntryTime(tok, 5, count, 8); - if (jobprio < base_prio) { - jobstat = LPQ_PAUSED; - DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n", jobid, jobprio, base_prio, jobstat)); - } - else { - jobstat = LPQ_QUEUED; - if ((count >8) && (((strequal(tok[8],"on")) || - ((strequal(tok[8],"from")) && - ((count > 10)&&(strequal(tok[10],"on"))))))) - jobstat = LPQ_PRINTING; - } - - header_line_ok=True; /* information is correct */ - return(False); /* need subline info to include into queuelist */ - } -} - - -/**************************************************************************** -parse a lpstat line - -here is an example of "lpstat -o dcslw" output under sysv - -dcslw-896 tridge 4712 Dec 20 10:30:30 on dcslw -dcslw-897 tridge 4712 Dec 20 10:30:30 being held - -****************************************************************************/ -static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first) -{ - fstring tok[9]; - int count=0; - char *p; - const char *cline = line; - - /* - * Handle the dash in the job id, but make sure that we skip over - * the printer name in case we have a dash in that. - * Patch from Dom.Mitchell@palmerharvey.co.uk. - */ - - /* - * Move to the first space. - */ - for (p = line ; !isspace(*p) && *p; p++) - ; - - /* - * Back up until the last '-' character or - * start of line. - */ - for (; (p >= line) && (*p != '-'); p--) - ; - - if((p >= line) && (*p == '-')) - *p = ' '; - - for (count=0; count<9 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) - ; - - /* we must get 7 tokens */ - if (count < 7) - return(False); - - /* the 2nd and 4th, 6th columns must be integer */ - if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[3])) - return(False); - if (!isdigit((int)*tok[5])) - return(False); - - /* if the user contains a ! then trim the first part of it */ - if ((p=strchr_m(tok[2],'!'))) { - fstring tmp; - fstrcpy(tmp,p+1); - fstrcpy(tok[2],tmp); - } - - buf->job = atoi(tok[1]); - buf->size = atoi(tok[3]); - if (count > 7 && strequal(tok[7],"on")) - buf->status = LPQ_PRINTING; - else if (count > 8 && strequal(tok[7],"being") && strequal(tok[8],"held")) - buf->status = LPQ_PAUSED; - else - buf->status = LPQ_QUEUED; - buf->priority = 0; - buf->time = EntryTime(tok, 4, count, 7); - StrnCpy(buf->fs_user,tok[2],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[2],sizeof(buf->fs_file)-1); - return(True); -} - -/**************************************************************************** -parse a lpq line - -here is an example of lpq output under qnx -Spooler: /qnx/spooler, on node 1 -Printer: txt (ready) -0000: root [job #1 ] active 1146 bytes /etc/profile -0001: root [job #2 ] ready 2378 bytes /etc/install -0002: root [job #3 ] ready 1146 bytes -- standard input -- -****************************************************************************/ -static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first) -{ - fstring tok[7]; - int count=0; - const char *cline; - - DEBUG(4,("antes [%s]\n", line)); - - /* handle the case of "-- standard input --" as a filename */ - string_sub(line,"standard input","STDIN",0); - DEBUG(4,("despues [%s]\n", line)); - all_string_sub(line,"-- ","\"",0); - all_string_sub(line," --","\"",0); - DEBUG(4,("despues 1 [%s]\n", line)); - - string_sub(line,"[job #","",0); - string_sub(line,"]","",0); - DEBUG(4,("despues 2 [%s]\n", line)); - - for (count=0; count<7 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) ; - - /* we must get 7 tokens */ - if (count < 7) - return(False); - - /* the 3rd and 5th columns must be integer */ - if (!isdigit((int)*tok[2]) || !isdigit((int)*tok[4])) return(False); - - /* only take the last part of the filename */ - { - fstring tmp; - char *p = strrchr_m(tok[6],'/'); - if (p) - { - fstrcpy(tmp,p+1); - fstrcpy(tok[6],tmp); - } - } - - - buf->job = atoi(tok[2]); - buf->size = atoi(tok[4]); - buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[1],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[6],sizeof(buf->fs_file)-1); - return(True); -} - - -/**************************************************************************** - parse a lpq line for the plp printing system - Bertrand Wallrich <Bertrand.Wallrich@loria.fr> - -redone by tridge. Here is a sample queue: - -Local Printer 'lp2' (fjall): - Printing (started at Jun 15 13:33:58, attempt 1). - Rank Owner Pr Opt Job Host Files Size Date - active tridge X - 6 fjall /etc/hosts 739 Jun 15 13:33 - 3rd tridge X - 7 fjall /etc/hosts 739 Jun 15 13:33 - -****************************************************************************/ -static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first) -{ - fstring tok[11]; - int count=0; - const char *cline = line; - - /* handle the case of "(standard input)" as a filename */ - string_sub(line,"stdin","STDIN",0); - all_string_sub(line,"(","\"",0); - all_string_sub(line,")","\"",0); - - for (count=0; count<11 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) ; - - /* we must get 11 tokens */ - if (count < 11) - return(False); - - /* the first must be "active" or begin with an integer */ - if (strcmp(tok[0],"active") && !isdigit((int)tok[0][0])) - return(False); - - /* the 5th and 8th must be integer */ - if (!isdigit((int)*tok[4]) || !isdigit((int)*tok[7])) - return(False); - - /* if the fname contains a space then use STDIN */ - if (strchr_m(tok[6],' ')) - fstrcpy(tok[6],"STDIN"); - - /* only take the last part of the filename */ - { - fstring tmp; - char *p = strrchr_m(tok[6],'/'); - if (p) - { - fstrcpy(tmp,p+1); - fstrcpy(tok[6],tmp); - } - } - - - buf->job = atoi(tok[4]); - - buf->size = atoi(tok[7]); - if (strchr_m(tok[7],'K')) - buf->size *= 1024; - if (strchr_m(tok[7],'M')) - buf->size *= 1024*1024; - - buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[1],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[6],sizeof(buf->fs_file)-1); - return(True); -} - -/**************************************************************************** -parse a qstat line - -here is an example of "qstat -l -d qms" output under softq - -Queue qms: 2 jobs; daemon active (313); enabled; accepting; - job-ID submission-time pri size owner title -205980: H 98/03/09 13:04:05 0 15733 stephenf chap1.ps -206086:> 98/03/12 17:24:40 0 659 chris - -206087: 98/03/12 17:24:45 0 4876 chris - -Total: 21268 bytes in queue - - -****************************************************************************/ -static BOOL parse_lpq_softq(char *line,print_queue_struct *buf,BOOL first) -{ - fstring tok[10]; - int count=0; - const char *cline = line; - - /* mung all the ":"s to spaces*/ - string_sub(line,":"," ",0); - - for (count=0; count<10 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) ; - - /* we must get 9 tokens */ - if (count < 9) - return(False); - - /* the 1st and 7th columns must be integer */ - if (!isdigit((int)*tok[0]) || !isdigit((int)*tok[6])) return(False); - /* if the 2nd column is either '>' or 'H' then the 7th and 8th must be - * integer, else it's the 6th and 7th that must be - */ - if (*tok[1] == 'H' || *tok[1] == '>') - { - if (!isdigit((int)*tok[7])) - return(False); - buf->status = *tok[1] == '>' ? LPQ_PRINTING : LPQ_PAUSED; - count = 1; - } - else - { - if (!isdigit((int)*tok[5])) - return(False); - buf->status = LPQ_QUEUED; - count = 0; - } - - - buf->job = atoi(tok[0]); - buf->size = atoi(tok[count+6]); - buf->priority = atoi(tok[count+5]); - StrnCpy(buf->fs_user,tok[count+7],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[count+8],sizeof(buf->fs_file)-1); - buf->time = time(NULL); /* default case: take current time */ - { - time_t jobtime; - struct tm *t; - - t = localtime(&buf->time); - t->tm_mday = atoi(tok[count+2]+6); - t->tm_mon = atoi(tok[count+2]+3); - switch (*tok[count+2]) - { - case 7: case 8: case 9: t->tm_year = atoi(tok[count+2]); break; - default: t->tm_year = atoi(tok[count+2]); break; - } - - t->tm_hour = atoi(tok[count+3]); - t->tm_min = atoi(tok[count+4]); - t->tm_sec = atoi(tok[count+5]); - jobtime = mktime(t); - if (jobtime != (time_t)-1) - buf->time = jobtime; - } - - return(True); -} - -/******************************************************************* -parse lpq on an NT system - - Windows 2000 LPD Server - Printer \\10.0.0.2\NP17PCL (Paused) - -Owner Status Jobname Job-Id Size Pages Priority ----------------------------------------------------------------------------- -root (9.99. Printing /usr/lib/rhs/rhs-pr 3 625 0 1 -root (9.99. Paused /usr/lib/rhs/rhs-pr 4 625 0 1 -jmcd Waiting Re: Samba Open Sour 26 32476 1 1 - -********************************************************************/ -static BOOL parse_lpq_nt(char *line,print_queue_struct *buf,BOOL first) -{ -#define LPRNT_OWNSIZ 11 -#define LPRNT_STATSIZ 9 -#define LPRNT_JOBSIZ 19 -#define LPRNT_IDSIZ 6 -#define LPRNT_SIZSIZ 9 - typedef struct - { - char owner[LPRNT_OWNSIZ]; - char space1; - char status[LPRNT_STATSIZ]; - char space2; - char jobname[LPRNT_JOBSIZ]; - char space3; - char jobid[LPRNT_IDSIZ]; - char space4; - char size[LPRNT_SIZSIZ]; - char terminator; - } nt_lpq_line; - - nt_lpq_line parse_line; -#define LPRNT_PRINTING "Printing" -#define LPRNT_WAITING "Waiting" -#define LPRNT_PAUSED "Paused" - - memset(&parse_line, '\0', sizeof(parse_line)); - strncpy((char *) &parse_line, line, sizeof(parse_line) -1); - - if (strlen((char *) &parse_line) != sizeof(parse_line) - 1) - return(False); - - /* Just want the first word in the owner field - the username */ - if (strchr_m(parse_line.owner, ' ')) - *(strchr_m(parse_line.owner, ' ')) = '\0'; - else - parse_line.space1 = '\0'; - - /* Make sure we have an owner */ - if (!strlen(parse_line.owner)) - return(False); - - /* Make sure the status is valid */ - parse_line.space2 = '\0'; - trim_string(parse_line.status, NULL, " "); - if (!strequal(parse_line.status, LPRNT_PRINTING) && - !strequal(parse_line.status, LPRNT_PAUSED) && - !strequal(parse_line.status, LPRNT_WAITING)) - return(False); - - parse_line.space3 = '\0'; - trim_string(parse_line.jobname, NULL, " "); - - buf->job = atoi(parse_line.jobid); - buf->priority = 0; - buf->size = atoi(parse_line.size); - buf->time = time(NULL); - StrnCpy(buf->fs_user, parse_line.owner, sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file, parse_line.jobname, sizeof(buf->fs_file)-1); - if (strequal(parse_line.status, LPRNT_PRINTING)) - buf->status = LPQ_PRINTING; - else if (strequal(parse_line.status, LPRNT_PAUSED)) - buf->status = LPQ_PAUSED; - else - buf->status = LPQ_QUEUED; - - return(True); -} - -/******************************************************************* -parse lpq on an OS2 system - -JobID File Name Rank Size Status Comment ------ --------------- ------ -------- ------------ ------------ - 3 Control 1 68 Queued root@psflinu - 4 /etc/motd 2 11666 Queued root@psflinu - -********************************************************************/ -static BOOL parse_lpq_os2(char *line,print_queue_struct *buf,BOOL first) -{ -#define LPROS2_IDSIZ 5 -#define LPROS2_JOBSIZ 15 -#define LPROS2_SIZSIZ 8 -#define LPROS2_STATSIZ 12 -#define LPROS2_OWNSIZ 12 - typedef struct - { - char jobid[LPROS2_IDSIZ]; - char space1[2]; - char jobname[LPROS2_JOBSIZ]; - char space2[14]; - char size[LPROS2_SIZSIZ]; - char space3[4]; - char status[LPROS2_STATSIZ]; - char space4[4]; - char owner[LPROS2_OWNSIZ]; - char terminator; - } os2_lpq_line; - - os2_lpq_line parse_line; -#define LPROS2_PRINTING "Printing" -#define LPROS2_WAITING "Queued" -#define LPROS2_PAUSED "Paused" - - memset(&parse_line, '\0', sizeof(parse_line)); - strncpy((char *) &parse_line, line, sizeof(parse_line) -1); - - if (strlen((char *) &parse_line) != sizeof(parse_line) - 1) - return(False); - - /* Get the jobid */ - buf->job = atoi(parse_line.jobid); - - /* Get the job name */ - parse_line.space2[0] = '\0'; - trim_string(parse_line.jobname, NULL, " "); - StrnCpy(buf->fs_file, parse_line.jobname, sizeof(buf->fs_file)-1); - - buf->priority = 0; - buf->size = atoi(parse_line.size); - buf->time = time(NULL); - - /* Make sure we have an owner */ - if (!strlen(parse_line.owner)) - return(False); - - /* Make sure we have a valid status */ - parse_line.space4[0] = '\0'; - trim_string(parse_line.status, NULL, " "); - if (!strequal(parse_line.status, LPROS2_PRINTING) && - !strequal(parse_line.status, LPROS2_PAUSED) && - !strequal(parse_line.status, LPROS2_WAITING)) - return(False); - - StrnCpy(buf->fs_user, parse_line.owner, sizeof(buf->fs_user)-1); - if (strequal(parse_line.status, LPROS2_PRINTING)) - buf->status = LPQ_PRINTING; - else if (strequal(parse_line.status, LPROS2_PAUSED)) - buf->status = LPQ_PAUSED; - else - buf->status = LPQ_QUEUED; - - return(True); -} - -static const char *stat0_strings[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL }; -static const char *stat1_strings[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL }; -static const char *stat2_strings[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL }; - -#ifdef DEVELOPER - -/**************************************************************************** -parse a vlp line -****************************************************************************/ -static BOOL parse_lpq_vlp(char *line,print_queue_struct *buf,BOOL first) -{ - int toknum = 0; - fstring tok; - const char *cline = line; - - /* First line is printer status */ - - if (!isdigit(line[0])) return False; - - /* Parse a print job entry */ - - while(next_token(&cline, tok, NULL, sizeof(fstring))) { - switch (toknum) { - case 0: - buf->job = atoi(tok); - break; - case 1: - buf->size = atoi(tok); - break; - case 2: - buf->status = atoi(tok); - break; - case 3: - buf->time = atoi(tok); - break; - case 4: - fstrcpy(buf->fs_user, tok); - break; - case 5: - fstrcpy(buf->fs_file, tok); - break; - } - toknum++; - } - - return True; -} - -#endif /* DEVELOPER */ - -/**************************************************************************** -parse a lpq line. Choose printing style -****************************************************************************/ - -BOOL parse_lpq_entry(int snum,char *line, - print_queue_struct *buf, - print_status_struct *status,BOOL first) -{ - BOOL ret; - - switch (lp_printing(snum)) - { - case PRINT_SYSV: - ret = parse_lpq_sysv(line,buf,first); - break; - case PRINT_AIX: - ret = parse_lpq_aix(line,buf,first); - break; - case PRINT_HPUX: - ret = parse_lpq_hpux(line,buf,first); - break; - case PRINT_QNX: - ret = parse_lpq_qnx(line,buf,first); - break; - case PRINT_LPRNG: - ret = parse_lpq_lprng(line,buf,first); - break; - case PRINT_PLP: - ret = parse_lpq_plp(line,buf,first); - break; - case PRINT_SOFTQ: - ret = parse_lpq_softq(line,buf,first); - break; - case PRINT_LPRNT: - ret = parse_lpq_nt(line,buf,first); - break; - case PRINT_LPROS2: - ret = parse_lpq_os2(line,buf,first); - break; -#ifdef DEVELOPER - case PRINT_VLP: - case PRINT_TEST: - ret = parse_lpq_vlp(line,buf,first); - break; -#endif /* DEVELOPER */ - default: - ret = parse_lpq_bsd(line,buf,first); - break; - } - - /* We don't want the newline in the status message. */ - { - char *p = strchr_m(line,'\n'); - if (p) *p = 0; - } - - /* in the LPRNG case, we skip lines starting by a space.*/ - if (line && !ret && (lp_printing(snum)==PRINT_LPRNG) ) - { - if (line[0]==' ') - return ret; - } - - - if (status && !ret) - { - /* a few simple checks to see if the line might be a - printer status line: - handle them so that most severe condition is shown */ - int i; - strlower(line); - - switch (status->status) { - case LPSTAT_OK: - for (i=0; stat0_strings[i]; i++) - if (strstr(line,stat0_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_OK; - return ret; - } - case LPSTAT_STOPPED: - for (i=0; stat1_strings[i]; i++) - if (strstr(line,stat1_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_STOPPED; - return ret; - } - case LPSTAT_ERROR: - for (i=0; stat2_strings[i]; i++) - if (strstr(line,stat2_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_ERROR; - return ret; - } - break; - } - } - - return(ret); -} diff --git a/source4/printing/notify.c b/source4/printing/notify.c deleted file mode 100644 index a745e9e308..0000000000 --- a/source4/printing/notify.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 2.2 - printing backend routines - Copyright (C) Tim Potter, 2002 - Copyright (C) Gerald Carter, 2002 - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "printing.h" - -static TALLOC_CTX *send_ctx; - -static BOOL create_send_ctx(void) -{ - if (!send_ctx) - send_ctx = talloc_init("print notify queue"); - - if (!send_ctx) - return False; - - return True; -} - -/**************************************************************************** - Turn a queue name into a snum. -****************************************************************************/ - -int print_queue_snum(const char *qname) -{ - int snum = lp_servicenumber(qname); - if (snum == -1 || !lp_print_ok(snum)) - return -1; - return snum; -} - -/******************************************************************* - Used to decide if we need a short select timeout. -*******************************************************************/ - -BOOL print_notify_messages_pending(void) -{ - return (notify_queue_head != NULL); -} - -/******************************************************************* - Flatten data into a message. -*******************************************************************/ - -static BOOL flatten_message(struct notify_queue *q) -{ - struct spoolss_notify_msg *msg = q->msg; - char *buf = NULL; - size_t buflen = 0, len; - -again: - len = 0; - - /* Pack header */ - - len += tdb_pack(buf + len, buflen - len, "f", msg->printer); - - len += tdb_pack(buf + len, buflen - len, "ddddd", - msg->type, msg->field, msg->id, msg->len, msg->flags); - - /* Pack data */ - - if (msg->len == 0) - len += tdb_pack(buf + len, buflen - len, "dd", - msg->notify.value[0], msg->notify.value[1]); - else - len += tdb_pack(buf + len, buflen - len, "B", - msg->len, msg->notify.data); - - if (buflen != len) { - buf = talloc_realloc(send_ctx, buf, len); - if (!buf) - return False; - buflen = len; - goto again; - } - - q->buf = buf; - q->buflen = buflen; - - return True; -} - -/******************************************************************* - Send the batched messages - on a per-printer basis. -*******************************************************************/ - -static void print_notify_send_messages_to_printer(const char *printer, unsigned int timeout) -{ - char *buf; - struct notify_queue *pq, *pq_next; - size_t msg_count = 0, offset = 0; - size_t num_pids = 0; - size_t i; - pid_t *pid_list = NULL; - - /* Count the space needed to send the messages. */ - for (pq = notify_queue_head; pq; pq = pq->next) { - if (strequal(printer, pq->msg->printer)) { - if (!flatten_message(pq)) { - DEBUG(0,("print_notify_send_messages: Out of memory\n")); - talloc_destroy_pool(send_ctx); - return; - } - offset += (pq->buflen + 4); - msg_count++; - } - } - offset += 4; /* For count. */ - - buf = talloc(send_ctx, offset); - if (!buf) { - DEBUG(0,("print_notify_send_messages: Out of memory\n")); - talloc_destroy_pool(send_ctx); - return; - } - - offset = 0; - SIVAL(buf,offset,msg_count); - offset += 4; - for (pq = notify_queue_head; pq; pq = pq_next) { - pq_next = pq->next; - - if (strequal(printer, pq->msg->printer)) { - SIVAL(buf,offset,pq->buflen); - offset += 4; - memcpy(buf + offset, pq->buf, pq->buflen); - offset += pq->buflen; - - /* Remove from list. */ - DLIST_REMOVE(notify_queue_head, pq); - } - } - - DEBUG(5, ("print_notify_send_messages_to_printer: sending %d print notify message%s to printer %s\n", - msg_count, msg_count != 1 ? "s" : "", printer)); - - /* - * Get the list of PID's to send to. - */ - - if (!print_notify_pid_list(printer, send_ctx, &num_pids, &pid_list)) - return; - - for (i = 0; i < num_pids; i++) - message_send_pid_with_timeout(pid_list[i], MSG_PRINTER_NOTIFY2, buf, offset, True, timeout); -} - -/******************************************************************* - Actually send the batched messages. -*******************************************************************/ - -void print_notify_send_messages(unsigned int timeout) -{ - if (!print_notify_messages_pending()) - return; - - if (!create_send_ctx()) - return; - - while (print_notify_messages_pending()) - print_notify_send_messages_to_printer(notify_queue_head->msg->printer, timeout); - - talloc_destroy_pool(send_ctx); -} - -/********************************************************************** - deep copy a SPOOLSS_NOTIFY_MSG structure using a TALLOC_CTX - *********************************************************************/ - -static BOOL copy_notify2_msg( SPOOLSS_NOTIFY_MSG *to, SPOOLSS_NOTIFY_MSG *from ) -{ - - if ( !to || !from ) - return False; - - memcpy( to, from, sizeof(SPOOLSS_NOTIFY_MSG) ); - - if ( from->len ) { - to->notify.data = talloc_memdup(send_ctx, from->notify.data, from->len ); - if ( !to->notify.data ) { - DEBUG(0,("copy_notify2_msg: talloc_memdup() of size [%d] failed!\n", from->len )); - return False; - } - } - - - return True; -} - -/******************************************************************* - Batch up print notify messages. -*******************************************************************/ - -static void send_spoolss_notify2_msg(SPOOLSS_NOTIFY_MSG *msg) -{ - struct notify_queue *pnqueue; - - /* - * Ensure we only have one message unique to each name/type/field/id/flags - * tuple. There is no point in sending multiple messages that match - * as they will just cause flickering updates in the client. - */ - - for (tmp_ptr = notify_queue_head; tmp_ptr; tmp_ptr = tmp_ptr->next) { - if (tmp_ptr->msg->type == msg->type && - tmp_ptr->msg->field == msg->field && - tmp_ptr->msg->id == msg->id && - tmp_ptr->msg->flags == msg->flags && - strequal(tmp_ptr->msg->printer, msg->printer)) { - - DEBUG(5, ("send_spoolss_notify2_msg: replacing message 0x%02x/0x%02x for printer %s \ -in notify_queue\n", msg->type, msg->field, msg->printer)); - - tmp_ptr->msg = msg; - return; - } - } - - /* Store the message on the pending queue. */ - - pnqueue = talloc(send_ctx, sizeof(*pnqueue)); - if (!pnqueue) { - DEBUG(0,("send_spoolss_notify2_msg: Out of memory.\n")); - return; - } - - /* allocate a new msg structure and copy the fields */ - - if ( !(pnqueue->msg = (SPOOLSS_NOTIFY_MSG*)talloc(send_ctx, sizeof(SPOOLSS_NOTIFY_MSG))) ) { - DEBUG(0,("send_spoolss_notify2_msg: talloc() of size [%d] failed!\n", - sizeof(SPOOLSS_NOTIFY_MSG))); - return; - } - copy_notify2_msg(pnqueue->msg, msg); - pnqueue->buf = NULL; - pnqueue->buflen = 0; - - DEBUG(5, ("send_spoolss_notify2_msg: appending message 0x%02x/0x%02x for printer %s \ -to notify_queue_head\n", msg->type, msg->field, msg->printer)); - - /* - * Note we add to the end of the list to ensure - * the messages are sent in the order they were received. JRA. - */ - - DLIST_ADD_END(notify_queue_head, pnqueue, struct notify_queue *); -} - -static void send_notify_field_values(const char *printer_name, uint32 type, - uint32 field, uint32 id, uint32 value1, - uint32 value2, uint32 flags) -{ - struct spoolss_notify_msg *msg; - - if (lp_disable_spoolss()) - return; - - if (!create_send_ctx()) - return; - - msg = (struct spoolss_notify_msg *)talloc(send_ctx, sizeof(struct spoolss_notify_msg)); - if (!msg) - return; - - ZERO_STRUCTP(msg); - - fstrcpy(msg->printer, printer_name); - msg->type = type; - msg->field = field; - msg->id = id; - msg->notify.value[0] = value1; - msg->notify.value[1] = value2; - msg->flags = flags; - - send_spoolss_notify2_msg(msg); -} - -static void send_notify_field_buffer(const char *printer_name, uint32 type, - uint32 field, uint32 id, uint32 len, - char *buffer) -{ - struct spoolss_notify_msg *msg; - - if (lp_disable_spoolss()) - return; - - if (!create_send_ctx()) - return; - - msg = (struct spoolss_notify_msg *)talloc(send_ctx, sizeof(struct spoolss_notify_msg)); - if (!msg) - return; - - ZERO_STRUCTP(msg); - - fstrcpy(msg->printer, printer_name); - msg->type = type; - msg->field = field; - msg->id = id; - msg->len = len; - msg->notify.data = buffer; - - send_spoolss_notify2_msg(msg); -} - -/* Send a message that the printer status has changed */ - -void notify_printer_status_byname(const char *printer_name, uint32 status) -{ - /* Printer status stored in value1 */ - - send_notify_field_values(printer_name, PRINTER_NOTIFY_TYPE, - PRINTER_NOTIFY_STATUS, 0, - status, 0, 0); -} - -void notify_printer_status(int snum, uint32 status) -{ - const char *printer_name = SERVICE(snum); - - if (printer_name) - notify_printer_status_byname(printer_name, status); -} - -void notify_job_status_byname(const char *printer_name, uint32 jobid, uint32 status, - uint32 flags) -{ - /* Job id stored in id field, status in value1 */ - - send_notify_field_values(printer_name, JOB_NOTIFY_TYPE, - JOB_NOTIFY_STATUS, jobid, - status, 0, flags); -} - -void notify_job_status(int snum, uint32 jobid, uint32 status) -{ - const char *printer_name = SERVICE(snum); - - notify_job_status_byname(printer_name, jobid, status, 0); -} - -void notify_job_total_bytes(int snum, uint32 jobid, uint32 size) -{ - const char *printer_name = SERVICE(snum); - - /* Job id stored in id field, status in value1 */ - - send_notify_field_values(printer_name, JOB_NOTIFY_TYPE, - JOB_NOTIFY_TOTAL_BYTES, jobid, - size, 0, 0); -} - -void notify_job_total_pages(int snum, uint32 jobid, uint32 pages) -{ - const char *printer_name = SERVICE(snum); - - /* Job id stored in id field, status in value1 */ - - send_notify_field_values(printer_name, JOB_NOTIFY_TYPE, - JOB_NOTIFY_TOTAL_PAGES, jobid, - pages, 0, 0); -} - -void notify_job_username(int snum, uint32 jobid, char *name) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, - jobid, strlen(name) + 1, name); -} - -void notify_job_name(int snum, uint32 jobid, char *name) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, - jobid, strlen(name) + 1, name); -} - -void notify_job_submitted(int snum, uint32 jobid, time_t submitted) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, - jobid, sizeof(submitted), (char *)&submitted); -} - -void notify_printer_driver(int snum, char *driver_name) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, - snum, strlen(driver_name) + 1, driver_name); -} - -void notify_printer_comment(int snum, char *comment) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, - snum, strlen(comment) + 1, comment); -} - -void notify_printer_sharename(int snum, char *share_name) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, - snum, strlen(share_name) + 1, share_name); -} - -void notify_printer_port(int snum, char *port_name) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, - snum, strlen(port_name) + 1, port_name); -} - -void notify_printer_location(int snum, char *location) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, - snum, strlen(location) + 1, location); -} - -void notify_printer_byname( char *printername, uint32 change, char *value ) -{ - int snum = print_queue_snum(printername); - int type = PRINTER_NOTIFY_TYPE; - - if ( snum == -1 ) - return; - - send_notify_field_buffer( printername, type, change, snum, strlen(value)+1, value ); -} - - -/**************************************************************************** - Return a malloced list of pid_t's that are interested in getting update - messages on this print queue. Used in printing/notify to send the messages. -****************************************************************************/ - -BOOL print_notify_pid_list(const char *printername, TALLOC_CTX *mem_ctx, size_t *p_num_pids, pid_t **pp_pid_list) -{ - struct tdb_print_db *pdb = NULL; - TDB_CONTEXT *tdb = NULL; - TDB_DATA data; - BOOL ret = True; - size_t i, num_pids, offset; - pid_t *pid_list; - - *p_num_pids = 0; - *pp_pid_list = NULL; - - pdb = get_print_db_byname(printername); - if (!pdb) - return False; - tdb = pdb->tdb; - - if (tdb_read_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) { - DEBUG(0,("print_notify_pid_list: Failed to lock printer %s database\n", - printername)); - if (pdb) - release_print_db(pdb); - return False; - } - - data = get_printer_notify_pid_list( tdb, printername, True ); - - if (!data.dptr) { - ret = True; - goto done; - } - - num_pids = data.dsize / 8; - - if ((pid_list = (pid_t *)talloc(mem_ctx, sizeof(pid_t) * num_pids)) == NULL) { - ret = False; - goto done; - } - - for( i = 0, offset = 0; offset < data.dsize; offset += 8, i++) - pid_list[i] = (pid_t)IVAL(data.dptr, offset); - - *pp_pid_list = pid_list; - *p_num_pids = num_pids; - - ret = True; - - done: - - tdb_read_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY); - if (pdb) - release_print_db(pdb); - SAFE_FREE(data.dptr); - return ret; -} diff --git a/source4/printing/pcap.c b/source4/printing/pcap.c deleted file mode 100644 index c399c3c6cc..0000000000 --- a/source4/printing/pcap.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - Unix SMB/CIFS implementation. - printcap parsing - Copyright (C) Karl Auer 1993-1998 - - Re-working by Martin Kiff, 1994 - - Re-written again by Andrew Tridgell - - Modified for SVID support by Norm Jacobs, 1997 - - Modified for CUPS support by Michael Sweet, 1999 - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - * Parse printcap file. - * - * This module does exactly one thing - it looks into the printcap file - * and tells callers if a specified string appears as a printer name. - * - * The way this module looks at the printcap file is very simplistic. - * Only the local printcap file is inspected (no searching of NIS - * databases etc). - * - * There are assumed to be one or more printer names per record, held - * as a set of sub-fields separated by vertical bar symbols ('|') in the - * first field of the record. The field separator is assumed to be a colon - * ':' and the record separator a newline. - * - * Lines ending with a backspace '\' are assumed to flag that the following - * line is a continuation line so that a set of lines can be read as one - * printcap entry. - * - * A line stating with a hash '#' is assumed to be a comment and is ignored - * Comments are discarded before the record is strung together from the - * set of continuation lines. - * - * Opening a pipe for "lpc status" and reading that would probably - * be pretty effective. Code to do this already exists in the freely - * distributable PCNFS server code. - * - * Modified to call SVID/XPG4 support if printcap name is set to "lpstat" - * in smb.conf under Solaris. - * - * Modified to call CUPS support if printcap name is set to "cups" - * in smb.conf. - */ - -#include "includes.h" - -#ifdef AIX -/* ****************************************** - Extend for AIX system and qconfig file - from 'boulard@univ-rennes1.fr - ****************************************** */ -static int strlocate(char *xpLine,char *xpS) -{ - int iS,iL,iRet; - char *p; - iS = strlen(xpS); - iL = strlen(xpLine); - - iRet = 0; - p = xpLine; - while (iL >= iS) - { - if (strncmp(p,xpS,iS) == 0) {iRet =1;break;}; - p++; - iL--; - } - /*DEBUG(3,(" strlocate %s in line '%s',ret=%d\n",xpS,xpLine,iRet));*/ - - return(iRet); -} - - -/* ******************************************************************* */ -/* * Scan qconfig and search all virtual printer (device printer) * */ -/* ******************************************************************* */ -static void ScanQconfig_fn(char *psz,void (*fn)(char *, char *)) -{ - int iEtat; - XFILE *pfile; - char *line,*p; - pstring name,comment; - line = NULL; - *name = 0; - *comment = 0; - - if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL) - { - DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz)); - return; - } - - iEtat = 0; - /* scan qconfig file for searching <printername>: */ - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line)) - { - if (*line == '*' || *line == 0) - continue; - switch (iEtat) - { - case 0: /* locate an entry */ - if (*line == '\t' || *line == ' ') continue; - if ((p=strchr_m(line,':'))) - { - *p = '\0'; - p = strtok(line,":"); - if (strcmp(p,"bsh")!=0) - { - pstrcpy(name,p); - iEtat = 1; - continue; - } - } - break; - case 1: /* scanning device stanza */ - if (*line == '*' || *line == 0) continue; - if (*line != '\t' && *line != ' ') - { - /* name is found without stanza device */ - /* probably a good printer ??? */ - fn(name,comment); - iEtat = 0; - continue; - } - - if (strlocate(line,"backend")) - { - /* it's a device, not a virtual printer*/ - iEtat = 0; - } - else if (strlocate(line,"device")) - { - /* it's a good virtual printer */ - fn(name,comment); - iEtat = 0; - continue; - } - break; - } - } - x_fclose(pfile); -} - -/* Scan qconfig file and locate de printername */ - -static BOOL ScanQconfig(char *psz,char *pszPrintername) -{ - int iLg,iEtat; - XFILE *pfile; - char *pName; - char *line; - - pName = NULL; - line = NULL; - if ((pszPrintername!= NULL) && ((iLg = strlen(pszPrintername)) > 0)) - pName = malloc(iLg+10); - if (pName == NULL) - { - DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername)); - return(False); - } - if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL) - { - DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz)); - SAFE_FREE(pName); - return(False); - } - slprintf(pName, iLg + 9, "%s:",pszPrintername); - iLg = strlen(pName); - /*DEBUG(3,( " Looking for entry %s\n",pName));*/ - iEtat = 0; - /* scan qconfig file for searching <printername>: */ - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line)) - { - if (*line == '*' || *line == 0) - continue; - switch (iEtat) - { - case 0: /* scanning entry */ - if (strncmp(line,pName,iLg) == 0) - { - iEtat = 1; - continue; - } - break; - case 1: /* scanning device stanza */ - if (*line == '*' || *line == 0) continue; - if (*line != '\t' && *line != ' ') - { - /* name is found without stanza device */ - /* probably a good printer ??? */ - free (line); - SAFE_FREE(pName); - fclose(pfile); - return(True); - } - - if (strlocate(line,"backend")) - { - /* it's a device, not a virtual printer*/ - iEtat = 0; - } - else if (strlocate(line,"device")) - { - /* it's a good virtual printer */ - free (line); - SAFE_FREE(pName); - fclose(pfile); - return(True); - } - break; - } - } - free (pName); - x_fclose(pfile); - return(False); -} -#endif /* AIX */ - - -/*************************************************************************** -Scan printcap file pszPrintcapname for a printer called pszPrintername. -Return True if found, else False. Returns False on error, too, after logging -the error at level 0. For generality, the printcap name may be passed - if -passed as NULL, the configuration will be queried for the name. -***************************************************************************/ -BOOL pcap_printername_ok(const char *pszPrintername, const char *pszPrintcapname) -{ - char *line=NULL; - const char *psz; - char *p,*q; - XFILE *pfile; - - if (pszPrintername == NULL || pszPrintername[0] == '\0') - { - DEBUG(0,( "Attempt to locate null printername! Internal error?\n")); - return(False); - } - - /* only go looking if no printcap name supplied */ - if ((psz = pszPrintcapname) == NULL || psz[0] == '\0') - if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0')) - { - DEBUG(0,( "No printcap file name configured!\n")); - return(False); - } - -#ifdef HAVE_CUPS - if (strequal(psz, "cups")) - return (cups_printername_ok(pszPrintername)); -#endif /* HAVE_CUPS */ - -#ifdef SYSV - if (strequal(psz, "lpstat")) - return (sysv_printername_ok(pszPrintername)); -#endif - -#ifdef AIX - if (strlocate(psz,"/qconfig")) - return(ScanQconfig(psz,pszPrintername)); -#endif - - if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL) - { - DEBUG(0,( "Unable to open printcap file %s for read!\n", psz)); - return(False); - } - - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line)) - { - if (*line == '#' || *line == 0) - continue; - - /* now we have a real printer line - cut it off at the first : */ - p = strchr_m(line,':'); - if (p) *p = 0; - - /* now just check if the name is in the list */ - /* NOTE: I avoid strtok as the fn calling this one may be using it */ - for (p=line; p; p=q) - { - if ((q = strchr_m(p,'|'))) *q++ = 0; - - if (strequal(p,pszPrintername)) - { - SAFE_FREE(line); - x_fclose(pfile); - return(True); - } - p = q; - } - } - - x_fclose(pfile); - return(False); -} - - -/*************************************************************************** -run a function on each printer name in the printcap file. The function is -passed the primary name and the comment (if possible). Note the fn() takes -strings in DOS codepage. This means the xxx_printer_fn() calls must be fixed -to return DOS codepage. FIXME !! JRA. -***************************************************************************/ -void pcap_printer_fn(void (*fn)(char *, char *)) -{ - pstring name,comment; - char *line; - char *psz; - char *p,*q; - XFILE *pfile; - - /* only go looking if no printcap name supplied */ - if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0')) - { - DEBUG(0,( "No printcap file name configured!\n")); - return; - } - -#ifdef HAVE_CUPS - if (strequal(psz, "cups")) { - cups_printer_fn(fn); - return; - } -#endif /* HAVE_CUPS */ - -#ifdef SYSV - if (strequal(psz, "lpstat")) { - sysv_printer_fn(fn); - return; - } -#endif - -#ifdef AIX - if (strlocate(psz,"/qconfig")) - { - ScanQconfig_fn(psz,fn); - return; - } -#endif - - if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL) - { - DEBUG(0,( "Unable to open printcap file %s for read!\n", psz)); - return; - } - - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line)) - { - if (*line == '#' || *line == 0) - continue; - - /* now we have a real printer line - cut it off at the first : */ - p = strchr_m(line,':'); - if (p) *p = 0; - - /* now find the most likely printer name and comment - this is pure guesswork, but it's better than nothing */ - *name = 0; - *comment = 0; - for (p=line; p; p=q) - { - BOOL has_punctuation; - if ((q = strchr_m(p,'|'))) *q++ = 0; - - has_punctuation = (strchr_m(p,' ') || strchr_m(p,'\t') || strchr_m(p,'(') || strchr_m(p,')')); - - if (strlen(p)>strlen(comment) && has_punctuation) - { - StrnCpy(comment,p,sizeof(comment)-1); - continue; - } - - if (strlen(p) <= MAXPRINTERLEN && strlen(p)>strlen(name) && !has_punctuation) - { - if (!*comment) pstrcpy(comment,name); - pstrcpy(name,p); - continue; - } - - if (!strchr_m(comment,' ') && - strlen(p) > strlen(comment)) - { - StrnCpy(comment,p,sizeof(comment)-1); - continue; - } - } - - comment[60] = 0; - name[MAXPRINTERLEN] = 0; - - if (*name) - fn(name,comment); - } - x_fclose(pfile); -} diff --git a/source4/printing/print_cups.c b/source4/printing/print_cups.c deleted file mode 100644 index 7cf21c966e..0000000000 --- a/source4/printing/print_cups.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* - * Support code for the Common UNIX Printing System ("CUPS") - * - * Copyright 1999-2003 by Michael R Sweet. - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "printing.h" - -#ifdef HAVE_CUPS -#include <cups/cups.h> -#include <cups/language.h> - - -/* - * CUPS printing interface definitions... - */ - -static int cups_job_delete(int snum, struct printjob *pjob); -static int cups_job_pause(int snum, struct printjob *pjob); -static int cups_job_resume(int snum, struct printjob *pjob); -static int cups_job_submit(int snum, struct printjob *pjob); -static int cups_queue_get(int snum, print_queue_struct **q, - print_status_struct *status); -static int cups_queue_pause(int snum); -static int cups_queue_resume(int snum); - - -struct printif cups_printif = - { - cups_queue_get, - cups_queue_pause, - cups_queue_resume, - cups_job_delete, - cups_job_pause, - cups_job_resume, - cups_job_submit, - }; - -/* - * 'cups_passwd_cb()' - The CUPS password callback... - */ - -static const char * /* O - Password or NULL */ -cups_passwd_cb(const char *prompt) /* I - Prompt */ -{ - /* - * Always return NULL to indicate that no password is available... - */ - - return (NULL); -} - - -/* - * 'cups_printer_fn()' - Call a function for every printer known to the - * system. - */ - -void cups_printer_fn(void (*fn)(char *, char *)) -{ - /* I - Function to call */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - ipp_attribute_t *attr; /* Current attribute */ - cups_lang_t *language; /* Default language */ - char *name, /* printer-name attribute */ - *make_model, /* printer-make-and-model attribute */ - *info; /* printer-info attribute */ - static const char *requested[] =/* Requested attributes */ - { - "printer-name", - "printer-make-and-model", - "printer-info" - }; - - - DEBUG(5,("cups_printer_fn(%p)\n", fn)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return; - } - - /* - * Build a CUPS_GET_PRINTERS request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - */ - - request = ippNew(); - - request->request.op.operation_id = CUPS_GET_PRINTERS; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", - (sizeof(requested) / sizeof(requested[0])), - NULL, requested); - - /* - * Do the request and get back a response... - */ - - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(0,("Unable to get printer list - %s\n", - ippErrorString(cupsLastError()))); - httpClose(http); - return; - } - - for (attr = response->attrs; attr != NULL;) - { - /* - * Skip leading attributes until we hit a printer... - */ - - while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) - attr = attr->next; - - if (attr == NULL) - break; - - /* - * Pull the needed attributes from this printer... - */ - - name = NULL; - make_model = NULL; - info = NULL; - - while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) - { - if (strcmp(attr->name, "printer-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - name = attr->values[0].string.text; - - if (strcmp(attr->name, "printer-make-and-model") == 0 && - attr->value_tag == IPP_TAG_TEXT) - make_model = attr->values[0].string.text; - - if (strcmp(attr->name, "printer-info") == 0 && - attr->value_tag == IPP_TAG_TEXT) - info = attr->values[0].string.text; - - attr = attr->next; - } - - /* - * See if we have everything needed... - */ - - if (name == NULL) - break; - - if (info == NULL || !info[0]) - (*fn)(name, make_model); - else - (*fn)(name, info); - - - } - - ippDelete(response); - - - /* - * Build a CUPS_GET_CLASSES request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - */ - - request = ippNew(); - - request->request.op.operation_id = CUPS_GET_CLASSES; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", - (sizeof(requested) / sizeof(requested[0])), - NULL, requested); - - /* - * Do the request and get back a response... - */ - - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(0,("Unable to get printer list - %s\n", - ippErrorString(cupsLastError()))); - httpClose(http); - return; - } - - for (attr = response->attrs; attr != NULL;) - { - /* - * Skip leading attributes until we hit a printer... - */ - - while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) - attr = attr->next; - - if (attr == NULL) - break; - - /* - * Pull the needed attributes from this printer... - */ - - name = NULL; - make_model = NULL; - info = NULL; - - while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) - { - if (strcmp(attr->name, "printer-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - name = attr->values[0].string.text; - - if (strcmp(attr->name, "printer-make-and-model") == 0 && - attr->value_tag == IPP_TAG_TEXT) - make_model = attr->values[0].string.text; - - if (strcmp(attr->name, "printer-info") == 0 && - attr->value_tag == IPP_TAG_TEXT) - info = attr->values[0].string.text; - - attr = attr->next; - } - - /* - * See if we have everything needed... - */ - - if (name == NULL) - break; - - if (info == NULL || !info[0]) - (*fn)(name, make_model); - else - (*fn)(name, info); - - - } - - ippDelete(response); - - /* - * Close the connection to the server... - */ - - httpClose(http); -} - - -/* - * 'cups_printername_ok()' - Provide the equivalent of pcap_printername_ok() - * for CUPS. - * O - 1 if printer name OK - * I - Name of printer - */ -int cups_printername_ok(const char *name) -{ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_printername_ok(\"%s\")\n", name)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(3,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (0); - } - - /* - * Build an IPP_GET_PRINTER_ATTRS request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - * printer-uri - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", NULL, "printer-uri"); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", name); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, uri); - - /* - * Do the request and get back a response... - */ - - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(3,("Unable to get printer status for %s - %s\n", name, - ippErrorString(cupsLastError()))); - httpClose(http); - return (0); - } - - httpClose(http); - - if (response->request.status.status_code >= IPP_OK_CONFLICT) - { - DEBUG(3,("Unable to get printer status for %s - %s\n", name, - ippErrorString(response->request.status.status_code))); - ippDelete(response); - return (0); - } - else - { - ippDelete(response); - return (1); - } -} - - -/* - * 'cups_job_delete()' - Delete a job. - */ - -static int -cups_job_delete(int snum, struct printjob *pjob) -{ - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_CANCEL_JOB request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * job-uri - * requesting-user-name - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_CANCEL_JOB; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); - - /* - * Do the request and get back a response... - */ - - ret = 1; - - if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - - httpClose(http); - - return (ret); -} - - -/* - * 'cups_job_pause()' - Pause a job. - */ - -static int -cups_job_pause(int snum, struct printjob *pjob) -{ - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_HOLD_JOB request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * job-uri - * requesting-user-name - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_HOLD_JOB; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); - - /* - * Do the request and get back a response... - */ - - ret = 1; - - if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - - httpClose(http); - - return (ret); -} - - -/* - * 'cups_job_resume()' - Resume a paused job. - */ - -static int -cups_job_resume(int snum, struct printjob *pjob) -{ - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_RELEASE_JOB request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * job-uri - * requesting-user-name - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_RELEASE_JOB; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); - - /* - * Do the request and get back a response... - */ - - ret = 1; - - if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - - httpClose(http); - - return (ret); -} - - -/* - * 'cups_job_submit()' - Submit a job for printing. - */ - -static int -cups_job_submit(int snum, struct printjob *pjob) -{ - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_PRINT_JOB request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * printer-uri - * requesting-user-name - * [document-data] - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_PRINT_JOB; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "job-originating-host-name", NULL, - get_remote_machine_name()); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, - pjob->jobname); - - /* - * Do the request and get back a response... - */ - - slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum)); - - ret = 1; - if ((response = cupsDoFileRequest(http, request, uri, - pjob->filename)) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - - httpClose(http); - - if ( ret == 0 ) - unlink(pjob->filename); - /* else print_job_end will do it for us */ - - return (ret); -} - - -/* - * 'cups_queue_get()' - Get all the jobs in the print queue. - */ - -static int -cups_queue_get(int snum, print_queue_struct **q, print_status_struct *status) -{ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - ipp_attribute_t *attr; /* Current attribute */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - int qcount, /* Number of active queue entries */ - qalloc; /* Number of queue entries allocated */ - print_queue_struct *queue, /* Queue entries */ - *temp; /* Temporary pointer for queue */ - const char *user_name, /* job-originating-user-name attribute */ - *job_name; /* job-name attribute */ - int job_id; /* job-id attribute */ - int job_k_octets; /* job-k-octets attribute */ - time_t job_time; /* time-at-creation attribute */ - ipp_jstate_t job_status; /* job-status attribute */ - int job_priority; /* job-priority attribute */ - static const char *jattrs[] = /* Requested job attributes */ - { - "job-id", - "job-k-octets", - "job-name", - "job-originating-user-name", - "job-priority", - "job-state", - "time-at-creation", - }; - static const char *pattrs[] = /* Requested printer attributes */ - { - "printer-state", - "printer-state-message" - }; - - - DEBUG(5,("cups_queue_get(%d, %p, %p)\n", snum, q, status)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (0); - } - - /* - * Generate the printer URI... - */ - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); - - /* - * Build an IPP_GET_JOBS request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - * printer-uri - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_GET_JOBS; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", - (sizeof(jattrs) / sizeof(jattrs[0])), - NULL, jattrs); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, uri); - - /* - * Do the request and get back a response... - */ - - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(0,("Unable to get jobs for %s - %s\n", uri, - ippErrorString(cupsLastError()))); - httpClose(http); - return (0); - } - - if (response->request.status.status_code >= IPP_OK_CONFLICT) - { - DEBUG(0,("Unable to get jobs for %s - %s\n", uri, - ippErrorString(response->request.status.status_code))); - ippDelete(response); - httpClose(http); - - return (0); - } - - /* - * Process the jobs... - */ - - qcount = 0; - qalloc = 0; - queue = NULL; - - for (attr = response->attrs; attr != NULL; attr = attr->next) - { - /* - * Skip leading attributes until we hit a job... - */ - - while (attr != NULL && attr->group_tag != IPP_TAG_JOB) - attr = attr->next; - - if (attr == NULL) - break; - - /* - * Allocate memory as needed... - */ - if (qcount >= qalloc) - { - qalloc += 16; - - temp = Realloc(queue, sizeof(print_queue_struct) * qalloc); - - if (temp == NULL) - { - DEBUG(0,("cups_queue_get: Not enough memory!")); - ippDelete(response); - httpClose(http); - - SAFE_FREE(queue); - return (0); - } - - queue = temp; - } - - temp = queue + qcount; - memset(temp, 0, sizeof(print_queue_struct)); - - /* - * Pull the needed attributes from this job... - */ - - job_id = 0; - job_priority = 50; - job_status = IPP_JOB_PENDING; - job_time = 0; - job_k_octets = 0; - user_name = NULL; - job_name = NULL; - - while (attr != NULL && attr->group_tag == IPP_TAG_JOB) - { - if (attr->name == NULL) - { - attr = attr->next; - break; - } - - if (strcmp(attr->name, "job-id") == 0 && - attr->value_tag == IPP_TAG_INTEGER) - job_id = attr->values[0].integer; - - if (strcmp(attr->name, "job-k-octets") == 0 && - attr->value_tag == IPP_TAG_INTEGER) - job_k_octets = attr->values[0].integer; - - if (strcmp(attr->name, "job-priority") == 0 && - attr->value_tag == IPP_TAG_INTEGER) - job_priority = attr->values[0].integer; - - if (strcmp(attr->name, "job-state") == 0 && - attr->value_tag == IPP_TAG_ENUM) - job_status = (ipp_jstate_t)(attr->values[0].integer); - - if (strcmp(attr->name, "time-at-creation") == 0 && - attr->value_tag == IPP_TAG_INTEGER) - job_time = attr->values[0].integer; - - if (strcmp(attr->name, "job-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - job_name = attr->values[0].string.text; - - if (strcmp(attr->name, "job-originating-user-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - user_name = attr->values[0].string.text; - - attr = attr->next; - } - - /* - * See if we have everything needed... - */ - - if (user_name == NULL || job_name == NULL || job_id == 0) - { - if (attr == NULL) - break; - else - continue; - } - - temp->job = job_id; - temp->size = job_k_octets * 1024; - temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED : - job_status == IPP_JOB_STOPPED ? LPQ_PAUSED : - job_status == IPP_JOB_HELD ? LPQ_PAUSED : - LPQ_PRINTING; - temp->priority = job_priority; - temp->time = job_time; - strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1); - strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1); - - qcount ++; - - if (attr == NULL) - break; - } - - ippDelete(response); - - /* - * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the - * following attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - * printer-uri - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", - (sizeof(pattrs) / sizeof(pattrs[0])), - NULL, pattrs); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, uri); - - /* - * Do the request and get back a response... - */ - - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - httpClose(http); - *q = queue; - return (qcount); - } - - if (response->request.status.status_code >= IPP_OK_CONFLICT) - { - DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum), - ippErrorString(response->request.status.status_code))); - ippDelete(response); - httpClose(http); - *q = queue; - return (qcount); - } - - /* - * Get the current printer status and convert it to the SAMBA values. - */ - - if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) - { - if (attr->values[0].integer == IPP_PRINTER_STOPPED) - status->status = LPSTAT_STOPPED; - else - status->status = LPSTAT_OK; - } - - if ((attr = ippFindAttribute(response, "printer-state-message", - IPP_TAG_TEXT)) != NULL) - fstrcpy(status->message, attr->values[0].string.text); - - ippDelete(response); - - /* - * Return the job queue... - */ - - httpClose(http); - - *q = queue; - return (qcount); -} - - -/* - * 'cups_queue_pause()' - Pause a print queue. - */ - -static int -cups_queue_pause(int snum) -{ - extern userdom_struct current_user_info; - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_queue_pause(%d)\n", snum)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_PAUSE_PRINTER request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * printer-uri - * requesting-user-name - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_PAUSE_PRINTER; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, current_user_info.unix_name); - - /* - * Do the request and get back a response... - */ - - ret = 1; - - if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - - httpClose(http); - - return (ret); -} - - -/* - * 'cups_queue_resume()' - Restart a print queue. - */ - -static int -cups_queue_resume(int snum) -{ - extern userdom_struct current_user_info; - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_queue_resume(%d)\n", snum)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_RESUME_PRINTER request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * printer-uri - * requesting-user-name - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_RESUME_PRINTER; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, current_user_info.unix_name); - - /* - * Do the request and get back a response... - */ - - ret = 1; - - if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - - httpClose(http); - - return (ret); -} - - -#else - /* this keeps fussy compilers happy */ - void print_cups_dummy(void) {} -#endif /* HAVE_CUPS */ diff --git a/source4/printing/print_generic.c b/source4/printing/print_generic.c deleted file mode 100644 index aae2844ded..0000000000 --- a/source4/printing/print_generic.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - Unix SMB/CIFS implementation. - printing command routines - Copyright (C) Andrew Tridgell 1992-2000 - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "printing.h" - - -/* - * Generic printing interface definitions... - */ - -static int generic_job_delete(int snum, struct printjob *pjob); -static int generic_job_pause(int snum, struct printjob *pjob); -static int generic_job_resume(int snum, struct printjob *pjob); -static int generic_job_submit(int snum, struct printjob *pjob); -static int generic_queue_get(int snum, print_queue_struct **q, - print_status_struct *status); -static int generic_queue_pause(int snum); -static int generic_queue_resume(int snum); - - -struct printif generic_printif = - { - generic_queue_get, - generic_queue_pause, - generic_queue_resume, - generic_job_delete, - generic_job_pause, - generic_job_resume, - generic_job_submit, - }; - -/**************************************************************************** -run a given print command -a null terminated list of value/substitute pairs is provided -for local substitution strings -****************************************************************************/ -static int print_run_command(int snum,char *command, int *outfd, ...) -{ - - pstring syscmd; - char *arg; - int ret; - va_list ap; - va_start(ap, outfd); - - if (!command || !*command) return -1; - - if (!VALID_SNUM(snum)) { - DEBUG(0,("Invalid snum %d for command %s\n", snum, command)); - return -1; - } - - pstrcpy(syscmd, command); - - while ((arg = va_arg(ap, char *))) { - char *value = va_arg(ap,char *); - pstring_sub(syscmd, arg, value); - } - va_end(ap); - - pstring_sub(syscmd, "%p", PRINTERNAME(snum)); - standard_sub_snum(snum,syscmd,sizeof(syscmd)); - - ret = smbrun(syscmd,outfd); - - DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret)); - - return ret; -} - - -/**************************************************************************** -delete a print job -****************************************************************************/ -static int generic_job_delete(int snum, struct printjob *pjob) -{ - fstring jobstr; - - /* need to delete the spooled entry */ - slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); - return print_run_command( - snum, - lp_lprmcommand(snum), NULL, - "%j", jobstr, - "%T", timestring(pjob->starttime), - NULL); -} - -/**************************************************************************** -pause a job -****************************************************************************/ -static int generic_job_pause(int snum, struct printjob *pjob) -{ - fstring jobstr; - - /* need to pause the spooled entry */ - slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); - return print_run_command(snum, - lp_lppausecommand(snum), NULL, - "%j", jobstr, - NULL); -} - -/**************************************************************************** -resume a job -****************************************************************************/ -static int generic_job_resume(int snum, struct printjob *pjob) -{ - fstring jobstr; - - /* need to pause the spooled entry */ - slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); - return print_run_command(snum, - lp_lpresumecommand(snum), NULL, - "%j", jobstr, - NULL); -} - -/**************************************************************************** - Submit a file for printing - called from print_job_end() -****************************************************************************/ - -static int generic_job_submit(int snum, struct printjob *pjob) -{ - int ret; - pstring current_directory; - pstring print_directory; - char *wd, *p; - pstring jobname; - fstring job_page_count, job_size; - - /* we print from the directory path to give the best chance of - parsing the lpq output */ - wd = sys_getwd(current_directory); - if (!wd) - return 0; - - pstrcpy(print_directory, pjob->filename); - p = strrchr_m(print_directory,'/'); - if (!p) - return 0; - *p++ = 0; - - if (chdir(print_directory) != 0) - return 0; - - pstrcpy(jobname, pjob->jobname); - pstring_sub(jobname, "'", "_"); - slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count); - slprintf(job_size, sizeof(job_size)-1, "%d", pjob->size); - - /* send it to the system spooler */ - ret = print_run_command(snum, - lp_printcommand(snum), NULL, - "%s", p, - "%J", jobname, - "%f", p, - "%z", job_size, - "%c", job_page_count, - NULL); - - chdir(wd); - - return ret; -} - - -/**************************************************************************** -get the current list of queued jobs -****************************************************************************/ -static int generic_queue_get(int snum, print_queue_struct **q, print_status_struct *status) -{ - char **qlines; - int fd; - int numlines, i, qcount; - print_queue_struct *queue = NULL; - fstring printer_name; - - fstrcpy(printer_name, lp_servicename(snum)); - - print_run_command(snum, lp_lpqcommand(snum), &fd, NULL); - - if (fd == -1) { - DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n", - printer_name )); - return 0; - } - - numlines = 0; - qlines = fd_lines_load(fd, &numlines); - close(fd); - - /* turn the lpq output into a series of job structures */ - qcount = 0; - ZERO_STRUCTP(status); - if (numlines) - queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1)); - - if (queue) { - for (i=0; i<numlines; i++) { - /* parse the line */ - if (parse_lpq_entry(snum,qlines[i], - &queue[qcount],status,qcount==0)) { - qcount++; - } - } - } - file_lines_free(qlines); - - *q = queue; - return qcount; -} - -/**************************************************************************** - pause a queue -****************************************************************************/ -static int generic_queue_pause(int snum) -{ - return print_run_command(snum, lp_queuepausecommand(snum), NULL, NULL); -} - -/**************************************************************************** - resume a queue -****************************************************************************/ -static int generic_queue_resume(int snum) -{ - return print_run_command(snum, lp_queueresumecommand(snum), NULL, NULL); -} diff --git a/source4/printing/print_svid.c b/source4/printing/print_svid.c deleted file mode 100644 index 07b157bcd9..0000000000 --- a/source4/printing/print_svid.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 1997-1998 by Norm Jacobs, Colorado Springs, Colorado, USA - * Copyright (C) 1997-1998 by Sun Microsystem, Inc. - * All Rights Reserved - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * This module implements support for gathering and comparing available - * printer information on a SVID or XPG4 compliant system. It does this - * through the use of the SVID/XPG4 command "lpstat(1)". - * - * The expectations is that execution of the command "lpstat -v" will - * generate responses in the form of: - * - * device for serial: /dev/term/b - * system for fax: server - * system for color: server (as printer chroma) - */ - - -#include "includes.h" - -#ifdef SYSV - -typedef struct printer { - char *name; - struct printer *next; -} printer_t; -static printer_t *printers = NULL; - -static void populate_printers(void) -{ - char **lines; - int i; - - lines = file_lines_pload("/usr/bin/lpstat -v", NULL); - if (!lines) return; - - for (i=0;lines[i];i++) { - printer_t *ptmp; - char *name, *tmp; - char *buf = lines[i]; - - /* eat "system/device for " */ - if (((tmp = strchr_m(buf, ' ')) == NULL) || - ((tmp = strchr_m(++tmp, ' ')) == NULL)) - continue; - - /* - * In case we're only at the "for ". - */ - - if(!strncmp("for ",++tmp,4)) { - tmp=strchr_m(tmp, ' '); - tmp++; - } - - /* Eat whitespace. */ - - while(*tmp == ' ') - ++tmp; - - /* - * On HPUX there is an extra line that can be ignored. - * d.thibadeau 2001/08/09 - */ - if(!strncmp("remote to",tmp,9)) - continue; - - name = tmp; - - /* truncate the ": ..." */ - if ((tmp = strchr_m(name, ':')) != NULL) - *tmp = '\0'; - - /* add it to the cache */ - if ((ptmp = malloc(sizeof (*ptmp))) != NULL) { - ZERO_STRUCTP(ptmp); - if((ptmp->name = strdup(name)) == NULL) - DEBUG(0,("populate_printers: malloc fail in strdup !\n")); - ptmp->next = printers; - printers = ptmp; - } else { - DEBUG(0,("populate_printers: malloc fail for ptmp\n")); - } - } - - file_lines_free(lines); -} - - -/* - * provide the equivalent of pcap_printer_fn() for SVID/XPG4 conforming - * systems. It was unclear why pcap_printer_fn() was tossing names longer - * than 8 characters. I suspect that its a protocol limit, but amazingly - * names longer than 8 characters appear to work with my test - * clients (Win95/NT). - */ -void sysv_printer_fn(void (*fn)(char *, char *)) -{ - printer_t *tmp; - - if (printers == NULL) - populate_printers(); - for (tmp = printers; tmp != NULL; tmp = tmp->next) - (fn)(tmp->name, ""); -} - - -/* - * provide the equivalent of pcap_printername_ok() for SVID/XPG4 conforming - * systems. - */ -int sysv_printername_ok(const char *name) -{ - printer_t *tmp; - - if (printers == NULL) - populate_printers(); - for (tmp = printers; tmp != NULL; tmp = tmp->next) - if (strcmp(tmp->name, name) == 0) - return (True); - return (False); -} - -#else -/* this keeps fussy compilers happy */ - void print_svid_dummy(void); - void print_svid_dummy(void) {} -#endif diff --git a/source4/printing/printfsp.c b/source4/printing/printfsp.c deleted file mode 100644 index 5d230f8be4..0000000000 --- a/source4/printing/printfsp.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - Unix SMB/CIFS implementation. - printing backend routines for smbd - using files_struct rather - than only snum - Copyright (C) Andrew Tridgell 1992-2000 - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/*************************************************************************** -open a print file and setup a fsp for it. This is a wrapper around -print_job_start(). -***************************************************************************/ - -files_struct *print_fsp_open(struct tcon_context *conn, char *fname) -{ - int jobid; - SMB_STRUCT_STAT sbuf; - extern struct current_user current_user; - files_struct *fsp = file_new(conn); - fstring name; - - if(!fsp) - return NULL; - - fstrcpy( name, "Remote Downlevel Document"); - if (fname) { - char *p = strrchr(fname, '/'); - fstrcat(name, " "); - if (!p) - p = fname; - fstrcat(name, p); - } - - jobid = print_job_start(¤t_user, SNUM(conn), name, NULL); - if (jobid == -1) { - file_free(fsp); - return NULL; - } - - /* Convert to RAP id. */ - fsp->rap_print_jobid = pjobid_to_rap(SNUM(conn), jobid); - if (fsp->rap_print_jobid == 0) { - /* We need to delete the entry in the tdb. */ - pjob_delete(SNUM(conn), jobid); - file_free(fsp); - return NULL; - } - - /* setup a full fsp */ - fsp->fd = print_job_fd(SNUM(conn),jobid); - GetTimeOfDay(&fsp->open_time); - fsp->vuid = current_user.vuid; - fsp->size = 0; - fsp->pos = -1; - fsp->can_lock = True; - fsp->can_read = False; - fsp->can_write = True; - fsp->share_mode = 0; - fsp->print_file = True; - fsp->modified = False; - fsp->oplock_type = NO_OPLOCK; - fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->is_directory = False; - fsp->directory_delete_on_close = False; - string_set(&fsp->fsp_name,print_job_fname(SNUM(conn),jobid)); - fsp->wbmpx_ptr = NULL; - fsp->wcp = NULL; - conn->vfs_ops.fstat(fsp,fsp->fd, &sbuf); - fsp->mode = sbuf.st_mode; - fsp->inode = sbuf.st_ino; - fsp->dev = sbuf.st_dev; - - conn->num_files_open++; - - return fsp; -} - -/**************************************************************************** -print a file - called on closing the file -****************************************************************************/ -void print_fsp_end(files_struct *fsp, BOOL normal_close) -{ - uint32 jobid; - int snum; - - if (fsp->share_mode == FILE_DELETE_ON_CLOSE) { - /* - * Truncate the job. print_job_end will take - * care of deleting it for us. JRA. - */ - sys_ftruncate(fsp->fd, 0); - } - - if (fsp->fsp_name) { - string_free(&fsp->fsp_name); - } - - if (!rap_to_pjobid(fsp->rap_print_jobid, &snum, &jobid)) { - DEBUG(3,("print_fsp_end: Unable to convert RAP jobid %u to print jobid.\n", - (unsigned int)fsp->rap_print_jobid )); - return; - } - - print_job_end(SNUM(fsp->conn),jobid, normal_close); -} diff --git a/source4/printing/printing.c b/source4/printing/printing.c deleted file mode 100644 index e4d9e5f785..0000000000 --- a/source4/printing/printing.c +++ /dev/null @@ -1,2128 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 3.0 - printing backend routines - Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 2002 - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "printing.h" - -/* Current printer interface */ -static struct printif *current_printif = &generic_printif; - -/* - the printing backend revolves around a tdb database that stores the - SMB view of the print queue - - The key for this database is a jobid - a internally generated number that - uniquely identifies a print job - - reading the print queue involves two steps: - - possibly running lpq and updating the internal database from that - - reading entries from the database - - jobids are assigned when a job starts spooling. -*/ - -/*************************************************************************** - Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32 - bit RPC jobids.... JRA. -***************************************************************************/ - -static TDB_CONTEXT *rap_tdb; -static uint16 next_rap_jobid; - -uint16 pjobid_to_rap(int snum, uint32 jobid) -{ - uint16 rap_jobid; - TDB_DATA data, key; - char jinfo[8]; - - DEBUG(10,("pjobid_to_rap: called.\n")); - - if (!rap_tdb) { - /* Create the in-memory tdb. */ - rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644); - if (!rap_tdb) - return 0; - } - - SIVAL(&jinfo,0,(int32)snum); - SIVAL(&jinfo,4,jobid); - - key.dptr = (char *)&jinfo; - key.dsize = sizeof(jinfo); - data = tdb_fetch(rap_tdb, key); - if (data.dptr && data.dsize == sizeof(uint16)) { - memcpy(&rap_jobid, data.dptr, sizeof(uint16)); - SAFE_FREE(data.dptr); - DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n", - (unsigned int)jobid, - (unsigned int)rap_jobid)); - return rap_jobid; - } - SAFE_FREE(data.dptr); - /* Not found - create and store mapping. */ - rap_jobid = ++next_rap_jobid; - if (rap_jobid == 0) - rap_jobid = ++next_rap_jobid; - data.dptr = (char *)&rap_jobid; - data.dsize = sizeof(rap_jobid); - tdb_store(rap_tdb, key, data, TDB_REPLACE); - tdb_store(rap_tdb, data, key, TDB_REPLACE); - - DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n", - (unsigned int)jobid, - (unsigned int)rap_jobid)); - return rap_jobid; -} - -BOOL rap_to_pjobid(uint16 rap_jobid, int *psnum, uint32 *pjobid) -{ - TDB_DATA data, key; - - DEBUG(10,("rap_to_pjobid called.\n")); - - if (!rap_tdb) - return False; - - key.dptr = (char *)&rap_jobid; - key.dsize = sizeof(rap_jobid); - data = tdb_fetch(rap_tdb, key); - if (data.dptr && data.dsize == 8) { - *psnum = IVAL(data.dptr,0); - *pjobid = IVAL(data.dptr,4); - DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n", - (unsigned int)*pjobid, - (unsigned int)rap_jobid)); - SAFE_FREE(data.dptr); - return True; - } - - DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n", - (unsigned int)rap_jobid)); - SAFE_FREE(data.dptr); - return False; -} - -static void rap_jobid_delete(int snum, uint32 jobid) -{ - TDB_DATA key, data; - uint16 rap_jobid; - char jinfo[8]; - - DEBUG(10,("rap_jobid_delete: called.\n")); - - if (!rap_tdb) - return; - - SIVAL(&jinfo,0,(int32)snum); - SIVAL(&jinfo,4,jobid); - - key.dptr = (char *)&jinfo; - key.dsize = sizeof(jinfo); - data = tdb_fetch(rap_tdb, key); - if (!data.dptr || (data.dsize != sizeof(uint16))) { - DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n", - (unsigned int)jobid )); - SAFE_FREE(data.dptr); - return; - } - - DEBUG(10,("rap_jobid_delete: deleting jobid %u\n", - (unsigned int)jobid )); - - memcpy(&rap_jobid, data.dptr, sizeof(uint16)); - SAFE_FREE(data.dptr); - data.dptr = (char *)&rap_jobid; - data.dsize = sizeof(rap_jobid); - tdb_delete(rap_tdb, key); - tdb_delete(rap_tdb, data); -} - -static pid_t local_pid; - -static int get_queue_status(int, print_status_struct *); - -/**************************************************************************** - Initialise the printing backend. Called once at startup before the fork(). -****************************************************************************/ - -BOOL print_backend_init(void) -{ - const char *sversion = "INFO/version"; - pstring printing_path; - int services = lp_numservices(); - int snum; - - if (local_pid == sys_getpid()) - return True; - - unlink(lock_path("printing.tdb")); - pstrcpy(printing_path,lock_path("printing")); - mkdir(printing_path,0755); - - local_pid = sys_getpid(); - - /* handle a Samba upgrade */ - - for (snum = 0; snum < services; snum++) { - struct tdb_print_db *pdb; - if (!lp_print_ok(snum)) - continue; - - pdb = get_print_db_byname(lp_const_servicename(snum)); - if (!pdb) - continue; - if (tdb_lock_bystring(pdb->tdb, sversion, 0) == -1) { - DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) )); - release_print_db(pdb); - return False; - } - if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) { - tdb_traverse(pdb->tdb, tdb_traverse_delete_fn, NULL); - tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION); - } - tdb_unlock_bystring(pdb->tdb, sversion); - release_print_db(pdb); - } - - close_all_print_db(); /* Don't leave any open. */ - - /* select the appropriate printing interface... */ -#ifdef HAVE_CUPS - if (strcmp(lp_printcapname(), "cups") == 0) - current_printif = &cups_printif; -#endif /* HAVE_CUPS */ - - /* do NT print initialization... */ - return nt_printing_init(); -} - -/**************************************************************************** - Shut down printing backend. Called once at shutdown to close the tdb. -****************************************************************************/ - -void printing_end(void) -{ - close_all_print_db(); /* Don't leave any open. */ -} - -/**************************************************************************** - Useful function to generate a tdb key. -****************************************************************************/ - -static TDB_DATA print_key(uint32 jobid) -{ - static uint32 j; - TDB_DATA ret; - - j = jobid; - ret.dptr = (void *)&j; - ret.dsize = sizeof(j); - return ret; -} - -/*********************************************************************** - unpack a pjob from a tdb buffer -***********************************************************************/ - -int unpack_pjob( char* buf, int buflen, struct printjob *pjob ) -{ - int len = 0; - int used; - - if ( !buf || !pjob ) - return -1; - - len += tdb_unpack(buf+len, buflen-len, "dddddddddffff", - &pjob->pid, - &pjob->sysjob, - &pjob->fd, - &pjob->starttime, - &pjob->status, - &pjob->size, - &pjob->page_count, - &pjob->spooled, - &pjob->smbjob, - pjob->filename, - pjob->jobname, - pjob->user, - pjob->queuename); - - if ( len == -1 ) - return -1; - - if ( (used = unpack_devicemode(&pjob->nt_devmode, buf+len, buflen-len)) == -1 ) - return -1; - - len += used; - - return len; - -} - -/**************************************************************************** - Useful function to find a print job in the database. -****************************************************************************/ - -static struct printjob *print_job_find(int snum, uint32 jobid) -{ - static struct printjob pjob; - TDB_DATA ret; - struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum)); - - - if (!pdb) - return NULL; - - ret = tdb_fetch(pdb->tdb, print_key(jobid)); - release_print_db(pdb); - - if (!ret.dptr) - return NULL; - - if ( pjob.nt_devmode ) - free_nt_devicemode( &pjob.nt_devmode ); - - ZERO_STRUCT( pjob ); - - if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) { - SAFE_FREE(ret.dptr); - return NULL; - } - - SAFE_FREE(ret.dptr); - return &pjob; -} - -/* Convert a unix jobid to a smb jobid */ - -static uint32 sysjob_to_jobid_value; - -static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, - TDB_DATA data, void *state) -{ - struct printjob *pjob; - int *sysjob = (int *)state; - - if (!data.dptr || data.dsize == 0) - return 0; - - pjob = (struct printjob *)data.dptr; - if (key.dsize != sizeof(uint32)) - return 0; - - if (*sysjob == pjob->sysjob) { - uint32 *jobid = (uint32 *)key.dptr; - - sysjob_to_jobid_value = *jobid; - return 1; - } - - return 0; -} - -/**************************************************************************** - This is a *horribly expensive call as we have to iterate through all the - current printer tdb's. Don't do this often ! JRA. -****************************************************************************/ - -uint32 sysjob_to_jobid(int unix_jobid) -{ - int services = lp_numservices(); - int snum; - - sysjob_to_jobid_value = (uint32)-1; - - for (snum = 0; snum < services; snum++) { - struct tdb_print_db *pdb; - if (!lp_print_ok(snum)) - continue; - pdb = get_print_db_byname(lp_const_servicename(snum)); - if (pdb) - tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid); - release_print_db(pdb); - if (sysjob_to_jobid_value != (uint32)-1) - return sysjob_to_jobid_value; - } - return (uint32)-1; -} - -/**************************************************************************** - Send notifications based on what has changed after a pjob_store. -****************************************************************************/ - -static struct { - uint32 lpq_status; - uint32 spoolss_status; -} lpq_to_spoolss_status_map[] = { - { LPQ_QUEUED, JOB_STATUS_QUEUED }, - { LPQ_PAUSED, JOB_STATUS_PAUSED }, - { LPQ_SPOOLING, JOB_STATUS_SPOOLING }, - { LPQ_PRINTING, JOB_STATUS_PRINTING }, - { LPQ_DELETING, JOB_STATUS_DELETING }, - { LPQ_OFFLINE, JOB_STATUS_OFFLINE }, - { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT }, - { LPQ_PRINTED, JOB_STATUS_PRINTED }, - { LPQ_DELETED, JOB_STATUS_DELETED }, - { LPQ_BLOCKED, JOB_STATUS_BLOCKED }, - { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION }, - { -1, 0 } -}; - -/* Convert a lpq status value stored in printing.tdb into the - appropriate win32 API constant. */ - -static uint32 map_to_spoolss_status(uint32 lpq_status) -{ - int i = 0; - - while (lpq_to_spoolss_status_map[i].lpq_status != -1) { - if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status) - return lpq_to_spoolss_status_map[i].spoolss_status; - i++; - } - - return 0; -} - -static void pjob_store_notify(int snum, uint32 jobid, struct printjob *old_data, - struct printjob *new_data) -{ - BOOL new_job = False; - - if (!old_data) - new_job = True; - - /* Notify the job name first */ - - if (new_job || !strequal(old_data->jobname, new_data->jobname)) - notify_job_name(snum, jobid, new_data->jobname); - - /* Job attributes that can't be changed. We only send - notification for these on a new job. */ - - if (new_job) { - notify_job_submitted(snum, jobid, new_data->starttime); - notify_job_username(snum, jobid, new_data->user); - } - - /* Job attributes of a new job or attributes that can be - modified. */ - - if (new_job || old_data->status != new_data->status) - notify_job_status(snum, jobid, map_to_spoolss_status(new_data->status)); - - if (new_job || old_data->size != new_data->size) - notify_job_total_bytes(snum, jobid, new_data->size); - - if (new_job || old_data->page_count != new_data->page_count) - notify_job_total_pages(snum, jobid, new_data->page_count); -} - -/**************************************************************************** - Store a job structure back to the database. -****************************************************************************/ - -static BOOL pjob_store(int snum, uint32 jobid, struct printjob *pjob) -{ - TDB_DATA old_data, new_data; - BOOL ret = False; - struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum)); - char *buf = NULL; - int len, newlen, buflen; - - - if (!pdb) - return False; - - /* Get old data */ - - old_data = tdb_fetch(pdb->tdb, print_key(jobid)); - - /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */ - - newlen = 0; - - do { - len = 0; - buflen = newlen; - len += tdb_pack(buf+len, buflen-len, "dddddddddffff", - pjob->pid, - pjob->sysjob, - pjob->fd, - pjob->starttime, - pjob->status, - pjob->size, - pjob->page_count, - pjob->spooled, - pjob->smbjob, - pjob->filename, - pjob->jobname, - pjob->user, - pjob->queuename); - - len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len); - - if (buflen != len) { - char *tb; - - tb = (char *)Realloc(buf, len); - if (!tb) { - DEBUG(0,("pjob_store: failed to enlarge buffer!\n")); - goto done; - } - else - buf = tb; - newlen = len; - } - } while ( buflen != len ); - - - /* Store new data */ - - new_data.dptr = buf; - new_data.dsize = len; - ret = (tdb_store(pdb->tdb, print_key(jobid), new_data, TDB_REPLACE) == 0); - - release_print_db(pdb); - - /* Send notify updates for what has changed */ - - if ( ret && (old_data.dsize == 0 || old_data.dsize == sizeof(*pjob)) ) - pjob_store_notify( snum, jobid, (struct printjob *)old_data.dptr, pjob ); - -done: - SAFE_FREE( old_data.dptr ); - SAFE_FREE( buf ); - - return ret; -} - -/**************************************************************************** - Remove a job structure from the database. -****************************************************************************/ - -void pjob_delete(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - uint32 job_status = 0; - struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum)); - - if (!pdb) - return; - - if (!pjob) { - DEBUG(5, ("pjob_delete(): we were asked to delete nonexistent job %u\n", - (unsigned int)jobid)); - release_print_db(pdb); - return; - } - - /* Send a notification that a job has been deleted */ - - job_status = map_to_spoolss_status(pjob->status); - - /* We must cycle through JOB_STATUS_DELETING and - JOB_STATUS_DELETED for the port monitor to delete the job - properly. */ - - job_status |= JOB_STATUS_DELETING; - notify_job_status(snum, jobid, job_status); - - job_status |= JOB_STATUS_DELETED; - notify_job_status(snum, jobid, job_status); - - /* Remove from printing.tdb */ - - tdb_delete(pdb->tdb, print_key(jobid)); - release_print_db(pdb); - rap_jobid_delete(snum, jobid); -} - -/**************************************************************************** - Parse a file name from the system spooler to generate a jobid. -****************************************************************************/ - -static uint32 print_parse_jobid(char *fname) -{ - int jobid; - - if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0) - return (uint32)-1; - fname += strlen(PRINT_SPOOL_PREFIX); - - jobid = atoi(fname); - if (jobid <= 0) - return (uint32)-1; - - return (uint32)jobid; -} - -/**************************************************************************** - List a unix job in the print database. -****************************************************************************/ - -static void print_unix_job(int snum, print_queue_struct *q, uint32 jobid) -{ - struct printjob pj, *old_pj; - - if (jobid == (uint32)-1) - jobid = q->job + UNIX_JOB_START; - - /* Preserve the timestamp on an existing unix print job */ - - old_pj = print_job_find(snum, jobid); - - ZERO_STRUCT(pj); - - pj.pid = (pid_t)-1; - pj.sysjob = q->job; - pj.fd = -1; - pj.starttime = old_pj ? old_pj->starttime : q->time; - pj.status = q->status; - pj.size = q->size; - pj.spooled = True; - pj.smbjob = (old_pj != NULL ? True : False); - fstrcpy(pj.filename, old_pj ? old_pj->filename : ""); - if (jobid < UNIX_JOB_START) - fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document"); - else - fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file); - fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user); - fstrcpy(pj.queuename, old_pj ? old_pj->queuename : lp_const_servicename(snum)); - - pjob_store(snum, jobid, &pj); -} - - -struct traverse_struct { - print_queue_struct *queue; - int qcount, snum, maxcount, total_jobs; - time_t lpq_time; -}; - -/**************************************************************************** - Utility fn to delete any jobs that are no longer active. -****************************************************************************/ - -static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state) -{ - struct traverse_struct *ts = (struct traverse_struct *)state; - struct printjob pjob; - uint32 jobid; - int i; - - if ( key.dsize != sizeof(jobid) ) - return 0; - - memcpy(&jobid, key.dptr, sizeof(jobid)); - if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 ) - return 0; - free_nt_devicemode( &pjob.nt_devmode ); - - - if (ts->snum != lp_servicenumber(pjob.queuename)) { - /* this isn't for the queue we are looking at - this cannot happen with the split tdb's. JRA */ - return 0; - } - - if (!pjob.smbjob) { - /* remove a unix job if it isn't in the system queue any more */ - - for (i=0;i<ts->qcount;i++) { - uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START); - if (jobid == u_jobid) - break; - } - if (i == ts->qcount) - pjob_delete(ts->snum, jobid); - else - ts->total_jobs++; - return 0; - } - - /* maybe it hasn't been spooled yet */ - if (!pjob.spooled) { - /* if a job is not spooled and the process doesn't - exist then kill it. This cleans up after smbd - deaths */ - if (!process_exists(pjob.pid)) - pjob_delete(ts->snum, jobid); - else - ts->total_jobs++; - return 0; - } - - for (i=0;i<ts->qcount;i++) { - uint32 curr_jobid = print_parse_jobid(ts->queue[i].fs_file); - if (jobid == curr_jobid) - break; - } - - /* The job isn't in the system queue - we have to assume it has - completed, so delete the database entry. */ - - if (i == ts->qcount) { - - /* A race can occur between the time a job is spooled and - when it appears in the lpq output. This happens when - the job is added to printing.tdb when another smbd - running print_queue_update() has completed a lpq and - is currently traversing the printing tdb and deleting jobs. - Don't delete the job if it was submitted after the lpq_time. */ - - if (pjob.starttime < ts->lpq_time) - pjob_delete(ts->snum, jobid); - else - ts->total_jobs++; - } - else - ts->total_jobs++; - - return 0; -} - -/**************************************************************************** - Check if the print queue has been updated recently enough. -****************************************************************************/ - -static void print_cache_flush(int snum) -{ - fstring key; - const char *printername = lp_const_servicename(snum); - struct tdb_print_db *pdb = get_print_db_byname(printername); - - if (!pdb) - return; - slprintf(key, sizeof(key)-1, "CACHE/%s", printername); - tdb_store_int32(pdb->tdb, key, -1); - release_print_db(pdb); -} - -/**************************************************************************** - Check if someone already thinks they are doing the update. -****************************************************************************/ - -static pid_t get_updating_pid(fstring printer_name) -{ - fstring keystr; - TDB_DATA data, key; - pid_t updating_pid; - struct tdb_print_db *pdb = get_print_db_byname(printer_name); - - if (!pdb) - return (pid_t)-1; - slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", printer_name); - key.dptr = keystr; - key.dsize = strlen(keystr); - - data = tdb_fetch(pdb->tdb, key); - release_print_db(pdb); - if (!data.dptr || data.dsize != sizeof(pid_t)) { - SAFE_FREE(data.dptr); - return (pid_t)-1; - } - - memcpy(&updating_pid, data.dptr, sizeof(pid_t)); - SAFE_FREE(data.dptr); - - if (process_exists(updating_pid)) - return updating_pid; - - return (pid_t)-1; -} - -/**************************************************************************** - Set the fact that we're doing the update, or have finished doing the update - in the tdb. -****************************************************************************/ - -static void set_updating_pid(const fstring printer_name, BOOL delete) -{ - fstring keystr; - TDB_DATA key; - TDB_DATA data; - pid_t updating_pid = sys_getpid(); - struct tdb_print_db *pdb = get_print_db_byname(printer_name); - - if (!pdb) - return; - - slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", printer_name); - key.dptr = keystr; - key.dsize = strlen(keystr); - - if (delete) { - tdb_delete(pdb->tdb, key); - release_print_db(pdb); - return; - } - - data.dptr = (void *)&updating_pid; - data.dsize = sizeof(pid_t); - - tdb_store(pdb->tdb, key, data, TDB_REPLACE); - release_print_db(pdb); -} - -/**************************************************************************** - Update the internal database from the system print queue for a queue. -****************************************************************************/ - -static void print_queue_update(int snum) -{ - int i, qcount; - print_queue_struct *queue = NULL; - print_status_struct status; - print_status_struct old_status; - struct printjob *pjob; - struct traverse_struct tstruct; - fstring keystr, printer_name, cachestr; - TDB_DATA data, key; - struct tdb_print_db *pdb; - - fstrcpy(printer_name, lp_const_servicename(snum)); - pdb = get_print_db_byname(printer_name); - if (!pdb) - return; - - /* - * Check to see if someone else is doing this update. - * This is essentially a mutex on the update. - */ - - if (get_updating_pid(printer_name) != -1) { - release_print_db(pdb); - return; - } - - /* Lock the queue for the database update */ - - slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name); - /* Only wait 10 seconds for this. */ - if (tdb_lock_bystring(pdb->tdb, keystr, 10) == -1) { - DEBUG(0,("print_queue_update: Failed to lock printer %s database\n", printer_name)); - release_print_db(pdb); - return; - } - - /* - * Ensure that no one else got in here. - * If the updating pid is still -1 then we are - * the winner. - */ - - if (get_updating_pid(printer_name) != -1) { - /* - * Someone else is doing the update, exit. - */ - tdb_unlock_bystring(pdb->tdb, keystr); - release_print_db(pdb); - return; - } - - /* - * We're going to do the update ourselves. - */ - - /* Tell others we're doing the update. */ - set_updating_pid(printer_name, False); - - /* - * Allow others to enter and notice we're doing - * the update. - */ - - tdb_unlock_bystring(pdb->tdb, keystr); - - /* - * Update the cache time FIRST ! Stops others even - * attempting to get the lock and doing this - * if the lpq takes a long time. - */ - - slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", printer_name); - tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL)); - - /* get the current queue using the appropriate interface */ - ZERO_STRUCT(status); - - qcount = (*(current_printif->queue_get))(snum, &queue, &status); - - DEBUG(3, ("%d job%s in queue for %s\n", qcount, (qcount != 1) ? - "s" : "", printer_name)); - - /* - any job in the internal database that is marked as spooled - and doesn't exist in the system queue is considered finished - and removed from the database - - any job in the system database but not in the internal database - is added as a unix job - - fill in any system job numbers as we go - */ - for (i=0; i<qcount; i++) { - uint32 jobid = print_parse_jobid(queue[i].fs_file); - - if (jobid == (uint32)-1) { - /* assume its a unix print job */ - print_unix_job(snum, &queue[i], jobid); - continue; - } - - /* we have an active SMB print job - update its status */ - pjob = print_job_find(snum, jobid); - if (!pjob) { - /* err, somethings wrong. Probably smbd was restarted - with jobs in the queue. All we can do is treat them - like unix jobs. Pity. */ - print_unix_job(snum, &queue[i], jobid); - continue; - } - - pjob->sysjob = queue[i].job; - pjob->status = queue[i].status; - - pjob_store(snum, jobid, pjob); - } - - /* now delete any queued entries that don't appear in the - system queue */ - tstruct.queue = queue; - tstruct.qcount = qcount; - tstruct.snum = snum; - tstruct.total_jobs = 0; - tstruct.lpq_time = time(NULL); - - tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct); - - SAFE_FREE(tstruct.queue); - - DEBUG(10,("print_queue_update: printer %s INFO/total_jobs = %d\n", - printer_name, tstruct.total_jobs )); - - tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs); - - get_queue_status(snum, &old_status); - if (old_status.qcount != qcount) - DEBUG(10,("print_queue_update: queue status change %d jobs -> %d jobs for printer %s\n", - old_status.qcount, qcount, printer_name )); - - /* store the new queue status structure */ - slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", printer_name); - key.dptr = keystr; - key.dsize = strlen(keystr); - - status.qcount = qcount; - data.dptr = (void *)&status; - data.dsize = sizeof(status); - tdb_store(pdb->tdb, key, data, TDB_REPLACE); - - /* - * Update the cache time again. We want to do this call - * as little as possible... - */ - - slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", printer_name); - tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL)); - - /* Delete our pid from the db. */ - set_updating_pid(printer_name, True); - release_print_db(pdb); -} - -/**************************************************************************** - Create/Update an entry in the print tdb that will allow us to send notify - updates only to interested smbd's. -****************************************************************************/ - -BOOL print_notify_register_pid(int snum) -{ - TDB_DATA data; - struct tdb_print_db *pdb = NULL; - TDB_CONTEXT *tdb = NULL; - const char *printername; - uint32 mypid = (uint32)sys_getpid(); - BOOL ret = False; - size_t i; - - /* if (snum == -1), then the change notify request was - on a print server handle and we need to register on - all print queus */ - - if (snum == -1) - { - int num_services = lp_numservices(); - int idx; - - for ( idx=0; idx<num_services; idx++ ) { - if (lp_snum_ok(idx) && lp_print_ok(idx) ) - print_notify_register_pid(idx); - } - - return True; - } - else /* register for a specific printer */ - { - printername = lp_const_servicename(snum); - pdb = get_print_db_byname(printername); - if (!pdb) - return False; - tdb = pdb->tdb; - } - - if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) { - DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n", - printername)); - if (pdb) - release_print_db(pdb); - return False; - } - - data = get_printer_notify_pid_list( tdb, printername, True ); - - /* Add ourselves and increase the refcount. */ - - for (i = 0; i < data.dsize; i += 8) { - if (IVAL(data.dptr,i) == mypid) { - uint32 new_refcount = IVAL(data.dptr, i+4) + 1; - SIVAL(data.dptr, i+4, new_refcount); - break; - } - } - - if (i == data.dsize) { - /* We weren't in the list. Realloc. */ - data.dptr = Realloc(data.dptr, data.dsize + 8); - if (!data.dptr) { - DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n", - printername)); - goto done; - } - data.dsize += 8; - SIVAL(data.dptr,data.dsize - 8,mypid); - SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */ - } - - /* Store back the record. */ - if (tdb_store_by_string(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) { - DEBUG(0,("print_notify_register_pid: Failed to update pid \ -list for printer %s\n", printername)); - goto done; - } - - ret = True; - - done: - - tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY); - if (pdb) - release_print_db(pdb); - SAFE_FREE(data.dptr); - return ret; -} - -/**************************************************************************** - Update an entry in the print tdb that will allow us to send notify - updates only to interested smbd's. -****************************************************************************/ - -BOOL print_notify_deregister_pid(int snum) -{ - TDB_DATA data; - struct tdb_print_db *pdb = NULL; - TDB_CONTEXT *tdb = NULL; - const char *printername; - uint32 mypid = (uint32)sys_getpid(); - size_t i; - BOOL ret = False; - - /* if ( snum == -1 ), we are deregister a print server handle - which means to deregister on all print queues */ - - if (snum == -1) - { - int num_services = lp_numservices(); - int idx; - - for ( idx=0; idx<num_services; idx++ ) { - if ( lp_snum_ok(idx) && lp_print_ok(idx) ) - print_notify_deregister_pid(idx); - } - - return True; - } - else /* deregister a specific printer */ - { - printername = lp_const_servicename(snum); - pdb = get_print_db_byname(printername); - if (!pdb) - return False; - tdb = pdb->tdb; - } - - if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) { - DEBUG(0,("print_notify_register_pid: Failed to lock \ -printer %s database\n", printername)); - if (pdb) - release_print_db(pdb); - return False; - } - - data = get_printer_notify_pid_list( tdb, printername, True ); - - /* Reduce refcount. Remove ourselves if zero. */ - - for (i = 0; i < data.dsize; ) { - if (IVAL(data.dptr,i) == mypid) { - uint32 refcount = IVAL(data.dptr, i+4); - - refcount--; - - if (refcount == 0) { - if (data.dsize - i > 8) - memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8); - data.dsize -= 8; - continue; - } - SIVAL(data.dptr, i+4, refcount); - } - - i += 8; - } - - if (data.dsize == 0) - SAFE_FREE(data.dptr); - - /* Store back the record. */ - if (tdb_store_by_string(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) { - DEBUG(0,("print_notify_register_pid: Failed to update pid \ -list for printer %s\n", printername)); - goto done; - } - - ret = True; - - done: - - tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY); - if (pdb) - release_print_db(pdb); - SAFE_FREE(data.dptr); - return ret; -} - -/**************************************************************************** - Check if a jobid is valid. It is valid if it exists in the database. -****************************************************************************/ - -BOOL print_job_exists(int snum, uint32 jobid) -{ - struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum)); - BOOL ret; - - if (!pdb) - return False; - ret = tdb_exists(pdb->tdb, print_key(jobid)); - release_print_db(pdb); - return ret; -} - -/**************************************************************************** - Give the fd used for a jobid. -****************************************************************************/ - -int print_job_fd(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - if (!pjob) - return -1; - /* don't allow another process to get this info - it is meaningless */ - if (pjob->pid != local_pid) - return -1; - return pjob->fd; -} - -/**************************************************************************** - Give the filename used for a jobid. - Only valid for the process doing the spooling and when the job - has not been spooled. -****************************************************************************/ - -char *print_job_fname(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - if (!pjob || pjob->spooled || pjob->pid != local_pid) - return NULL; - return pjob->filename; -} - - -/**************************************************************************** - Give the filename used for a jobid. - Only valid for the process doing the spooling and when the job - has not been spooled. -****************************************************************************/ - -NT_DEVICEMODE *print_job_devmode(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - - if ( !pjob ) - return NULL; - - return pjob->nt_devmode; -} - -/**************************************************************************** - Set the place in the queue for a job. -****************************************************************************/ - -BOOL print_job_set_place(int snum, uint32 jobid, int place) -{ - DEBUG(2,("print_job_set_place not implemented yet\n")); - return False; -} - -/**************************************************************************** - Set the name of a job. Only possible for owner. -****************************************************************************/ - -BOOL print_job_set_name(int snum, uint32 jobid, char *name) -{ - struct printjob *pjob = print_job_find(snum, jobid); - if (!pjob || pjob->pid != local_pid) - return False; - - fstrcpy(pjob->jobname, name); - return pjob_store(snum, jobid, pjob); -} - -/**************************************************************************** - Delete a print job - don't update queue. -****************************************************************************/ - -static BOOL print_job_delete1(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - int result = 0; - - if (!pjob) - return False; - - /* - * If already deleting just return. - */ - - if (pjob->status == LPQ_DELETING) - return True; - - /* Hrm - we need to be able to cope with deleting a job before it - has reached the spooler. */ - - if (pjob->sysjob == -1) { - DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid)); - } - - /* Set the tdb entry to be deleting. */ - - pjob->status = LPQ_DELETING; - pjob_store(snum, jobid, pjob); - - if (pjob->spooled && pjob->sysjob != -1) - result = (*(current_printif->job_delete))(snum, pjob); - - /* Delete the tdb entry if the delete suceeded or the job hasn't - been spooled. */ - - if (result == 0) - pjob_delete(snum, jobid); - - return (result == 0); -} - -/**************************************************************************** - Return true if the current user owns the print job. -****************************************************************************/ - -static BOOL is_owner(struct current_user *user, int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - user_struct *vuser; - - if (!pjob || !user) - return False; - - if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { - return strequal(pjob->user, vuser->user.smb_name); - } else { - return strequal(pjob->user, uidtoname(user->uid)); - } -} - -/**************************************************************************** - Delete a print job. -****************************************************************************/ - -BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode) -{ - BOOL owner, deleted; - char *fname; - - *errcode = WERR_OK; - - owner = is_owner(user, snum, jobid); - - /* Check access against security descriptor or whether the user - owns their job. */ - - if (!owner && - !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { - DEBUG(3, ("delete denied by security descriptor\n")); - *errcode = WERR_ACCESS_DENIED; - - /* BEGIN_ADMIN_LOG */ - sys_adminlog( LOG_ERR, - "Permission denied-- user not allowed to delete, \ -pause, or resume print job. User name: %s. Printer name: %s.", - uidtoname(user->uid), PRINTERNAME(snum) ); - /* END_ADMIN_LOG */ - - return False; - } - - /* - * get the spooled filename of the print job - * if this works, then the file has not been spooled - * to the underlying print system. Just delete the - * spool file & return. - */ - - if ( (fname = print_job_fname( snum, jobid )) != NULL ) - { - /* remove the spool file */ - DEBUG(10,("print_job_delete: Removing spool file [%s]\n", fname )); - if ( unlink( fname ) == -1 ) { - *errcode = map_werror_from_unix(errno); - return False; - } - - return True; - } - - if (!print_job_delete1(snum, jobid)) { - *errcode = WERR_ACCESS_DENIED; - return False; - } - - /* force update the database and say the delete failed if the - job still exists */ - - print_queue_update(snum); - - deleted = !print_job_exists(snum, jobid); - if ( !deleted ) - *errcode = WERR_ACCESS_DENIED; - - return deleted; -} - -/**************************************************************************** - Pause a job. -****************************************************************************/ - -BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *errcode) -{ - struct printjob *pjob = print_job_find(snum, jobid); - int ret = -1; - - if (!pjob || !user) - return False; - - if (!pjob->spooled || pjob->sysjob == -1) - return False; - - if (!is_owner(user, snum, jobid) && - !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { - DEBUG(3, ("pause denied by security descriptor\n")); - - /* BEGIN_ADMIN_LOG */ - sys_adminlog( LOG_ERR, - "Permission denied-- user not allowed to delete, \ -pause, or resume print job. User name: %s. Printer name: %s.", - uidtoname(user->uid), PRINTERNAME(snum) ); - /* END_ADMIN_LOG */ - - *errcode = WERR_ACCESS_DENIED; - return False; - } - - /* need to pause the spooled entry */ - ret = (*(current_printif->job_pause))(snum, pjob); - - if (ret != 0) { - *errcode = WERR_INVALID_PARAM; - return False; - } - - /* force update the database */ - print_cache_flush(snum); - - /* Send a printer notify message */ - - notify_job_status(snum, jobid, JOB_STATUS_PAUSED); - - /* how do we tell if this succeeded? */ - - return True; -} - -/**************************************************************************** - Resume a job. -****************************************************************************/ - -BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR *errcode) -{ - struct printjob *pjob = print_job_find(snum, jobid); - int ret; - - if (!pjob || !user) - return False; - - if (!pjob->spooled || pjob->sysjob == -1) - return False; - - if (!is_owner(user, snum, jobid) && - !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { - DEBUG(3, ("resume denied by security descriptor\n")); - *errcode = WERR_ACCESS_DENIED; - - /* BEGIN_ADMIN_LOG */ - sys_adminlog( LOG_ERR, - "Permission denied-- user not allowed to delete, \ -pause, or resume print job. User name: %s. Printer name: %s.", - uidtoname(user->uid), PRINTERNAME(snum) ); - /* END_ADMIN_LOG */ - return False; - } - - ret = (*(current_printif->job_resume))(snum, pjob); - - if (ret != 0) { - *errcode = WERR_INVALID_PARAM; - return False; - } - - /* force update the database */ - print_cache_flush(snum); - - /* Send a printer notify message */ - - notify_job_status(snum, jobid, JOB_STATUS_QUEUED); - - return True; -} - -/**************************************************************************** - Write to a print file. -****************************************************************************/ - -int print_job_write(int snum, uint32 jobid, const char *buf, int size) -{ - int return_code; - struct printjob *pjob = print_job_find(snum, jobid); - - if (!pjob) - return -1; - /* don't allow another process to get this info - it is meaningless */ - if (pjob->pid != local_pid) - return -1; - - return_code = write(pjob->fd, buf, size); - if (return_code>0) { - pjob->size += size; - pjob_store(snum, jobid, pjob); - } - return return_code; -} - -/**************************************************************************** - Check if the print queue has been updated recently enough. -****************************************************************************/ - -static BOOL print_cache_expired(int snum) -{ - fstring key; - time_t last_qscan_time, time_now = time(NULL); - const char *printername = lp_const_servicename(snum); - struct tdb_print_db *pdb = get_print_db_byname(printername); - - if (!pdb) - return False; - - slprintf(key, sizeof(key), "CACHE/%s", printername); - last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key); - - /* - * Invalidate the queue for 3 reasons. - * (1). last queue scan time == -1. - * (2). Current time - last queue scan time > allowed cache time. - * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default). - * This last test picks up machines for which the clock has been moved - * forward, an lpq scan done and then the clock moved back. Otherwise - * that last lpq scan would stay around for a loooong loooong time... :-). JRA. - */ - - if (last_qscan_time == ((time_t)-1) || (time_now - last_qscan_time) >= lp_lpqcachetime() || - last_qscan_time > (time_now + MAX_CACHE_VALID_TIME)) { - DEBUG(3, ("print cache expired for queue %s \ -(last_qscan_time = %d, time now = %d, qcachetime = %d)\n", printername, - (int)last_qscan_time, (int)time_now, (int)lp_lpqcachetime() )); - release_print_db(pdb); - return True; - } - release_print_db(pdb); - return False; -} - -/**************************************************************************** - Get the queue status - do not update if db is out of date. -****************************************************************************/ - -static int get_queue_status(int snum, print_status_struct *status) -{ - fstring keystr; - TDB_DATA data, key; - const char *printername = lp_const_servicename(snum); - struct tdb_print_db *pdb = get_print_db_byname(printername); - int len; - - if (!pdb) - return 0; - - if (status) { - ZERO_STRUCTP(status); - slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", printername); - key.dptr = keystr; - key.dsize = strlen(keystr); - data = tdb_fetch(pdb->tdb, key); - if (data.dptr) { - if (data.dsize == sizeof(print_status_struct)) - memcpy(status, data.dptr, sizeof(print_status_struct)); - SAFE_FREE(data.dptr); - } - } - len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs"); - release_print_db(pdb); - return (len == -1 ? 0 : len); -} - -/**************************************************************************** - Determine the number of jobs in a queue. -****************************************************************************/ - -int print_queue_length(int snum, print_status_struct *pstatus) -{ - print_status_struct status; - int len; - - /* make sure the database is up to date */ - if (print_cache_expired(snum)) - print_queue_update(snum); - - /* also fetch the queue status */ - memset(&status, 0, sizeof(status)); - len = get_queue_status(snum, &status); - - if (pstatus) - *pstatus = status; - - return len; -} - -/*************************************************************************** - Allocate a jobid. Hold the lock for as short a time as possible. -***************************************************************************/ - -static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char *printername, uint32 *pjobid) -{ - int i; - uint32 jobid; - - *pjobid = (uint32)-1; - - for (i = 0; i < 3; i++) { - /* Lock the database - only wait 20 seconds. */ - if (tdb_lock_bystring(pdb->tdb, "INFO/nextjob", 20) == -1) { - DEBUG(0,("allocate_print_jobid: failed to lock printing database %s\n", printername )); - return False; - } - - if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) { - if (tdb_error(pdb->tdb) != TDB_ERR_NOEXIST) { - DEBUG(0, ("allocate_print_jobid: failed to fetch INFO/nextjob for print queue %s\n", - printername )); - return False; - } - jobid = 0; - } - - jobid = NEXT_JOBID(jobid); - - if (tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid)==-1) { - DEBUG(3, ("allocate_print_jobid: failed to store INFO/nextjob.\n")); - tdb_unlock_bystring(pdb->tdb, "INFO/nextjob"); - return False; - } - - /* We've finished with the INFO/nextjob lock. */ - tdb_unlock_bystring(pdb->tdb, "INFO/nextjob"); - - if (!print_job_exists(snum, jobid)) - break; - } - - if (i > 2) { - DEBUG(0, ("allocate_print_jobid: failed to allocate a print job for queue %s\n", - printername )); - /* Probably full... */ - errno = ENOSPC; - return False; - } - - /* Store a dummy placeholder. */ - { - TDB_DATA dum; - dum.dptr = NULL; - dum.dsize = 0; - if (tdb_store(pdb->tdb, print_key(jobid), dum, TDB_INSERT) == -1) { - DEBUG(3, ("allocate_print_jobid: jobid (%d) failed to store placeholder.\n", - jobid )); - return False; - } - } - - *pjobid = jobid; - return True; -} - -/*************************************************************************** - Start spooling a job - return the jobid. -***************************************************************************/ - -uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DEVICEMODE *nt_devmode ) -{ - uint32 jobid; - char *path; - struct printjob pjob; - user_struct *vuser; - const char *printername = lp_const_servicename(snum); - struct tdb_print_db *pdb = get_print_db_byname(printername); - int njobs; - - errno = 0; - - if (!pdb) - return (uint32)-1; - - if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) { - DEBUG(3, ("print_job_start: job start denied by security descriptor\n")); - release_print_db(pdb); - return (uint32)-1; - } - - if (!print_time_access_check(snum)) { - DEBUG(3, ("print_job_start: job start denied by time check\n")); - release_print_db(pdb); - return (uint32)-1; - } - - path = lp_pathname(snum); - - /* see if we have sufficient disk space */ - if (lp_minprintspace(snum)) { - SMB_BIG_UINT dspace, dsize; - if (sys_fsusage(path, &dspace, &dsize) == 0 && - dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) { - DEBUG(3, ("print_job_start: disk space check failed.\n")); - release_print_db(pdb); - errno = ENOSPC; - return (uint32)-1; - } - } - - /* for autoloaded printers, check that the printcap entry still exists */ - if (lp_autoloaded(snum) && !pcap_printername_ok(lp_const_servicename(snum), NULL)) { - DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_const_servicename(snum) )); - release_print_db(pdb); - errno = ENOENT; - return (uint32)-1; - } - - /* Insure the maximum queue size is not violated */ - if ((njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) { - DEBUG(3, ("print_job_start: Queue %s number of jobs (%d) larger than max printjobs per queue (%d).\n", - printername, njobs, lp_maxprintjobs(snum) )); - release_print_db(pdb); - errno = ENOSPC; - return (uint32)-1; - } - - DEBUG(10,("print_job_start: Queue %s number of jobs (%d), max printjobs = %d\n", - printername, njobs, lp_maxprintjobs(snum) )); - - if (!allocate_print_jobid(pdb, snum, printername, &jobid)) - goto fail; - - /* create the database entry */ - - ZERO_STRUCT(pjob); - - pjob.pid = local_pid; - pjob.sysjob = -1; - pjob.fd = -1; - pjob.starttime = time(NULL); - pjob.status = LPQ_SPOOLING; - pjob.size = 0; - pjob.spooled = False; - pjob.smbjob = True; - pjob.nt_devmode = nt_devmode; - - fstrcpy(pjob.jobname, jobname); - - if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { - fstrcpy(pjob.user, vuser->user.smb_name); - } else { - fstrcpy(pjob.user, uidtoname(user->uid)); - } - - fstrcpy(pjob.queuename, lp_const_servicename(snum)); - - /* we have a job entry - now create the spool file */ - slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX", - path, PRINT_SPOOL_PREFIX, (unsigned int)jobid); - pjob.fd = smb_mkstemp(pjob.filename); - - if (pjob.fd == -1) { - if (errno == EACCES) { - /* Common setup error, force a report. */ - DEBUG(0, ("print_job_start: insufficient permissions \ -to open spool file %s.\n", pjob.filename)); - } else { - /* Normal case, report at level 3 and above. */ - DEBUG(3, ("print_job_start: can't open spool file %s,\n", pjob.filename)); - DEBUGADD(3, ("errno = %d (%s).\n", errno, strerror(errno))); - } - goto fail; - } - - pjob_store(snum, jobid, &pjob); - - /* Ensure we keep a rough count of the number of total jobs... */ - tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1); - - release_print_db(pdb); - - return jobid; - - fail: - if (jobid != -1) - pjob_delete(snum, jobid); - - release_print_db(pdb); - - DEBUG(3, ("print_job_start: returning fail. Error = %s\n", strerror(errno) )); - return (uint32)-1; -} - -/**************************************************************************** - Update the number of pages spooled to jobid -****************************************************************************/ - -void print_job_endpage(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - if (!pjob) - return; - /* don't allow another process to get this info - it is meaningless */ - if (pjob->pid != local_pid) - return; - - pjob->page_count++; - pjob_store(snum, jobid, pjob); -} - -/**************************************************************************** - Print a file - called on closing the file. This spools the job. - If normal close is false then we're tearing down the jobs - treat as an - error. -****************************************************************************/ - -BOOL print_job_end(int snum, uint32 jobid, BOOL normal_close) -{ - struct printjob *pjob = print_job_find(snum, jobid); - int ret; - SMB_STRUCT_STAT sbuf; - - if (!pjob) - return False; - - if (pjob->spooled || pjob->pid != local_pid) - return False; - - if (normal_close && (sys_fstat(pjob->fd, &sbuf) == 0)) { - pjob->size = sbuf.st_size; - close(pjob->fd); - pjob->fd = -1; - } else { - - /* - * Not a normal close or we couldn't stat the job file, - * so something has gone wrong. Cleanup. - */ - close(pjob->fd); - pjob->fd = -1; - DEBUG(3,("print_job_end: failed to stat file for jobid %d\n", jobid )); - goto fail; - } - - /* Technically, this is not quite right. If the printer has a separator - * page turned on, the NT spooler prints the separator page even if the - * print job is 0 bytes. 010215 JRR */ - if (pjob->size == 0 || pjob->status == LPQ_DELETING) { - /* don't bother spooling empty files or something being deleted. */ - DEBUG(5,("print_job_end: canceling spool of %s (%s)\n", - pjob->filename, pjob->size ? "deleted" : "zero length" )); - unlink(pjob->filename); - pjob_delete(snum, jobid); - return True; - } - - ret = (*(current_printif->job_submit))(snum, pjob); - - if (ret) - goto fail; - - /* The print job has been sucessfully handed over to the back-end */ - - pjob->spooled = True; - pjob->status = LPQ_QUEUED; - pjob_store(snum, jobid, pjob); - - /* make sure the database is up to date */ - if (print_cache_expired(snum)) - print_queue_update(snum); - - return True; - -fail: - - /* The print job was not succesfully started. Cleanup */ - /* Still need to add proper error return propagation! 010122:JRR */ - unlink(pjob->filename); - pjob_delete(snum, jobid); - return False; -} - -/**************************************************************************** - Utility fn to enumerate the print queue. -****************************************************************************/ - -static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state) -{ - struct traverse_struct *ts = (struct traverse_struct *)state; - struct printjob pjob; - int i; - uint32 jobid; - - /* sanity checks */ - - if ( key.dsize != sizeof(jobid) ) - return 0; - - memcpy(&jobid, key.dptr, sizeof(jobid)); - - if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 ) - return 0; - free_nt_devicemode( &pjob.nt_devmode ); - - /* maybe it isn't for this queue */ - if (ts->snum != lp_servicenumber(pjob.queuename)) - return 0; - - if (ts->qcount >= ts->maxcount) - return 0; - - i = ts->qcount; - - ts->queue[i].job = jobid; - ts->queue[i].size = pjob.size; - ts->queue[i].page_count = pjob.page_count; - ts->queue[i].status = pjob.status; - ts->queue[i].priority = 1; - ts->queue[i].time = pjob.starttime; - fstrcpy(ts->queue[i].fs_user, pjob.user); - fstrcpy(ts->queue[i].fs_file, pjob.jobname); - - ts->qcount++; - - return 0; -} - -struct traverse_count_struct { - int snum, count; -}; - -/**************************************************************************** - Utility fn to count the number of entries in the print queue. -****************************************************************************/ - -static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state) -{ - struct traverse_count_struct *ts = (struct traverse_count_struct *)state; - struct printjob pjob; - uint32 jobid; - - /* sanity checks */ - - if ( key.dsize != sizeof(jobid) ) - return 0; - - memcpy(&jobid, key.dptr, sizeof(jobid)); - - if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 ) - return 0; - - free_nt_devicemode( &pjob.nt_devmode ); - - /* maybe it isn't for this queue - this cannot happen with the tdb/printer code. JRA */ - if (ts->snum != lp_servicenumber(pjob.queuename)) - return 0; - - ts->count++; - - return 0; -} - -/**************************************************************************** - Sort print jobs by submittal time. -****************************************************************************/ - -static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2) -{ - /* Silly cases */ - - if (!j1 && !j2) - return 0; - if (!j1) - return -1; - if (!j2) - return 1; - - /* Sort on job start time */ - - if (j1->time == j2->time) - return 0; - return (j1->time > j2->time) ? 1 : -1; -} - -/**************************************************************************** - Get a printer queue listing. - set queue = NULL and status = NULL if you just want to update the cache -****************************************************************************/ - -int print_queue_status(int snum, - print_queue_struct **queue, - print_status_struct *status) -{ - struct traverse_struct tstruct; - struct traverse_count_struct tsc; - fstring keystr; - TDB_DATA data, key; - const char *printername; - struct tdb_print_db *pdb; - - /* make sure the database is up to date */ - - if (print_cache_expired(snum)) - print_queue_update(snum); - - /* return if we are done */ - - if ( !queue || !status ) - return 0; - - *queue = NULL; - printername = lp_const_servicename(snum); - pdb = get_print_db_byname(printername); - - if (!pdb) - return 0; - - /* - * Fetch the queue status. We must do this first, as there may - * be no jobs in the queue. - */ - ZERO_STRUCTP(status); - slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", printername); - key.dptr = keystr; - key.dsize = strlen(keystr); - data = tdb_fetch(pdb->tdb, key); - if (data.dptr) { - if (data.dsize == sizeof(*status)) { - memcpy(status, data.dptr, sizeof(*status)); - } - SAFE_FREE(data.dptr); - } - - /* - * Now, fetch the print queue information. We first count the number - * of entries, and then only retrieve the queue if necessary. - */ - tsc.count = 0; - tsc.snum = snum; - - tdb_traverse(pdb->tdb, traverse_count_fn_queue, (void *)&tsc); - - if (tsc.count == 0) { - release_print_db(pdb); - return 0; - } - - /* Allocate the queue size. */ - if ((tstruct.queue = (print_queue_struct *) - malloc(sizeof(print_queue_struct)*tsc.count)) == NULL) { - release_print_db(pdb); - return 0; - } - - /* - * Fill in the queue. - * We need maxcount as the queue size may have changed between - * the two calls to tdb_traverse. - */ - tstruct.qcount = 0; - tstruct.maxcount = tsc.count; - tstruct.snum = snum; - - tdb_traverse(pdb->tdb, traverse_fn_queue, (void *)&tstruct); - release_print_db(pdb); - - /* Sort the queue by submission time otherwise they are displayed - in hash order. */ - - qsort(tstruct.queue, tstruct.qcount, sizeof(print_queue_struct), - QSORT_CAST printjob_comp); - - *queue = tstruct.queue; - return tstruct.qcount; -} - -/**************************************************************************** - Pause a queue. -****************************************************************************/ - -BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode) -{ - int ret; - - if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) { - *errcode = WERR_ACCESS_DENIED; - return False; - } - - ret = (*(current_printif->queue_pause))(snum); - - if (ret != 0) { - *errcode = WERR_INVALID_PARAM; - return False; - } - - /* force update the database */ - print_cache_flush(snum); - - /* Send a printer notify message */ - - notify_printer_status(snum, PRINTER_STATUS_PAUSED); - - return True; -} - -/**************************************************************************** - Resume a queue. -****************************************************************************/ - -BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode) -{ - int ret; - - if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) { - *errcode = WERR_ACCESS_DENIED; - return False; - } - - ret = (*(current_printif->queue_resume))(snum); - - if (ret != 0) { - *errcode = WERR_INVALID_PARAM; - return False; - } - - /* make sure the database is up to date */ - if (print_cache_expired(snum)) - print_queue_update(snum); - - /* Send a printer notify message */ - - notify_printer_status(snum, PRINTER_STATUS_OK); - - return True; -} - -/**************************************************************************** - Purge a queue - implemented by deleting all jobs that we can delete. -****************************************************************************/ - -BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode) -{ - print_queue_struct *queue; - print_status_struct status; - int njobs, i; - BOOL can_job_admin; - - /* Force and update so the count is accurate (i.e. not a cached count) */ - print_queue_update(snum); - - can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER); - njobs = print_queue_status(snum, &queue, &status); - - for (i=0;i<njobs;i++) { - BOOL owner = is_owner(user, snum, queue[i].job); - - if (owner || can_job_admin) { - print_job_delete1(snum, queue[i].job); - } - } - - SAFE_FREE(queue); - - return True; -} diff --git a/source4/printing/printing_db.c b/source4/printing/printing_db.c deleted file mode 100644 index 0aa8dfafa5..0000000000 --- a/source4/printing/printing_db.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 3.0 - printing backend routines - Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 2002 - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "printing.h" - -static struct tdb_print_db *print_db_head; - -/**************************************************************************** - Function to find or create the printer specific job tdb given a printername. - Limits the number of tdb's open to MAX_PRINT_DBS_OPEN. -****************************************************************************/ - -struct tdb_print_db *get_print_db_byname(const char *printername) -{ - struct tdb_print_db *p = NULL, *last_entry = NULL; - int num_open = 0; - pstring printdb_path; - BOOL done_become_root = False; - - for (p = print_db_head, last_entry = print_db_head; p; p = p->next) { - /* Ensure the list terminates... JRA. */ - SMB_ASSERT(p->next != print_db_head); - - if (p->tdb && strequal(p->printer_name, printername)) { - DLIST_PROMOTE(print_db_head, p); - p->ref_count++; - return p; - } - num_open++; - last_entry = p; - } - - /* Not found. */ - if (num_open >= MAX_PRINT_DBS_OPEN) { - /* Try and recycle the last entry. */ - DLIST_PROMOTE(print_db_head, last_entry); - - for (p = print_db_head; p; p = p->next) { - if (p->ref_count) - continue; - if (p->tdb) { - if (tdb_close(print_db_head->tdb)) { - DEBUG(0,("get_print_db: Failed to close tdb for printer %s\n", - print_db_head->printer_name )); - return NULL; - } - } - p->tdb = NULL; - p->ref_count = 0; - memset(p->printer_name, '\0', sizeof(p->printer_name)); - break; - } - if (p) { - DLIST_PROMOTE(print_db_head, p); - p = print_db_head; - } - } - - if (!p) { - /* Create one. */ - p = (struct tdb_print_db *)malloc(sizeof(struct tdb_print_db)); - if (!p) { - DEBUG(0,("get_print_db: malloc fail !\n")); - return NULL; - } - ZERO_STRUCTP(p); - DLIST_ADD(print_db_head, p); - } - - pstrcpy(printdb_path, lock_path("printing/")); - pstrcat(printdb_path, printername); - pstrcat(printdb_path, ".tdb"); - - if (geteuid() != 0) { - become_root(); - done_become_root = True; - } - - p->tdb = tdb_open_log(printdb_path, 5000, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - - if (done_become_root) - unbecome_root(); - - if (!p->tdb) { - DEBUG(0,("get_print_db: Failed to open printer backend database %s.\n", - printdb_path )); - DLIST_REMOVE(print_db_head, p); - SAFE_FREE(p); - return NULL; - } - fstrcpy(p->printer_name, printername); - p->ref_count++; - return p; -} - -/*************************************************************************** - Remove a reference count. -****************************************************************************/ - -void release_print_db( struct tdb_print_db *pdb) -{ - pdb->ref_count--; - SMB_ASSERT(pdb->ref_count >= 0); -} - -/*************************************************************************** - Close all open print db entries. -****************************************************************************/ - -void close_all_print_db(void) -{ - struct tdb_print_db *p = NULL, *next_p = NULL; - - for (p = print_db_head; p; p = next_p) { - next_p = p->next; - - if (p->tdb) - tdb_close(p->tdb); - DLIST_REMOVE(print_db_head, p); - ZERO_STRUCTP(p); - SAFE_FREE(p); - } -} - - -/**************************************************************************** - Fetch and clean the pid_t record list for all pids interested in notify - messages. data needs freeing on exit. -****************************************************************************/ - -TDB_DATA get_printer_notify_pid_list(TDB_CONTEXT *tdb, const char *printer_name, BOOL cleanlist) -{ - TDB_DATA data; - size_t i; - - ZERO_STRUCT(data); - - data = tdb_fetch_by_string( tdb, NOTIFY_PID_LIST_KEY ); - - if (!data.dptr) { - ZERO_STRUCT(data); - return data; - } - - if (data.dsize % 8) { - DEBUG(0,("get_printer_notify_pid_list: Size of record for printer %s not a multiple of 8 !\n", printer_name )); - tdb_delete_by_string(tdb, NOTIFY_PID_LIST_KEY ); - SAFE_FREE(data.dptr); - ZERO_STRUCT(data); - return data; - } - - if (!cleanlist) - return data; - - /* - * Weed out all dead entries. - */ - - for( i = 0; i < data.dsize; i += 8) { - pid_t pid = (pid_t)IVAL(data.dptr, i); - - if (pid == sys_getpid()) - continue; - - /* Entry is dead if process doesn't exist or refcount is zero. */ - - while ((i < data.dsize) && ((IVAL(data.dptr, i + 4) == 0) || !process_exists(pid))) { - - /* Refcount == zero is a logic error and should never happen. */ - if (IVAL(data.dptr, i + 4) == 0) { - DEBUG(0,("get_printer_notify_pid_list: Refcount == 0 for pid = %u printer %s !\n", - (unsigned int)pid, printer_name )); - } - - if (data.dsize - i > 8) - memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8); - data.dsize -= 8; - } - } - - return data; -} - - |