ramkomd.c 12.8 KB
Newer Older
Linus Tolke Y's avatar
Linus Tolke Y committed
1
/*
2
 * $Id: ramkomd.c,v 0.45 1994/01/12 04:08:51 ceder Exp $
Linus Tolke Y's avatar
Linus Tolke Y committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * Copyright (C) 1991  Lysator Academic Computer Association.
 *
 * This file is part of the LysKOM server.
 * 
 * LysKOM is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 1, or (at your option) 
 * any later version.
 * 
 * LysKOM is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with LysKOM; see the file COPYING.  If not, write to
 * Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
 * or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
 * MA 02139, USA.
 *
 * Please mail bug reports to bug-lyskom@lysator.liu.se. 
 */
Per Cederqvist's avatar
Per Cederqvist committed
25 26 27 28 29 30 31 32 33
/*
 * Detta {r serverns huvudprogram. Det kommer f|rhoppningsvis bli st|rre
 * {n det {r just nu...
 *
 * Created by Willf|r 31/3-90
 *
 * It has grown! /ceder
 */

34
static char *rcsid = "$Id: ramkomd.c,v 0.45 1994/01/12 04:08:51 ceder Exp $";
35 36
#include "rcs.h"
USE(rcsid);
Per Cederqvist's avatar
Per Cederqvist committed
37

38 39 40
#ifdef HAVE_LOCALE_H
#  include <locale.h>
#endif
Per Cederqvist's avatar
Per Cederqvist committed
41
#include <stdio.h>
Per Cederqvist's avatar
Per Cederqvist committed
42
#include <signal.h>
Per Cederqvist's avatar
Per Cederqvist committed
43 44 45
#ifdef HAVE_STDARG_H
#  include <stdarg.h>
#endif
46 47 48 49 50 51
#ifdef HAVE_STDLIB_H
#  include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#  include <string.h>
#endif
Per Cederqvist's avatar
Per Cederqvist committed
52
#include <sys/wait.h>
Per Cederqvist's avatar
Per Cederqvist committed
53
#include <time.h>
Per Cederqvist's avatar
Per Cederqvist committed
54
#include <unistd.h>
Per Cederqvist's avatar
Per Cederqvist committed
55 56 57 58 59 60 61
#include <setjmp.h>
#if defined(HAVE_SYS_PARAM_H) && !defined(HAVE_GETCWD)
# include <sys/param.h>
#endif
#if defined(HAVE_GETCWD)
#  include <errno.h>
#endif
Per Cederqvist's avatar
Per Cederqvist committed
62
#include <sys/types.h>
63
#include <sys/socket.h>
Per Cederqvist's avatar
Per Cederqvist committed
64

Per Cederqvist's avatar
Per Cederqvist committed
65
#include "exp.h"
66
#include "s-string.h"
Per Cederqvist's avatar
Per Cederqvist committed
67
#include "misc-types.h"
68
#include "kom-types.h"
Per Cederqvist's avatar
Per Cederqvist committed
69 70 71 72
#include "com.h"
#include "connections.h"
#include "internal-connections.h"
#include "kom-errno.h"
Per Cederqvist's avatar
Per Cederqvist committed
73
#include "isc-malloc.h"
74
#include "isc-interface.h"
Per Cederqvist's avatar
Per Cederqvist committed
75
#include "config.h"
Per Cederqvist's avatar
Per Cederqvist committed
76
#include "cache.h"
Per Cederqvist's avatar
Per Cederqvist committed
77 78
#include "string-malloc.h"
#include "lyskomd.h"
Per Cederqvist's avatar
Per Cederqvist committed
79
#include "log.h"
Per Cederqvist's avatar
Per Cederqvist committed
80 81 82
#include "internal-services.h"
#include "server/smalloc.h"
#include "kom-memory.h"
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#include "conf-file.h"
#include "param.h"
#include "admin.h"

struct kom_par param;
 
Kom_err		  kom_errno = KOM_NO_ERROR;
unsigned long	  err_stat = 0;

