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 /*
28 * efdaemon - Emebbed Fcode Interpreter daemon.
29 *
30 * Opens /dev/fcode, detaches from tty and reads a request. Upon successful
31 * return, invokes the Fcode interpreter via the shell script:
32 * /usr/lib/efcode/efcode.sh Waits for completion of the interpreter.
33 */
34
35 #include <stdio.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <stdlib.h>
39 #include <strings.h>
40 #include <syslog.h>
41 #include <errno.h>
42 #include <sys/wait.h>
43 #include <sys/fcode.h>
44
45 char efcode_sh_file[] = "/usr/lib/efcode/efcode.sh";
46 char dev_fcode_file[] = "/dev/fcode";
47
48 int debug = 0;
49
50 int
main(int argc,char ** argv)51 main(int argc, char **argv)
52 {
53 extern char *optarg;
54 extern int optind, opterr, optopt;
55 int c, fd, nbytes, status;
56 char tc;
57 pid_t pid, tpid;
58 long nerr = 0;
59 int error;
60
61 openlog("efdaemon", LOG_PID|LOG_CONS, LOG_DAEMON);
62
63 while ((c = getopt(argc, argv, "d")) != EOF) {
64 switch (c) {
65
66 case 'd':
67 debug++;
68 break;
69
70 case '?':
71 syslog(LOG_ERR, "Usage: efdaemon [ -d ]\n");
72 exit(1);
73 }
74 }
75
76 /*
77 * Ensure we can open /dev/fcode
78 */
79 if ((fd = open(dev_fcode_file, O_RDONLY)) < 0) {
80 /*
81 * Only output message if debug is on. On most systems,
82 * /dev/fcode will not exist, so this message would pollute the
83 * console.
84 */
85 if (debug)
86 syslog(LOG_ERR, "Can't open %s: %s\n", dev_fcode_file,
87 strerror(errno));
88 exit(1);
89 }
90 (void) close(fd);
91
92 /*
93 * Ensure that /usr/lib/efcode/efcode.sh exists and is executable.
94 */
95 if (access(efcode_sh_file, X_OK | R_OK)) {
96 syslog(LOG_ERR, "%s: %s\n", efcode_sh_file, strerror(errno));
97 exit(1);
98 }
99
100 /*
101 * Fork a child then parent exits so we're a child of initd.
102 */
103 if ((pid = fork()) < 0) {
104 syslog(LOG_ERR, "Fork failed: %s\n", strerror(errno));
105 exit(1);
106 }
107 if (pid)
108 exit(0);
109
110
111 /*
112 * detach from tty here.
113 */
114 (void) setpgrp();
115 (void) close(0);
116 (void) close(1);
117 (void) close(2);
118 (void) open("/dev/null", O_RDWR);
119 (void) dup(0);
120 (void) dup(0);
121
122 for (;;) {
123 while ((fd = open(dev_fcode_file, O_RDONLY)) < 0) {
124 nerr++;
125 if (nerr == 1)
126 syslog(LOG_ERR, "Can't open %s: %s\n",
127 dev_fcode_file, strerror(errno));
128 (void) sleep(1);
129 }
130 if (nerr > 1) {
131 syslog(LOG_ERR, "Open on %s failed %d times\n",
132 dev_fcode_file, nerr);
133 }
134 nerr = 0;
135 nbytes = read(fd, &tc, sizeof (tc));
136 if (nbytes < 0) {
137 syslog(LOG_ERR, "Read of %s: %s\n", dev_fcode_file,
138 strerror(errno));
139 (void) close(fd);
140 continue;
141 }
142 if (debug)
143 syslog(LOG_DEBUG, "Got request\n");
144 while ((pid = fork()) < 0) {
145 nerr++;
146 if (nerr == 1)
147 syslog(LOG_ERR, "Fork failed: %s\n",
148 strerror(errno));
149 (void) sleep(1);
150 }
151 if ((nerr > 1) && pid) {
152 syslog(LOG_ERR, "Fork failed %d times\n", nerr);
153 }
154 nerr = 0;
155 if (pid) {
156 tpid = wait(&status);
157 if (tpid < 0)
158 syslog(LOG_ERR, "Wait error: %s\n",
159 strerror(errno));
160 else if (pid != tpid)
161 syslog(LOG_ERR, "Wait error, expect pid: %d"
162 " got %d, status: %x\n", pid, tpid, status);
163 else if (status) {
164 syslog(LOG_ERR, "Wait pid: %d status: %x\n",
165 pid, status);
166 if (WIFEXITED(status) &&
167 (WEXITSTATUS(status) == 1)) {
168 error = FC_FCODE_ABORT;
169 } else {
170 error = FC_EXEC_FAILED;
171 }
172 if (ioctl(fd, FC_SET_FCODE_ERROR, &error) < 0) {
173 syslog(LOG_ERR,
174 "ioctl(FC_SET_FCODE_ERROR)"
175 " failed\n");
176 }
177 } else if (debug)
178 syslog(LOG_DEBUG, "Wait: pid: %d\n", pid);
179 (void) close(fd);
180 continue;
181 }
182 if (debug)
183 syslog(LOG_DEBUG, "Child: %d processing request\n",
184 getpid());
185 (void) fcntl(fd, F_DUP2FD, 0);
186 while (execl("/bin/sh", "sh", efcode_sh_file, NULL)) {
187 nerr++;
188 if (nerr == 1)
189 syslog(LOG_ERR, "execl(/bin/sh) failed: %s\n",
190 strerror(errno));
191 (void) sleep(1);
192 }
193 }
194
195 return (0);
196 }
197