summaryrefslogtreecommitdiff
path: root/testsuite/printing
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/printing')
-rw-r--r--testsuite/printing/.cvsignore2
-rw-r--r--testsuite/printing/Makefile.psec22
-rw-r--r--testsuite/printing/Makefile.vlp14
-rw-r--r--testsuite/printing/README.vlp35
-rw-r--r--testsuite/printing/psec.c433
-rw-r--r--testsuite/printing/vlp.c426
6 files changed, 932 insertions, 0 deletions
diff --git a/testsuite/printing/.cvsignore b/testsuite/printing/.cvsignore
new file mode 100644
index 0000000000..392f277768
--- /dev/null
+++ b/testsuite/printing/.cvsignore
@@ -0,0 +1,2 @@
+vlp
+psec
diff --git a/testsuite/printing/Makefile.psec b/testsuite/printing/Makefile.psec
new file mode 100644
index 0000000000..1410c9e009
--- /dev/null
+++ b/testsuite/printing/Makefile.psec
@@ -0,0 +1,22 @@
+#
+# Makefile for psec utility
+#
+
+#
+# NOTE: Samba must be configured with the --srcdir option before this Makefile
+# will work: ./configure --srcdir=`pwd`
+#
+# Compile with: make -f Makefile.psec psec
+#
+
+psec_default: psec
+
+include ../../source/Makefile
+
+PSEC_OBJ1 = $(LIB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(RPC_PARSE_OBJ) \
+ $(LIBSMB_OBJ) $(PASSDB_OBJ) $(RPC_CLIENT_OBJ)
+
+PSEC_OBJS = $(PSEC_OBJ1:%=$(srcdir)/%)
+
+psec: $(PSEC_OBJS) psec.o
+ $(CC) -o $@ psec.o $(PSEC_OBJS) $(LIBS)
diff --git a/testsuite/printing/Makefile.vlp b/testsuite/printing/Makefile.vlp
new file mode 100644
index 0000000000..142082ebfe
--- /dev/null
+++ b/testsuite/printing/Makefile.vlp
@@ -0,0 +1,14 @@
+#
+# Makefile for vlp utility
+#
+
+vlp_default: vlp
+
+include ../../source/Makefile
+
+VLP_OBJ1 = $(LIB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ)
+
+VLP_OBJS = $(VLP_OBJ1:%=$(srcdir)/%)
+
+vlp: $(VLP_OBJS) vlp.o
+ $(CC) -o $@ vlp.o $(VLP_OBJS) $(LIBS)
diff --git a/testsuite/printing/README.vlp b/testsuite/printing/README.vlp
new file mode 100644
index 0000000000..48d2c8c0a2
--- /dev/null
+++ b/testsuite/printing/README.vlp
@@ -0,0 +1,35 @@
+Virtual line printer test program (vlp)
+=======================================
+
+This can be useful for testing/debugging Samba print code. It gives you a
+virtual full-function printer.
+
+Setup
+
+1) Configure and build Samba.
+ For this to work, you need to add:
+ -DDEVELOPER
+ to your CFLAGS, and add:
+ --srcdir=<wherever your source is>
+ when running configure. Generally
+ ./configure --srcdir=`pwd` <other configure options>
+ should work.
+
+2) Build and install vlp.
+ # cd testsuite/printing
+ # make -f Makefile.vlp vlp
+ # su
+ # cp vlp /usr/local/samba/bin
+
+3) Set up Samba to use vlp.
+ In your smb.conf file under [global], add the following option:
+ printing = vlp
+ and then add any number of print shares, without needing to make them
+ really exist.
+
+ [testprinter]
+ printable = yes
+
+ is all you need for the most basic virtual printer.
+
+
diff --git a/testsuite/printing/psec.c b/testsuite/printing/psec.c
new file mode 100644
index 0000000000..9d38b9b10a
--- /dev/null
+++ b/testsuite/printing/psec.c
@@ -0,0 +1,433 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+
+ Printer security permission manipulation.
+
+ Copyright (C) Tim Potter 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.
+*/
+
+/* This program can get or set NT printer security permissions from the
+ command line. Usage: psec getsec|setsec printername. You must have
+ write access to the ntdrivers.tdb file to set permissions and read
+ access to get permissions.
+
+ For this program to compile using the supplied Makefile.psec, Samba
+ must be configured with the --srcdir option
+
+ For getsec, output like the following is sent to standard output:
+
+ S-1-5-21-1067277791-1719175008-3000797951-500
+
+ 1 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-501
+ 1 2 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-501
+ 0 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-500
+ 0 2 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-500
+ 0 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-513
+ 0 2 0x00020000 S-1-5-21-1067277791-1719175008-3000797951-513
+ 0 2 0xe0000000 S-1-1-0
+
+ The first two lines describe the owner user and owner group of the printer.
+ If either of these lines are blank then the respective owner property is
+ not set. The remaining lines list the printer permissions or ACE entries,
+ one per line. Each column describes a different property of the ACE:
+
+ Column Description
+ -------------------------------------------------------------------
+ 1 ACE type (allow/deny etc) defined in rpc_secdes.h
+ 2 ACE flags defined in rpc_secdes.h
+ 3 ACE mask - printer ACE masks are defined in rpc_spoolss.h
+ 4 SID the ACE applies to
+
+ The above example describes the following permissions in order:
+
+ - The guest user has No Access to the printer
+ - The domain administrator has Full Access
+ - Domain Users can Manage Documents
+ - Everyone has Print access
+
+ The setsec command takes the output format but sets the security descriptor
+ appropriately. */
+
+#include "includes.h"
+
+TDB_CONTEXT *tdb;
+
+/* ACE type conversions */
+
+char *ace_type_to_str(uint ace_type)
+{
+ static fstring temp;
+
+ switch(ace_type) {
+ case SEC_ACE_TYPE_ACCESS_DENIED:
+ return "DENY";
+ case SEC_ACE_TYPE_ACCESS_ALLOWED:
+ return "ALLOW";
+ }
+
+ slprintf(temp, sizeof(temp) - 1, "0x%02x", ace_type);
+ return temp;
+}
+
+uint str_to_ace_type(char *ace_type)
+{
+ if (strcmp(ace_type, "ALLOWED") == 0)
+ return SEC_ACE_TYPE_ACCESS_ALLOWED;
+
+ if (strcmp(ace_type, "DENIED") == 0)
+ return SEC_ACE_TYPE_ACCESS_DENIED;
+
+ return -1;
+}
+
+/* ACE mask (permission) conversions */
+
+char *ace_mask_to_str(uint32 ace_mask)
+{
+ static fstring temp;
+
+ switch (ace_mask) {
+ case PRINTER_ACE_FULL_CONTROL:
+ return "Full Control";
+ case PRINTER_ACE_MANAGE_DOCUMENTS:
+ return "Manage Documents";
+ case PRINTER_ACE_PRINT:
+ return "Print";
+ }
+
+ slprintf(temp, sizeof(temp) - 1, "0x%08x", ace_mask);
+ return temp;
+}
+
+uint32 str_to_ace_mask(char *ace_mask)
+{
+ if (strcmp(ace_mask, "Full Control") == 0)
+ return PRINTER_ACE_FULL_CONTROL;
+
+ if (strcmp(ace_mask, "Manage Documents") == 0)
+ return PRINTER_ACE_MANAGE_DOCUMENTS;
+
+ if (strcmp(ace_mask, "Print") == 0)
+ return PRINTER_ACE_PRINT;
+
+ return -1;
+}
+
+/* ACE conversions */
+
+char *ace_to_str(SEC_ACE *ace)
+{
+ static pstring temp;
+ fstring sidstr;
+
+ sid_to_string(sidstr, &ace->sid);
+
+ slprintf(temp, sizeof(temp) - 1, "%s %d %s %s",
+ ace_type_to_str(ace->type), ace->flags,
+ ace_mask_to_str(ace->info.mask), sidstr);
+
+ return temp;
+}
+
+void str_to_ace(SEC_ACE *ace, char *ace_str)
+{
+ SEC_ACCESS sa;
+ DOM_SID sid;
+ uint32 mask;
+ uint8 type, flags;
+
+ init_sec_access(&sa, mask);
+ init_sec_ace(ace, &sid, type, sa, flags);
+}
+
+/* Get a printer security descriptor */
+
+int psec_getsec(char *printer)
+{
+ SEC_DESC_BUF *secdesc_ctr = NULL;
+ TALLOC_CTX *mem_ctx = NULL;
+ fstring keystr, sidstr, tdb_path;
+ prs_struct ps;
+ int result = 0, i;
+
+ ZERO_STRUCT(ps);
+
+ /* Open tdb for reading */
+
+ slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb",
+ lp_lockdir());
+
+ tdb = tdb_open(tdb_path, 0, 0, O_RDONLY, 0600);
+
+ if (!tdb) {
+ printf("psec: failed to open nt drivers database: %s\n",
+ sys_errlist[errno]);
+ return 1;
+ }
+
+ /* Get security blob from tdb */
+
+ slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
+
+ mem_ctx = talloc_init();
+
+ if (!mem_ctx) {
+ printf("memory allocation error\n");
+ result = 1;
+ goto done;
+ }
+
+ if (tdb_prs_fetch(tdb, keystr, &ps, mem_ctx) != 0) {
+ printf("error fetching descriptor for printer %s\n",
+ printer);
+ result = 1;
+ goto done;
+ }
+
+ /* Unpack into security descriptor buffer */
+
+ if (!sec_io_desc_buf("nt_printing_getsec", &secdesc_ctr, &ps, 1)) {
+ printf("error unpacking sec_desc_buf\n");
+ result = 1;
+ goto done;
+ }
+
+ /* Print owner and group sid */
+
+ if (secdesc_ctr->sec->owner_sid) {
+ sid_to_string(sidstr, secdesc_ctr->sec->owner_sid);
+ } else {
+ fstrcpy(sidstr, "");
+ }
+
+ printf("%s\n", sidstr);
+
+ if (secdesc_ctr->sec->grp_sid) {
+ sid_to_string(sidstr, secdesc_ctr->sec->grp_sid);
+ } else {
+ fstrcpy(sidstr, "");
+ }
+
+ printf("%s\n", sidstr);
+
+ /* Print aces */
+
+ if (!secdesc_ctr->sec->dacl) {
+ result = 0;
+ goto done;
+ }
+
+ for (i = 0; i < secdesc_ctr->sec->dacl->num_aces; i++) {
+ SEC_ACE *ace = &secdesc_ctr->sec->dacl->ace[i];
+
+ sid_to_string(sidstr, &ace->sid);
+
+ printf("%d %d 0x%08x %s\n", ace->type, ace->flags,
+ ace->info.mask, sidstr);
+ }
+
+ done:
+ if (tdb) tdb_close(tdb);
+ if (mem_ctx) talloc_destroy(mem_ctx);
+ if (secdesc_ctr) free_sec_desc_buf(&secdesc_ctr);
+ prs_mem_free(&ps);
+
+ return result;
+}
+
+/* Set a printer security descriptor */
+
+int psec_setsec(char *printer)
+{
+ DOM_SID user_sid, group_sid;
+ SEC_ACE *ace_list = NULL;
+ SEC_ACL *dacl = NULL;
+ SEC_DESC *sd;
+ SEC_DESC_BUF *sdb = NULL;
+ int result = 0, num_aces = 0;
+ fstring line, keystr, tdb_path;
+ size_t size;
+ prs_struct ps;
+ TALLOC_CTX *mem_ctx = NULL;
+ BOOL has_user_sid = False, has_group_sid = False;
+
+ ZERO_STRUCT(ps);
+
+ /* Open tdb for reading */
+
+ slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb",
+ lp_lockdir());
+
+ tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);
+
+ if (!tdb) {
+ printf("psec: failed to open nt drivers database: %s\n",
+ sys_errlist[errno]);
+ result = 1;
+ goto done;
+ }
+
+ /* Read owner and group sid */
+
+ fgets(line, sizeof(fstring), stdin);
+ if (line[0] != '\n') {
+ string_to_sid(&user_sid, line);
+ has_user_sid = True;
+ }
+
+ fgets(line, sizeof(fstring), stdin);
+ if (line[0] != '\n') {
+ string_to_sid(&group_sid, line);
+ has_group_sid = True;
+ }
+
+ /* Read ACEs from standard input for discretionary ACL */
+
+ while(fgets(line, sizeof(fstring), stdin)) {
+ int ace_type, ace_flags;
+ uint32 ace_mask;
+ fstring sidstr;
+ DOM_SID sid;
+ SEC_ACCESS sa;
+
+ if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags,
+ &ace_mask, sidstr) != 4) {
+ continue;
+ }
+
+ string_to_sid(&sid, sidstr);
+
+ ace_list = Realloc(ace_list, sizeof(SEC_ACE) *
+ (num_aces + 1));
+
+ init_sec_access(&sa, ace_mask);
+ init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa,
+ ace_flags);
+
+ num_aces++;
+ }
+
+ dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
+ free(ace_list);
+
+ /* Create security descriptor */
+
+ sd = make_sec_desc(SEC_DESC_REVISION,
+ has_user_sid ? &user_sid : NULL,
+ has_group_sid ? &group_sid : NULL,
+ NULL, /* System ACL */
+ dacl, /* Discretionary ACL */
+ &size);
+
+ free_sec_acl(&dacl);
+
+ sdb = make_sec_desc_buf(size, sd);
+
+ free_sec_desc(&sd);
+
+ /* Write security descriptor to tdb */
+
+ mem_ctx = talloc_init();
+
+ if (!mem_ctx) {
+ printf("memory allocation error\n");
+ result = 1;
+ goto done;
+ }
+
+ prs_init(&ps, (uint32)sec_desc_size(sdb->sec) +
+ sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
+
+ if (!sec_io_desc_buf("nt_printing_setsec", &sdb, &ps, 1)) {
+ printf("sec_io_desc_buf failed\n");
+ goto done;
+ }
+
+ slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
+
+ if (!tdb_prs_store(tdb, keystr, &ps)==0) {
+ printf("Failed to store secdesc for %s\n", printer);
+ goto done;
+ }
+
+ done:
+ if (tdb) tdb_close(tdb);
+ if (sdb) free_sec_desc_buf(&sdb);
+ if (mem_ctx) talloc_destroy(mem_ctx);
+ prs_mem_free(&ps);
+
+ return result;
+}
+
+/* Help */
+
+void usage(void)
+{
+ printf("Usage: psec getsec|setsec printername\n");
+}
+
+/* Main function */
+
+int main(int argc, char **argv)
+{
+ pstring servicesf = CONFIGFILE;
+
+ /* Argument check */
+
+ if (argc == 1) {
+ usage();
+ return 1;
+ }
+
+ /* Load smb.conf file */
+
+ charset_initialise();
+
+ if (!lp_load(servicesf,False,False,True)) {
+ fprintf(stderr, "Couldn't load confiuration file %s\n",
+ servicesf);
+ return 1;
+ }
+
+ /* Do commands */
+
+ if (strcmp(argv[1], "setsec") == 0) {
+
+ if (argc != 3) {
+ usage();
+ return 1;
+ }
+
+ return psec_setsec(argv[2]);
+ }
+
+ if (strcmp(argv[1], "getsec") == 0) {
+
+ if (argc != 3) {
+ usage();
+ return 1;
+ }
+
+ return psec_getsec(argv[2]);
+ }
+
+ /* An unknown command */
+
+ printf("psec: unknown command %s\n", argv[1]);
+ return 1;
+}
diff --git a/testsuite/printing/vlp.c b/testsuite/printing/vlp.c
new file mode 100644
index 0000000000..2dd028fcd3
--- /dev/null
+++ b/testsuite/printing/vlp.c
@@ -0,0 +1,426 @@
+/*
+ Unix SMB/Netbios implementation.
+
+ Virtual lp system for printer testing
+
+ Copyright (C) Tim Potter 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"
+
+#define PRINT_TDB "/tmp/vlp.tdb"
+#define PRINT_FIRSTJOB "100"
+
+static TDB_CONTEXT *tdb;
+
+struct vlp_job {
+ fstring owner;
+ int jobid;
+ fstring jobname;
+ int size;
+ int status;
+ time_t submit_time;
+ int deleted;
+};
+
+/* Print usage */
+
+static void usage(void)
+{
+ printf("Usage: print-test lpq|lprm|print|queuepause|queueresume|"
+ "lppause|lpresume [args]\n");
+}
+
+/* Return an array of vlp jobs that is the printer queue */
+
+static void get_job_list(char *printer, struct vlp_job **job_list,
+ int *num_jobs)
+{
+ fstring keystr;
+ TDB_DATA data;
+
+ slprintf(keystr, sizeof(keystr) - 1, "LPQ/%s", printer);
+ data = tdb_fetch_by_string(tdb, keystr);
+
+ *job_list = (struct vlp_job *)data.dptr;
+ *num_jobs = data.dsize / sizeof(struct vlp_job);
+}
+
+/* Store an array of vl jobs for the queue */
+
+static void set_job_list(char *printer, struct vlp_job *job_list,
+ int num_jobs)
+{
+ fstring keystr;
+
+ slprintf(keystr, sizeof(keystr) - 1, "LPQ/%s", printer);
+
+ tdb_store_by_string(tdb, keystr, job_list,
+ num_jobs * sizeof(struct vlp_job));
+}
+
+/* Return the next job number for a printer */
+
+static int next_jobnum(char *printer)
+{
+ fstring keystr;
+ int jobnum;
+
+ slprintf(keystr, sizeof(keystr) - 1, "JOBNUM/%s", printer);
+
+ tdb_lock_bystring(tdb, keystr);
+
+ jobnum = tdb_fetch_int(tdb, keystr);
+
+ /* Create next job index if none exists */
+
+ if (jobnum == -1) {
+ jobnum = atoi(PRINT_FIRSTJOB);
+ }
+
+ jobnum++;
+ tdb_store_int(tdb, keystr, jobnum);
+
+ tdb_unlock_bystring(tdb, keystr);
+
+ return jobnum;
+}
+
+static void set_printer_status(char *printer, int status)
+{
+ fstring keystr;
+ int result;
+
+ slprintf(keystr, sizeof(keystr) - 1, "STATUS/%s", printer);
+ result = tdb_store_int(tdb, keystr, status);
+}
+
+static int get_printer_status(char *printer)
+{
+ fstring keystr;
+ TDB_DATA data;
+
+ slprintf(keystr, sizeof(keystr) - 1, "STATUS/%s", printer);
+
+ data.dptr = keystr;
+ data.dsize = strlen(keystr) + 1;
+
+ if (!tdb_exists(tdb, data)) {
+ set_printer_status(printer, LPSTAT_OK);
+ return LPSTAT_OK;
+ }
+
+ return tdb_fetch_int(tdb, keystr);
+}
+
+/* Display printer queue */
+
+static int lpq_command(int argc, char **argv)
+{
+ char *printer;
+ struct vlp_job *job_list = NULL;
+ int i, num_jobs, job_count = 0;
+
+ if (argc != 2) {
+ printf("Usage: lpq <printername>\n");
+ return 1;
+ }
+
+ printer = argv[1];
+
+ /* Display printer status */
+
+ switch (get_printer_status(printer)) {
+ case LPSTAT_OK:
+ printf("enabled\n");
+ break;
+ case LPSTAT_STOPPED:
+ printf("disabled\n");
+ break;
+ case LPSTAT_ERROR:
+ default:
+ printf("error\n");
+ break;
+ }
+
+ /* Print queued documents */
+
+ get_job_list(printer, &job_list, &num_jobs);
+
+ for (i = 0; i < num_jobs; i++) {
+ if (job_list[i].deleted) continue;
+ printf("%d\t%d\t%d\t%ld\t%s\t%s\n", job_list[i].jobid,
+ job_list[i].size,
+ (i == 0 && job_list[i].status == LPQ_QUEUED) ?
+ LPQ_SPOOLING : job_list[i].status,
+ job_list[i].submit_time, job_list[i].owner,
+ job_list[i].jobname);
+ job_count++;
+ }
+
+ free(job_list);
+
+ return 0;
+}
+
+/* Remove a job */
+
+static int lprm_command(int argc, char **argv)
+{
+ char *printer;
+ int jobid, num_jobs, i;
+ struct vlp_job *job_list;
+
+ if (argc < 3) {
+ printf("Usage: lprm <printername> <jobid>\n");
+ return 1;
+ }
+
+ printer = argv[1];
+ jobid = atoi(argv[2]);
+
+ get_job_list(printer, &job_list, &num_jobs);
+
+ for (i = 0; i < num_jobs; i++) {
+ if (job_list[i].jobid == jobid) {
+ job_list[i].deleted = 1;
+ set_job_list(printer, job_list, num_jobs);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* print command = print-test %p %s */
+
+static int print_command(int argc, char **argv)
+{
+ char *printer;
+ fstring keystr;
+ struct passwd *pw;
+ TDB_DATA value;
+ struct vlp_job job;
+ int i;
+
+ if (argc < 3) {
+ printf("Usage: print <printername> <jobname>\n");
+ return 1;
+ }
+
+ printer = argv[1];
+
+ ZERO_STRUCT(job);
+
+ /* Create a job record */
+
+ for (i = 2; i < argc; i++) {
+ fstrcat(job.jobname, argv[i]);
+ if (i < argc - 1) {
+ fstrcat(job.jobname, " ");
+ }
+ }
+
+ if (!(pw = getpwuid(getuid()))) {
+ return 1;
+ }
+
+ fstrcpy(job.owner, pw->pw_name);
+
+ job.jobid = next_jobnum(printer);
+ job.size = 666;
+ job.submit_time = time(NULL);
+
+ /* Store job entry in queue */
+
+ slprintf(keystr, sizeof(keystr) - 1, "LPQ/%s", printer);
+
+ value = tdb_fetch_by_string(tdb, keystr);
+
+ if (value.dptr) {
+
+ /* Add job to end of queue */
+
+ value.dptr = realloc(value.dptr, value.dsize +
+ sizeof(struct vlp_job));
+ if (!value.dptr) return 1;
+
+ memcpy(value.dptr + value.dsize, &job, sizeof(struct vlp_job));
+
+ tdb_store_by_string(tdb, keystr, value.dptr, value.dsize +
+ sizeof(struct vlp_job));
+
+ free(value.dptr);
+
+ } else {
+
+ /* Create new queue */
+
+ tdb_store_by_string(tdb, keystr, &job, sizeof(struct vlp_job));
+ }
+
+ return 0;
+}
+
+/* Pause the queue */
+
+static int queuepause_command(int argc, char **argv)
+{
+ char *printer;
+
+ if (argc != 2) {
+ printf("Usage: queuepause <printername>\n");
+ return 1;
+ }
+
+ printer = argv[1];
+ set_printer_status(printer, LPSTAT_STOPPED);
+
+ return 0;
+}
+
+/* Resume the queue */
+
+static int queueresume_command(int argc, char **argv)
+{
+ char *printer;
+
+ if (argc != 2) {
+ printf("Usage: queueresume <printername>\n");
+ return 1;
+ }
+
+ printer = argv[1];
+ set_printer_status(printer, LPSTAT_OK);
+
+ return 0;
+}
+
+/* Pause a job */
+
+static int lppause_command(int argc, char **argv)
+{
+ struct vlp_job *job_list;
+ char *printer;
+ int jobid, num_jobs, i;
+
+ if (argc != 3) {
+ printf("Usage: lppause <printername> <jobid>\n");
+ return 1;
+ }
+
+ printer = argv[1];
+ jobid = atoi(argv[2]);
+
+ get_job_list(printer, &job_list, &num_jobs);
+
+ for (i = 0; i < num_jobs; i++) {
+ if (job_list[i].jobid == jobid) {
+ job_list[i].status = LPQ_PAUSED;
+ set_job_list(printer, job_list, num_jobs);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/* Resume a job */
+
+static int lpresume_command(int argc, char **argv)
+{
+ struct vlp_job *job_list;
+ char *printer;
+ int jobid, num_jobs, i;
+
+ if (argc != 3) {
+ printf("Usage: lpresume <printername> <jobid>\n");
+ return 1;
+ }
+
+ printer = argv[1];
+ jobid = atoi(argv[2]);
+
+ get_job_list(printer, &job_list, &num_jobs);
+
+ for (i = 0; i < num_jobs; i++) {
+ if (job_list[i].jobid == jobid) {
+ job_list[i].status = LPQ_QUEUED;
+ set_job_list(printer, job_list, num_jobs);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ /* Parameter check */
+
+ if (argc == 1) {
+ usage();
+ return 1;
+ }
+
+ /* Initialise */
+
+ if (!(tdb = tdb_open(PRINT_TDB, 0, 0, O_RDWR | O_CREAT,
+ 0666))) {
+ printf("%s: unable to open %s\n", argv[0], PRINT_TDB);
+ return 1;
+ }
+
+ /* Ensure we are modes 666 */
+
+ chmod(PRINT_TDB, 0666);
+
+ /* Do commands */
+
+ if (strcmp(argv[1], "lpq") == 0) {
+ return lpq_command(argc - 1, &argv[1]);
+ }
+
+ if (strcmp(argv[1], "lprm") == 0) {
+ return lprm_command(argc - 1, &argv[1]);
+ }
+
+ if (strcmp(argv[1], "print") == 0) {
+ return print_command(argc - 1, &argv[1]);
+ }
+
+ if (strcmp(argv[1], "queuepause") == 0) {
+ return queuepause_command(argc - 1, &argv[1]);
+ }
+
+ if (strcmp(argv[1], "queueresume") == 0) {
+ return queueresume_command(argc - 1, &argv[1]);
+ }
+
+ if (strcmp(argv[1], "lppause") == 0) {
+ return lppause_command(argc - 1, &argv[1]);
+ }
+
+ if (strcmp(argv[1], "lpresume") == 0) {
+ return lpresume_command(argc - 1, &argv[1]);
+ }
+
+ /* Unknown command */
+
+ printf("%s: invalid command %s\n", argv[0], argv[1]);
+ return 1;
+}