static Conf_no c1 = 1;
static Conf_no c2 = 2;
static Conf_no c3 = 3;
static Conf_no c4 = 4;
static Text_no t0 = 0;

98 99
static Success log_param(const char *val, const struct parameter *par);

100
static const struct parameter parameters[] = {
101
    /* "Normal" configuration */
102
    {"Locale",
103 104 105
	 assign_string,  0, 1, NULL, &param.use_locale},
    {"Prefix",
	 assign_string,  0, 1, NULL, &param.dbase_dir},
106
    {"Send async",
107
	 assign_bool,    0, 1, "1",  &param.send_async_messages},
108
    {"Client port",
109
	 assign_string,  1, 1, NULL, &param.ip_client_port},
110
    {"Mux port",   
111
	 assign_string,  1, 1, NULL, &param.ip_mux_port},
112
    {"Presentation of conferences",
113
	 assign_conf_no, 0, 1, &c1, &kom_info.conf_pres_conf},
114
    {"Presentation of persons",
115
	 assign_conf_no, 0, 1, &c2, &kom_info.pers_pres_conf},
116
    {"Motd-conference",
117
	 assign_conf_no, 0, 1, &c3, &kom_info.motd_conf},
118
    {"News-conference", 
119
	 assign_conf_no, 0, 1, &c4, &kom_info.kom_news_conf},
120
    {"Message of the day",
121
	 assign_text_no, 0, 1, &t0, &kom_info.motd_of_lyskom},
Per Cederqvist's avatar
Per Cederqvist committed
122
#ifdef DEBUG
123
    {"Never save",
124
	 assign_bool,    0, 1, "0", &param.never_save},
Per Cederqvist's avatar
Per Cederqvist committed
125
#endif
126
#ifdef LOGACCESSES
127
    {"Log accesses", 
128
	 assign_string,  0, 1, NULL, &param.logaccess_file},
129
#endif
130 131 132 133

    /* Echo the value to the log. */
    {"Echo",
	 log_param,     0, -1, NULL, NULL},
134 135 136 137
    {NULL, NULL, NULL, FALSE, NULL}}; /* end marker */

#ifdef DEBUG
int	buglevel = 0;
138
#endif
Per Cederqvist's avatar
Per Cederqvist committed
139

140 141 142 143 144 145
EXPORT char datafilename[BUFSIZ];      /* Full pathname to the database file */
EXPORT char backupfilename[BUFSIZ];    /* Full pathname to the backup file */
EXPORT char textfilename[BUFSIZ];      /* Full pathname to the text file. */
EXPORT char statisticfile[BUFSIZ];     /* Dito to statistics file. */
EXPORT char pidfile[BUFSIZ];	       /* Dito pid-file. */
INTERNAL char memusefile[BUFSIZ];      /* Memory usage file. */
Per Cederqvist's avatar
Per Cederqvist committed
146

147 148
static IscSession *listen_client = NULL;      /* ISC listen identifier */
static IscSession *listen_mux    = NULL;      /*          -"-          */
Per Cederqvist's avatar
Per Cederqvist committed
149

150
static void dump_exit_statistics(void);
151

152 153 154 155 156 157 158 159
static Success
log_param(const char *val, const struct parameter *par)
{
    if (val != NULL)
	log ("config: %s\n", val);
    return OK;
}

