summaryrefslogtreecommitdiffstats
path: root/usr.sbin/lpr/common_source
diff options
context:
space:
mode:
authorgad <gad@FreeBSD.org>2002-06-13 01:55:48 +0000
committergad <gad@FreeBSD.org>2002-06-13 01:55:48 +0000
commit1c055fbea9cfb02ca0226882de37e40e7f2039af (patch)
tree62174a323cfa41c4a76460294d1ddeecd6d65475 /usr.sbin/lpr/common_source
parent514fa7d23f6019976043679704f14745fea8b8ef (diff)
downloadFreeBSD-src-1c055fbea9cfb02ca0226882de37e40e7f2039af.zip
FreeBSD-src-1c055fbea9cfb02ca0226882de37e40e7f2039af.tar.gz
Almost complete rewrite of the lpc commands 'abort', 'enable', 'disable',
'restart', 'start', 'stop' and 'up'. These are commands which mainly just alter the access bits on the lock-file of a queue, and they all now use a central routine to do that. This reduces the amount of code that is run as the priv userid, and eliminates a number of cases where error messages were written while that priv uid was in effect. As far as users are concerned, there should be no noticable difference in the new versions. In case there *is*, the previous implementations are still there as 'xabort', 'xenable', etc, so they are available for instant fallback. If no one reports a problem after a few weeks, then a later update will remove those x-commands. Reviewed by: freebsd-audit and freebsd-print@bostonradio.org MFC after: 10 days
Diffstat (limited to 'usr.sbin/lpr/common_source')
-rw-r--r--usr.sbin/lpr/common_source/common.c133
-rw-r--r--usr.sbin/lpr/common_source/lp.h18
2 files changed, 151 insertions, 0 deletions
diff --git a/usr.sbin/lpr/common_source/common.c b/usr.sbin/lpr/common_source/common.c
index a61bba3..d04e8f2 100644
--- a/usr.sbin/lpr/common_source/common.c
+++ b/usr.sbin/lpr/common_source/common.c
@@ -50,6 +50,7 @@ static const char rcsid[] =
#include <sys/types.h>
#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
@@ -252,6 +253,138 @@ status_file_name(const struct printer *pp, char *buf, size_t len)
return buf;
}
+/*
+ * Routine to change operational state of a print queue. The operational
+ ¥Êstate is indicated by the access bits on the lock file for the queue.
+ * At present, this is only called from various routines in lpc/cmds.c.
+ *
+ * XXX - Note that this works by changing access-bits on the
+ * file, and you can only do that if you are the owner of
+ * the file, or root. Thus, this won't really work for
+ * userids in the "LPR_OPER" group, unless lpc is running
+ * setuid to root (or maybe setuid to daemon).
+ * Generally lpc is installed setgid to daemon, but does
+ * not run setuid.
+ */
+int
+set_qstate(int action, const char *lfname)
+{
+ struct stat stbuf;
+ mode_t chgbits, newbits, oldmask;
+ const char *failmsg, *okmsg;
+ int chres, errsav, fd, res, statres;
+
+ /*
+ * Find what the current access-bits are.
+ */
+ memset(&stbuf, 0, sizeof(stbuf));
+ seteuid(euid);
+ statres = stat(lfname, &stbuf);
+ errsav = errno;
+ seteuid(uid);
+ if ((statres < 0) && (errsav != ENOENT)) {
+ printf("\tcannot stat() lock file\n");
+ return (SQS_STATFAIL);
+ /* NOTREACHED */
+ }
+
+ /*
+ * Determine which bit(s) should change for the requested action.
+ */
+ chgbits = stbuf.st_mode;
+ newbits = LOCK_FILE_MODE;
+ okmsg = NULL;
+ failmsg = NULL;
+ if (action & SQS_DISABLEQ) {
+ chgbits |= LFM_QUEUE_DIS;
+ newbits |= LFM_QUEUE_DIS;
+ okmsg = "queuing disabled";
+ failmsg = "disable queuing";
+ }
+ if (action & SQS_STOPP) {
+ chgbits |= LFM_PRINT_DIS;
+ newbits |= LFM_PRINT_DIS;
+ okmsg = "printing disabled";
+ failmsg = "disable printing";
+ if (action & SQS_DISABLEQ) {
+ okmsg = "printer and queuing disabled";
+ failmsg = "disable queuing and printing";
+ }
+ }
+ if (action & SQS_ENABLEQ) {
+ chgbits &= ~LFM_QUEUE_DIS;
+ newbits &= ~LFM_QUEUE_DIS;
+ okmsg = "queuing enabled";
+ failmsg = "enable queuing";
+ }
+ if (action & SQS_STARTP) {
+ chgbits &= ~LFM_PRINT_DIS;
+ newbits &= ~LFM_PRINT_DIS;
+ okmsg = "printing enabled";
+ failmsg = "enable printing";
+ }
+ if (okmsg == NULL) {
+ /* This routine was called with an invalid action. */
+ printf("\t<error in set_qstate!>\n");
+ return (SQS_PARMERR);
+ /* NOTREACHED */
+ }
+
+ res = 0;
+ if (statres >= 0) {
+ /* The file already exists, so change the access. */
+ seteuid(euid);
+ chres = chmod(lfname, chgbits);
+ errsav = errno;
+ seteuid(uid);
+ res = SQS_CHGOK;
+ if (res < 0)
+ res = SQS_CHGFAIL;
+ } else if (newbits == LOCK_FILE_MODE) {
+ /*
+ * The file does not exist, but the state requested is
+ * the same as the default state when no file exists.
+ * Thus, there is no need to create the file.
+ */
+ res = SQS_SKIPCREOK;
+ } else {
+ /*
+ * The file did not exist, so create it with the
+ * appropriate access bits for the requested action.
+ * Push a new umask around that create, to make sure
+ * all the read/write bits are set as desired.
+ */
+ oldmask = umask(S_IWOTH);
+ seteuid(euid);
+ fd = open(lfname, O_WRONLY|O_CREAT, newbits);
+ errsav = errno;
+ seteuid(uid);
+ umask(oldmask);
+ res = SQS_CREFAIL;
+ if (fd >= 0) {
+ res = SQS_CREOK;
+ close(fd);
+ }
+ }
+
+ switch (res) {
+ case SQS_CHGOK:
+ case SQS_CREOK:
+ case SQS_SKIPCREOK:
+ printf("\t%s\n", okmsg);
+ break;
+ case SQS_CREFAIL:
+ printf("\tcannot create lock file: %s\n",
+ strerror(errsav));
+ break;
+ default:
+ printf("\tcannot %s: %s\n", failmsg, strerror(errsav));
+ break;
+ }
+
+ return (res);
+}
+
/* routine to get a current timestamp, optionally in a standard-fmt string */
void
lpd_gettime(struct timespec *tsp, char *strp, size_t strsize)
diff --git a/usr.sbin/lpr/common_source/lp.h b/usr.sbin/lpr/common_source/lp.h
index 6faaf4d..81ac7ae 100644
--- a/usr.sbin/lpr/common_source/lp.h
+++ b/usr.sbin/lpr/common_source/lp.h
@@ -223,6 +223,23 @@ typedef enum { TR_SENDING, TR_RECVING, TR_PRINTING } tr_sendrecv;
#define TEMP_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
/*
+ * Bit-flags for set_qstate() actions, followed by the return values.
+ */
+#define SQS_DISABLEQ 0x01 /* Disable the queuing of new jobs */
+#define SQS_STOPP 0x02 /* Stop the printing of jobs */
+#define SQS_ENABLEQ 0x10 /* Enable the queuing of new jobs */
+#define SQS_STARTP 0x20 /* Start the printing of jobs */
+
+#define SQS_PARMERR -9 /* Invalid parameters from caller */
+#define SQS_CREFAIL -3 /* File did not exist, and create failed */
+#define SQS_CHGFAIL -2 /* File exists, but unable to change state */
+#define SQS_STATFAIL -1 /* Unable to stat() the lock file */
+#define SQS_CHGOK 1 /* File existed, and the state was changed */
+#define SQS_CREOK 2 /* File did not exist, but was created OK */
+#define SQS_SKIPCREOK 3 /* File did not exist, and there was */
+ /* no need to create it */
+
+/*
* Command codes used in the protocol.
*/
#define CMD_CHECK_QUE '\1'
@@ -272,6 +289,7 @@ void process(const struct printer *_pp, char *_file);
void rmjob(const char *_printer);
void rmremote(const struct printer *_pp);
void setprintcap(char *_newfile);
+int set_qstate(int _action, const char *_lfname);
void show(const char *_nfile, const char *_datafile, int _copies);
int startdaemon(const struct printer *_pp);
char *status_file_name(const struct printer *_pp, char *_buf,
OpenPOWER on IntegriCloud