struct timeval tv;
struct tm tim;
time_t unixtime;
+ struct CitContext *CCC = CC;
gettimeofday(&tv, NULL);
/* Promote to time_t; types differ on some OSes (like darwin) */
unixtime = tv.tv_sec;
localtime_r(&unixtime, &tim);
- if (CC->cs_pid != 0) {
+ if ((CCC != NULL) && (CCC->cs_pid != 0)) {
sprintf(buf,
"%04d/%02d/%02d %2d:%02d:%02d.%06ld [%3d] ",
tim.tm_year + 1900, tim.tm_mon + 1,
tim.tm_mday, tim.tm_hour, tim.tm_min,
tim.tm_sec, (long)tv.tv_usec,
- CC->cs_pid);
+ CCC->cs_pid);
} else {
sprintf(buf,
"%04d/%02d/%02d %2d:%02d:%02d.%06ld ",
int s;
int i;
int actual_queue_len;
+#ifdef HAVE_STRUCT_UCRED
+ int passcred = 1;
+#endif
actual_queue_len = queue_len;
if (actual_queue_len < 5) actual_queue_len = 5;
return(-1);
}
+#ifdef HAVE_STRUCT_UCRED
+ setsockopt(s, SOL_SOCKET, SO_PASSCRED, &passcred, sizeof(passcred));
+#endif
+
chmod(sockpath, S_ISGID|S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
return(s);
}
}
/*
- * The following functions implement output buffering. If the kernel supplies
- * native TCP buffering (Linux & *BSD), use that; otherwise, emulate it with
- * user-space buffering.
+ * The following functions implement output buffering on operating systems which
+ * support it (such as Linux and various BSD flavors).
*/
#ifndef HAVE_DARWIN
#ifdef TCP_CORK
#endif /* TCP_CORK */
#endif /* HAVE_DARWIN */
-#ifdef HAVE_TCP_BUFFERING
static unsigned on = 1, off = 0;
-void buffer_output(void) {
- struct CitContext *ctx = MyContext();
- setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
- ctx->buffering = 1;
-}
-
-void unbuffer_output(void) {
- struct CitContext *ctx = MyContext();
- setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
- ctx->buffering = 0;
-}
-void flush_output(void) {
- struct CitContext *ctx = MyContext();
- setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
- setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
-}
-#else
-#ifdef HAVE_DARWIN
-/* Stub functions for Darwin/OS X where TCP buffering isn't liked at all */
void buffer_output(void) {
- CC->buffering = 0;
+#ifdef HAVE_TCP_BUFFERING
+#ifdef HAVE_OPENSSL
+ if (!CC->redirect_ssl)
+#endif
+ setsockopt(CC->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
+#endif
}
+
void unbuffer_output(void) {
- CC->buffering = 0;
-}
-void flush_output(void) {
-}
-#else
-void buffer_output(void) {
- if (CC->buffering == 0) {
- CC->buffering = 1;
- CC->buffer_len = 0;
- CC->output_buffer = malloc(SIZ);
- }
+#ifdef HAVE_TCP_BUFFERING
+#ifdef HAVE_OPENSSL
+ if (!CC->redirect_ssl)
+#endif
+ setsockopt(CC->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
+#endif
}
void flush_output(void) {
- if (CC->buffering == 1) {
- client_write(CC->output_buffer, CC->buffer_len);
- CC->buffer_len = 0;
- }
-}
-
-void unbuffer_output(void) {
- if (CC->buffering == 1) {
- CC->buffering = 0;
- /* We don't call flush_output because we can't. */
- client_write(CC->output_buffer, CC->buffer_len);
- CC->buffer_len = 0;
- free(CC->output_buffer);
- CC->output_buffer = NULL;
- }
+#ifdef HAVE_TCP_BUFFERING
+ struct CitContext *CCC = CC;
+ setsockopt(CCC->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
+ setsockopt(CCC->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
+#endif
}
-#endif /* HAVE_DARWIN */
-#endif /* HAVE_TCP_BUFFERING */
return 0;
}
-#ifndef HAVE_TCP_BUFFERING
- /* If we're buffering for later, do that now. */
- if (Ctx->buffering) {
- old_buffer_len = Ctx->buffer_len;
- Ctx->buffer_len += nbytes;
- Ctx->output_buffer = realloc(Ctx->output_buffer, Ctx->buffer_len);
- memcpy(&Ctx->output_buffer[old_buffer_len], buf, nbytes);
- return 0;
- }
-#endif
-
- /* Ok, at this point we're not buffering. Go ahead and write. */
-
#ifdef HAVE_OPENSSL
if (Ctx->redirect_ssl) {
client_write_ssl(buf, nbytes);
CtdlDestroySessionHooks();
CtdlDestroyServiceHook();
CtdlDestroyRoomHooks();
- CtdlDestroyDirectoryServiceFuncs();
#ifdef HAVE_BACKTRACE
eCrash_Uninit();
#endif
exit(0);
}
+int nFireUps = 0;
+int nFireUpsNonRestart = 0;
+pid_t ForkedPid = 1;
/*
* Start running as a daemon.
}
waitpid(current_child, &status, 0);
}
-
do_restart = 0;
+ nFireUpsNonRestart = nFireUps;
+
+ /* Exit code 0 means the watcher should exit */
+ if (WIFEXITED(status) && (WEXITSTATUS(status) == CTDLEXIT_SHUTDOWN)) {
+ do_restart = 0;
+ }
- /* Did the main process exit with an actual exit code? */
- if (WIFEXITED(status)) {
-
- /* Exit code 0 means the watcher should exit */
- if (WEXITSTATUS(status) == 0) {
- do_restart = 0;
- }
-
- /* Exit code 101-109 means the watcher should exit */
- else if ( (WEXITSTATUS(status) >= 101) && (WEXITSTATUS(status) <= 109) ) {
- do_restart = 0;
- }
-
- /* Any other exit code means we should restart. */
- else {
- do_restart = 1;
- }
+ /* Exit code 101-109 means the watcher should exit */
+ else if (WIFEXITED(status) && (WEXITSTATUS(status) >= 101) && (WEXITSTATUS(status) <= 109)) {
+ do_restart = 0;
}
- /* Any other type of termination (signals, etc.) should also restart. */
+ /* Any other exit code, or no exit code, means we should restart. */
else {
do_restart = 1;
+ nFireUps++;
+ ForkedPid = current_child;
}
} while (do_restart);
+void checkcrash(void)
+{
+ if (nFireUpsNonRestart != nFireUps)
+ {
+ StrBuf *CrashMail;
+
+ CrashMail = NewStrBuf();
+ CtdlLogPrintf(CTDL_ALERT, "Posting crash message\n");
+ StrBufPrintf(CrashMail,
+ " \n"
+ " The Citadel server process (citserver) terminated unexpectedly."
+ "\n \n"
+ " This could be the result of a bug in the server program, or some external "
+ "factor. You can obtain more information about this by enabling core dumps. "
+ "For more information, please see: "
+ "http://citadel.org/doku.php/faq:mastering_your_os:gdb#how.do.i.make.my.system.produce.core-files"
+ "\n \n"
+ " If you have already done this, the core dump is likely to be found at %score.%d\n"
+ ,
+ ctdl_run_dir, ForkedPid);
+ CtdlAideMessage(ChrPtr(CrashMail), "Citadel server process terminated unexpectedly");
+ FreeStrBuf(&CrashMail);
+ }
+}
+
+
/*
* Generic routine to convert a login name to a full name (gecos)
* Returns nonzero if a conversion took place