Per Cederqvist's avatar
Per Cederqvist committed
160
static void
161
server_init (char * client_port, char * mux_port)
Per Cederqvist's avatar
Per Cederqvist committed
162
{
Per Cederqvist's avatar
Per Cederqvist committed
163
    IscConfig config;
164
    IscAddress *isc_adr = NULL;
Per Cederqvist's avatar
Per Cederqvist committed
165
    
Per Cederqvist's avatar
Per Cederqvist committed
166 167 168
    /*
    ** Setup some parameters here
    */
Per Cederqvist's avatar
Per Cederqvist committed
169 170 171 172 173
    config.version = 1005;
    config.master.version = 1001;
    config.master.memfn.alloc = &isc_malloc_wrapper;
    config.master.memfn.realloc = &isc_realloc_wrapper;
    config.master.memfn.free = &isc_free_wrapper;
174
    config.master.abortfn = NULL; /* Use default abort function. */
Per Cederqvist's avatar
Per Cederqvist committed
175
    config.session.version = 1001;
176
    config.session.max.msgsize = -1; /* Use default sizes. */
Per Cederqvist's avatar
Per Cederqvist committed
177 178 179 180
    config.session.max.queuedsize = -1;
    config.session.max.dequeuelen = -1;
    config.session.max.openretries = -1;
    config.session.max.backlog = -1;
Per Cederqvist's avatar
Per Cederqvist committed
181

182
    kom_server_mcb  = isc_initialize(&config);
Per Cederqvist's avatar
Per Cederqvist committed
183
    if ( kom_server_mcb == NULL )
Per Cederqvist's avatar
Per Cederqvist committed
184 185 186 187 188
	restart_kom("server_init: can't isc_initialize()\n");

    listen_client = isc_listentcp(kom_server_mcb, NULL, client_port);
    if (listen_client == NULL)
        restart_kom("server_init: can't isc_listentcp(CLIENT)\n");
Per Cederqvist's avatar
Per Cederqvist committed
189

190 191 192 193
    isc_adr = isc_getladdress (listen_client);
    if (isc_adr == NULL)
	restart_kom("server_init(): can't isc_getladdress (listen_client)\n");

194
    param.num_ip_client_port = isc_getportnum (isc_adr);
195 196 197
    isc_freeaddress (isc_adr);
    
    listen_mux = isc_listentcp (kom_server_mcb, NULL, mux_port);
Per Cederqvist's avatar
Per Cederqvist committed
198 199
    if (listen_mux == NULL)
        restart_kom("server_init: can't isc_listentcp(MUX)\n");
200 201 202 203

    isc_adr = isc_getladdress (listen_mux);
    if (isc_adr == NULL)
	restart_kom("server_init(): can't isc_getladdress (listen_mux)\n");
Per Cederqvist's avatar
Per Cederqvist committed
204
    
205
    param.num_ip_mux_port = isc_getportnum (isc_adr);
206 207 208
    isc_freeaddress (isc_adr);

    log("Listening for clients on %d and muxes on %d.\n",
209
	param.num_ip_client_port, param.num_ip_mux_port);
Per Cederqvist's avatar
Per Cederqvist committed
210 211 212 213 214 215 216 217 218 219

    /*
     * Ignore SIGPIPE, which the server gets if it tries to write to a
     * socket and the client has died. The server will anyhow handle
     * this situation correct.
     */
    signal(SIGPIPE, SIG_IGN);
}

static void
220
init_data_base(const char *dir_base)
Per Cederqvist's avatar
Per Cederqvist committed
221 222 223 224
{
    String a = EMPTY_STRING, b = EMPTY_STRING, c = EMPTY_STRING,
	    d = EMPTY_STRING;

225 226
    if (dir_base == NULL)
      dir_base = DEFAULT_DBASE_DIR;
Per Cederqvist's avatar
Per Cederqvist committed
227
    
228 229 230 231 232 233
    sprintf(datafilename,   "%s/%s", dir_base, DATAFILE_NAME);
    sprintf(backupfilename, "%s/%s", dir_base, BACKUPFILE_NAME);
    sprintf(textfilename, "%s/%s", dir_base, TEXTFILE_NAME);
    sprintf(statisticfile, "%s/%s", dir_base, STATISTIC_NAME);
    sprintf(pidfile, "%s/%s", dir_base, PID_NAME);
    sprintf(memusefile, "%s/%s", dir_base, MEMUSE_NAME);
Per Cederqvist's avatar
Per Cederqvist committed
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256

    log("Database = %s\n",  datafilename);
    log("Backup = %s\n", backupfilename);
    
    if ( init_cache() == FAILURE )
    {
	log ( "Setting up first four conferences.\n");

	if ( s_crea_str(&a, "Presentation (av nya) m|ten") != OK
	    || s_crea_str(&b, "Presentation (av nya) medlemmar") != OK
	    || s_crea_str(&c, "Lappar (p}) d|rren") != OK
	    || s_crea_str(&d, "Nyheter om LysKOM") != OK)
	{
	    restart_kom("init_data_base: can't create strings\n");
	}
	
	if ( ! (   do_create_conf(a, 0, 0, 0, NULL_CONF_TYPE)
		&& do_create_conf(b, 0, 0, 0, NULL_CONF_TYPE)
		&& do_create_conf(c, 0, 0, 0, NULL_CONF_TYPE)
		&& do_create_conf(d, 0, 0, 0, NULL_CONF_TYPE)))
	{
	    restart_kom("init_data_base: Kan ej skapa m|ten\n");
	}
257 258 259 260 261

	s_clear(&a);
	s_clear(&b);
	s_clear(&c);
	s_clear(&d);
Per Cederqvist's avatar
Per Cederqvist committed
262 263 264
    }
}

