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]
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.
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() */
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
;
74 boolean_t syslog_open
= B_FALSE
;
75 boolean_t debug_enabled
= B_FALSE
;
80 openlog(SYSLOG_IDENT
, LOG_PID
|LOG_CONS
, LOG_DAEMON
);
87 syslog_open
= B_FALSE
;
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.
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
];
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.
128 warn_msg(const char *format
, ...)
133 openlog(SYSLOG_IDENT
, LOG_PID
, LOG_DAEMON
);
135 va_start(ap
, format
);
136 msg(MT_WARN
, format
, ap
);
140 openlog(SYSLOG_IDENT
, LOG_PID
|LOG_CONS
, LOG_DAEMON
);
144 debug_msg(const char *format
, ...)
148 va_start(ap
, format
);
149 msg(MT_DEBUG
, format
, ap
);
154 error_msg(const char *format
, ...)
158 va_start(ap
, format
);
159 msg(MT_ERROR
, format
, ap
);
166 if (poll_fds
!= NULL
) {
177 for (n
= 0; n
< num_pollfds
; n
++) {
178 if (poll_fds
[n
].fd
== fd
)
179 return (&(poll_fds
[n
]));
185 set_pollfd(int fd
, uint16_t events
)
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
) {
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
;
218 if ((p
= find_pollfd(fd
)) != NULL
) {
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
)
246 char *cp
= (char *)buf
;
252 switch (ret
= read(fd
, cp
+ cnt
, sz
- cnt
)) {
253 case 0: /* other end of pipe/socket closed */
256 if (errno
== EAGAIN
) { /* nothing to read */
258 } else if (errno
!= EINTR
) {
259 error_msg(gettext("Unexpected read error: %s"),
274 * Return B_TRUE if instance 'inst' has exceeded its configured maximum
275 * concurrent copies limit, else B_FALSE.
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.
289 cancel_inst_timer(instance_t
*inst
)
291 (void) iu_cancel_timer(timer_queue
, inst
->timer_id
, NULL
);
296 * Cancel the bind retry timer associated with the instance.
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;
306 enable_blocking(int fd
)
308 int flags
= fcntl(fd
, F_GETFL
, 0);
309 (void) fcntl(fd
, F_SETFL
, (flags
& ~O_NONBLOCK
));
313 disable_blocking(int fd
)
315 int flags
= fcntl(fd
, F_GETFL
, 0);
316 (void) fcntl(fd
, F_SETFL
, (flags
| O_NONBLOCK
));