X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fcitserver.c;h=6dba619936c800ab85004676a4f547c02d10d46d;hb=cf934431c7c8c1091b38c0b374f6a3b9293841ca;hp=90a7f4f969005530ed4dcb2a323fc4251f45de30;hpb=079f33bf491a2718e54829da13804d266f935204;p=citadel.git diff --git a/citadel/citserver.c b/citadel/citserver.c index 90a7f4f96..6dba61993 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -26,6 +26,10 @@ # endif #endif +#if HAVE_BACKTRACE +#include +#endif + #include #include #include @@ -36,9 +40,11 @@ #include #include #include +#include #include "citadel.h" #include "server.h" #include "sysdep_decls.h" +#include "threads.h" #include "citserver.h" #include "config.h" #include "database.h" @@ -51,20 +57,68 @@ #include "file_ops.h" #include "policy.h" #include "control.h" -#include "tools.h" #include "euidindex.h" -#include "serv_network.h" /* Needed for destroy_network_queue_room called from master_cleanup */ #ifndef HAVE_SNPRINTF #include "snprintf.h" #endif +#include "ctdl_module.h" + + struct CitContext *ContextList = NULL; struct CitContext* next_session = NULL; char *unique_session_numbers; int ScheduledShutdown = 0; -int do_defrag = 0; time_t server_startup_time; +int panic_fd; + +/** + * \brief print the actual stack frame. + */ +void cit_backtrace(void) +{ +#ifdef HAVE_BACKTRACE + void *stack_frames[50]; + size_t size, i; + char **strings; + + + size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*)); + strings = backtrace_symbols(stack_frames, size); + for (i = 0; i < size; i++) { + if (strings != NULL) + lprintf(1, "%s\n", strings[i]); + else + lprintf(1, "%p\n", stack_frames[i]); + } + free(strings); +#endif +} + +/** + * \brief print the actual stack frame. + */ +void cit_panic_backtrace(int SigNum) +{ +#ifdef HAVE_BACKTRACE + void *stack_frames[10]; + size_t size, i; + char **strings; + + printf("caught signal 11\n"); + size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*)); + strings = backtrace_symbols(stack_frames, size); + for (i = 0; i < size; i++) { + if (strings != NULL) + lprintf(1, "%s\n", strings[i]); + else + lprintf(1, "%p\n", stack_frames[i]); + } + free(strings); +#endif + exit(-1); +} /* * Various things that need to be initialized at startup @@ -81,10 +135,10 @@ void master_startup(void) { lprintf(CTDL_INFO, "Opening databases\n"); open_databases(); - if (do_defrag) { - defrag_databases(); - } - + ctdl_thread_internal_init_tsd(); + + CtdlThreadAllocTSD(); + check_ref_counts(); lprintf(CTDL_INFO, "Creating base rooms (if necessary)\n"); @@ -99,6 +153,12 @@ void master_startup(void) { lputroom(&qrbuf); } + /* Aide needs to be public postable, else we're not RFC conformant. */ + if (lgetroom(&qrbuf, AIDEROOM) == 0) { + qrbuf.QRflags2 |= QR2_SMTP_PUBLIC; + lputroom(&qrbuf); + } + lprintf(CTDL_INFO, "Seeding the pseudo-random number generator...\n"); urandom = fopen("/dev/urandom", "r"); if (urandom != NULL) { @@ -125,7 +185,6 @@ void master_startup(void) { */ void master_cleanup(int exitcode) { struct CleanupFunctionHook *fcn; - struct MaintenanceThreadHook *m_fcn; static int already_cleaning_up = 0; if (already_cleaning_up) while(1) sleep(1); @@ -139,22 +198,13 @@ void master_cleanup(int exitcode) { /* Close the AdjRefCount queue file */ AdjRefCount(-1, 0); - for (m_fcn = MaintenanceThreadHookTable; m_fcn != NULL; m_fcn = m_fcn->next) { - lprintf(CTDL_INFO, "Waiting for maintenance thread \"%s\" to shut down\n", m_fcn->name); - pthread_join(m_fcn->MaintenanceThread_tid, NULL); - } + /* Do system-dependent stuff */ + sysdep_master_cleanup(); - /* Close databases */ lprintf(CTDL_INFO, "Closing databases\n"); close_databases(); - /* flush the networker stuff */ - destroy_network_queue_room(); - - /* Do system-dependent stuff */ - sysdep_master_cleanup(); - #ifdef DEBUG_MEMORY_LEAKS dump_heap(); #endif @@ -244,15 +294,23 @@ void cmd_info(void) { cprintf("0\n"); /* 1 = no, this server is not LDAP-enabled */ #endif - if (config.c_auth_mode == 1) { - cprintf("1\n"); /* "create new user" never works with host auth */ + if (config.c_auth_mode == AUTHMODE_NATIVE) { + cprintf("%d\n", config.c_disable_newu); } else { - cprintf("%d\n", config.c_disable_newu); /* otherwise, site defined */ + cprintf("1\n"); /* "create new user" does not work with non-native auth modes */ } cprintf("%s\n", config.c_default_cal_zone); + /* Output load averages */ + cprintf("%f\n", CtdlThreadLoadAvg); + cprintf("%f\n", CtdlThreadWorkerAvg); + cprintf("%d\n", CtdlThreadGetCount()); + + cprintf("1\n"); /* yes, Sieve mail filtering is supported */ + cprintf("%d\n", config.c_enable_fulltext); + cprintf("000\n"); } @@ -299,11 +357,16 @@ int is_public_client(void) char addrbuf[1024]; FILE *fp; int i; + char *public_clientspos; + char *public_clientsend; + char *paddr = NULL; struct stat statbuf; static time_t pc_timestamp = 0; static char public_clients[SIZ]; static char public_clients_file[SIZ]; +#define LOCALHOSTSTR "127.0.0.1" + snprintf(public_clients_file, sizeof public_clients_file, "%s/public_clients", @@ -326,29 +389,45 @@ int is_public_client(void) begin_critical_section(S_PUBLIC_CLIENTS); lprintf(CTDL_INFO, "Loading %s\n", public_clients_file); - safestrncpy(public_clients, "127.0.0.1", sizeof public_clients); + public_clientspos = &public_clients[0]; + public_clientsend = public_clientspos + SIZ; + safestrncpy(public_clientspos, LOCALHOSTSTR, sizeof public_clients); + public_clientspos += sizeof(LOCALHOSTSTR) - 1; + if (hostname_to_dotted_quad(addrbuf, config.c_fqdn) == 0) { - strcat(public_clients, "|"); - strcat(public_clients, addrbuf); + *(public_clientspos++) = '|'; + paddr = &addrbuf[0]; + while (!IsEmptyStr (paddr) && + (public_clientspos < public_clientsend)) + *(public_clientspos++) = *(paddr++); } fp = fopen(public_clients_file, "r"); - if (fp != NULL) while (fgets(buf, sizeof buf, fp)!=NULL) { - for (i=0; ibuf && isspace(*ptr)) { + *(ptr--) = 0; + } + if (hostname_to_dotted_quad(addrbuf, buf) == 0) { + *(public_clientspos++) = '|'; + paddr = addrbuf; + while (!IsEmptyStr(paddr) && + (public_clientspos < public_clientsend)){ + *(public_clientspos++) = *(paddr++); + } } } - } fclose(fp); pc_timestamp = time(NULL); end_critical_section(S_PUBLIC_CLIENTS); @@ -403,7 +482,7 @@ void cmd_iden(char *argbuf) safestrncpy(CC->cs_clientname, desc, sizeof CC->cs_clientname); CC->cs_clientname[31] = 0; - if (strlen(from_host) > 0) { + if (!IsEmptyStr(from_host)) { if (CC->is_local_socket) do_lookup = 1; else if (is_public_client()) do_lookup = 1; } @@ -474,12 +553,12 @@ void cmd_mesg(char *mname) /* Otherwise, look for the requested file by name. */ else { mesg_locate(targ, sizeof targ, buf2, 2, (const char **)dirs); - if (strlen(targ) == 0) { + if (IsEmptyStr(targ)) { snprintf(buf2, sizeof buf2, "%s.%d", buf, CC->cs_clientdev); mesg_locate(targ, sizeof targ, buf2, 2, (const char **)dirs); - if (strlen(targ) == 0) { + if (IsEmptyStr(targ)) { mesg_locate(targ, sizeof targ, buf, 2, (const char **)dirs); } @@ -489,7 +568,7 @@ void cmd_mesg(char *mname) free(dirs[0]); free(dirs[1]); - if (strlen(targ)==0) { + if (IsEmptyStr(targ)) { cprintf("%d '%s' not found. (Searching in %s and %s)\n", ERROR + FILE_NOT_FOUND, mname, @@ -534,7 +613,7 @@ void cmd_emsg(char *mname) if (CtdlAccessCheck(ac_aide)) return; extract_token(buf, mname, 0, '|', sizeof buf); - for (a=0; acs_flags & CS_CHAT) { - while (strlen(real_room) < 14) + while (strlen(real_room) < 14) { strcat(real_room, " "); - + } strcpy(&real_room[14], ""); } @@ -769,9 +848,9 @@ void cmd_down(char *argbuf) { } else { - cprintf(Reply, CIT_OK); + cprintf(Reply, CIT_OK + SERVER_SHUTTING_DOWN); } - time_to_die = 1; + CtdlThreadStopAll(); } /* @@ -782,7 +861,7 @@ void cmd_halt(void) { if (CtdlAccessCheck(ac_aide)) return; cprintf("%d Halting server. Goodbye.\n", CIT_OK); - time_to_die = 1; + CtdlThreadStopAll(); shutdown_and_halt = 1; } @@ -873,10 +952,10 @@ void begin_session(struct CitContext *con) strcpy(con->lastcmdname, " "); strcpy(con->cs_clientname, "(unknown)"); strcpy(con->curr_user, NLI); - strcpy(con->net_node, ""); - strcpy(con->fake_username, ""); - strcpy(con->fake_hostname, ""); - strcpy(con->fake_roomname, ""); + *con->net_node = '\0'; + *con->fake_username = '\0'; + *con->fake_hostname = '\0'; + *con->fake_roomname = '\0'; generate_nonce(con); safestrncpy(con->cs_host, config.c_fqdn, sizeof con->cs_host); safestrncpy(con->cs_addr, "", sizeof con->cs_addr); @@ -902,7 +981,12 @@ void begin_session(struct CitContext *con) con->nologin = 1; } - lprintf(CTDL_NOTICE, "Session started.\n"); + if (!CC->is_local_socket) { + lprintf(CTDL_NOTICE, "Session started from %s [%s].\n", con->cs_host, con->cs_addr); + } + else { + lprintf(CTDL_NOTICE, "Session started via local socket.\n"); + } /* Run any session startup routines registered by loadable modules */ PerformSessionHooks(EVT_START); @@ -931,12 +1015,16 @@ void citproto_begin_session() { */ void do_command_loop(void) { char cmdbuf[SIZ]; - + const char *old_name = NULL; + + old_name = CtdlThreadName("do_command_loop"); + time(&CC->lastcmd); memset(cmdbuf, 0, sizeof cmdbuf); /* Clear it, just in case */ if (client_getln(cmdbuf, sizeof cmdbuf) < 1) { lprintf(CTDL_ERR, "Client disconnected: ending session.\n"); CC->kill_me = 1; + CtdlThreadName(old_name); return; } @@ -965,6 +1053,8 @@ void do_command_loop(void) { safestrncpy(CC->lastcmdname, cmdbuf, sizeof(CC->lastcmdname)); time(&CC->lastidle); } + + CtdlThreadName(cmdbuf); if ((strncasecmp(cmdbuf, "ENT0", 4)) && (strncasecmp(cmdbuf, "MESG", 4)) @@ -977,6 +1067,10 @@ void do_command_loop(void) { cprintf("%d%cok\n", CIT_OK, CtdlCheckExpress() ); } + else if (!strncasecmp(cmdbuf, "XYZZY", 5)) { + cprintf("%d Nothing happens.\n", CIT_OK); + } + else if (!strncasecmp(cmdbuf, "QNOP", 4)) { /* do nothing, this command returns no response */ } @@ -1327,15 +1421,19 @@ void do_command_loop(void) { cmd_isme(&cmdbuf[5]); } + else if (!strncasecmp(cmdbuf, "RENU", 4)) { + cmd_renu(&cmdbuf[5]); + } + else if (!DLoader_Exec_Cmd(cmdbuf)) { - cprintf("%d Unrecognized or unsupported command.\n", - ERROR + CMD_NOT_SUPPORTED); - } + cprintf("%d Unrecognized or unsupported command.\n", ERROR + CMD_NOT_SUPPORTED); + } unbuffer_output(); /* Run any after-each-command routines registered by modules */ PerformSessionHooks(EVT_CMD); + CtdlThreadName(old_name); }