3 Unix SMB/Netbios implementation.
5 printing backend routines
6 Copyright (C) Andrew Tridgell 1992-2000
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern int DEBUGLEVEL;
27 the printing backend revolves around a tdb database that stores the
28 SMB view of the print queue
30 The key for this database is a jobid - a internally generated number that
31 uniquely identifies a print job
33 reading the print queue involves two steps:
34 - possibly running lpq and updating the internal database from that
35 - reading entries from the database
37 jobids are assigned when a job starts spooling.
41 pid_t pid; /* which process launched the job */
42 int sysjob; /* the system (lp) job number */
43 int fd; /* file descriptor of open file if open */
44 time_t starttime; /* when the job started spooling */
45 int status; /* the status of this job */
46 size_t size; /* the size of the job so far */
47 BOOL spooled; /* has it been sent to the spooler yet? */
48 BOOL smbjob; /* set if the job is a SMB job */
49 fstring filename; /* the filename used to spool the file */
50 fstring jobname; /* the job name given to us by the client */
51 fstring user; /* the user who started the job */
52 fstring qname; /* name of the print queue the job was sent to */
55 /* the open printing.tdb database */
56 static TDB_CONTEXT *tdb;
57 static pid_t local_pid;
59 #define PRINT_MAX_JOBID 10000
60 #define UNIX_JOB_START PRINT_MAX_JOBID
62 #define PRINT_SPOOL_PREFIX "smbprn."
63 #define PRINT_DATABASE_VERSION 2
65 /****************************************************************************
66 initialise the printing backend. Called once at startup.
67 Does not survive a fork
68 ****************************************************************************/
69 BOOL print_backend_init(void)
71 char *sversion = "INFO/version";
73 if (tdb && local_pid == sys_getpid()) return True;
74 tdb = tdb_open(lock_path("printing.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
76 DEBUG(0,("Failed to open printing backend database\n"));
78 local_pid = sys_getpid();
80 /* handle a Samba upgrade */
81 tdb_lock_bystring(tdb, sversion);
82 if (tdb_fetch_int(tdb, sversion) != PRINT_DATABASE_VERSION) {
83 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
84 tdb_store_int(tdb, sversion, PRINT_DATABASE_VERSION);
86 tdb_unlock_bystring(tdb, sversion);
88 return nt_printing_init();
91 /****************************************************************************
92 useful function to generate a tdb key
93 ****************************************************************************/
94 static TDB_DATA print_key(int jobid)
100 ret.dptr = (void *)&j;
101 ret.dsize = sizeof(j);
105 /****************************************************************************
106 useful function to find a print job in the database
107 ****************************************************************************/
108 static struct printjob *print_job_find(int jobid)
110 static struct printjob pjob;
113 ret = tdb_fetch(tdb, print_key(jobid));
114 if (!ret.dptr || ret.dsize != sizeof(pjob)) return NULL;
116 memcpy(&pjob, ret.dptr, sizeof(pjob));
121 /****************************************************************************
122 store a job structure back to the database
123 ****************************************************************************/
124 static BOOL print_job_store(int jobid, struct printjob *pjob)
127 d.dptr = (void *)pjob;
128 d.dsize = sizeof(*pjob);
129 return (0 == tdb_store(tdb, print_key(jobid), d, TDB_REPLACE));
132 /****************************************************************************
133 run a given print command
134 a null terminated list of value/substitute pairs is provided
135 for local substitution strings
136 ****************************************************************************/
137 static int print_run_command(int snum,char *command,
146 if (!command || !*command) return -1;
148 if (!VALID_SNUM(snum)) {
149 DEBUG(0,("Invalid snum %d for command %s\n", snum, command));
153 pstrcpy(syscmd, command);
155 va_start(ap, outfile);
156 while ((arg = va_arg(ap, char *))) {
157 char *value = va_arg(ap,char *);
158 pstring_sub(syscmd, arg, value);
162 p = PRINTERNAME(snum);
163 if (!p || !*p) p = SERVICE(snum);
165 pstring_sub(syscmd, "%p", p);
166 standard_sub_snum(snum,syscmd);
168 ret = smbrun(syscmd,outfile,False);
170 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
175 /****************************************************************************
176 parse a file name from the system spooler to generate a jobid
177 ****************************************************************************/
178 static int print_parse_jobid(char *fname)
182 if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0) return -1;
183 fname += strlen(PRINT_SPOOL_PREFIX);
186 if (jobid <= 0) return -1;
192 /****************************************************************************
193 list a unix job in the print database
194 ****************************************************************************/
195 static void print_unix_job(int snum, print_queue_struct *q)
197 int jobid = q->job + UNIX_JOB_START;
205 pj.starttime = q->time;
206 pj.status = q->status;
210 fstrcpy(pj.filename, "");
211 fstrcpy(pj.jobname, q->file);
212 fstrcpy(pj.user, q->user);
213 fstrcpy(pj.qname, lp_servicename(snum));
215 print_job_store(jobid, &pj);
219 struct traverse_struct {
220 print_queue_struct *queue;
221 int qcount, snum, maxcount;
224 /* utility fn to delete any jobs that are no longer active */
225 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
227 struct traverse_struct *ts = (struct traverse_struct *)state;
228 struct printjob pjob;
231 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
232 memcpy(&jobid, key.dptr, sizeof(jobid));
233 memcpy(&pjob, data.dptr, sizeof(pjob));
235 if (strcmp(lp_servicename(ts->snum), pjob.qname)) {
236 /* this isn't for the queue we are looking at */
241 /* remove a unix job if it isn't in the system queue
243 for (i=0;i<ts->qcount;i++) {
244 if (jobid == ts->queue[i].job + UNIX_JOB_START) break;
246 if (i == ts->qcount) tdb_delete(tdb, key);
250 /* maybe it hasn't been spooled yet */
252 /* if a job is not spooled and the process doesn't
253 exist then kill it. This cleans up after smbd
255 if (!process_exists(pjob.pid)) {
256 tdb_delete(tdb, key);
261 for (i=0;i<ts->qcount;i++) {
262 int qid = print_parse_jobid(ts->queue[i].file);
263 if (jobid == qid) break;
266 if (i == ts->qcount) {
267 /* the job isn't in the system queue - we have to
268 assume it has completed, so delete the database
276 /****************************************************************************
277 check if the print queue has been updated recently enough
278 ****************************************************************************/
279 static void print_cache_flush(int snum)
282 slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
283 tdb_store_int(tdb, key, -1);
286 /****************************************************************************
287 update the internal database from the system print queue for a queue
288 ****************************************************************************/
289 static void print_queue_update(int snum)
291 char *path = lp_pathname(snum);
292 char *cmd = lp_lpqcommand(snum);
295 int numlines, i, qcount;
296 print_queue_struct *queue = NULL;
297 print_status_struct status;
298 struct printjob *pjob;
299 struct traverse_struct tstruct;
304 * Update the cache time FIRST ! Stops others doing this
305 * if the lpq takes a long time.
308 slprintf(keystr, sizeof(keystr), "CACHE/%s", lp_servicename(snum));
309 tdb_store_int(tdb, keystr, (int)time(NULL));
311 slprintf(tmp_file, sizeof(tmp_file), "%s/smblpq.%d", path, local_pid);
314 print_run_command(snum, cmd, tmp_file,
318 qlines = file_lines_load(tmp_file, &numlines);
321 /* turn the lpq output into a series of job structures */
325 queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1));
328 for (i=0; i<numlines; i++) {
330 if (parse_lpq_entry(snum,qlines[i],
331 &queue[qcount],&status,qcount==0)) {
336 file_lines_free(qlines);
339 any job in the internal database that is marked as spooled
340 and doesn't exist in the system queue is considered finished
341 and removed from the database
343 any job in the system database but not in the internal database
344 is added as a unix job
346 fill in any system job numbers as we go
348 for (i=0; i<qcount; i++) {
349 int jobid = print_parse_jobid(queue[i].file);
352 /* assume its a unix print job */
353 print_unix_job(snum, &queue[i]);
357 /* we have an active SMB print job - update its status */
358 pjob = print_job_find(jobid);
360 /* err, somethings wrong. Probably smbd was restarted
361 with jobs in the queue. All we can do is treat them
362 like unix jobs. Pity. */
363 print_unix_job(snum, &queue[i]);
367 pjob->sysjob = queue[i].job;
368 pjob->status = queue[i].status;
370 print_job_store(jobid, pjob);
373 /* now delete any queued entries that don't appear in the
375 tstruct.queue = queue;
376 tstruct.qcount = qcount;
379 tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct);
381 safe_free(tstruct.queue);
383 /* store the queue status structure */
384 status.qcount = qcount;
385 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
386 data.dptr = (void *)&status;
387 data.dsize = sizeof(status);
389 key.dsize = strlen(keystr);
390 tdb_store(tdb, key, data, TDB_REPLACE);
393 * Update the cache time again. We want to do this call
394 * as little as possible...
397 slprintf(keystr, sizeof(keystr), "CACHE/%s", lp_servicename(snum));
398 tdb_store_int(tdb, keystr, (int)time(NULL));
401 /****************************************************************************
402 check if a jobid is valid. It is valid if it exists in the database
403 ****************************************************************************/
404 BOOL print_job_exists(int jobid)
406 return tdb_exists(tdb, print_key(jobid));
410 /****************************************************************************
411 work out which service a jobid is for
412 note that we have to look up by queue name to ensure that it works for
413 other than the process that started the job
414 ****************************************************************************/
415 int print_job_snum(int jobid)
417 struct printjob *pjob = print_job_find(jobid);
418 if (!pjob) return -1;
420 return lp_servicenumber(pjob->qname);
423 /****************************************************************************
424 give the fd used for a jobid
425 ****************************************************************************/
426 int print_job_fd(int jobid)
428 struct printjob *pjob = print_job_find(jobid);
429 if (!pjob) return -1;
430 /* don't allow another process to get this info - it is meaningless */
431 if (pjob->pid != local_pid) return -1;
435 /****************************************************************************
436 give the filename used for a jobid
437 only valid for the process doing the spooling and when the job
439 ****************************************************************************/
440 char *print_job_fname(int jobid)
442 struct printjob *pjob = print_job_find(jobid);
443 if (!pjob || pjob->spooled || pjob->pid != local_pid) return NULL;
444 return pjob->filename;
448 /****************************************************************************
449 set the place in the queue for a job
450 ****************************************************************************/
451 BOOL print_job_set_place(int jobid, int place)
453 DEBUG(2,("print_job_set_place not implemented yet\n"));
457 /****************************************************************************
458 set the name of a job. Only possible for owner
459 ****************************************************************************/
460 BOOL print_job_set_name(int jobid, char *name)
462 struct printjob *pjob = print_job_find(jobid);
463 if (!pjob || pjob->pid != local_pid) return False;
465 fstrcpy(pjob->jobname, name);
466 return print_job_store(jobid, pjob);
470 /****************************************************************************
471 delete a print job - don't update queue
472 ****************************************************************************/
473 static BOOL print_job_delete1(int jobid)
475 struct printjob *pjob = print_job_find(jobid);
478 if (!pjob) return False;
480 snum = print_job_snum(jobid);
482 if (pjob->spooled && pjob->sysjob != -1) {
483 /* need to delete the spooled entry */
485 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
486 print_run_command(snum,
487 lp_lprmcommand(snum), NULL,
489 "%T", http_timestring(pjob->starttime),
496 /****************************************************************************
497 return true if the current user owns the print job
498 ****************************************************************************/
499 static BOOL is_owner(struct current_user *user, int jobid)
501 struct printjob *pjob = print_job_find(jobid);
504 if (!pjob || !user) return False;
506 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
507 return strequal(pjob->user, vuser->user.smb_name);
509 return strequal(pjob->user, uidtoname(user->uid));
513 /****************************************************************************
515 ****************************************************************************/
516 BOOL print_job_delete(struct current_user *user, int jobid)
518 int snum = print_job_snum(jobid);
521 if (!user) return False;
523 owner = is_owner(user, jobid);
525 /* Check access against security descriptor or whether the user
529 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
530 DEBUG(3, ("delete denied by security descriptor\n"));
534 if (!print_job_delete1(jobid)) return False;
536 /* force update the database and say the delete failed if the
539 print_queue_update(snum);
541 return !print_job_exists(jobid);
545 /****************************************************************************
547 ****************************************************************************/
548 BOOL print_job_pause(struct current_user *user, int jobid)
550 struct printjob *pjob = print_job_find(jobid);
556 if (!pjob || !user) return False;
558 if (!pjob->spooled || pjob->sysjob == -1) return False;
560 snum = print_job_snum(jobid);
561 owner = is_owner(user, jobid);
564 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
565 DEBUG(3, ("pause denied by security descriptor\n"));
569 /* need to pause the spooled entry */
570 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
571 ret = print_run_command(snum,
572 lp_lppausecommand(snum), NULL,
576 /* force update the database */
577 print_cache_flush(snum);
579 /* how do we tell if this succeeded? */
583 /****************************************************************************
585 ****************************************************************************/
586 BOOL print_job_resume(struct current_user *user, int jobid)
588 struct printjob *pjob = print_job_find(jobid);
593 if (!pjob || !user) return False;
595 if (!pjob->spooled || pjob->sysjob == -1) return False;
597 snum = print_job_snum(jobid);
598 owner = is_owner(user, jobid);
600 if (!is_owner(user, jobid) &&
601 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
602 DEBUG(3, ("resume denied by security descriptor\n"));
606 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
607 ret = print_run_command(snum,
608 lp_lpresumecommand(snum), NULL,
612 /* force update the database */
613 print_cache_flush(snum);
615 /* how do we tell if this succeeded? */
619 /****************************************************************************
620 write to a print file
621 ****************************************************************************/
622 int print_job_write(int jobid, const char *buf, int size)
626 fd = print_job_fd(jobid);
627 if (fd == -1) return -1;
629 return write(fd, buf, size);
632 /****************************************************************************
633 Check if the print queue has been updated recently enough.
634 ****************************************************************************/
636 static BOOL print_cache_expired(int snum)
639 time_t t2, t = time(NULL);
640 slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
641 t2 = tdb_fetch_int(tdb, key);
642 if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
648 /****************************************************************************
649 Determine the number of jobs in a queue.
650 ****************************************************************************/
652 static int print_queue_length(int snum)
656 print_status_struct status;
658 /* make sure the database is up to date */
659 if (print_cache_expired(snum)) print_queue_update(snum);
661 /* also fetch the queue status */
662 ZERO_STRUCTP(&status);
663 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
665 key.dsize = strlen(keystr);
666 data = tdb_fetch(tdb, key);
668 if (data.dsize == sizeof(status)) {
669 memcpy(&status, data.dptr, sizeof(status));
673 return status.qcount;
676 /***************************************************************************
677 start spooling a job - return the jobid
678 ***************************************************************************/
679 int print_job_start(struct current_user *user, int snum, char *jobname)
683 struct printjob pjob;
689 if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
690 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
694 if (!print_time_access_check(snum)) {
695 DEBUG(3, ("print_job_start: job start denied by time check\n"));
699 path = lp_pathname(snum);
701 /* see if we have sufficient disk space */
702 if (lp_minprintspace(snum)) {
703 SMB_BIG_UINT dspace, dsize;
704 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
705 dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
711 /* for autoloaded printers, check that the printcap entry still exists */
712 if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
717 if (print_queue_length(snum) > lp_maxprintjobs(snum)) {
722 /* create the database entry */
724 pjob.pid = local_pid;
727 pjob.starttime = time(NULL);
728 pjob.status = LPQ_QUEUED;
730 pjob.spooled = False;
733 fstrcpy(pjob.jobname, jobname);
735 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
736 fstrcpy(pjob.user, vuser->user.smb_name);
738 fstrcpy(pjob.user, uidtoname(user->uid));
741 fstrcpy(pjob.qname, lp_servicename(snum));
743 /* lock the database */
744 tdb_lock_bystring(tdb, "INFO/nextjob");
747 next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
748 if (next_jobid == -1) next_jobid = 1;
750 for (jobid = next_jobid+1; jobid != next_jobid; ) {
751 if (!print_job_exists(jobid)) break;
752 jobid = (jobid + 1) % PRINT_MAX_JOBID;
753 if (jobid == 0) jobid = 1;
755 if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
760 tdb_store_int(tdb, "INFO/nextjob", jobid);
762 /* we have a job entry - now create the spool file
764 we unlink first to cope with old spool files and also to beat
765 a symlink security hole - it allows us to use O_EXCL
766 There may be old spool files owned by other users lying around.
768 slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d",
769 path, PRINT_SPOOL_PREFIX, jobid);
770 if (unlink(pjob.filename) == -1 && errno != ENOENT) {
773 pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
774 if (pjob.fd == -1) goto fail;
776 print_job_store(jobid, &pjob);
778 tdb_unlock_bystring(tdb, "INFO/nextjob");
781 * If the printer is marked as postscript output a leading
782 * file identifier to ensure the file is treated as a raw
784 * This has a similar effect as CtrlD=0 in WIN.INI file.
785 * tim@fsg.com 09/06/94
787 if (lp_postscript(snum)) {
788 print_job_write(jobid, "%!\n",3);
795 tdb_delete(tdb, print_key(jobid));
798 tdb_unlock_bystring(tdb, "INFO/nextjob");
802 /****************************************************************************
803 Print a file - called on closing the file. This spools the job.
804 ****************************************************************************/
806 BOOL print_job_end(int jobid)
808 struct printjob *pjob = print_job_find(jobid);
810 SMB_STRUCT_STAT sbuf;
811 pstring current_directory;
812 pstring print_directory;
819 if (pjob->spooled || pjob->pid != local_pid)
822 snum = print_job_snum(jobid);
824 if (sys_fstat(pjob->fd, &sbuf) == 0)
825 pjob->size = sbuf.st_size;
830 if (pjob->size == 0) {
831 /* don't bother spooling empty files */
832 unlink(pjob->filename);
833 tdb_delete(tdb, print_key(jobid));
837 /* we print from the directory path to give the best chance of
838 parsing the lpq output */
839 wd = sys_getwd(current_directory);
843 pstrcpy(print_directory, pjob->filename);
844 p = strrchr(print_directory,'/');
849 if (chdir(print_directory) != 0)
852 pstrcpy(jobname, pjob->jobname);
853 pstring_sub(jobname, "'", "_");
855 /* send it to the system spooler */
856 print_run_command(snum,
857 lp_printcommand(snum), NULL,
865 pjob->spooled = True;
866 print_job_store(jobid, pjob);
868 /* force update the database */
869 print_cache_flush(snum);
874 /* utility fn to enumerate the print queue */
875 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
877 struct traverse_struct *ts = (struct traverse_struct *)state;
878 struct printjob pjob;
881 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
882 memcpy(&jobid, key.dptr, sizeof(jobid));
883 memcpy(&pjob, data.dptr, sizeof(pjob));
885 /* maybe it isn't for this queue */
886 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
888 if (ts->qcount >= ts->maxcount) return 0;
892 ts->queue[i].job = jobid;
893 ts->queue[i].size = pjob.size;
894 ts->queue[i].status = pjob.status;
895 ts->queue[i].priority = 1;
896 ts->queue[i].time = pjob.starttime;
897 fstrcpy(ts->queue[i].user, pjob.user);
898 fstrcpy(ts->queue[i].file, pjob.jobname);
905 struct traverse_count_struct {
909 /* utility fn to count the number of entries in the print queue */
910 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
912 struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
913 struct printjob pjob;
916 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
917 memcpy(&jobid, key.dptr, sizeof(jobid));
918 memcpy(&pjob, data.dptr, sizeof(pjob));
920 /* maybe it isn't for this queue */
921 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
928 /****************************************************************************
929 get a printer queue listing
930 ****************************************************************************/
931 int print_queue_status(int snum,
932 print_queue_struct **queue,
933 print_status_struct *status)
935 struct traverse_struct tstruct;
936 struct traverse_count_struct tsc;
940 /* make sure the database is up to date */
941 if (print_cache_expired(snum)) print_queue_update(snum);
944 * Count the number of entries.
948 tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
950 /* Allocate the queue size. */
951 if (( tstruct.queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*tsc.count))
957 * We need maxcount as the queue size may have changed between
958 * the two calls to tdb_traverse.
961 tstruct.maxcount = tsc.count;
964 tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
966 /* also fetch the queue status */
967 ZERO_STRUCTP(status);
968 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
970 key.dsize = strlen(keystr);
971 data = tdb_fetch(tdb, key);
973 if (data.dsize == sizeof(*status)) {
974 memcpy(status, data.dptr, sizeof(*status));
979 *queue = tstruct.queue;
980 return tstruct.qcount;
984 /****************************************************************************
985 turn a queue name into a snum
986 ****************************************************************************/
987 int print_queue_snum(char *qname)
989 int snum = lp_servicenumber(qname);
990 if (snum == -1 || !lp_print_ok(snum)) return -1;
995 /****************************************************************************
997 ****************************************************************************/
998 BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
1002 if (!user) return False;
1004 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1005 *errcode = ERROR_ACCESS_DENIED;
1009 ret = print_run_command(snum, lp_queuepausecommand(snum), NULL,
1012 /* force update the database */
1013 print_cache_flush(snum);
1018 /****************************************************************************
1020 ****************************************************************************/
1021 BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
1025 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1026 *errcode = ERROR_ACCESS_DENIED;
1030 ret = print_run_command(snum, lp_queueresumecommand(snum), NULL,
1033 /* force update the database */
1034 print_cache_flush(snum);
1039 /****************************************************************************
1040 purge a queue - implemented by deleting all jobs that we can delete
1041 ****************************************************************************/
1042 BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
1044 print_queue_struct *queue;
1045 print_status_struct status;
1048 njobs = print_queue_status(snum, &queue, &status);
1049 for (i=0;i<njobs;i++) {
1050 if (print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
1051 print_job_delete1(queue[i].job);
1055 print_cache_flush(snum);