/*
* $Id$
*
- * Citadel/UX "system dependent" stuff.
+ * Citadel "system dependent" stuff.
* See copyright.txt for copyright information.
*
* Here's where we (hopefully) have most parts of the Citadel server that
* log data sent through this function. BE CAREFUL!
*/
void lprintf(enum LogLevel loglevel, const char *format, ...) {
- va_list arg_ptr;
+ va_list arg_ptr;
char buf[SIZ];
- va_start(arg_ptr, format);
- vsnprintf(buf, sizeof(buf), format, arg_ptr);
- va_end(arg_ptr);
+ va_start(arg_ptr, format);
+ vsnprintf(buf, sizeof(buf), format, arg_ptr);
+ va_end(arg_ptr);
if (syslog_facility >= 0) {
if (loglevel <= verbosity) {
* a TCP port. The server shuts down if the bind fails.
*
*/
-int ig_tcp_server(int port_number, int queue_len)
+int ig_tcp_server(char *ip_addr, int port_number, int queue_len)
{
struct sockaddr_in sin;
int s, i;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons((u_short)port_number);
+ if (ip_addr == NULL) {
+ sin.sin_addr.s_addr = INADDR_ANY;
+ }
+ else {
+ sin.sin_addr.s_addr = inet_addr(ip_addr);
+ }
+
+ if (sin.sin_addr.s_addr == INADDR_NONE) {
+ sin.sin_addr.s_addr = INADDR_ANY;
+ }
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
/*
* buffer_output() ... tell client_write to buffer all output until
- * instructed to dump it all out later
+ * instructed to dump it all out later
*/
void buffer_output(void) {
if (CC->buffering == 0) {
/*
* cprintf() ... Send formatted printable data to the client. It is
- * implemented in terms of client_write() but remains in
- * sysdep.c in case we port to somewhere without va_args...
+ * implemented in terms of client_write() but remains in
+ * sysdep.c in case we port to somewhere without va_args...
*/
void cprintf(const char *format, ...) {
- va_list arg_ptr;
- char buf[SIZ];
+ va_list arg_ptr;
+ char buf[SIZ];
- va_start(arg_ptr, format);
- if (vsnprintf(buf, sizeof buf, format, arg_ptr) == -1)
+ va_start(arg_ptr, format);
+ if (vsnprintf(buf, sizeof buf, format, arg_ptr) == -1)
buf[sizeof buf - 2] = '\n';
client_write(buf, strlen(buf));
va_end(arg_ptr);
while (!time_to_die) {
- /*
- * A naive implementation would have all idle threads
- * calling select() and then they'd all wake up at once
- * (known in computer science as the "thundering herd"
- * problem). We solve this problem by putting the select()
- * in a critical section, so only one thread has the
- * opportunity to wake up. If we wake up on a master
- * socket, create a new session context; otherwise, just
- * bind the thread to the context we want and go on our
- * merry way.
- */
-
/* make doubly sure we're not holding any stale db handles
* which might cause a deadlock.
*/
cdb_check_handles();
- force_purge = 0;
+do_select: force_purge = 0;
bind_me = NULL; /* Which session shall we handle? */
- begin_critical_section(S_I_WANNA_SELECT);
-
/* Initialize the fdset. */
FD_ZERO(&readfds);
highest = 0;
if (bind_me) goto SKIP_SELECT;
-do_select: /* Only select() if the server isn't being told to shut down. */
+ /* If we got this far, it means that there are no sessions
+ * which a previous thread marked for attention, so we go
+ * ahead and get ready to select().
+ */
- /* Add the various master sockets to the fdset. */
+ /* First, add the various master sockets to the fdset. */
for (serviceptr = ServiceHookTable; serviceptr != NULL;
serviceptr = serviceptr->next ) {
m = serviceptr->msock;
retval = select(highest + 1, &readfds, NULL, NULL, &tv);
}
else {
- end_critical_section(S_I_WANNA_SELECT);
break;
}
}
if (time_to_die) {
- end_critical_section(S_I_WANNA_SELECT);
break;
}
}
}
end_critical_section(S_SESSION_TABLE);
-SKIP_SELECT: end_critical_section(S_I_WANNA_SELECT);
+SKIP_SELECT:
/* We're bound to a session */
if (bind_me != NULL) {
become_session(bind_me);