summaryrefslogtreecommitdiffstats
path: root/usr.sbin/lpr
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/lpr')
-rw-r--r--usr.sbin/lpr/lpc/cmds.c121
-rw-r--r--usr.sbin/lpr/lpc/cmdtab.c7
-rw-r--r--usr.sbin/lpr/lpc/extern.h4
-rw-r--r--usr.sbin/lpr/lpc/lpc.819
-rw-r--r--usr.sbin/lpr/lpc/lpc.c12
-rw-r--r--usr.sbin/lpr/lpc/lpc.h5
6 files changed, 140 insertions, 28 deletions
diff --git a/usr.sbin/lpr/lpc/cmds.c b/usr.sbin/lpr/lpc/cmds.c
index c87915c..8ab39b0 100644
--- a/usr.sbin/lpr/lpc/cmds.c
+++ b/usr.sbin/lpr/lpc/cmds.c
@@ -79,6 +79,7 @@ static const char rcsid[] =
#define KQT_KILLOK 1
static void abortpr(struct printer *_pp, int _dis);
+static char *args2line(int argc, char **argv);
static int doarg(char *_job);
static int doselect(struct dirent *_d);
static int kill_qtask(const char *lf);
@@ -87,7 +88,7 @@ static int sortq(const void *_a, const void *_b);
static void startpr(struct printer *_pp, int _chgenable);
static int touch(struct jobqueue *_jq);
static void unlinkf(char *_name);
-static void upstat(struct printer *_pp, const char *_msg);
+static void upstat(struct printer *_pp, const char *_msg, int _notify);
static void wrapup_clean(int _laststatus);
/*
@@ -103,11 +104,12 @@ enum qsel_val { /* how a given ptr was selected */
static enum qsel_val generic_qselect; /* indicates how ptr was selected */
static int generic_initerr; /* result of initrtn processing */
+static char *generic_msg; /* if a -msg was specified */
static char *generic_nullarg;
static void (*generic_wrapup)(int _last_status); /* perform rtn wrap-up */
void
-generic(void (*specificrtn)(struct printer *_pp),
+generic(void (*specificrtn)(struct printer *_pp), int cmdopts,
void (*initrtn)(int _argc, char *_argv[]), int argc, char *argv[])
{
int cmdstatus, more, targc;
@@ -115,7 +117,10 @@ generic(void (*specificrtn)(struct printer *_pp),
char **targv;
if (argc == 1) {
- printf("usage: %s {all | printer ...}\n", argv[0]);
+ printf("usage: %s {all | printer ...}", argv[0]);
+ if (cmdopts & LPC_MSGOPT)
+ printf(" [-msg <text> ...]");
+ printf("\n");
return;
}
@@ -136,6 +141,24 @@ generic(void (*specificrtn)(struct printer *_pp),
if (generic_nullarg == NULL)
generic_nullarg = strdup("");
+ /*
+ * Some commands accept a -msg argument, which indicates that
+ * all remaining arguments should be combined into a string.
+ */
+ generic_msg = NULL;
+ if (cmdopts & LPC_MSGOPT) {
+ targc = argc;
+ targv = argv;
+ while (--targc) {
+ ++targv;
+ if (strcmp(*targv, "-msg") == 0) {
+ argc -= targc;
+ generic_msg = args2line(targc - 1, targv + 1);
+ break;
+ }
+ }
+ }
+
/* call initialization routine, if there is one for this cmd */
if (initrtn != NULL) {
generic_initerr = 0;
@@ -209,7 +232,34 @@ wrapup:
if (generic_wrapup) {
(*generic_wrapup)(cmdstatus);
}
+ if (generic_msg)
+ free(generic_msg);
+}
+/*
+ * Convert an argv-array of character strings into a single string.
+ */
+static char *
+args2line(int argc, char **argv)
+{
+ char *cp1, *cend;
+ const char *cp2;
+ char buf[1024];
+
+ if (argc <= 0)
+ return strdup("\n");
+
+ cp1 = buf;
+ cend = buf + sizeof(buf) - 1; /* save room for '\0' */
+ while (--argc >= 0) {
+ cp2 = *argv++;
+ while ((cp1 < cend) && (*cp1++ = *cp2++))
+ ;
+ cp1[-1] = ' ';
+ }
+ cp1[-1] = '\n';
+ *cp1 = '\0';
+ return strdup(buf);
}
/*
@@ -242,7 +292,10 @@ abortpr(struct printer *pp, int dis)
printf("\tcannot disable printing: %s\n",
strerror(errno));
else {
- upstat(pp, "printing disabled\n");
+ /* ..call newer upstat() in obsolete code.. */
+ upstat(pp, "printing disabled\n", 0);
+ /* ..the new upstat() did a setuid(uid).. */
+ seteuid(euid);
printf("\tprinting disabled\n");
}
} else if (errno == ENOENT) {
@@ -252,7 +305,10 @@ abortpr(struct printer *pp, int dis)
strerror(errno));
else {
(void) close(fd);
- upstat(pp, "printing disabled\n");
+ /* ..call newer upstat() in obsolete code.. */
+ upstat(pp, "printing disabled\n", 0);
+ /* ..the new upstat() did a setuid(uid).. */
+ seteuid(euid);
printf("\tprinting disabled\n");
printf("\tno daemon to abort\n");
}
@@ -377,14 +433,16 @@ killdone:
* Write a message into the status file.
*/
static void
-upstat(struct printer *pp, const char *msg)
+upstat(struct printer *pp, const char *msg, int notifyuser)
{
- register int fd;
+ int fd;
char statfile[MAXPATHLEN];
status_file_name(pp, statfile, sizeof statfile);
umask(0);
+ seteuid(euid);
fd = open(statfile, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE);
+ seteuid(uid);
if (fd < 0) {
printf("\tcannot create status file: %s\n", strerror(errno));
return;
@@ -395,6 +453,12 @@ upstat(struct printer *pp, const char *msg)
else
(void) write(fd, msg, strlen(msg));
(void) close(fd);
+ if (notifyuser) {
+ if ((msg == (char *)NULL) || (strcmp(msg, "\n") == 0))
+ printf("\tstatus message is now set to nothing.\n");
+ else
+ printf("\tstatus message is now: %s", msg);
+ }
}
/*
@@ -442,11 +506,8 @@ abort_q(struct printer *pp)
break;
}
- if (setres >= 0) {
- seteuid(euid);
- upstat(pp, "printing disabled\n");
- seteuid(uid);
- }
+ if (setres >= 0)
+ upstat(pp, "printing disabled\n", 0);
}
/*
@@ -1133,6 +1194,31 @@ restart_q(struct printer *pp)
}
/*
+ * Set the status message of each queue listed. Requires a "-msg"
+ * parameter to indicate the end of the queue list and start of msg text.
+ */
+void
+setstatus_gi(int argc __unused, char *argv[] __unused)
+{
+
+ if (generic_msg == NULL) {
+ printf("You must specify '-msg' before the text of the new status message.\n");
+ generic_initerr = 1;
+ }
+}
+
+void
+setstatus_q(struct printer *pp)
+{
+ char lf[MAXPATHLEN];
+
+ lock_file_name(pp, lf, sizeof lf);
+ printf("%s:\n", pp->printer);
+
+ upstat(pp, generic_msg, 1);
+}
+
+/*
* Enable printing on the specified printer and startup the daemon.
*/
void
@@ -1279,7 +1365,7 @@ stop(struct printer *pp)
printf("\tcannot disable printing: %s\n",
strerror(errno));
else {
- upstat(pp, "printing disabled\n");
+ upstat(pp, "printing disabled\n", 0);
printf("\tprinting disabled\n");
}
} else if (errno == ENOENT) {
@@ -1289,7 +1375,7 @@ stop(struct printer *pp)
strerror(errno));
else {
(void) close(fd);
- upstat(pp, "printing disabled\n");
+ upstat(pp, "printing disabled\n", 0);
printf("\tprinting disabled\n");
}
} else
@@ -1312,11 +1398,8 @@ stop_q(struct printer *pp)
setres = set_qstate(SQS_STOPP, lf);
- if (setres >= 0) {
- seteuid(euid);
- upstat(pp, "printing disabled\n");
- seteuid(uid);
- }
+ if (setres >= 0)
+ upstat(pp, "printing disabled\n", 0);
}
struct jobqueue **queue;
diff --git a/usr.sbin/lpr/lpc/cmdtab.c b/usr.sbin/lpr/lpc/cmdtab.c
index acae213..570c5fb 100644
--- a/usr.sbin/lpr/lpc/cmdtab.c
+++ b/usr.sbin/lpr/lpc/cmdtab.c
@@ -55,6 +55,8 @@ char downhelp[] = "do a 'stop' followed by 'disable' and put a message in status
char helphelp[] = "get help on commands";
char quithelp[] = "exit lpc";
char restarthelp[] = "kill (if possible) and restart a spooling daemon";
+char setstatushelp[] = "set the status message of a queue, requires\n"
+ "\t\t\"-msg\" before the text of the new message";
char starthelp[] = "enable printing and start a spooling daemon";
char statushelp[] = "show status of daemon and queue";
char stophelp[] = "stop a spooling daemon after current job completes and disable printing";
@@ -62,7 +64,9 @@ char tcleanhelp[] = "test to see what files a clean cmd would remove";
char topqhelp[] = "put job at top of printer queue";
char uphelp[] = "enable everything and restart spooling daemon";
-#define PR 1 /* a privileged command */
+/* Use some abbreviations so entries won't need to wrap */
+#define PR LPC_PRIVCMD
+#define M LPC_MSGOPT
struct cmd cmdtab[] = {
{ "abort", aborthelp, PR, 0, abort_q },
@@ -76,6 +80,7 @@ struct cmd cmdtab[] = {
{ "restart", restarthelp, 0, 0, restart_q },
{ "start", starthelp, PR, 0, start_q },
{ "status", statushelp, 0, 0, status },
+ { "setstatus", setstatushelp, PR|M, setstatus_gi, setstatus_q },
{ "stop", stophelp, PR, 0, stop_q },
{ "tclean", tcleanhelp, 0, init_tclean, clean_q },
{ "topq", topqhelp, PR, topq, 0 },
diff --git a/usr.sbin/lpr/lpc/extern.h b/usr.sbin/lpr/lpc/extern.h
index dc9fe9d..211f115 100644
--- a/usr.sbin/lpr/lpc/extern.h
+++ b/usr.sbin/lpr/lpc/extern.h
@@ -47,7 +47,7 @@ void clean_q(struct printer *_pp);
void disable_q(struct printer *_pp);
void down(int _argc, char *_argv[]);
void enable_q(struct printer *_pp);
-void generic(void (*_specificrtn)(struct printer *_pp),
+void generic(void (*_specificrtn)(struct printer *_pp), int _cmdopts,
void (*_initcmd)(int _argc, char *_argv[]),
int _argc, char *_argv[]);
void help(int _argc, char *_argv[]);
@@ -55,6 +55,8 @@ void init_clean(int _argc, char *_argv[]);
void init_tclean(int _argc, char *_argv[]);
void quit(int _argc, char *_argv[]);
void restart_q(struct printer *_pp);
+void setstatus_gi(int _argc, char *_argv[]);
+void setstatus_q(struct printer *_pp);
void start_q(struct printer *_pp);
void status(struct printer *_pp);
void stop_q(struct printer *_pp);
diff --git a/usr.sbin/lpr/lpc/lpc.8 b/usr.sbin/lpr/lpc/lpc.8
index d993a83..039a4a2 100644
--- a/usr.sbin/lpr/lpc/lpc.8
+++ b/usr.sbin/lpr/lpc/lpc.8
@@ -32,7 +32,7 @@
.\" @(#)lpc.8 8.5 (Berkeley) 4/28/95
.\" $FreeBSD$
.\"
-.Dd June 20, 2001
+.Dd June 15, 2002
.Dt LPC 8
.Os
.Sh NAME
@@ -58,7 +58,11 @@ disable or enable a printer's spooling queue,
rearrange the order of jobs in a spooling queue,
.It
find the status of printers, and their associated
-spooling queues and printer daemons.
+spooling queues and printer daemons,
+.It
+change the status message for printer queues (the status message
+may be seen by users as part of the output of the
+.Xr lpq 1 utility).
.El
.Pp
Without any arguments,
@@ -139,6 +143,17 @@ will report that there is no daemon present when this condition occurs.
If the user is the super-user,
try to abort the current daemon first (i.e., kill and restart a stuck daemon).
.Pp
+.It Ic setstatus Bro Cm all | Ar printer Brc Cm -msg Ar message ...
+Set the status message for the specified printers.
+The
+.Ic -msg
+argument is required to separate the list of printers from the text
+that will be the new status message.
+This is normally used to change the status message when the printer
+queue is no longer active after printing has been disabled, and you
+want to change what users will see in the output of the
+.Xr lpq 1 utility.
+.Pp
.It Ic start Brq Cm all | Ar printer
Enable printing and start a spooling daemon for the listed printers.
.Pp
diff --git a/usr.sbin/lpr/lpc/lpc.c b/usr.sbin/lpr/lpc/lpc.c
index 457ad70..357e4ad 100644
--- a/usr.sbin/lpr/lpc/lpc.c
+++ b/usr.sbin/lpr/lpc/lpc.c
@@ -110,12 +110,14 @@ main(int argc, char *argv[])
printf("?Invalid command\n");
exit(1);
}
- if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) {
+ if ((c->c_opts & LPC_PRIVCMD) && getuid() &&
+ ingroup(LPR_OPER) == 0) {
printf("?Privileged command\n");
exit(1);
}
if (c->c_generic != 0)
- generic(c->c_generic, c->c_handler, argc, argv);
+ generic(c->c_generic, c->c_opts, c->c_handler,
+ argc, argv);
else
(*c->c_handler)(argc, argv);
exit(0);
@@ -210,7 +212,8 @@ cmdscanner(void)
printf("?Invalid command\n");
continue;
}
- if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) {
+ if ((c->c_opts & LPC_PRIVCMD) && getuid() &&
+ ingroup(LPR_OPER) == 0) {
printf("?Privileged command\n");
continue;
}
@@ -223,7 +226,8 @@ cmdscanner(void)
* initial parameter processing.
*/
if (c->c_generic != 0)
- generic(c->c_generic, c->c_handler, margc, margv);
+ generic(c->c_generic, c->c_opts, c->c_handler,
+ margc, margv);
else
(*c->c_handler)(margc, margv);
}
diff --git a/usr.sbin/lpr/lpc/lpc.h b/usr.sbin/lpr/lpc/lpc.h
index 9511c24..73e4cc5 100644
--- a/usr.sbin/lpr/lpc/lpc.h
+++ b/usr.sbin/lpr/lpc/lpc.h
@@ -40,10 +40,13 @@
*/
struct printer;
+#define LPC_PRIVCMD 0x0001 /* a privileged command */
+#define LPC_MSGOPT 0x0002 /* command recognizes -msg option */
+
struct cmd {
const char *c_name; /* command name */
const char *c_help; /* help message */
- const int c_priv; /* privileged command */
+ const int c_opts; /* flags (eg: privileged command) */
/* routine to do all the work for plain cmds, or
* initialization work for generic-printer cmds: */
void (*c_handler)(int, char *[]);
OpenPOWER on IntegriCloud