Per Cederqvist's avatar
Per Cederqvist committed
265
static void
Per Cederqvist's avatar
Per Cederqvist committed
266
sighandler_hup (int sig)
Per Cederqvist's avatar
Per Cederqvist committed
267 268 269 270 271
{
    log ("Signal HUP received. Shutting down server.\n");
    go_and_die = TRUE;
}

Per Cederqvist's avatar
Per Cederqvist committed
272
static void
Per Cederqvist's avatar
Per Cederqvist committed
273
sighandler_quit (int sig)
Per Cederqvist's avatar
Per Cederqvist committed
274 275 276 277 278 279 280
{
    log ("Signal QUIT received - syncing...\n");
    cache_sync_all();
    log ("Dumping core now.\n");
    abort();
}

Per Cederqvist's avatar
Per Cederqvist committed
281
static void
Per Cederqvist's avatar
Per Cederqvist committed
282
sighandler_usr1 (int sig)
Per Cederqvist's avatar
Per Cederqvist committed
283
{
284
    signal(SIGUSR1, sighandler_usr1);
Per Cederqvist's avatar
Per Cederqvist committed
285 286 287
    do_sync_db = TRUE;
}

Per Cederqvist's avatar
Per Cederqvist committed
288
static void
Per Cederqvist's avatar
Per Cederqvist committed
289
sighandler_usr2 (int sig)
Per Cederqvist's avatar
Per Cederqvist committed
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
{
    int		  child;

    log ("Signal USR2 received - will dump core now.  (Check that child dies.)\n");
    if ((child = fork()) == 0)
    {
	abort();
	log ("Abort() failed!!!");
	exit(1);
    }
    else if (child < 0)
    {
	log ("Couldn't fork.\n");
    }
    else
    {
	wait (NULL);
    }
}

Per Cederqvist's avatar
Per Cederqvist committed
310
static void
Per Cederqvist's avatar
Per Cederqvist committed
311 312 313 314 315 316 317
save_pid(void)
{
    FILE *fp;

    if ( (fp = fopen(pidfile, "w")) == NULL )
	return;

318
    fprintf(fp, "%ld\n", (long)getpid());
Per Cederqvist's avatar
Per Cederqvist committed
319 320 321
    fclose(fp);
}

322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
void
initialize(const char *config_file)
{
    read_config(config_file, parameters);

#ifdef HAVE_LOCALE_H
    if (param.use_locale != NULL)
	if (setlocale(LC_CTYPE, param.use_locale) == NULL)
	{
	    fprintf(stderr, "setlocale: ");
	    perror(param.use_locale);
	    exit(1);
	}
#else
    if (param.use_locale != NULL)
    {
	fprintf(stderr, "locale not supported in your environment.\n");
	exit(1);
    }
#endif
    server_init(param.ip_client_port, param.ip_mux_port);
    init_data_base(param.dbase_dir);
}

