summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/param/loadparm.c4
-rw-r--r--source3/printing/printing.c67
4 files changed, 56 insertions, 17 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 6911c43be7..b68209434f 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1544,6 +1544,7 @@ int _lp_force_dir_security_mode(int );
int lp_max_connections(int );
int lp_defaultcase(int );
int lp_minprintspace(int );
+int lp_maxprintjobs(int );
int lp_printing(int );
int lp_oplock_contention_limit(int );
int lp_write_cache_size(int );
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 16fb954ad8..b1efb4260a 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -660,6 +660,7 @@ enum {LPSTAT_OK, LPSTAT_STOPPED, LPSTAT_ERROR};
typedef struct
{
fstring message;
+ int qcount;
int status;
} print_status_struct;
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 09ecdf83fa..bad2ad2fdb 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -316,6 +316,7 @@ typedef struct
char *szVfsObjectFile;
char *szVfsOptions;
int iMinPrintSpace;
+ int iMaxPrintJobs;
int iWriteCacheSize;
int iCreate_mask;
int iCreate_force_mode;
@@ -429,6 +430,7 @@ static service sDefault = {
NULL, /* vfs object */
NULL, /* vfs options */
0, /* iMinPrintSpace */
+ 1000, /* iMaxPrintJobs */
0, /* iWriteCacheSize */
0744, /* iCreate_mask */
0000, /* iCreate_force_mode */
@@ -793,6 +795,7 @@ static struct parm_struct parm_table[] = {
{"Printing Options", P_SEP, P_SEPARATOR},
+ {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
{"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, FLAG_PRINT},
{"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_PRINT},
{"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, 0},
@@ -1578,6 +1581,7 @@ FN_LOCAL_INTEGER(_lp_force_dir_security_mode, iDir_Security_force_mode)
FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase)
FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
+FN_LOCAL_INTEGER(lp_maxprintjobs, iMaxPrintJobs)
FN_LOCAL_INTEGER(lp_printing, iPrinting)
FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
diff --git a/source3/printing/printing.c b/source3/printing/printing.c
index d71ea25d0d..d856023567 100644
--- a/source3/printing/printing.c
+++ b/source3/printing/printing.c
@@ -60,7 +60,7 @@ static pid_t local_pid;
#define UNIX_JOB_START PRINT_MAX_JOBID
#define PRINT_SPOOL_PREFIX "smbprn."
-#define PRINT_DATABASE_VERSION 1
+#define PRINT_DATABASE_VERSION 2
/****************************************************************************
initialise the printing backend. Called once at startup.
@@ -381,6 +381,7 @@ static void print_queue_update(int snum)
safe_free(tstruct.queue);
/* store the queue status structure */
+ status.qcount = qcount;
slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
data.dptr = (void *)&status;
data.dsize = sizeof(status);
@@ -628,6 +629,49 @@ int print_job_write(int jobid, const char *buf, int size)
return write(fd, buf, size);
}
+/****************************************************************************
+ Check if the print queue has been updated recently enough.
+****************************************************************************/
+
+static BOOL print_cache_expired(int snum)
+{
+ fstring key;
+ time_t t2, t = time(NULL);
+ slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
+ t2 = tdb_fetch_int(tdb, key);
+ if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
+ return True;
+ }
+ return False;
+}
+
+/****************************************************************************
+ Determine the number of jobs in a queue.
+****************************************************************************/
+
+static int print_queue_length(int snum)
+{
+ fstring keystr;
+ TDB_DATA data, key;
+ print_status_struct status;
+
+ /* make sure the database is up to date */
+ if (print_cache_expired(snum)) print_queue_update(snum);
+
+ /* also fetch the queue status */
+ ZERO_STRUCTP(&status);
+ slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
+ key.dptr = keystr;
+ key.dsize = strlen(keystr);
+ data = tdb_fetch(tdb, key);
+ if (data.dptr) {
+ if (data.dsize == sizeof(status)) {
+ memcpy(&status, data.dptr, sizeof(status));
+ }
+ free(data.dptr);
+ }
+ return status.qcount;
+}
/***************************************************************************
start spooling a job - return the jobid
@@ -670,6 +714,11 @@ int print_job_start(struct current_user *user, int snum, char *jobname)
return -1;
}
+ if (print_queue_length(snum) > lp_maxprintjobs(snum)) {
+ errno = ENOSPC;
+ return -1;
+ }
+
/* create the database entry */
ZERO_STRUCT(pjob);
pjob.pid = local_pid;
@@ -822,22 +871,6 @@ BOOL print_job_end(int jobid)
return True;
}
-/****************************************************************************
- Check if the print queue has been updated recently enough.
-****************************************************************************/
-
-static BOOL print_cache_expired(int snum)
-{
- fstring key;
- time_t t2, t = time(NULL);
- slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
- t2 = tdb_fetch_int(tdb, key);
- if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
- return True;
- }
- 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)
{