8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.lib / inetd / util.c
blob4653561e2b5eef42c972de0e98a65af2fb057b68
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * General utility routines.
32 #include <syslog.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <stdarg.h>
36 #include <strings.h>
37 #include <time.h>
38 #include <errno.h>
39 #include <libintl.h>
40 #include <unistd.h>
41 #include "inetd_impl.h"
44 /* size of buffer used in msg() to expand printf() like messages into */
45 #define MSG_BUF_SIZE 1024
47 /* number of pollfd we grow the pollfd array by at a time in set_pollfd() */
48 #define POLLFDS_GROWTH_SIZE 16
50 /* enumeration of message types supported by msg() */
51 typedef enum {
52 MT_ERROR,
53 MT_DEBUG,
54 MT_WARN
55 } si_msg_type_t;
58 * Collection of information for each method type.
59 * NOTE: This table is indexed into using the instance_method_t
60 * enumeration, so the ordering needs to be kept in synch.
62 method_type_info_t methods[] = {
63 {IM_START, START_METHOD_NAME, IIS_NONE},
64 {IM_ONLINE, ONLINE_METHOD_NAME, IIS_ONLINE},
65 {IM_OFFLINE, OFFLINE_METHOD_NAME, IIS_OFFLINE},
66 {IM_DISABLE, DISABLE_METHOD_NAME, IIS_DISABLED},
67 {IM_REFRESH, REFRESH_METHOD_NAME, IIS_ONLINE},
68 {IM_NONE, "none", IIS_NONE}
71 struct pollfd *poll_fds = NULL;
72 nfds_t num_pollfds;
74 boolean_t syslog_open = B_FALSE;
75 boolean_t debug_enabled = B_FALSE;
77 void
78 msg_init(void)
80 openlog(SYSLOG_IDENT, LOG_PID|LOG_CONS, LOG_DAEMON);
81 syslog_open = B_TRUE;
84 void
85 msg_fini(void)
87 syslog_open = B_FALSE;
88 closelog();
92 * Outputs a msg. If 'type' is set tp MT_ERROR or MT_WARN the message goes
93 * to syslog with severitys LOG_ERROR and LOG_WARN respectively. For all
94 * values of 'type' the message is written to the debug log file, if it
95 * was openable when inetd started.
97 static void
98 msg(si_msg_type_t type, const char *format, va_list ap)
101 * Use a stack buffer so we stand more chance of reporting a
102 * memory shortage failure.
104 char buf[MSG_BUF_SIZE];
106 if (!syslog_open)
107 return;
109 (void) vsnprintf(buf, sizeof (buf), format, ap);
112 * Log error and warning messages to syslog with appropriate severity.
114 if (type == MT_ERROR) {
115 syslog(LOG_ERR, "%s", buf);
116 } else if (type == MT_WARN) {
117 syslog(LOG_WARNING, "%s", buf);
118 } else if (debug_enabled && type == MT_DEBUG) {
119 syslog(LOG_DEBUG, "%s", buf);
124 * Output a warning message. Unlike error_msg(), syslog doesn't get told
125 * to log to the console if syslogd isn't around.
127 void
128 warn_msg(const char *format, ...)
130 va_list ap;
132 closelog();
133 openlog(SYSLOG_IDENT, LOG_PID, LOG_DAEMON);
135 va_start(ap, format);
136 msg(MT_WARN, format, ap);
137 va_end(ap);
139 closelog();
140 openlog(SYSLOG_IDENT, LOG_PID|LOG_CONS, LOG_DAEMON);
143 void
144 debug_msg(const char *format, ...)
146 va_list ap;
148 va_start(ap, format);
149 msg(MT_DEBUG, format, ap);
150 va_end(ap);
153 void
154 error_msg(const char *format, ...)
156 va_list ap;
158 va_start(ap, format);
159 msg(MT_ERROR, format, ap);
160 va_end(ap);
163 void
164 poll_fini(void)
166 if (poll_fds != NULL) {
167 free(poll_fds);
168 poll_fds = NULL;
172 struct pollfd *
173 find_pollfd(int fd)
175 nfds_t n;
177 for (n = 0; n < num_pollfds; n++) {
178 if (poll_fds[n].fd == fd)
179 return (&(poll_fds[n]));
181 return (NULL);
185 set_pollfd(int fd, uint16_t events)
187 struct pollfd *p;
188 int i;
190 p = find_pollfd(fd);
191 if ((p == NULL) && ((p = find_pollfd(-1)) == NULL)) {
192 if ((p = realloc(poll_fds,
193 ((num_pollfds + POLLFDS_GROWTH_SIZE) *
194 sizeof (struct pollfd)))) == NULL) {
195 return (-1);
197 poll_fds = p;
199 for (i = 1; i < POLLFDS_GROWTH_SIZE; i++)
200 poll_fds[num_pollfds + i].fd = -1;
202 p = &poll_fds[num_pollfds];
203 num_pollfds += POLLFDS_GROWTH_SIZE;
206 p->fd = fd;
207 p->events = events;
208 p->revents = 0;
210 return (0);
213 void
214 clear_pollfd(int fd)
216 struct pollfd *p;
218 if ((p = find_pollfd(fd)) != NULL) {
219 p->fd = -1;
220 p->events = 0;
221 p->revents = 0;
225 boolean_t
226 isset_pollfd(int fd)
228 struct pollfd *p = find_pollfd(fd);
230 return ((p != NULL) && (p->revents & POLLIN));
234 * An extension of read() that keeps retrying until either the full request has
235 * completed, the other end of the connection/pipe is closed, no data is
236 * readable for a non-blocking socket/pipe, or an unexpected error occurs.
237 * Returns 0 if the data is successfully read, 1 if the other end of the pipe/
238 * socket is closed or there's nothing to read from a non-blocking socket/pipe,
239 * else -1 if an unexpected error occurs.
242 safe_read(int fd, void *buf, size_t sz)
244 int ret;
245 size_t cnt = 0;
246 char *cp = (char *)buf;
248 if (sz == 0)
249 return (0);
251 do {
252 switch (ret = read(fd, cp + cnt, sz - cnt)) {
253 case 0: /* other end of pipe/socket closed */
254 return (1);
255 case -1:
256 if (errno == EAGAIN) { /* nothing to read */
257 return (1);
258 } else if (errno != EINTR) {
259 error_msg(gettext("Unexpected read error: %s"),
260 strerror(errno));
261 return (-1);
263 break;
265 default:
266 cnt += ret;
268 } while (cnt != sz);
270 return (0);
274 * Return B_TRUE if instance 'inst' has exceeded its configured maximum
275 * concurrent copies limit, else B_FALSE.
277 boolean_t
278 copies_limit_exceeded(instance_t *inst)
280 /* any value <=0 means that copies limits are disabled */
281 return ((inst->config->basic->max_copies > 0) &&
282 (inst->copies >= inst->config->basic->max_copies));
286 * Cancel the method/con-rate offline timer associated with the instance.
288 void
289 cancel_inst_timer(instance_t *inst)
291 (void) iu_cancel_timer(timer_queue, inst->timer_id, NULL);
292 inst->timer_id = -1;
296 * Cancel the bind retry timer associated with the instance.
298 void
299 cancel_bind_timer(instance_t *inst)
301 (void) iu_cancel_timer(timer_queue, inst->bind_timer_id, NULL);
302 inst->bind_timer_id = -1;
305 void
306 enable_blocking(int fd)
308 int flags = fcntl(fd, F_GETFL, 0);
309 (void) fcntl(fd, F_SETFL, (flags & ~O_NONBLOCK));
312 void
313 disable_blocking(int fd)
315 int flags = fcntl(fd, F_GETFL, 0);
316 (void) fcntl(fd, F_SETFL, (flags | O_NONBLOCK));