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