1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * efdaemon - Emebbed Fcode Interpreter daemon.
31 *
32 * Opens /dev/fcode, detaches from tty and reads a request. Upon successful
33 * return, invokes the Fcode interpreter via the shell script:
34 * /usr/lib/efcode/efcode.sh Waits for completion of the interpreter.
35 */
36
37 #include <stdio.h>
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <stdlib.h>
41 #include <strings.h>
42 #include <syslog.h>
43 #include <errno.h>
44 #include <sys/wait.h>
45 #include <sys/fcode.h>
46
47 char efcode_sh_file[] = "/usr/lib/efcode/efcode.sh";
48 char dev_fcode_file[] = "/dev/fcode";
49
50 int debug = 0;
51
52 int
main(int argc,char ** argv)53 main(int argc, char **argv)
54 {
55 extern char *optarg;
56 extern int optind, opterr, optopt;
57 int c, fd, nbytes, status;
58 char tc;
59 pid_t pid, tpid;
60 long nerr = 0;
61 int error;
62
63 openlog("efdaemon", LOG_PID|LOG_CONS, LOG_DAEMON);
64
65 while ((c = getopt(argc, argv, "d")) != EOF) {
66 switch (c) {
67
68 case 'd':
69 debug++;
70 break;
71
72 case '?':
73 syslog(LOG_ERR, "Usage: efdaemon [ -d ]\n");
74 exit(1);
75 }
76 }
77
78 /*
79 * Ensure we can open /dev/fcode
80 */
81 if ((fd = open(dev_fcode_file, O_RDONLY)) < 0) {
82 /*
83 * Only output message if debug is on. On most systems,
84 * /dev/fcode will not exist, so this message would pollute the
85 * console.
86 */
87 if (debug)
88 syslog(LOG_ERR, "Can't open %s: %s\n", dev_fcode_file,
89 strerror(errno));
90 exit(1);
91 }
92 close(fd);
93
94 /*
95 * Ensure that /usr/lib/efcode/efcode.sh exists and is executable.
96 */
97 if (access(efcode_sh_file, X_OK | R_OK)) {
98 syslog(LOG_ERR, "%s: %s\n", efcode_sh_file, strerror(errno));
99 exit(1);
100 }
101
102 /*
103 * Fork a child then parent exits so we're a child of initd.
104 */
105 if ((pid = fork()) < 0) {
106 syslog(LOG_ERR, "Fork failed: %s\n", strerror(errno));
107 exit(1);
108 }
109 if (pid)
110 exit(0);
111
112
113 /*
114 * detach from tty here.
115 */
116 setpgrp();
117 close(0);
118 close(1);
119 close(2);
120 (void) open("/dev/null", O_RDWR);
121 (void) dup(0);
122 (void) dup(0);
123
124 for (;;) {
125 while ((fd = open(dev_fcode_file, O_RDONLY)) < 0) {
126 nerr++;
127 if (nerr == 1)
128 syslog(LOG_ERR, "Can't open %s: %s\n",
129 dev_fcode_file, strerror(errno));
130 sleep(1);
131 }
132 if (nerr > 1) {
133 syslog(LOG_ERR, "Open on %s failed %d times\n",
134 dev_fcode_file, nerr);
135 }
136 nerr = 0;
137 nbytes = read(fd, &tc, sizeof (tc));
138 if (nbytes < 0) {
139 syslog(LOG_ERR, "Read of %s: %s\n", dev_fcode_file,
140 strerror(errno));
141 close(fd);
142 continue;
143 }
144 if (debug)
145 syslog(LOG_DEBUG, "Got request\n");
146 while ((pid = fork()) < 0) {
147 nerr++;
148 if (nerr == 1)
149 syslog(LOG_ERR, "Fork failed: %s\n",
150 strerror(errno));
151 sleep(1);
152 }
153 if ((nerr > 1) && pid) {
154 syslog(LOG_ERR, "Fork failed %d times\n", nerr);
155 }
156 nerr = 0;
157 if (pid) {
158 tpid = wait(&status);
159 if (tpid < 0)
160 syslog(LOG_ERR, "Wait error: %s\n",
161 strerror(errno));
162 else if (pid != tpid)
163 syslog(LOG_ERR, "Wait error, expect pid: %d"
164 " got %d, status: %x\n", pid, tpid, status);
165 else if (status) {
166 syslog(LOG_ERR, "Wait pid: %d status: %x\n",
167 pid, status);
168 if (WIFEXITED(status) &&
169 (WEXITSTATUS(status) == 1)) {
170 error = FC_FCODE_ABORT;
171 } else {
172 error = FC_EXEC_FAILED;
173 }
174 if (ioctl(fd, FC_SET_FCODE_ERROR, &error) < 0) {
175 syslog(LOG_ERR,
176 "ioctl(FC_SET_FCODE_ERROR)"
177 " failed\n");
178 }
179 } else if (debug)
180 syslog(LOG_DEBUG, "Wait: pid: %d\n", pid);
181 close(fd);
182 continue;
183 }
184 if (debug)
185 syslog(LOG_DEBUG, "Child: %d processing request\n",
186 getpid());
187 fcntl(fd, F_DUP2FD, 0);
188 while (execl("/bin/sh", "sh", efcode_sh_file, NULL)) {
189 nerr++;
190 if (nerr == 1)
191 syslog(LOG_ERR, "execl(/bin/sh) failed: %s\n",
192 strerror(errno));
193 sleep(1);
194 }
195 }
196
197 return (0);
198 }
199