This is bbs.c in view mode; [Download] [Up]
/* $Id: bbs.c,v 1.2 1995/12/19 19:30:47 eilts Exp eilts $ */
#include "bbs.h"
volatile SIG_ATOMIC_T signumber = -1;
volatile SIG_ATOMIC_T canjump_sigalrm = (int)FALSE;
volatile SIG_ATOMIC_T canjump_sigenv = (int)FALSE;
volatile SIG_ATOMIC_T canjump_talkaccept = (int)FALSE;
volatile SIG_ATOMIC_T canjump_sigusr1 = (int)FALSE;
volatile SIG_ATOMIC_T canjump_sigusr2 = (int)FALSE;
SIGSET_T old_blocksigset;
sigmaskstatusenum blocksigsetstatus = SIGMASK_UNSET;
sigjmp_buf sigenv, sigalrmenv, talkacceptenv, sigusr1env, sigusr2env;
const char *protokollnamen[] = {"Kermit","Z-Modem"};
const char *charsets[] = {"original","ASCII","NeXT","?",NULL};
const char *sprachennamen[] = {"Deutsch","English"};
const char *sprachensuffix[] = {"ger","eng"};
boolean bbsdaemon = FALSE;
struct termios save_termios;
ttystateenum ttystate = TTY_RESET;
int main(int argc, char *argv[], char *environ[])
/*
Die Clients (bbs)
*/
{
PID_T pid;
int cmdnr, seclevel;
char cmd[S_STRLEN+1], params[ARG_MAX+1], cmdline[ARG_MAX+1],
path[PATH_MAX+1], conffile[PATH_MAX+1], tzenvstr[S_STRLEN], *sp, c;
chrootrecordtyp chrootrecord;
confrecordtyp confrecord;
SIGSET_T sigset;
boolean argserror=FALSE;
extern int optind, opterr, optopt;
extern char *optarg;
menuetyp startmenue[] = {
{HELP_KEY,{"Kurzhilfe anzeigen","show Help"},"help"},
{DOC_KEY,{"ausfuehrliche Anleitung anzeigen","show Manual"},"anl"},
{SYS_KEY,{"Systemparameter aendern","system configuration"},"sys"},
{' ',{"",""},""},
{DIR_KEY,{"aktuelles Directory auflisten","list directory"},"dir"},
{CD_KEY,{"aktuelles Directory wechseln","change directory"},"cd"},
{PWD_KEY,{"Namen vom aktuellen Directory anzeigen","directoryname"},"pwd"},
{SHOW_KEY,{"Dateiinhalt anzeigen","show file"},"show"},
{' ',{"",""},""},
{DOWNLOAD_KEY,{"Dateien downladen","download files"},"get"},
{UPLOAD_KEY,{"Dateien upladen","upload files"},"put"},
{' ',{"",""},""},
{BBS_KEY,{"BBS-System","BBS-System"},"bbssys"},
{' ',{"",""},""},
{QUIT_KEY,{"Programm beenden und Verbindung abbauen","exit program"},
"quit"},
{'\0',{"",""},""}
};
menuetyp sysmenue[] = {
{ENV_KEY,{"momentane Parameter abfragen","show current settings"},"env"},
{LANG_KEY,{"Sprachwahl","Language"},"lang"},
{PROT_KEY,{"Datenuebertragungsprotokoll","change transmittion protocol"},
"pr"},
#ifndef NO_TV_USEC
{AUTOZ_KEY,{"Z-Modem Uploadautomatik","automatic Z-Modem uploads"},"azm"},
#endif
{FULLIST_KEY,{"Dateien bei Directorywechsel listen",
"list files on change directory"},"fullist"},
{TERM_KEY,{"Terminaltyp und Zeichensatz einstellen",
"change terminaltype and charset"},"te"},
{PASSWD_KEY,{"neues Password","new password"},"npass"},
{' ',{"",""},""},
{QUIT_KEY,{"Zurueck zum Hauptmenue","back to Mainmenue"},""},
{'\0',{"",""},""}
};
menuetyp bbsmenue[] = {
{TALK_KEY,{"Dialog mit anderem User","talking to another user"},"talk"},
{MESSAGE_KEY,{"Nachricht an BBS-Benutzer","message to BBS user"},"messag"},
{SYSOPMAIL_KEY,{"E-Mail an Sysop","e-mail to sysop"},"sysmail"},
{EMAIL_KEY,{"E-Mail an Externe","e-mail to external"},"sysmail"},
{MSGBROWSE_KEY,{"Nachrichten/E-Mail lesen","read messages/e-mail"},"msgbrowse"},
{NEWSBROWSE_KEY,{"News lesen","read news"},"newsbrowse"},
{NEWSPOST_KEY,{"Newsartikel senden","post news article"},"newspost"},
{NEWSSUBSCR_KEY,{"Newsgruppen abbonieren","subscribe newsgroups"},"newssubscr"},
{' ',{"",""},""},
{QUIT_KEY,{"Zurueck zum Hauptmenue","back to Mainmenue"},""},
{'\0',{"",""},""}
};
/* Environment loeschen und einige Variable vorbesetzen */
*tzenvstr = '\0';
if ((sp=getenv("TZ")) != NULL) {
strncpy(tzenvstr,sp,S_STRLEN);
}
environ[0] = (char *)NULL;
mputenv("EDITOR=/bin/false");
if (*tzenvstr != '\0') mdefenv("TZ",tzenvstr);
openlog("bbs",LOG_PID,LOG_BBS);
seclevel = -1;
confrecord.curses_on = FALSE;
strcpy(conffile,CONFFILE);
confrecord.userrecord.seclevel = -1;
confrecord.userrecord.name[0] = '\0';
/* Optionen verarbeiten */
opterr = FALSE;
while ((c = getopt(argc, argv, "c:l:s:")) != EOF) {
switch (c) {
case 's':
seclevel = atoi(optarg);
break;
case 'l':
strmaxcpy(confrecord.userrecord.name,optarg,S_STRLEN);
break;
case 'c':
strmaxcpy(conffile,optarg,PATH_MAX);
break;
case '?':
fprintf(stderr,"bbs: unrecognized option: -%c\n", optopt);
argserror = TRUE;
}
}
if (argserror || (optind < argc)) {
fprintf(stderr,"usage: bbs [-s seclevel] [-l username] [-c conffile]\n");
exit(-1);
}
/* sigusr1 und sigusr2 blockieren */
sigemptyset(&sigset);
sigaddset(&sigset,SIGUSR1);
sigaddset(&sigset,SIGUSR2);
sigprocmask(SIG_SETMASK,&sigset,NULL);
/* Einsprungpunkt fuer einige Signale (ausser sigalrm) */
signumber = -1;
if (sigsetjmp(sigenv,(int)FALSE)==0) {
canjump_sigenv = TRUE;
setsighandler(SIGINT, SIG_IGN);
setsighandler(SIGTERM, sighandler);
setsighandler(SIGHUP, sighandler);
}
else {
switch(signumber) {
case -1:
errormsg(E_LOGFILE|E_USER,&confrecord,"bbs","bbs",
msg("bbs",0,confrecord.lang));
break;
case SIGTERM:
errormsg(E_LOGFILE|E_USER,&confrecord,"bbs","bbs",
msg("bbs",1,confrecord.lang));
break;
case SIGHUP:
errormsg(E_LOGFILE|E_USER,&confrecord,"bbs","bbs",
msg("bbs",2,confrecord.lang));
break;
default:
errormsg(E_LOGFILE|E_USER, &confrecord,"bbs","bbs",
msg("bbs",3,confrecord.lang));
}
bbsexit(0,&confrecord);
}
/* Sitzung initialisieren */
if ((pid=bbsinit(&chrootrecord, &confrecord, conffile)) < 0) {
if (pid < -1) removesession(-pid,&confrecord);
exit(-1);
}
/* ab hier laeuft der Daemon bereits */
/* Menue (curses) initialisieren */
if (window_on(&save_termios,&ttystate,&confrecord) < 0) exit(-1);
if (seclevel >= 0) confrecord.userrecord.seclevel = seclevel;
#ifdef NO_TV_USEC
confrecord.userrecord.autozmodem = FALSE;
#endif
#ifdef AUTOLISTFILE
if (checkfileperms(AUTOLISTFILE,geteuid(),getegid()) == 0) {
do_showfile(AUTOLISTFILE,NULL,chrootrecord.cwd,chrootrecord.root,
&confrecord);
}
#endif
/* Befehle vom User einlesen und abarbeiten */
cmdline[0] = '\0';
cmdnr = 1;
do {
if (sigsetjmp(talkacceptenv,(int)FALSE)==0) {
canjump_talkaccept = TRUE;
}
else {
alarm(0);
remconnecttouser(&confrecord);
}
#ifndef DEBUG
/* Timer fuer Befehlseingabe-Timeout */
setsighandler(SIGALRM, sighandler);
alarm(confrecord.idletimeout);
#endif
if (sigsetjmp(sigalrmenv,(int)FALSE)==0) {
canjump_sigalrm = TRUE;
/* Menue ausgeben und Kommando einlesen */
if (getcmdline_c(cmdline,startmenue,sysmenue,bbsmenue,&chrootrecord,
&confrecord) < 0) {
cmdline[0] = '\0';
}
/* Befehlseingabe-Timeout abstellen */
alarm(0);
setsighandler(SIGALRM, SIG_IGN);
canjump_sigalrm = FALSE;
/* Eingabe loggen */
if (cmdline[0] != '\0' || confrecord.userrecord.loglevel > 1) {
bbslogn(LOG_FILE,&confrecord,"%s",cmdline);
}
}
else {
/* bei Befehlseingabe-Timeout: User benachrichtigen und rausschmeissen */
errormsg(E_LOGFILE|E_USER,&confrecord,"bbs","bbs",
msg("bbs",6,confrecord.lang));
bbsexit(0,&confrecord);
}
cmdnr++;
/* Kommando in Kleinschreibung */
if (str2cmdparams(cmdline,cmd,params) < 0) {
errormsg(E_LOGFILE|E_USER,&confrecord,"bbs","bbs",
"command too long");
}
lowercases(cmd);
sprintf(cmdline,"%s %s",cmd,params);
/* fprintf(stderr,"%s:%s\n",cmd,params); */
/* Kommandos ausfuehren */
if (cmd[0] == '\0') {
/* */
}
else if (strncmp(cmd,"help",4)==0 || strncmp(cmd,"?",1)==0) {
if (buildhelppath(params,"bbshelp",sprachensuffix[confrecord.userrecord.lang],&confrecord) != NULL) {
do_showfile(params,NULL,NULL,chrootrecord.root,&confrecord);
}
else {
errormsg(E_LOGFILE|E_USER,&confrecord,"bbs","bbs",
"path to bbshelp too long");
}
}
else if (strncmp(cmd,"anl",3)==0) {
if (buildhelppath(params,"manual",sprachensuffix[confrecord.userrecord.lang],&confrecord) != NULL) {
do_showfile(params,NULL,NULL,chrootrecord.root,&confrecord);
}
else {
errormsg(E_LOGFILE|E_USER,&confrecord,"bbs","bbs",
"path to manual too long");
}
}
else if (strncmp(cmd,"less",4)==0 || strncmp(cmd,"more",4)==0 ||
strncmp(cmd,"show",4)==0) {
do_showfile(params,params,chrootrecord.cwd,chrootrecord.root,
&confrecord);
}
else if (strncmp(cmd,"dir",3)==0) {
do_ls(params,&chrootrecord,&confrecord);
}
else if (strncmp(cmd,"cd",2)==0) {
do_cd(params,&chrootrecord,&confrecord);
}
else if (strncmp(cmd,"pwd",3)==0) {
do_pwd(chrootrecord.cwd,&confrecord);
}
else if (strncmp(cmd,"env",3)==0) {
do_showenv(&confrecord.userrecord,&confrecord);
}
else if (strncmp(cmd,"pr",2)==0) {
do_protokoll(params,protokollnamen,&confrecord.userrecord.protokoll,
&confrecord);
}
else if (strncmp(cmd,"ho",2)==0) {
do_home(params,&chrootrecord,&confrecord.userrecord,&confrecord);
}
else if (strncmp(cmd,"te",2)==0) {
do_term(params,&confrecord.userrecord,&confrecord);
}
else if (strncmp(cmd,"get",3)==0) {
do_get(params,&chrootrecord,protokollnamen,
confrecord.userrecord.protokoll,&confrecord);
}
else if (strncmp(cmd,"put",3)==0) {
do_put(params,&chrootrecord,confrecord.userrecord.protokoll,
&confrecord);
}
else if (strncmp(cmd,"npass",4)==0) {
do_newpasswd(params,&confrecord.userrecord,&confrecord);
}
#ifndef NO_TV_USEC
else if (strncmp(cmd,"azm",4)==0) {
do_autozmodem(params,&confrecord);
}
#endif
else if (strncmp(cmd,"fullist",7)==0) {
do_fullist(params,&confrecord);
}
else if (strncmp(cmd,"lang",4)==0) {
do_sprache(params,sprachennamen,&confrecord);
}
else if (strncmp(cmd,"talk",4)==0) {
do_talk(params,&confrecord);
}
else if (strncmp(cmd,"sysmail",7)==0) {
if (do_sendmail(params,path,chrootrecord.cwd,chrootrecord.root,
&confrecord) == 0) {
unlink(path);
}
}
else if (strncmp(cmd,"messag",6)==0) {
do_sendmessage(params,chrootrecord.cwd,chrootrecord.root,&confrecord);
}
else if (strncmp(cmd,"msgbrowse",7)==0) {
do_msgbrowser(params,&confrecord);
}
else if (strcmp(cmd,"quit")==0 || strcmp(cmd,"exit")==0 ||
strcmp(cmd,"ende")==0 || strcmp(cmd,"bye")==0) {
}
else {
errormsg(E_LOGFILE|E_USER,&confrecord,"bbs","bbs",
msg("bbs",7,confrecord.lang),cmd,params);
}
} while (strcmp(cmd,"quit")!=0 && strcmp(cmd,"exit")!=0 &&
strcmp(cmd,"ende")!=0 && strcmp(cmd,"bye")!=0);
/* Userenvironment speichern */
if (confrecord.userrecord.seclevel != HIGHSECURITY) {
saveuserrecord(&confrecord.userrecord,&confrecord);
}
/* User verabschieden und Sitzung beenden */
printf("\nBye\n");
bbsexit(0,&confrecord);
return(0);
}
PID_T bbsinit(chrootrecordtyp *chrootrecord, confrecordtyp *confrecord,
const char *conffile)
/*
Initialisiert die Sitzung: Daemon eventuell starten, User einloggen
und sein Environment laden
Rueckgabewerte: ok: pid vom Programm, wenn es beim Daemon angemeldet wurde
und ein User sich erfolgreich einlogte
Fehler: -pid vom Programm, wenn es beim Daemon angemeldet wurde
-1, sonst
*/
{
PID_T dpid;
char *ptr, *spary[2], str[PATH_MAX+1];
boolean isuser;
int status;
sessionrecordtyp sr;
/* umask setzen */
umask(022);
/* Konfigurationsfile einlesen */
if (readconffile(confrecord,conffile) < 0) {
errormsg(E_SYSLOG|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit","readconffile failed");
return(-1);
}
/* chrootdir initialisieren */
strmaxcpy(str,confrecord->rootdir,PATH_MAX);
if (splitstring(spary,str,':',1) == 0) {
errormsg(E_SYSLOG|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit","no rootdir");
return(-1);
}
strcpy(chrootrecord->primaryroot,spary[0]);
normalizepath(chrootrecord->primaryroot);
strcpy(chrootrecord->root,chrootrecord->primaryroot);
strcpy(chrootrecord->rootname,"/");
/* Daemon starten (es darf nur einen geben) und anmelden */
if ((dpid=testdaemon(confrecord->bbsdpidpath,confrecord)) < 0) {
unlink(confrecord->sockpath);
}
/* dpid enthaelt die Pid des Daemons, wenn > 0 */
if (dpid <= 0) {
if ((dpid=fork())<0) {
errormsg(E_SYSLOG|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit","fork: %m");
return(-1);
}
if (dpid==0) {
execl(confrecord->bbsdpath,"bbsd","-d","-c",conffile,
"-p",confrecord->bbsdpath,NULL);
errormsg(E_SYSLOG|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit","execl %s: %m",
confrecord->bbsdpath);
exit(-1);
}
while (wait(&status)!=dpid);
if (!WIFEXITED(status)) {
errormsg(E_SYSLOG|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit","starting bbsd failed");
return(-1);
}
if (WIFEXITED(status) && WEXITSTATUS(status)!=0) {
errormsg(E_SYSLOG|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit","bbsd exited with %i",
WEXITSTATUS(status));
return(-1);
}
}
/* Homedir von bbs aufsuchen */
#ifdef PGHOME
mdefenv("HOME",PGHOME);
#else
mdefenv("HOME",chrootrecord->root);
#endif
if ((ptr=getenv("HOME"))==NULL) {
errormsg(E_LOGFILE|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit",
"cannot find homedir in environment");
return(-1);
}
/* cwd bezueglich chroot auf ROOT setzen */
if (chdir(ptr)<0) {
errormsg(E_SYSLOG|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit","chdir to %s: %m",ptr);
return(-1);
}
if (getchrootcwd(chrootrecord) == (char *)0) {
errormsg(E_LOGFILE|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit",
"cannot set chroot-homedir (chroot: %s, home: %s)",
chrootrecord->root,ptr);
return(-1);
}
isuser = FALSE;
/* User einloggen */
if (sigsetjmp(sigalrmenv,(int)FALSE)==0) {
#ifndef DEBUG
canjump_sigalrm = TRUE;
setsighandler(SIGALRM, sighandler);
alarm(confrecord->logintimeout);
#endif
isuser = userlogin(confrecord,confrecord->userrecord.name);
}
else {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","bbsinit","Timeout (login)");
}
alarm(0);
setsighandler(SIGALRM, SIG_IGN);
canjump_sigalrm = FALSE;
if (isuser) {
bbslog(LOG_FILE,confrecord,"Login %s (Level %i) OK",
confrecord->userrecord.name, confrecord->userrecord.seclevel);
printf("Login %s (Level %i) OK\n\n", confrecord->userrecord.name,
confrecord->userrecord.seclevel);
}
else {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","bbsinit",
msg("bbsinit",0,confrecord->lang));
return(-1);
}
/* beim Daemon anmelden */
sr.pid = getpid();
if (isatty(0) && (ptr=ttyname(0))!=NULL) strcpy(sr.tty,ptr);
strcpy(sr.user,confrecord->userrecord.name);
sr.talking_to = 0;
if (addsession(&sr,confrecord)!=0) {
errormsg(E_SYSLOG|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit","cannot send sessionrecord to daemon");
return(-sr.pid);
}
strcpy(str,confrecord->userrecord.home);
chrootpath(str,chrootrecord->cwd,chrootrecord->root);
mdefenv("HOME",str);
if (chdir(str)<0) {
errormsg(E_LOGFILE|E_USER|E_CONSOLE,confrecord,"bbs","bbsinit",
"chdir to %s: %m",str);
return(-sr.pid);
}
getchrootcwd(chrootrecord);
mdefenv("SHELL",confrecord->userrecord.shell);
mdefenv("PATH",confrecord->userrecord.path);
mdefenv("TERM",confrecord->userrecord.term);
mdefenv("LINES","%i",confrecord->userrecord.lines);
mdefenv("COLUMNS","%i",confrecord->userrecord.columns);
/* User begruessen (ohne curses, falls Terminaltyp nicht stimmt) */
if (sigsetjmp(sigalrmenv,(int)FALSE)==0) {
#ifndef DEBUG
canjump_sigalrm = TRUE;
setsighandler(SIGALRM, sighandler);
alarm(confrecord->idletimeout);
#endif
status = usergreeting(confrecord);
}
else {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","bbsinit","Timeout (term)");
status = -2;
}
alarm(0);
setsighandler(SIGALRM, SIG_IGN);
canjump_sigalrm = FALSE;
if (status < 0) return(-sr.pid);
return sr.pid;
}
void bbsexit(const int k, confrecordtyp *confrecord)
{
removesession(getpid(),confrecord);
closelog();
window_off(&save_termios,&ttystate,confrecord);
exit(k);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.