1 /* $OpenBSD: engine.c,v 1.2 2018/09/05 17:32:56 eric Exp $ */ 2 3 /* 4 * Copyright (c) 2017 Eric Faurot <eric@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <pwd.h> 20 #include <stdlib.h> 21 #include <signal.h> 22 #include <syslog.h> 23 #include <unistd.h> 24 25 #include "lpd.h" 26 #include "lp.h" 27 28 #include "log.h" 29 #include "proc.h" 30 31 static void engine_shutdown(void); 32 static void engine_dispatch_priv(struct imsgproc *, struct imsg *, void *); 33 static void engine_dispatch_frontend(struct imsgproc *, struct imsg *, void *); 34 35 char *lpd_hostname; 36 37 void 38 engine(int debug, int verbose) 39 { 40 struct passwd *pw; 41 42 /* Early initialisation. */ 43 log_init(debug, LOG_LPR); 44 log_setverbose(verbose); 45 log_procinit("engine"); 46 setproctitle("engine"); 47 48 if ((lpd_hostname = malloc(HOST_NAME_MAX+1)) == NULL) 49 fatal("%s: malloc", __func__); 50 gethostname(lpd_hostname, HOST_NAME_MAX + 1); 51 52 /* Drop priviledges. */ 53 if ((pw = getpwnam(LPD_USER)) == NULL) 54 fatal("%s: getpwnam: %s", __func__, LPD_USER); 55 56 if (setgroups(1, &pw->pw_gid) || 57 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 58 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 59 fatal("%s: cannot drop privileges", __func__); 60 61 /* We need proc for kill(2) in lp_getcurrtask(). */ 62 if (pledge("stdio rpath wpath cpath flock dns sendfd recvfd proc", 63 NULL) == -1) 64 fatal("%s: pledge", __func__); 65 66 event_init(); 67 68 signal(SIGPIPE, SIG_IGN); 69 70 /* Setup parent imsg socket. */ 71 p_priv = proc_attach(PROC_PRIV, 3); 72 if (p_priv == NULL) 73 fatal("%s: proc_attach", __func__); 74 proc_setcallback(p_priv, engine_dispatch_priv, NULL); 75 proc_enable(p_priv); 76 77 event_dispatch(); 78 79 engine_shutdown(); 80 } 81 82 static void 83 engine_shutdown() 84 { 85 lpr_shutdown(); 86 87 log_debug("exiting"); 88 89 exit(0); 90 } 91 92 static void 93 engine_dispatch_priv(struct imsgproc *proc, struct imsg *imsg, void *arg) 94 { 95 struct lp_printer lp; 96 97 if (imsg == NULL) { 98 log_debug("%s: imsg connection lost", __func__); 99 event_loopexit(NULL); 100 return; 101 } 102 103 if (log_getverbose() > LOGLEVEL_IMSG) 104 log_imsg(proc, imsg); 105 106 switch (imsg->hdr.type) { 107 case IMSG_SOCK_FRONTEND: 108 m_end(proc); 109 110 if (imsg->fd == -1) 111 fatalx("failed to receive frontend socket"); 112 113 p_frontend = proc_attach(PROC_FRONTEND, imsg->fd); 114 proc_setcallback(p_frontend, engine_dispatch_frontend, NULL); 115 proc_enable(p_frontend); 116 break; 117 118 case IMSG_CONF_START: 119 m_end(proc); 120 break; 121 122 case IMSG_CONF_END: 123 m_end(proc); 124 125 /* Fork a printer process for every queue. */ 126 while (lp_scanprinters(&lp) == 1) { 127 lpr_printjob(lp.lp_name); 128 lp_clearprinter(&lp); 129 } 130 break; 131 132 default: 133 fatalx("%s: unexpected imsg %s", __func__, 134 log_fmt_imsgtype(imsg->hdr.type)); 135 } 136 } 137 138 static void 139 engine_dispatch_frontend(struct imsgproc *proc, struct imsg *imsg, void *arg) 140 { 141 if (imsg == NULL) { 142 log_debug("%s: imsg connection lost", __func__); 143 event_loopexit(NULL); 144 return; 145 } 146 147 if (log_getverbose() > LOGLEVEL_IMSG) 148 log_imsg(proc, imsg); 149 150 switch (imsg->hdr.type) { 151 case IMSG_GETADDRINFO: 152 case IMSG_GETNAMEINFO: 153 resolver_dispatch_request(proc, imsg); 154 break; 155 156 case IMSG_LPR_ALLOWEDHOST: 157 case IMSG_LPR_DISPLAYQ: 158 case IMSG_LPR_PRINTJOB: 159 case IMSG_LPR_RECVJOB: 160 case IMSG_LPR_RECVJOB_CLEAR: 161 case IMSG_LPR_RECVJOB_CF: 162 case IMSG_LPR_RECVJOB_DF: 163 case IMSG_LPR_RECVJOB_COMMIT: 164 case IMSG_LPR_RECVJOB_ROLLBACK: 165 case IMSG_LPR_RMJOB: 166 lpr_dispatch_frontend(proc, imsg); 167 break; 168 169 default: 170 fatalx("%s: unexpected imsg %s", __func__, 171 log_fmt_imsgtype(imsg->hdr.type)); 172 } 173 } 174