xref: /openbsd-src/usr.sbin/lpd/engine.c (revision af27b3cce1070d60f0e791a83d790160efdc2be8)
1*af27b3ccSclaudio /*	$OpenBSD: engine.c,v 1.4 2024/11/21 13:34:51 claudio Exp $	*/
23b188dabSeric 
33b188dabSeric /*
43b188dabSeric  * Copyright (c) 2017 Eric Faurot <eric@openbsd.org>
53b188dabSeric  *
63b188dabSeric  * Permission to use, copy, modify, and distribute this software for any
73b188dabSeric  * purpose with or without fee is hereby granted, provided that the above
83b188dabSeric  * copyright notice and this permission notice appear in all copies.
93b188dabSeric  *
103b188dabSeric  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
113b188dabSeric  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
123b188dabSeric  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
133b188dabSeric  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
143b188dabSeric  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
153b188dabSeric  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
163b188dabSeric  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
173b188dabSeric  */
183b188dabSeric 
193b188dabSeric #include <pwd.h>
203b188dabSeric #include <stdlib.h>
213b188dabSeric #include <signal.h>
223b188dabSeric #include <syslog.h>
233b188dabSeric #include <unistd.h>
243b188dabSeric 
253b188dabSeric #include "lpd.h"
263b188dabSeric #include "lp.h"
273b188dabSeric 
283b188dabSeric #include "log.h"
293b188dabSeric #include "proc.h"
303b188dabSeric 
313b188dabSeric static void engine_shutdown(void);
323b188dabSeric static void engine_dispatch_priv(struct imsgproc *, struct imsg *, void *);
333b188dabSeric static void engine_dispatch_frontend(struct imsgproc *, struct imsg *, void *);
343b188dabSeric 
353b188dabSeric char *lpd_hostname;
363b188dabSeric 
373b188dabSeric void
383b188dabSeric engine(int debug, int verbose)
393b188dabSeric {
403b188dabSeric 	struct passwd *pw;
413b188dabSeric 
423b188dabSeric 	/* Early initialisation. */
433b188dabSeric 	log_init(debug, LOG_LPR);
443b188dabSeric 	log_setverbose(verbose);
453b188dabSeric 	log_procinit("engine");
463b188dabSeric 	setproctitle("engine");
473b188dabSeric 
483b188dabSeric 	if ((lpd_hostname = malloc(HOST_NAME_MAX+1)) == NULL)
493b188dabSeric 		fatal("%s: malloc", __func__);
503b188dabSeric 	gethostname(lpd_hostname, HOST_NAME_MAX + 1);
513b188dabSeric 
523a50f0a9Sjmc 	/* Drop privileges. */
533b188dabSeric 	if ((pw = getpwnam(LPD_USER)) == NULL)
543b188dabSeric 		fatal("%s: getpwnam: %s", __func__, LPD_USER);
553b188dabSeric 
563b188dabSeric 	if (setgroups(1, &pw->pw_gid) ||
573b188dabSeric 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
583b188dabSeric 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
593b188dabSeric 		fatal("%s: cannot drop privileges", __func__);
603b188dabSeric 
613b188dabSeric 	/* We need proc for kill(2) in lp_getcurrtask(). */
623b188dabSeric 	if (pledge("stdio rpath wpath cpath flock dns sendfd recvfd proc",
633b188dabSeric 	    NULL) == -1)
643b188dabSeric 		fatal("%s: pledge", __func__);
653b188dabSeric 
663b188dabSeric 	event_init();
673b188dabSeric 
683b188dabSeric 	signal(SIGPIPE, SIG_IGN);
693b188dabSeric 
703b188dabSeric 	/* Setup parent imsg socket. */
713b188dabSeric 	p_priv = proc_attach(PROC_PRIV, 3);
723b188dabSeric 	if (p_priv == NULL)
733b188dabSeric 		fatal("%s: proc_attach", __func__);
743b188dabSeric 	proc_setcallback(p_priv, engine_dispatch_priv, NULL);
753b188dabSeric 	proc_enable(p_priv);
763b188dabSeric 
773b188dabSeric 	event_dispatch();
783b188dabSeric 
793b188dabSeric 	engine_shutdown();
803b188dabSeric }
813b188dabSeric 
823b188dabSeric static void
833b188dabSeric engine_shutdown()
843b188dabSeric {
853b188dabSeric 	lpr_shutdown();
863b188dabSeric 
873b188dabSeric 	log_debug("exiting");
883b188dabSeric 
893b188dabSeric 	exit(0);
903b188dabSeric }
913b188dabSeric 
923b188dabSeric static void
933b188dabSeric engine_dispatch_priv(struct imsgproc *proc, struct imsg *imsg, void *arg)
943b188dabSeric {
953b188dabSeric 	struct lp_printer lp;
96*af27b3ccSclaudio 	int fd;
973b188dabSeric 
983b188dabSeric 	if (imsg == NULL) {
993b188dabSeric 		log_debug("%s: imsg connection lost", __func__);
1003b188dabSeric 		event_loopexit(NULL);
1013b188dabSeric 		return;
1023b188dabSeric 	}
1033b188dabSeric 
1043b188dabSeric 	if (log_getverbose() > LOGLEVEL_IMSG)
1053b188dabSeric 		log_imsg(proc, imsg);
1063b188dabSeric 
1073b188dabSeric 	switch (imsg->hdr.type) {
1083b188dabSeric 	case IMSG_SOCK_FRONTEND:
1093b188dabSeric 		m_end(proc);
1103b188dabSeric 
111*af27b3ccSclaudio 		if ((fd = imsg_get_fd(imsg)) == -1)
1123b188dabSeric 			fatalx("failed to receive frontend socket");
1133b188dabSeric 
114*af27b3ccSclaudio 		p_frontend = proc_attach(PROC_FRONTEND, fd);
1153b188dabSeric 		proc_setcallback(p_frontend, engine_dispatch_frontend, NULL);
1163b188dabSeric 		proc_enable(p_frontend);
1173b188dabSeric 		break;
1183b188dabSeric 
1193b188dabSeric 	case IMSG_CONF_START:
1203b188dabSeric 		m_end(proc);
1213b188dabSeric 		break;
1223b188dabSeric 
1233b188dabSeric 	case IMSG_CONF_END:
1243b188dabSeric 		m_end(proc);
1253b188dabSeric 
1263b188dabSeric 		/* Fork a printer process for every queue. */
1273b188dabSeric 		while (lp_scanprinters(&lp) == 1) {
1283b188dabSeric 			lpr_printjob(lp.lp_name);
1293b188dabSeric 			lp_clearprinter(&lp);
1303b188dabSeric 		}
1313b188dabSeric 		break;
1323b188dabSeric 
1333b188dabSeric 	default:
1343b188dabSeric 		fatalx("%s: unexpected imsg %s", __func__,
1353b188dabSeric 		    log_fmt_imsgtype(imsg->hdr.type));
1363b188dabSeric 	}
1373b188dabSeric }
1383b188dabSeric 
1393b188dabSeric static void
1403b188dabSeric engine_dispatch_frontend(struct imsgproc *proc, struct imsg *imsg, void *arg)
1413b188dabSeric {
1423b188dabSeric 	if (imsg == NULL) {
1433b188dabSeric 		log_debug("%s: imsg connection lost", __func__);
1443b188dabSeric 		event_loopexit(NULL);
1453b188dabSeric 		return;
1463b188dabSeric 	}
1473b188dabSeric 
1483b188dabSeric 	if (log_getverbose() > LOGLEVEL_IMSG)
1493b188dabSeric 		log_imsg(proc, imsg);
1503b188dabSeric 
1513b188dabSeric 	switch (imsg->hdr.type) {
152db7b06acSeric 	case IMSG_GETADDRINFO:
153db7b06acSeric 	case IMSG_GETNAMEINFO:
1543b188dabSeric 		resolver_dispatch_request(proc, imsg);
1553b188dabSeric 		break;
1563b188dabSeric 
1573b188dabSeric 	case IMSG_LPR_ALLOWEDHOST:
1583b188dabSeric 	case IMSG_LPR_DISPLAYQ:
1593b188dabSeric 	case IMSG_LPR_PRINTJOB:
1603b188dabSeric 	case IMSG_LPR_RECVJOB:
1613b188dabSeric 	case IMSG_LPR_RECVJOB_CLEAR:
1623b188dabSeric 	case IMSG_LPR_RECVJOB_CF:
1633b188dabSeric 	case IMSG_LPR_RECVJOB_DF:
1643b188dabSeric 	case IMSG_LPR_RECVJOB_COMMIT:
1653b188dabSeric 	case IMSG_LPR_RECVJOB_ROLLBACK:
1663b188dabSeric 	case IMSG_LPR_RMJOB:
1673b188dabSeric 		lpr_dispatch_frontend(proc, imsg);
1683b188dabSeric 		break;
1693b188dabSeric 
1703b188dabSeric 	default:
1713b188dabSeric 		fatalx("%s: unexpected imsg %s", __func__,
1723b188dabSeric 		    log_fmt_imsgtype(imsg->hdr.type));
1733b188dabSeric 	}
1743b188dabSeric }
175