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.