Commit 6e33ec06 authored by Per Cederqvist's avatar Per Cederqvist
Browse files

Checked into RCS.

parent 18b5cd74
/*
* admin.c
*
* Administrative calls.
*/
#include <stdlib.h>
#include "lyskomd.h"
#include <kom-types.h>
#include <services.h>
#include "manipulate.h"
#include "smalloc.h"
#include "cache.h"
#include "log.h"
#include "admin.h"
#include <kom-errno.h>
#include "com.h"
#include "connections.h"
#include "send-async.h"
#include "config.h"
Info kom_info =
{
#include "version.incl"
, /* version */
1, /* conf_pres_conf */
2, /* pers_pres_conf */
3, /* motd_conf */
4, /* kom_news_conf */
0 /* motd_of_lyskom */
};
/*
* Return info about this server. This can (and should) be done
* before logging in. modt_of_lyskom should be displayed before
* prompting for username if it isn't 0.
*/
extern Success
get_info( Info *result )
{
*result = kom_info;
return OK;
}
/* /// */
extern Success
set_motd_of_lyskom (Text_no motd)
{
Text_stat *old_motd = NULL;
Text_stat *new_motd = NULL;
CHK_LOGIN(FAILURE);
if ( !ENA(admin, 1) )
{
kom_errno = KOM_PERM;
return FAILURE;
}
/* Check that the new motd exists before deleting the old*/
if ( motd != 0 )
{
GET_T_STAT(new_motd, motd, FAILURE);
if ( new_motd->no_of_marks >= MAX_MARKS_TEXT )
{
log(
"LIMIT: set_motd_of_lyskom(): New motd very marked.\n");
return FAILURE;
}
}
/* Unmark the previous motd if it exists. */
if ( kom_info.motd_of_lyskom != 0
&& (old_motd = cached_get_text_stat(kom_info.motd_of_lyskom)) != NULL)
{
if ( old_motd->no_of_marks > 0 )
{
--old_motd->no_of_marks;
mark_text_as_changed( kom_info.motd_of_lyskom );
}
else
{
log("ERROR: do_set_motd(): Old motd not marked\n");
}
}
/* Mark the new motd */
if ( motd != 0 )
{
++new_motd->no_of_marks;
mark_text_as_changed( motd );
}
kom_info.motd_of_lyskom = motd;
return OK;
}
/*
* Force all clients to read a message.
* Sends an asynchronous message. This is obsoleted by send_message.
*/
extern Success
broadcast (String message)
{
CHK_LOGIN(FAILURE);
async_broadcast(ACTPERS, message);
return OK;
}
/*
* Send a message
*/
extern Success
send_message (Pers_no recipient,
const String message)
{
CHK_LOGIN(FAILURE);
return async_send_message(recipient, ACTPERS, message);
}
/*
* Make LysKOM sync its files.
*/
extern Success
sync (void)
{
cache_sync_all();
dump_statistics();
return OK;
}
/*
* Close LysKOM. exit_val is (currently) not used. The database is synced.
*/
extern Success
shutdown (int exit_val)
{
CHK_LOGIN(FAILURE);
if ( !ENA(admin, 1) )
{
kom_errno = KOM_PERM;
return FAILURE;
}
go_and_die = TRUE;
return OK;
}
/*
* admin.h
*/
extern Info kom_info;
/*
* This file contains the cached data that the server stores.
* .h file created by ceder 1990-04-18
*/
/* cache_sync_all only returns when everything is written to disk. */
extern void
cache_sync_all(void);
/* First, some things which I want here. /ceder */
extern struct matching_info *match_table;
extern void
cached_lock_conf(Conf_no conf_no);
extern Success
init_cache(void);
extern void
cached_unlock_conf(Conf_no conf);
extern void
cached_lock_person(Pers_no pers);
extern void
cached_unlock_person(Pers_no pers);
extern Success
cached_delete_person(Pers_no pres);
extern Success
cached_delete_text(Text_no text);
extern Success
build_matching_info(void);
extern void /* Write out everything. */
cache_sync(void);
/* S}d{r ja. Tack f|r mig. /ceder */
#define MAX_CACHED_PERSONS 5 /* To be increased after debugging */
#define MAX_CACHED_WHATEVER /* To be added */
/*
* Name caching routines
*/
/*
* change_name changes the cached conference name. It is only called when
* a conference name is changed or a conference is deleted.
*
* cached_change_name(foo, EMPTY_STRING); should be used when a conference
* is deleted. (Eller ska det vara annorlunda? S} g|r jag nu... /ceder)
*/
extern void
cached_change_name(Conf_no name_num,
String new_name );
/* add_name adds a name to the list of cached conference names. It is only
* used when a new conference is created.
*/
extern void
cached_add_name( char * new_name );
/* load all the conference names from disk and store them in memory */
extern void
cached_load_names( void );
#if 0
/* get one name (I want this call! /ceder) */
/* I no longer want it. */
extern String
cached_get_name( Conf_no conf_no ); /* Returns NULL if the conference */
/* doesn't exist. */
#endif
extern Bool
cached_conf_exists( Conf_no conf_no );
/*
* Calls for the cacheing of conf_type:
* cached_get_conf_type() returns the type, and
* cached_set_conf_type() sets the type.
*/
/* Get conference type */
/* Undefined result if the conf doesn't exist. */
extern Conf_type
cached_get_conf_type (Conf_no conf_no);
/*
* Set the type. This call is used whenever a conference is created or the
* conf_type is changed.
*/
extern void
cached_set_conf_type (Conf_no conf_no,
Conf_type type);
/*
* Get/set garb_nice for a certain conference.
*/
extern Garb_nice
cached_get_garb_nice (Conf_no conf_no);
extern void
cached_set_garb_nice (Conf_no conf_no,
Garb_nice nice);
extern Local_text_no
cached_get_highest_local_no (Conf_no conf_no);
/*
* Person caching routines
*/
#if 0
extern Person *
cached_read_person( Pers_no pers_no );
#endif
/*
* Various function calls to tell the cache that something is changed.
*/
void
mark_person_as_changed(Pers_no pers_no);
void
mark_conference_as_changed(Conf_no conf_no);
void
mark_text_as_changed(Text_no text_no);
/*
* Person-related calls
*/
extern Success
cached_create_person( Pers_no person );
extern Person *
cached_get_person_stat( Pers_no person ); /* Returns NULL if person
doesn't exist */
/*
* Conference-related calls
*/
extern Conf_no
cached_create_conf( String name );
extern Success
cached_delete_conf( Conf_no conf );
extern Success
cached_lookup_name(const String name,
Conf_list_old *result);
extern Conference *
cached_get_conf_stat( Conf_no conf_no );
/*
* Calls to handle texts
*/
extern String
cached_get_text( Text_no text );/* The string should be free'd by the caller */
extern Text_stat *
cached_get_text_stat( Text_no text );
extern Text_no
cached_create_text( String message);
/*
* traverse_text can be used to cycle through all existing texts. 0 will
* be returned once in the "cycle".
*/
extern Text_no
traverse_text(Text_no seed);
/*
* traverse_person can be used to cycle through all existing persons. 0 will
* be returned once in the "cycle".
*/
extern Pers_no
traverse_person(Pers_no seed);
/*
* traverse_conference can be used to cycle through all existing conferences.
* 0 will be returned once in the "cycle".
*/
extern Conf_no
traverse_conference(Conf_no seed);
This diff is collapsed.
/*
* connections.c
*
* Denna fil inneh}ller niv}n ovanf|r isc.
*
* Created by Willf|r 31/3-90. Mostly written by ceder.
*/
#include <errno.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/time.h>
#include <kom-types.h>
#include "lyskomd.h"
#include "s-string.h"
#include <config.h>
#include <debug.h>
#include "end-of-atomic.h"
#include "log.h"
#include <services.h>
#include "isc.h"
#include <kom-errno.h>
#include "com.h"
#include "connections.h"
#include "prot-a-parse.h"
#include "prot-a-output.h"
#include "prot-a.h"
#include "smalloc.h"
#include "prot-a-parse-arg.h"
#include "isc-parse.h"
#include "cache.h"
#include "send-async.h"
#include "mux.h"
#include "mux-parse.h"
#include "internal-connections.h"
ISCMCB * kom_server_mcb = NULL;
Connection * active_connection = NULL;
Bool go_and_die = FALSE;
Bool do_sync_db = FALSE;
jmp_buf parse_env;
const Fnc_descriptor fnc_defs[]={
#include "fnc-def-init.incl"
};
u_long service_statistics[sizeof (fnc_defs) / sizeof (Fnc_descriptor)];
BUGDECL;
void
logout_client(Connection *cp)
{
Connection *real_active_connection;
if ( active_connection != NULL )
{
log("BUGCHK: logout_client(%d): connection %d is active.\n",
cp->session_no, active_connection->session_no);
}
switch (cp->magic)
{
case CONN_MAGIC_ALLOC:
break;
case CONN_MAGIC_FREE:
log("LOGOUT_CLIENT: Trying to free freed Connection - ignored!\n");
return;
default:
restart_kom("LOGOUT_CLIENT: Bad magic number\n");
}
if ( cp->pers_no != 0 )
{
real_active_connection = active_connection; /* Shouldn't be needed +++ */
active_connection = cp;
logout();
active_connection = real_active_connection;
}
s_clear(&cp->unparsed);
s_clear(&cp->what_am_i_doing);
s_clear(&cp->username);
switch(cp->protocol)
{
case 0: /* Hasn't yet allocated any protocol. */
break;
case 'A':
prot_a_destruct(cp);
break;
default:
restart_kom("logout_client(): Bad protocol.\n");
}
mux_close(cp); /* Close fd's. Clear mux and isc structures. */
kill_client(cp); /* Free the Connection */
}
/*
* Call a function in services.c. A pointer to the result is returned.
* The pointer points to static data which is overwritten on each call.
*/
static Success
call_function (Connection * client,
Result_holder * res) /* This is a union. */
{
Success status=FAILURE; /* OK if the call was successful. */
if ( active_connection != NULL )
{
log("call_function(%d): active_connection = %d",
client->session_no, active_connection->session_no);
}
active_connection = client;
service_statistics[client->function]++;
#include "call-switch.incl"
active_connection = NULL;
return status;
}
static void
parse_packet(Connection *client)
{
if ( client->protocol == '\0' ) /* Not known yet. */
{
client->protocol = parse_char(client);
switch(client->protocol)
{
case 'A':
prot_a_init(client);
break;
default:
client->protocol = '\0';
mux_printf(client,
"%%%%LysKOM unsupported protocol.\n");
mux_flush(client);
BUG(("%%%%Unsupported protocol.\n"));
longjmp(parse_env, ISC_LOGOUT);
}
}
switch(client->protocol)
{
case 'A':
prot_a_parse_packet(client);
break;
default:
restart_kom("parse_packet(): Bad protocol.\n");
break;
}
}
/*
* Free all parsed areas which are no longer needed. Re-initialize all
* parse_pos fields so that the parse will expect a new function.
*
* This function is called
* when a parse error occurs
* when a parse is complete and the function has executed.
*/
static void
free_parsed(Connection *client)
{
s_clear(&client->c_string0);
s_clear(&client->c_string1);
client->string0 = EMPTY_STRING; /* So that no one frees it. */
sfree( client->c_misc_info_p);
client->c_misc_info_p = NULL;
sfree( client->c_local_text_no_p);
client->c_local_text_no_p = NULL;
client->parse_pos = 0;
client->fnc_parse_pos = 0;
client->array_parse_pos = 0;
client->struct_parse_pos = 0;
client->string_parse_pos = 0;
}
/*
* Send a reply to a call.
*/
static void
reply(Connection *client,
Success status,
Result_holder *result)
{
switch(client->protocol)
{
case 'A':
prot_a_reply(client, status, result);
break;
default:
restart_kom("reply(): Bad protocol.\n");
break;
}
}
/*
* Try to parse enough data from client->unparsed to call a function.
* If more data is needed set client->more_to_parse to FALSE.
*/
static void
parse_unparsed(Connection *client)
{
String tmp_str = EMPTY_STRING;
Success status;
Result_holder result;
switch ( setjmp(parse_env) )
{
case 0 :
/* Parse message. If message is complete call function and reply. */
parse_packet(client);
client->last_request = time(NULL);
status = call_function(client, &result);
reply(client, status, &result);
free_parsed(client);
end_of_atomic(FALSE);
break;
case ISC_PROTOCOL_ERR:
s_clear(&client->string0);
free_parsed(client);
mux_printf(client, "%% LysKOM protocol error.\n");
mux_flush(client);
BUG(("%%%% Protocol error.\n"));
s_clear(&client->unparsed);
client->first_to_parse = 0;
client->more_to_parse = FALSE;
end_of_atomic(FALSE);
break;
case ISC_MSG_INCOMPLETE:
client->more_to_parse = FALSE;
break;
case ISC_LOGOUT:
client->kill_me = TRUE;
break;
}
/* Delete the parsed part of 'unparsed' */
if ( s_substr(&tmp_str, client->unparsed,
client->first_to_parse, END_OF_STRING) != OK )
restart_kom("parse_unparsed: s_substr\n");