Per Cederqvist's avatar
Per Cederqvist committed
346 347 348
/* Stop complaint from gcc 2.0 about "no previous prototype for `main'". */
int main(int argc, char **argv);

349
	
Per Cederqvist's avatar
Per Cederqvist committed
350 351 352 353 354
int
main (int    argc,
      char **argv)
{
    int i;
355 356
    char *default_config_file;
    char *config_file;
Per Cederqvist's avatar
Per Cederqvist committed
357

358 359 360 361
    log("*** Version %d (process %d) started.\n",
#include "version.incl"
	, getpid());

362 363
    /* Find out how many connections we can handle. */

Per Cederqvist's avatar
Per Cederqvist committed
364 365 366 367
#if defined (HAVE_SYSCONF)
    MAX_NO_OF_CONNECTIONS = sysconf(_SC_OPEN_MAX) - PROTECTED_FDS;
#else
# ifdef HAVE_GETDTABLESIZE
368
    MAX_NO_OF_CONNECTIONS = getdtablesize() - PROTECTED_FDS;
369 370 371
# else
    /* If we don't have getdtablesize or sysconf, MAX_NO_OF_CONNECTIONS is
       set at compile time. */
Per Cederqvist's avatar
Per Cederqvist committed
372
# endif
373
#endif
374

375

Per Cederqvist's avatar
Per Cederqvist committed
376
#ifdef ENCRYPT_PASSWORDS
377
    /* Seed the random number generator. */
Per Cederqvist's avatar
Per Cederqvist committed
378 379
    srand(time(NULL) + getpid());
#endif
Per Cederqvist's avatar
Per Cederqvist committed
380

381 382
    /* Initialize the string handling package. */
    s_set_storage_management(string_malloc, string_realloc, string_free);
383

384
    /* Parse command line arguments. */
Per Cederqvist's avatar
Per Cederqvist committed
385 386 387 388 389 390 391
    for (i = 1; i < argc && argv[i][0] == '-'; i++)
	switch (argv[i][1])
	{
	case 'd':
	    buglevel++;
	    break;

392 393 394
	default:
	    restart_kom("usage: %s [-d ...] [config-file]\n", argv[0]);
	}
Per Cederqvist's avatar
Per Cederqvist committed
395

396

397
    /* Read in the configuration file. */
398

399 400
    default_config_file = smalloc(strlen(DEFAULT_DBASE_DIR) +
				  strlen(CONFIG_FILE) + 2);
401
    sprintf(default_config_file, "%s/%s", DEFAULT_DBASE_DIR, CONFIG_FILE);
Per Cederqvist's avatar
Per Cederqvist committed
402
    if (i < argc)
403 404 405
	config_file = argv[i++];
    else
	config_file = default_config_file;
Per Cederqvist's avatar
Per Cederqvist committed
406

407 408
    if (i < argc)
	    restart_kom("usage: %s [-d ...] [config-file]\n", argv[0]);
409

Per Cederqvist's avatar
Per Cederqvist committed
410 411 412 413 414
    signal(SIGHUP, sighandler_hup);
    signal(SIGQUIT, sighandler_quit);
    signal(SIGUSR1, sighandler_usr1);
    signal(SIGUSR2, sighandler_usr2);
  
415 416 417
    initialize(config_file);	/* Read config, listen, and start db */
    sfree(default_config_file);

Per Cederqvist's avatar
Per Cederqvist committed
418
    save_pid();
Per Cederqvist's avatar
Per Cederqvist committed
419

Per Cederqvist's avatar
Per Cederqvist committed
420
    toploop();
Per Cederqvist's avatar
Per Cederqvist committed
421 422

    logout_all_clients();
423
    isc_shutdown(kom_server_mcb);
Per Cederqvist's avatar
Per Cederqvist committed
424
    cache_sync_all();
Per Cederqvist's avatar
Per Cederqvist committed
425

426 427
    dump_exit_statistics();

Per Cederqvist's avatar
Per Cederqvist committed
428
    log("%s terminated normally.\n", argv[0]);
429 430 431 432 433 434 435 436 437 438 439 440
    
    return 0;
}

