Add a new command to 'lpc' called 'setstatus', which would be used to
change the status message of a print queue. This includes some minor changes to the upstat() routine, so that error messages are not printed while seteuid(priv-user). Reviewed by: freebsd-audit and freebsd-print@bostonradio.org MFC after: 10 days
This commit is contained in:
parent
4ce86ffd17
commit
54032d1198
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=98267
@ -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 @@ generic(void (*specificrtn)(struct printer *_pp),
|
||||
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 @@ kill_qtask(const char *lf)
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1132,6 +1193,31 @@ restart_q(struct printer *pp)
|
||||
printf("\tdaemon restarted\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@ -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;
|
||||
|
@ -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 },
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 *[]);
|
||||
|
Loading…
Reference in New Issue
Block a user