2001-08-17 05:46:24 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
2001-11-04 16:41:54 +00:00
|
|
|
* $Id$
|
2001-08-17 05:46:24 +00:00
|
|
|
* Purpose ...............: Main startup
|
|
|
|
*
|
|
|
|
*****************************************************************************
|
2007-02-11 14:52:47 +00:00
|
|
|
* Copyright (C) 1997-2007
|
2001-08-17 05:46:24 +00:00
|
|
|
*
|
|
|
|
* Michiel Broek FIDO: 2:280/2802
|
|
|
|
* Beekmansbos 10
|
|
|
|
* 1971 BV IJmuiden
|
|
|
|
* the Netherlands
|
|
|
|
*
|
|
|
|
* This file is part of MBSE BBS.
|
|
|
|
*
|
|
|
|
* This BBS 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 2, or (at your option) any
|
|
|
|
* later version.
|
|
|
|
*
|
|
|
|
* MBSE BBS 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 MBSE BBS; see the file COPYING. If not, write to the Free
|
2003-08-15 20:05:34 +00:00
|
|
|
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
2001-08-17 05:46:24 +00:00
|
|
|
*****************************************************************************/
|
|
|
|
|
2002-06-30 12:48:44 +00:00
|
|
|
#include "../config.h"
|
2004-02-21 17:22:00 +00:00
|
|
|
#include "../lib/mbselib.h"
|
2001-08-17 05:46:24 +00:00
|
|
|
#include "../lib/mbse.h"
|
2002-01-07 19:16:03 +00:00
|
|
|
#include "../lib/users.h"
|
2001-08-17 05:46:24 +00:00
|
|
|
#include "../lib/msg.h"
|
|
|
|
#include "mbsebbs.h"
|
|
|
|
#include "user.h"
|
2001-11-10 17:14:16 +00:00
|
|
|
#include "dispfile.h"
|
2001-08-17 05:46:24 +00:00
|
|
|
#include "language.h"
|
|
|
|
#include "menu.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include "bye.h"
|
|
|
|
#include "timeout.h"
|
2001-11-12 21:42:17 +00:00
|
|
|
#include "funcs.h"
|
2004-10-27 11:08:09 +00:00
|
|
|
#include "term.h"
|
2004-11-03 20:48:45 +00:00
|
|
|
#include "ttyio.h"
|
|
|
|
#include "openport.h"
|
2006-02-06 21:16:17 +00:00
|
|
|
#include "input.h"
|
2001-11-12 21:42:17 +00:00
|
|
|
|
2004-02-26 20:16:10 +00:00
|
|
|
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2005-10-07 20:42:35 +00:00
|
|
|
extern int do_quiet; /* Logging quiet flag */
|
2001-08-17 05:46:24 +00:00
|
|
|
time_t t_start;
|
2005-10-07 20:42:35 +00:00
|
|
|
int cols = 80; /* Screen columns */
|
|
|
|
int rows = 24; /* Screen rows */
|
2001-08-17 05:46:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2005-08-26 20:52:32 +00:00
|
|
|
FILE *pTty;
|
|
|
|
char *p, *tty, temp[PATH_MAX];
|
2005-11-22 19:39:32 +00:00
|
|
|
int i, rc, Fix;
|
2005-08-26 20:52:32 +00:00
|
|
|
struct stat sb;
|
|
|
|
struct winsize ws;
|
2006-02-06 21:16:17 +00:00
|
|
|
unsigned char ch = 0;
|
|
|
|
|
2002-12-05 20:44:38 +00:00
|
|
|
pTTY = calloc(15, sizeof(char));
|
|
|
|
tty = ttyname(1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find username from the environment
|
|
|
|
*/
|
|
|
|
sUnixName[0] = '\0';
|
|
|
|
if (getenv("LOGNAME") != NULL) {
|
|
|
|
strncpy(sUnixName, getenv("LOGNAME"), 8);
|
|
|
|
} else if (getenv("USER") != NULL) {
|
|
|
|
strcpy(sUnixName, getenv("USER"));
|
|
|
|
} else {
|
2004-11-03 20:48:45 +00:00
|
|
|
fprintf(stderr, "No username in environment\n");
|
2002-12-05 20:44:38 +00:00
|
|
|
Quick_Bye(MBERR_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get MBSE_ROOT Path and load Config into Memory
|
|
|
|
*/
|
|
|
|
FindMBSE();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set local time and statistic indexes.
|
|
|
|
*/
|
|
|
|
Time_Now = t_start = time(NULL);
|
|
|
|
l_date = localtime(&Time_Now);
|
|
|
|
Diw = l_date->tm_wday;
|
|
|
|
Miy = l_date->tm_mon;
|
|
|
|
ltime = time(NULL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize this client with the server.
|
|
|
|
*/
|
|
|
|
do_quiet = TRUE;
|
2003-09-09 19:39:51 +00:00
|
|
|
InitClient(sUnixName, (char *)"mbsebbs", (char *)"Unknown", CFG.logfile,
|
|
|
|
CFG.bbs_loglevel, CFG.error_log, CFG.mgrlog, CFG.debuglog);
|
2002-12-05 20:44:38 +00:00
|
|
|
IsDoing("Loging in");
|
|
|
|
Syslog(' ', " ");
|
|
|
|
Syslog(' ', "MBSEBBS v%s", VERSION);
|
|
|
|
|
2006-02-06 21:16:17 +00:00
|
|
|
if ((rc = rawport()) != 0) {
|
|
|
|
WriteError("Unable to set raw mode");
|
|
|
|
Quick_Bye(MBERR_OK);;
|
|
|
|
}
|
|
|
|
|
2005-10-07 20:42:35 +00:00
|
|
|
if (ioctl(1, TIOCGWINSZ, &ws) != -1 && (ws.ws_col > 0) && (ws.ws_row > 0)) {
|
|
|
|
cols = ws.ws_col;
|
|
|
|
rows = ws.ws_row;
|
2006-02-06 21:16:17 +00:00
|
|
|
PUTSTR((char *)"Loading MBSE BBS ...");
|
|
|
|
Enter(1);
|
2006-02-05 11:20:59 +00:00
|
|
|
} else {
|
|
|
|
Syslog('b', "Could not get screensize using ioctl() call");
|
|
|
|
if (getenv("LINES") != NULL) {
|
|
|
|
rows = atoi(getenv("LINES"));
|
2006-02-06 21:16:17 +00:00
|
|
|
PUTSTR((char *)"Loading MBSE BBS ...");
|
|
|
|
Enter(1);
|
2006-02-05 11:20:59 +00:00
|
|
|
} else {
|
2006-02-06 14:23:35 +00:00
|
|
|
Syslog('b', "Could not get screensize from environment too");
|
2006-02-06 21:16:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Next idea borrowed from Synchronet BBS
|
|
|
|
*/
|
|
|
|
PUTSTR((char *)"\r\n"); /* Locate cursor at column 1 */
|
|
|
|
PUTSTR((char *)"\x1b[s"); /* Save cursor position (necessary for HyperTerm auto-ANSI) */
|
|
|
|
PUTSTR((char *)"\x1b[99B_"); /* locate cursor as far down as possible */
|
|
|
|
PUTSTR((char *)"\x1b[6n"); /* Get cursor position */
|
|
|
|
PUTSTR((char *)"\x1b[u"); /* Restore cursor position */
|
|
|
|
// PUTSTR((char *)"\x1b[!_"); /* RIP? */
|
|
|
|
// PUTSTR((char *)"\x1b[0t_"); /* WIP? */
|
|
|
|
// PUTSTR((char *)"\2\2?HTML?"); /* HTML? */
|
|
|
|
PUTSTR((char *)"\x1b[0m_"); /* "Normal" colors */
|
|
|
|
PUTSTR((char *)"\x1b[2J"); /* clear screen */
|
|
|
|
PUTSTR((char *)"\x1b[H"); /* home cursor */
|
|
|
|
PUTSTR((char *)"\xC"); /* clear screen (in case not ANSI) */
|
|
|
|
PUTSTR((char *)"\r"); /* Move cursor left (in case previous char printed) */
|
2007-02-11 14:52:47 +00:00
|
|
|
PUTSTR((char *)"Loading MBSE BBS ..."); /* Let the user think something is happening */
|
2006-02-06 21:16:17 +00:00
|
|
|
Enter(1);
|
|
|
|
|
|
|
|
memset(&temp, 0, sizeof(temp));
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
|
|
rc = Waitchar(&ch, 200); /* 4 seconds timeout */
|
|
|
|
if (rc == 1) {
|
|
|
|
temp[i] = ch;
|
|
|
|
if (ch > 31)
|
|
|
|
Syslog('b', "detect rc=%d ch=%d ch=%c", rc, ch, ch);
|
|
|
|
else
|
|
|
|
Syslog('b', "detect rc=%d ch=%d ch=^%c", rc, ch, ch+64);
|
|
|
|
}
|
|
|
|
if (rc == TIMEOUT)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((temp[0] == '\x1b') && (temp[1] == '[') && strchr(temp, ';') /*&& strchr(temp, 'R') */) {
|
|
|
|
rows = atoi(strtok(temp +2, ";"));
|
|
|
|
Syslog('b', "detected ANSI cursor position at row %d", rows);
|
|
|
|
if (rows < 24)
|
|
|
|
rows = 24;
|
|
|
|
}
|
2006-02-05 11:20:59 +00:00
|
|
|
}
|
2005-08-26 20:52:32 +00:00
|
|
|
}
|
|
|
|
|
2002-12-05 20:44:38 +00:00
|
|
|
if ((p = getenv("CONNECT")) != NULL)
|
|
|
|
Syslog('+', "CONNECT %s", p);
|
|
|
|
if ((p = getenv("CALLER_ID")) != NULL)
|
|
|
|
if (strncmp(p, "none", 4))
|
2003-08-04 19:32:07 +00:00
|
|
|
Syslog('+', "CALLER_ID %s", p);
|
2005-07-03 16:14:17 +00:00
|
|
|
if ((p = getenv("TERM")) != NULL)
|
2005-10-07 21:56:12 +00:00
|
|
|
Syslog('+', "TERM=%s %dx%d", p, cols, rows);
|
|
|
|
else
|
|
|
|
Syslog('+', "TERM=invalid %dx%d", cols, rows);
|
2005-07-14 19:29:59 +00:00
|
|
|
if ((p = getenv("LANG")) != NULL)
|
2005-07-14 19:29:25 +00:00
|
|
|
Syslog('+', "LANG=%s", p);
|
|
|
|
if ((p = getenv("LC_ALL")) != NULL)
|
|
|
|
Syslog('+', "LC_ALL=%s", p);
|
2002-12-05 20:44:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize
|
|
|
|
*/
|
2007-02-17 12:14:16 +00:00
|
|
|
snprintf(current_language, 10, "%s", CFG.deflang);
|
2002-12-05 20:44:38 +00:00
|
|
|
InitLanguage();
|
|
|
|
InitMenu();
|
|
|
|
memset(&MsgBase, 0, sizeof(MsgBase));
|
2005-10-08 17:58:23 +00:00
|
|
|
|
2002-12-05 20:44:38 +00:00
|
|
|
i = getpid();
|
|
|
|
|
|
|
|
if ((tty = ttyname(0)) == NULL) {
|
|
|
|
WriteError("Not at a tty");
|
2003-12-04 22:07:33 +00:00
|
|
|
Free_Language();
|
2002-12-05 20:44:38 +00:00
|
|
|
Quick_Bye(MBERR_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strncmp("/dev/", tty, 5) == 0)
|
2005-08-29 10:59:47 +00:00
|
|
|
snprintf(pTTY, 15, "%s", tty+5);
|
2002-12-05 20:44:38 +00:00
|
|
|
else if (*tty == '/') {
|
|
|
|
tty = strrchr(ttyname(0), '/');
|
|
|
|
++tty;
|
2005-08-29 10:59:47 +00:00
|
|
|
snprintf(pTTY, 15, "%s", tty);
|
2002-12-05 20:44:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
umask(007);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Trap signals
|
|
|
|
*/
|
2004-11-03 20:48:45 +00:00
|
|
|
for (i = 0; i < NSIG; i++) {
|
|
|
|
if ((i == SIGHUP) || (i == SIGPIPE) || (i == SIGBUS) || (i == SIGILL) || (i == SIGSEGV) || (i == SIGTERM))
|
2002-12-05 20:44:38 +00:00
|
|
|
signal(i, (void (*))die);
|
2004-04-09 18:31:22 +00:00
|
|
|
else if (i == SIGCHLD)
|
|
|
|
signal(i, SIG_DFL);
|
2002-12-05 20:44:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Default set the terminal to ANSI mode. If your logo
|
|
|
|
* is in color, the user will see color no mather what.
|
|
|
|
*/
|
2005-10-07 21:56:12 +00:00
|
|
|
TermInit(1);
|
2004-11-03 20:48:45 +00:00
|
|
|
|
2002-12-05 20:44:38 +00:00
|
|
|
/*
|
|
|
|
* Now it's time to check if the bbs is open. If not, we
|
|
|
|
* log the user off.
|
|
|
|
*/
|
|
|
|
if (CheckStatus() == FALSE) {
|
|
|
|
Syslog('+', "Kicking user out, the BBS is closed");
|
2003-12-04 22:07:33 +00:00
|
|
|
Free_Language();
|
2002-12-05 20:44:38 +00:00
|
|
|
Quick_Bye(MBERR_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
clear();
|
|
|
|
DisplayLogo();
|
|
|
|
|
2005-08-29 10:59:47 +00:00
|
|
|
snprintf(temp, 81, "MBSE BBS v%s (Release: %s) on %s/%s", VERSION, ReleaseDate, OsName(), OsCPU());
|
2004-11-03 20:48:45 +00:00
|
|
|
poutCR(YELLOW, BLACK, temp);
|
|
|
|
pout(WHITE, BLACK, (char *)COPYRIGHT);
|
2005-10-08 17:58:23 +00:00
|
|
|
|
2006-02-06 14:23:35 +00:00
|
|
|
/*
|
|
|
|
* Use 80 wide screens
|
|
|
|
*/
|
|
|
|
if (cols > 80)
|
|
|
|
cols = 80;
|
|
|
|
|
2005-10-08 17:58:23 +00:00
|
|
|
/*
|
|
|
|
* Check and report screens that are too small
|
|
|
|
*/
|
|
|
|
if ((cols < 80) || (rows < 24)) {
|
|
|
|
snprintf(temp, 81, "Your screen is set to %dx%d, we use 80x24 at least", cols, rows);
|
|
|
|
poutCR(LIGHTRED, BLACK, temp);
|
|
|
|
Enter(1);
|
|
|
|
cols = 80;
|
|
|
|
rows = 24;
|
|
|
|
} else {
|
|
|
|
Enter(2);
|
|
|
|
}
|
2002-12-05 20:44:38 +00:00
|
|
|
|
2004-07-04 13:33:43 +00:00
|
|
|
/*
|
|
|
|
* Check users homedirectory, some *nix systems let users in if no
|
2005-11-22 19:39:32 +00:00
|
|
|
* homedirectory exists. Then check the permissions.
|
2004-07-04 13:33:43 +00:00
|
|
|
*/
|
2005-08-29 10:59:47 +00:00
|
|
|
snprintf(temp, PATH_MAX, "%s/%s", CFG.bbs_usersdir, sUnixName);
|
2004-07-04 13:33:43 +00:00
|
|
|
if (stat(temp, &sb)) {
|
2005-08-29 10:59:47 +00:00
|
|
|
snprintf(temp, 81, "No homedirectory\r\n\r\n");
|
2004-11-03 20:48:45 +00:00
|
|
|
PUTSTR(temp);
|
2004-07-04 13:33:43 +00:00
|
|
|
WriteError("homedirectory %s doesn't exist", temp);
|
|
|
|
Quick_Bye(MBERR_OK);
|
|
|
|
}
|
2005-11-22 19:39:32 +00:00
|
|
|
Fix = FALSE;
|
|
|
|
if ((sb.st_mode & S_IRUSR) == 0) {
|
|
|
|
Fix = TRUE;
|
|
|
|
WriteError("No owner read access in %s, mode is %04o", temp, sb.st_mode & 0x1ff);
|
|
|
|
}
|
|
|
|
if ((sb.st_mode & S_IWUSR) == 0) {
|
|
|
|
Fix = TRUE;
|
|
|
|
WriteError("No owner write access in %s, mode is %04o", temp, sb.st_mode & 0x1ff);
|
|
|
|
}
|
|
|
|
if ((sb.st_mode & S_IXUSR) == 0) {
|
|
|
|
Fix = TRUE;
|
|
|
|
WriteError("No owner execute access in %s, mode is %04o", temp, sb.st_mode & 0x1ff);
|
|
|
|
}
|
|
|
|
if ((sb.st_mode & S_IRGRP) == 0) {
|
|
|
|
Fix = TRUE;
|
|
|
|
WriteError("No group read access in %s, mode is %04o", temp, sb.st_mode & 0x1ff);
|
|
|
|
}
|
|
|
|
if ((sb.st_mode & S_IWGRP) == 0) {
|
|
|
|
Fix = TRUE;
|
|
|
|
WriteError("No group write access in %s, mode is %04o", temp, sb.st_mode & 0x1ff);
|
|
|
|
}
|
|
|
|
if ((sb.st_mode & S_IXGRP) == 0) {
|
|
|
|
Fix = TRUE;
|
|
|
|
WriteError("No group execute access in %s, mode is %04o", temp, sb.st_mode & 0x1ff);
|
|
|
|
}
|
|
|
|
if ((sb.st_mode & S_IROTH)) {
|
|
|
|
Fix = TRUE;
|
|
|
|
WriteError("Others have read access in %s, mode is %04o", temp, sb.st_mode & 0x1ff);
|
|
|
|
}
|
|
|
|
if ((sb.st_mode & S_IWOTH)) {
|
|
|
|
Fix = TRUE;
|
|
|
|
WriteError("Others have write access in %s, mode is %04o", temp, sb.st_mode & 0x1ff);
|
|
|
|
}
|
|
|
|
if ((sb.st_mode & S_IXOTH)) {
|
|
|
|
Fix = TRUE;
|
|
|
|
WriteError("Others have execute access in %s, mode is %04o", temp, sb.st_mode & 0x1ff);
|
|
|
|
}
|
|
|
|
if (Fix) {
|
|
|
|
if (chmod(temp, 0770)) {
|
|
|
|
WriteError("Could not set home directory mode to 0770");
|
|
|
|
snprintf(temp, 81, "Internal error, the sysop is notified");
|
|
|
|
poutCR(LIGHTRED, BLACK, temp);
|
|
|
|
Enter(1);
|
|
|
|
Quick_Bye(MBERR_OK);
|
|
|
|
} else {
|
|
|
|
Syslog('+', "Corrected home directory mode to 0770");
|
|
|
|
}
|
|
|
|
}
|
2005-10-08 17:58:23 +00:00
|
|
|
|
2005-10-17 11:23:11 +00:00
|
|
|
if (((p = getenv("REMOTEHOST")) != NULL) || ((p = getenv("SSH_CLIENT")) != NULL)) {
|
2005-10-08 17:58:23 +00:00
|
|
|
/*
|
|
|
|
* Network connection, no tty checking but fill a ttyinfo record.
|
|
|
|
*/
|
|
|
|
memset(&ttyinfo, 0, sizeof(ttyinfo));
|
|
|
|
snprintf(ttyinfo.comment, 41, "%s", p);
|
|
|
|
snprintf(ttyinfo.tty, 7, "%s", pTTY);
|
|
|
|
snprintf(ttyinfo.speed, 21, "10 mbit");
|
|
|
|
snprintf(ttyinfo.flags, 31, "IBN,IFC,XX");
|
|
|
|
ttyinfo.type = NETWORK;
|
|
|
|
ttyinfo.available = TRUE;
|
2005-10-17 11:23:11 +00:00
|
|
|
ttyinfo.honor_zmh = FALSE;
|
2005-10-08 17:58:23 +00:00
|
|
|
snprintf(ttyinfo.name, 36, "Network port #%d", iNode);
|
2002-12-05 20:44:38 +00:00
|
|
|
} else {
|
2005-10-08 17:58:23 +00:00
|
|
|
/*
|
|
|
|
* Check if this port is available.
|
|
|
|
*/
|
|
|
|
snprintf(temp, PATH_MAX, "%s/etc/ttyinfo.data", getenv("MBSE_ROOT"));
|
|
|
|
if ((pTty = fopen(temp, "r")) == NULL) {
|
|
|
|
WriteError("Can't read %s", temp);
|
|
|
|
} else {
|
|
|
|
fread(&ttyinfohdr, sizeof(ttyinfohdr), 1, pTty);
|
2002-12-05 20:44:38 +00:00
|
|
|
|
2005-10-08 17:58:23 +00:00
|
|
|
while (fread(&ttyinfo, ttyinfohdr.recsize, 1, pTty) == 1) {
|
|
|
|
if (strcmp(ttyinfo.tty, pTTY) == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fclose(pTty);
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2005-10-08 17:58:23 +00:00
|
|
|
if ((strcmp(ttyinfo.tty, pTTY) != 0) || (!ttyinfo.available)) {
|
|
|
|
Syslog('+', "No BBS allowed on port \"%s\"", pTTY);
|
|
|
|
snprintf(temp, 81, "No BBS on this port allowed!\r\n\r\n");
|
|
|
|
PUTSTR(temp);
|
|
|
|
Free_Language();
|
|
|
|
Quick_Bye(MBERR_OK);
|
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
2002-12-05 20:44:38 +00:00
|
|
|
}
|
2001-08-17 05:46:24 +00:00
|
|
|
|
2005-10-08 17:58:23 +00:00
|
|
|
/*
|
|
|
|
* Display Connect String if turned on.
|
|
|
|
*/
|
|
|
|
if (CFG.iConnectString) {
|
|
|
|
/* Connected from */
|
|
|
|
snprintf(temp, 81, "%s\"%s\" ", (char *) Language(348), ttyinfo.comment);
|
|
|
|
pout(CYAN, BLACK, temp);
|
|
|
|
/* line */
|
|
|
|
snprintf(temp, 81, "%s%d ", (char *) Language(31), iNode);
|
|
|
|
pout(CYAN, BLACK, temp);
|
|
|
|
/* on */
|
|
|
|
snprintf(temp, 81, "%s %s", (char *) Language(135), ctime(<ime));
|
|
|
|
PUTSTR(temp);
|
|
|
|
Enter(1);
|
|
|
|
}
|
|
|
|
|
2005-08-29 10:59:47 +00:00
|
|
|
snprintf(sMailbox, 21, "mailbox");
|
2002-12-05 20:44:38 +00:00
|
|
|
colour(LIGHTGRAY, BLACK);
|
|
|
|
user();
|
|
|
|
return 0;
|
2001-08-17 05:46:24 +00:00
|
|
|
}
|
|
|
|
|