static void 
dump_exit_statistics(void)
{
    FILE *stat_file;
    time_t now;

    time(&now);
    stat_file = fopen(memusefile, "a");
Per Cederqvist's avatar
Per Cederqvist committed
441 442 443 444

    if ( stat_file == NULL )
	restart_kom("Can't open file to save memory usage to.\n");

445 446
    fprintf(stat_file, "\nLysKOM Server going down at %s\n", ctime(&now));

447 448 449 450 451
    dump_cache_stats (stat_file);

    free_all_tmp();
    free_all_cache();

Per Cederqvist's avatar
Per Cederqvist committed
452 453
    dump_smalloc_counts(stat_file);
    dump_alloc_counts(stat_file);
454
    dump_cache_mem_usage(stat_file);
Per Cederqvist's avatar
Per Cederqvist committed
455
    dump_string_alloc_counts(stat_file);
456
    dump_allocated_connections(stat_file);
457
    dump_isc_alloc_counts(stat_file);
Per Cederqvist's avatar
Per Cederqvist committed
458
    fclose (stat_file);
Per Cederqvist's avatar
Per Cederqvist committed
459
}
460
    
Per Cederqvist's avatar
Per Cederqvist committed
461
void
Per Cederqvist's avatar
Per Cederqvist committed
462
#if defined(HAVE_VFPRINTF) && defined(HAVE_STDARG_H)
Per Cederqvist's avatar
Per Cederqvist committed
463
restart_kom(const char * format, ...)
464 465 466 467 468 469
#else
restart_kom(format,
	    a, b, c, d, e, f, g)
     const char *format;
     int a, b, c, d, e, f, g;
#endif
Per Cederqvist's avatar
Per Cederqvist committed
470
{
Per Cederqvist's avatar
Per Cederqvist committed
471
#if defined(HAVE_VFPRINTF) && defined(HAVE_STDARG_H)
Per Cederqvist's avatar
Per Cederqvist committed
472
    va_list AP;
473
#endif
Per Cederqvist's avatar
Per Cederqvist committed
474 475 476
#if defined(HAVE_GETCWD)
    char pathname[1026];
#else /* !defined(HAVE_GETCWD) */
477
    char *getwd(char *); /* +++ should be in sys/param.h */
Per Cederqvist's avatar
Per Cederqvist committed
478 479 480 481 482 483
# if defined(MAXPATHLEN)
    char pathname[MAXPATHLEN];
# else
    char pathname[1024];
# endif /* !defined(MAXPATHLEN) */
#endif /* !defined(HAVE_GETCWD) */
Per Cederqvist's avatar
Per Cederqvist committed
484

Per Cederqvist's avatar
Per Cederqvist committed
485
#if defined(HAVE_VFPRINTF) && defined(HAVE_STDARG_H)
Per Cederqvist's avatar
Per Cederqvist committed
486 487 488
    va_start(AP, format);
    logv(format, AP);
    va_end(AP);
489 490 491
#else
    log(format, a, b, c, d, e, f, g);
#endif
Per Cederqvist's avatar
Per Cederqvist committed
492 493

    log("Previous message is fatal. Will dump core now.\n");
494

Per Cederqvist's avatar
Per Cederqvist committed
495 496 497 498 499 500 501
#ifdef HAVE_GETCWD
    /* getcwd is POSIX, so try that first. */
    if (getcwd(pathname, 1026) == NULL)
	log("getcwd failed: errno %d\n", errno);
    else
	log("Search for the core in %s\n", pathname);
#else
502 503 504 505
    if ( getwd(pathname) == NULL )
	log("getwd failed: %s\n", pathname);
    else
	log("Search for the core in %s\n", pathname);
Per Cederqvist's avatar
Per Cederqvist committed
506
#endif
507
    
Per Cederqvist's avatar
Per Cederqvist committed
508 509
    abort();
}