ramkomd.c 10.6 KB
Newer Older
Linus Tolke Y's avatar
Linus Tolke Y committed
1
/*
2
 * $Id: ramkomd.c,v 0.46 1994/02/19 04:44:56 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.46 1994/02/19 04:44:56 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
#include "conf-file.h"
#include "param.h"
85 86
#include "server-config.h"
#include "manipulate.h"
87 88 89 90 91 92 93 94 95

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


#ifdef DEBUG
int	buglevel = 0;
96
#endif
Per Cederqvist's avatar
Per Cederqvist committed
97

98 99 100 101 102 103
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
104

105 106
static IscSession *listen_client = NULL;      /* ISC listen identifier */
static IscSession *listen_mux    = NULL;      /*          -"-          */
Per Cederqvist's avatar
Per Cederqvist committed
107

108
static void dump_exit_statistics(void);
109

Per Cederqvist's avatar
Per Cederqvist committed
110
static void
111
server_init (char * client_port, char * mux_port)
Per Cederqvist's avatar
Per Cederqvist committed
112
{
Per Cederqvist's avatar
Per Cederqvist committed
113
    IscConfig config;
114
    IscAddress *isc_adr = NULL;
Per Cederqvist's avatar
Per Cederqvist committed
115
    
Per Cederqvist's avatar
Per Cederqvist committed
116 117 118
    /*
    ** Setup some parameters here
    */
Per Cederqvist's avatar
Per Cederqvist committed
119 120 121 122 123
    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;
124
    config.master.abortfn = NULL; /* Use default abort function. */
Per Cederqvist's avatar
Per Cederqvist committed
125
    config.session.version = 1001;
126
    config.session.max.msgsize = -1; /* Use default sizes. */
Per Cederqvist's avatar
Per Cederqvist committed
127 128 129 130
    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
131

132
    kom_server_mcb  = isc_initialize(&config);
Per Cederqvist's avatar
Per Cederqvist committed
133
    if ( kom_server_mcb == NULL )
Per Cederqvist's avatar
Per Cederqvist committed
134 135 136 137 138
	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
139

140 141 142 143
    isc_adr = isc_getladdress (listen_client);
    if (isc_adr == NULL)
	restart_kom("server_init(): can't isc_getladdress (listen_client)\n");

144
    param.num_ip_client_port = isc_getportnum (isc_adr);
145 146 147
    isc_freeaddress (isc_adr);
    
    listen_mux = isc_listentcp (kom_server_mcb, NULL, mux_port);
Per Cederqvist's avatar
Per Cederqvist committed
148 149
    if (listen_mux == NULL)
        restart_kom("server_init: can't isc_listentcp(MUX)\n");
150 151 152 153

    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
154
    
155
    param.num_ip_mux_port = isc_getportnum (isc_adr);
156 157 158
    isc_freeaddress (isc_adr);

    log("Listening for clients on %d and muxes on %d.\n",
159
	param.num_ip_client_port, param.num_ip_mux_port);
Per Cederqvist's avatar
Per Cederqvist committed
160 161 162 163 164 165 166 167 168 169

    /*
     * 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
170
init_data_base(const char *dir_base)
Per Cederqvist's avatar
Per Cederqvist committed
171
{
172 173 174 175 176 177
    sprintf(datafilename,   "%s/%s", dir_base, param.datafile_name);
    sprintf(backupfilename, "%s/%s", dir_base, param.backupfile_name);
    sprintf(textfilename, "%s/%s", dir_base, param.textfile_name);
    sprintf(statisticfile, "%s/%s", dir_base, param.statistic_name);
    sprintf(pidfile, "%s/%s", dir_base, param.pid_name);
    sprintf(memusefile, "%s/%s", dir_base, param.memuse_name);
Per Cederqvist's avatar
Per Cederqvist committed
178 179 180 181 182

    log("Database = %s\n",  datafilename);
    log("Backup = %s\n", backupfilename);
    
    if ( init_cache() == FAILURE )
183
	restart_kom ("Cannot find database.\n");
Per Cederqvist's avatar
Per Cederqvist committed
184 185
}

Per Cederqvist's avatar
Per Cederqvist committed
186
static void
Per Cederqvist's avatar
Per Cederqvist committed
187
sighandler_hup (int sig)
Per Cederqvist's avatar
Per Cederqvist committed
188 189 190 191 192
{
    log ("Signal HUP received. Shutting down server.\n");
    go_and_die = TRUE;
}

Per Cederqvist's avatar
Per Cederqvist committed
193
static void
Per Cederqvist's avatar
Per Cederqvist committed
194
sighandler_quit (int sig)
Per Cederqvist's avatar
Per Cederqvist committed
195 196 197 198 199 200 201
{
    log ("Signal QUIT received - syncing...\n");
    cache_sync_all();
    log ("Dumping core now.\n");
    abort();
}

Per Cederqvist's avatar
Per Cederqvist committed
202
static void
Per Cederqvist's avatar
Per Cederqvist committed
203
sighandler_usr1 (int sig)
Per Cederqvist's avatar
Per Cederqvist committed
204
{
205
    signal(SIGUSR1, sighandler_usr1);
Per Cederqvist's avatar
Per Cederqvist committed
206 207 208
    do_sync_db = TRUE;
}

Per Cederqvist's avatar
Per Cederqvist committed
209
static void
Per Cederqvist's avatar
Per Cederqvist committed
210
sighandler_usr2 (int sig)
Per Cederqvist's avatar
Per Cederqvist committed
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
{
    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
231
static void
Per Cederqvist's avatar
Per Cederqvist committed
232 233 234 235 236 237 238
save_pid(void)
{
    FILE *fp;

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

239
    fprintf(fp, "%ld\n", (long)getpid());
Per Cederqvist's avatar
Per Cederqvist committed
240 241 242
    fclose(fp);
}

243 244 245
void
initialize(const char *config_file)
{
246
    read_configuration(config_file);
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266

#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
267 268 269
/* Stop complaint from gcc 2.0 about "no previous prototype for `main'". */
int main(int argc, char **argv);

270
	
Per Cederqvist's avatar
Per Cederqvist committed
271 272 273 274 275
int
main (int    argc,
      char **argv)
{
    int i;
276 277
    char *default_config_file;
    char *config_file;
Per Cederqvist's avatar
Per Cederqvist committed
278

279 280 281 282
    log("*** Version %d (process %d) started.\n",
#include "version.incl"
	, getpid());

283 284
    /* Find out how many connections we can handle. */

Per Cederqvist's avatar
Per Cederqvist committed
285 286 287 288
#if defined (HAVE_SYSCONF)
    MAX_NO_OF_CONNECTIONS = sysconf(_SC_OPEN_MAX) - PROTECTED_FDS;
#else
# ifdef HAVE_GETDTABLESIZE
289
    MAX_NO_OF_CONNECTIONS = getdtablesize() - PROTECTED_FDS;
290 291 292
# 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
293
# endif
294
#endif
295

296

Per Cederqvist's avatar
Per Cederqvist committed
297
#ifdef ENCRYPT_PASSWORDS
298
    /* Seed the random number generator. */
Per Cederqvist's avatar
Per Cederqvist committed
299 300
    srand(time(NULL) + getpid());
#endif
Per Cederqvist's avatar
Per Cederqvist committed
301

302 303
    /* Initialize the string handling package. */
    s_set_storage_management(string_malloc, string_realloc, string_free);
304

305
    /* Parse command line arguments. */
Per Cederqvist's avatar
Per Cederqvist committed
306 307 308 309 310 311 312
    for (i = 1; i < argc && argv[i][0] == '-'; i++)
	switch (argv[i][1])
	{
	case 'd':
	    buglevel++;
	    break;

313 314 315
	default:
	    restart_kom("usage: %s [-d ...] [config-file]\n", argv[0]);
	}
Per Cederqvist's avatar
Per Cederqvist committed
316

317

318
    /* Read in the configuration file. */
319

320 321
    default_config_file = smalloc(strlen(DEFAULT_DBASE_DIR) +
				  strlen(CONFIG_FILE) + 2);
322
    sprintf(default_config_file, "%s/%s", DEFAULT_DBASE_DIR, CONFIG_FILE);
Per Cederqvist's avatar
Per Cederqvist committed
323
    if (i < argc)
324 325 326
	config_file = argv[i++];
    else
	config_file = default_config_file;
Per Cederqvist's avatar
Per Cederqvist committed
327

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

Per Cederqvist's avatar
Per Cederqvist committed
331 332 333 334 335
    signal(SIGHUP, sighandler_hup);
    signal(SIGQUIT, sighandler_quit);
    signal(SIGUSR1, sighandler_usr1);
    signal(SIGUSR2, sighandler_usr2);
  
336 337 338
    initialize(config_file);	/* Read config, listen, and start db */
    sfree(default_config_file);

Per Cederqvist's avatar
Per Cederqvist committed
339
    save_pid();
Per Cederqvist's avatar
Per Cederqvist committed
340

Per Cederqvist's avatar
Per Cederqvist committed
341
    toploop();
Per Cederqvist's avatar
Per Cederqvist committed
342 343

    logout_all_clients();
344
    isc_shutdown(kom_server_mcb);
Per Cederqvist's avatar
Per Cederqvist committed
345
    cache_sync_all();
Per Cederqvist's avatar
Per Cederqvist committed
346

347 348
    dump_exit_statistics();

Per Cederqvist's avatar
Per Cederqvist committed
349
    log("%s terminated normally.\n", argv[0]);
350 351 352 353 354 355 356 357 358 359 360 361
    
    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
362 363 364 365

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

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

368 369 370 371
    dump_cache_stats (stat_file);

    free_all_tmp();
    free_all_cache();
372
    free_all_jubel();
373

Per Cederqvist's avatar
Per Cederqvist committed
374 375
    dump_smalloc_counts(stat_file);
    dump_alloc_counts(stat_file);
376
    dump_cache_mem_usage(stat_file);
Per Cederqvist's avatar
Per Cederqvist committed
377
    dump_string_alloc_counts(stat_file);
378
    dump_allocated_connections(stat_file);
379
    dump_isc_alloc_counts(stat_file);
Per Cederqvist's avatar
Per Cederqvist committed
380
    fclose (stat_file);
Per Cederqvist's avatar
Per Cederqvist committed
381
}
382
    
Per Cederqvist's avatar
Per Cederqvist committed
383
void
Per Cederqvist's avatar
Per Cederqvist committed
384
#if defined(HAVE_VFPRINTF) && defined(HAVE_STDARG_H)
Per Cederqvist's avatar
Per Cederqvist committed
385
restart_kom(const char * format, ...)
386 387 388 389 390 391
#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
392
{
Per Cederqvist's avatar
Per Cederqvist committed
393
#if defined(HAVE_VFPRINTF) && defined(HAVE_STDARG_H)
Per Cederqvist's avatar
Per Cederqvist committed
394
    va_list AP;
395
#endif
Per Cederqvist's avatar
Per Cederqvist committed
396 397 398
#if defined(HAVE_GETCWD)
    char pathname[1026];
#else /* !defined(HAVE_GETCWD) */
399
    char *getwd(char *); /* +++ should be in sys/param.h */
Per Cederqvist's avatar
Per Cederqvist committed
400 401 402 403 404 405
# if defined(MAXPATHLEN)
    char pathname[MAXPATHLEN];
# else
    char pathname[1024];
# endif /* !defined(MAXPATHLEN) */
#endif /* !defined(HAVE_GETCWD) */
Per Cederqvist's avatar
Per Cederqvist committed
406

Per Cederqvist's avatar
Per Cederqvist committed
407
#if defined(HAVE_VFPRINTF) && defined(HAVE_STDARG_H)
Per Cederqvist's avatar
Per Cederqvist committed
408 409 410
    va_start(AP, format);
    logv(format, AP);
    va_end(AP);
411 412 413
#else
    log(format, a, b, c, d, e, f, g);
#endif
Per Cederqvist's avatar
Per Cederqvist committed
414 415

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

Per Cederqvist's avatar
Per Cederqvist committed
417 418 419 420 421 422 423
#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
424 425 426 427
    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
428
#endif
429
    
Per Cederqvist's avatar
Per Cederqvist committed
430 431
    abort();
}