This is do.c in view mode; [Download] [Up]
/* $Id: do.c,v 1.2 1995/12/19 19:30:47 eilts Exp eilts $ */ #include "bbs.h" #ifdef NNTPNEWS int do_postart_nntp(const char *groups, const char *subject, const char *refs, const char *letter, newsstattyp *newsrecord, const confrecordtyp *confrecord) { char astr[ARG_MAX+1], str[STRLEN+1]; boolean deconnect_on_return = FALSE; newsstattyp newsrec, *newsrecp; newsrec.is_connected = FALSE; if (newsrecord != NULL) { newsrecp = newsrecord; } else { newsrecp = &newsrec; } if (checknewsperms(confrecord) < 1) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_nntp", "You are not allowed to post"); return 0; } strcpy(str,confrecord->userrecord.name); if (strchr(str,'@') == NULL && strchr(str,'!') == NULL) { strcat(str,"@"); strcat(str,confrecord->hostname); } if (*confrecord->userrecord.realname != '\0') { sprintf(astr,"From: %s <%s>\nNewsgroups: %s\nSubject: %s", confrecord->userrecord.realname,str,groups,subject); } else { sprintf(astr,"From: %s\nNewsgroups: %s\nSubject: %s",str,groups,subject); } if (refs != NULL && *refs != '\0') { strcat(astr,"\nReferences: "); strcat(astr,refs); } strcat(astr,"\n\n"); if (! newsrecp->is_connected) { if (nntp_connect(newsrecp,confrecord) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_nntp", "cannot connect to Newsserver %s",confrecord->nntpserver); return -1; } deconnect_on_return = TRUE; } if (nntp_postarticle(astr,letter,newsrecp,confrecord) == OK_POSTED) { writetouser(confrecord,"article send"); } else { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_nntp", "posting failed, got %s",newsrecp->lastretstr); writetouser(confrecord,"article NOT send"); return -1; } if (deconnect_on_return) nntp_close(newsrecp); return 0; } int do_postart_inews(const char *groups, const char *subject, const char *refs, const char *letter, const confrecordtyp *confrecord) { int status, pfds[2], fd, errfd, save_stderr; PID_T pid; SIZE_T len; SSIZE_T bytes; char astr[ARG_MAX+1], errfile[PATH_MAX+1]; struct stat stats; if (checknewsperms(confrecord) < 1) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_inews", "You are not allowed to post"); return 0; } sprintf(errfile,"%s/inews_err.%ld",confrecord->scratchdir, (long)getpid()); if ((errfd=open(errfile,O_CREAT|O_TRUNC|O_RDWR,0600)) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postaricle", "open %s: %m", errfile); return -1; } unlink(errfile); if ((fd=open(letter,O_RDONLY)) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_inews", "open letter %s: %m", letter); return -1; } if (pipe(pfds) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_inews","pipe: %m"); return -1; } if ((pid = fork()) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_inews","fork: %m"); return -1; } if (pid == 0) { save_stderr = dup(STDERR_FILENO); dup2(pfds[0],STDIN_FILENO); close(pfds[1]); dup2(errfd,STDOUT_FILENO); dup2(errfd,STDERR_FILENO); execl(INEWS,"inews: receiving from bbs","-h",(char *)0); close(errfd); dup2(STDERR_FILENO,save_stderr); perror("execv INEWS"); errormsg(E_LOGFILE,confrecord,"bbs","do_postart_inews","execv INEWS: %m"); exit(1); } close(pfds[0]); if (*confrecord->userrecord.realname != '\0') { sprintf(astr,"From: %s <%s>\nNewsgroups: %s\nSubject: %s", confrecord->userrecord.realname,confrecord->userrecord.name, groups,subject); } else { sprintf(astr,"From: %s\nNewsgroups: %s\nSubject:%s", confrecord->userrecord.name,groups,subject); } if (refs != NULL && *refs != '\0') { strcat(astr,"\nReferences: "); strcat(astr,refs); } strcat(astr,"\n\n"); len = strlen(astr); if (write(pfds[1],astr,len) != len) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_inews", "write (header): %m"); } else { bytes = 0; while (bytes >= 0 && (bytes=read(fd,(void *)astr,(SIZE_T)PATH_MAX)) > 0) { bytes = writen(pfds[1],astr,bytes); } } close(pfds[1]); close(fd); while (wait(&status) != pid); if (fstat(errfd,&stats) == 0 && stats.st_size > 0) { lseek(errfd,(OFF_T)0,SEEK_SET); bytes = read(errfd,astr,STRLEN); astr[bytes] = '\0'; errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_inews", "inews reports: %s",astr); } close(errfd); if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { writetouser(confrecord,"article send"); } else { if (WIFEXITED(status)) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_inews", "inews exited with status %d",WEXITSTATUS(status)); } if (WIFSIGNALED(status)) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_inews", "inews got signal %d",WTERMSIG(status)); if (WCOREDUMP(status)) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_postart_inews", "inews dumped core"); } } writetouser(confrecord,"article NOT send"); } return 0; } void do_shownewsheader(const char *header, const confrecordtyp *confrecord) { int fd; char scratch[PATH_MAX+1]; scratchfilename(scratch,"newsheader-",NULL,confrecord->scratchdir); if ((fd=open(scratch,O_CREAT|O_TRUNC|O_RDWR,0600)) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_shownewsheader", "open %s: %m",scratch); return; } write(fd,header,strlen(header)); close(fd); do_showfile(scratch,NULL,NULL,NULL,confrecord); unlink(scratch); return; } #endif void do_msgbrowser(const char params[], const confrecordtyp *confrecord) /* Format fuer params: -a Aktion -n Nummer [-i Message-Id] Aktion ist R (lesen), D (loeschen), A (beantworten), G (downladen) */ { int nr, lang; char action, option, msg_id[STRLEN+1], str[STRLEN+1], spath[PATH_MAX+1]; chrootrecordtyp chrootrec; lang = confrecord->userrecord.lang; *msg_id = '\0'; nr = -1; getarg(NULL,params); while ((option=getarg(str,params)) != '\0') { switch (option) { case 'a': action = *str; break; case 'n': nr = atoi(str); break; case 'i': strmaxcpy(msg_id,str,STRLEN); break; default: errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_msgbrowser", "%c: unknown option",option); return; } } if (nr < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_msgbrowser", "No message number given"); return; } switch (action) { case 'R': if (getmessage(spath,nr,msg_id,confrecord) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_msgbrowser", "message not found"); return; } do_showfile(spath,NULL,NULL,NULL,confrecord); unlink(spath); break; case 'D': if (removemessage(nr,msg_id,confrecord) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_msgbrowser", "message cannot be removed"); } break; case 'A': /* wird in menue_c erledigt */ break; case 'G': if (getmessage(spath,nr,msg_id,confrecord) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_msgbrowser", "message not found"); return; } strcpy(chrootrec.root,"/"); getcwd(chrootrec.cwd,PATH_MAX); do_get(spath,&chrootrec,protokollnamen,confrecord->userrecord.protokoll, confrecord); unlink(spath); break; } return; } void do_sendmessage(const char params[], const char *chrootcwd, const char *chrootdir, const confrecordtyp *confrecord) /* Format fuer params: -l letter -s subject -a address */ { char letter[PATH_MAX+1], subject[STRLEN+1], address[ARG_MAX+1], sender[2*S_STRLEN+4], str[ARG_MAX+1], option; *letter = '\0'; *subject = '\0'; *address = '\0'; getarg(NULL,params); while ((option=getarg(str,params)) != '\0') { switch (option) { case 'l': strcpy(letter,str); break; case 's': strcpy(subject,str); break; case 'a': strcpy(address,str); break; default: errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmessage", "%c: unknown option",option); return; } } if (*letter == '\0') { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmessage", "%s: no letter given",params); return; } if (*address == '\0') { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmessage", "%s: no address given",params); return; } chrootpath(letter,chrootcwd,confrecord->scratchdir); if (*subject == '\0') { strcpy(subject,"no subject given"); } if (*(confrecord->userrecord.realname)) { sprintf(sender,"%s <%s>",confrecord->userrecord.realname, confrecord->userrecord.name); } else { sprintf(sender,"<%s>",confrecord->userrecord.name); } if (sendmessage(sender,address,subject,letter,confrecord) == 0) { writetouser(confrecord,"message send"); } else { writetouser(confrecord,"message NOT send"); } return; } int do_sendmail(const char params[], char *letter, const char *chrootcwd, const char *chrootdir, const confrecordtyp *confrecord) /* Format fuer params: -l letter -a address [-s subject] letter und address duerfen keine Whitespaces beinhalten */ { int n, anz, status, pfds[2], fd, errfd, save_stderr, rw = -1; PID_T pid; SIZE_T len; SSIZE_T bytes; char *splits[MAXARGS+1], *arg[MAXARGS+1], str[PATH_MAX+2*STRLEN+20], astr[ARG_MAX+1], address[ARG_MAX+1], subject[STRLEN+1], errfile[PATH_MAX+1], option; boolean sendok = FALSE; struct stat stats; *letter = '\0'; *address = '\0'; strcpy(subject,"no subject given"); getarg(NULL,params); while ((option=getarg(str,params)) != '\0') { switch (option) { case 'a': strcpy(address,str); break; case 's': strcpy(subject,str); break; case 'l': strcpy(letter,str); if (chrootcwd != NULL) { chrootpath(letter,chrootcwd,confrecord->scratchdir); } break; default: errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "%c: unknown option",option); return -1; } } if (strchr(address,'!') != NULL) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "no '!' in address allowed: %s",address); return -1; } if (*address == '-') { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "no leading '-' in address allowed: %s",address); return -1; } if (strcmp(address,confrecord->sysop) == 0) { sendok = TRUE; } else { if (checkmailperms(address,confrecord) != 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "You are not allowed to send to this destination"); return -1; } else { sendok = TRUE; } } if (sendok) { sprintf(errfile,"%s/sendmail_err.%ld",confrecord->scratchdir, (long)getpid()); if ((errfd=open(errfile,O_CREAT|O_TRUNC|O_RDWR,0600)) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "open %s: %m", errfile); return -1; } unlink(errfile); if ((fd=open(letter,O_RDONLY)) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "open letter %s: %m", letter); return -1; } strcpy(astr,address); anz = splitstring(splits,astr,',',MAXARGS); arg[0] = "sendmail: receiving from bbs"; for (n=0; n < anz; n++) { if ((arg[n+1]=(char *)malloc(strlen(splits[n]+1))) == NULL) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail","malloc: %m"); return -1; } parseaddrline(arg[n+1],str,splits[n]); } arg[n+1] = NULL; if (pipe(pfds) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail","pipe: %m"); return -1; } if ((pid = fork()) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail","fork: %m"); return -1; } if (pid == 0) { save_stderr = dup(STDERR_FILENO); dup2(pfds[0],STDIN_FILENO); close(pfds[1]); dup2(errfd,STDOUT_FILENO); dup2(errfd,STDERR_FILENO); execv(SENDMAIL,arg); close(errfd); dup2(STDERR_FILENO,save_stderr); perror("execv INEWS"); errormsg(E_LOGFILE,confrecord,"bbs","do_sendmail","execv SENDMAIL: %m"); exit(1); } close(pfds[0]); if (*confrecord->userrecord.realname != '\0') { sprintf(str,"From: %s <%s>\nTo: %s\nSubject: %s\n\n", confrecord->userrecord.realname, confrecord->userrecord.name,address,subject); } else { sprintf(str,"From: %s\nTo: %s\nSubject: %s\n\n", confrecord->userrecord.name,address,subject); } len = strlen(str); if (write(pfds[1],str,len) != len) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "write (header): %m"); } else { bytes = 0; while (bytes >= 0 && (bytes=read(fd,(void *)str,(SIZE_T)PATH_MAX)) > 0) { bytes = writen(pfds[1],str,bytes); } } close(pfds[1]); close(fd); while (wait(&status) != pid); for (n=0; n < anz; n++) free(arg[n+1]); if (fstat(errfd,&stats) == 0 && stats.st_size > 0) { lseek(errfd,(OFF_T)0,SEEK_SET); bytes = read(errfd,str,STRLEN); str[bytes] = '\0'; errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "sendmail reports: %s",str); sendok = FALSE; } close(errfd); if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { rw = 0; sendok = TRUE; } else { if (WIFEXITED(status)) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "sendmail exited with status %d",WEXITSTATUS(status)); } if (WIFSIGNALED(status)) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "sendmail got signal %d",WTERMSIG(status)); if (WCOREDUMP(status)) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "sendmail dumped core"); } } sendok = FALSE; } } if (sendok) { writetouser(confrecord,"mail send"); } else { writetouser(confrecord,"mail NOT send"); } return rw; } void do_talk(const char params[], const confrecordtyp *confrecord) { int n; if (*params == '\0') return; n = 0; n = atoi(params); if (n < 1) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_talk","wrong pid %s", params); return; } iniconnecttouser(n,confrecord); } void do_sprache(const char params[], const char *sprachennamen[], confrecordtyp *confrecord) { int lang; char c; c = params[0]; c = tolower(c); if (c=='d') { confrecord->userrecord.lang = GERMAN; } else if (c=='e') { confrecord->userrecord.lang = ENGLISH; } lang = confrecord->userrecord.lang; writetouser(confrecord,msg("do_sprache",0,lang),sprachennamen[lang]); } void do_autozmodem(const char params[], confrecordtyp *confrecord) { char c; c = params[0]; c = tolower(c); if (c=='y' || c=='j') { confrecord->userrecord.autozmodem = TRUE; } else if (c=='n') { confrecord->userrecord.autozmodem = FALSE; } if (confrecord->userrecord.autozmodem) { writetouser(confrecord,msg("do_autozmodem",0,confrecord->userrecord.lang)); } else { writetouser(confrecord,msg("do_autozmodem",1,confrecord->userrecord.lang)); } } void do_fullist(const char params[], confrecordtyp *confrecord) { char c; c = params[0]; c = tolower(c); if (c=='y' || c=='j') { confrecord->userrecord.fullist_on_cd = TRUE; } else if (c=='n') { confrecord->userrecord.fullist_on_cd = FALSE; } if (confrecord->userrecord.fullist_on_cd) { writetouser(confrecord,msg("do_fullist",0,confrecord->userrecord.lang)); } else { writetouser(confrecord,msg("do_fullist",1,confrecord->userrecord.lang)); } } void do_cd(const char params[], chrootrecordtyp *chrootrecord, const confrecordtyp *confrecord) { int n; boolean rootchg = FALSE, cdok = TRUE; char *args[MAXARGS+1], *spary[MAXARGS+1], str[PATH_MAX+1], str2[PATH_MAX+1], realpath[PATH_MAX+1], ndir[PATH_MAX+1], oldchrootdir[PATH_MAX+1], oldrootname[PATH_MAX+1]; strmaxcpy(str,params,PATH_MAX); splitparams(args,str); if (args[0]==(char *)NULL) { strcpy(str,confrecord->userrecord.home); args[0] = str; strmaxcpy(chrootrecord->root,chrootrecord->primaryroot,PATH_MAX); strcpy(chrootrecord->rootname,"/"); chrootpath(args[0],chrootrecord->cwd,chrootrecord->root); } else if (strcmp(chrootrecord->root,chrootrecord->primaryroot)!=0 && strcmp(chrootrecord->cwd,"/")==0 && strcmp(args[0],"..")==0) { strcpy(chrootrecord->root,chrootrecord->primaryroot); strcpy(chrootrecord->rootname,"/"); rootchg = TRUE; strcpy(args[0],"/"); chrootpath(args[0],chrootrecord->cwd,chrootrecord->root); } else { strmaxcpy(ndir,args[0],PATH_MAX); chrootpath(args[0],chrootrecord->cwd,chrootrecord->root); if (access(args[0],F_OK)==0 && strcmp(chrootrecord->root,chrootrecord->primaryroot)==0) { if ((n=readlink(args[0],realpath,PATH_MAX)) > 0) { realpath[n] = '\0'; if (realpath[0] != '/') { getcwd(str2,PATH_MAX); strcat(str2,"/"); strprepend(realpath,str2); } if (strstr(realpath,chrootrecord->root) != realpath) { cdok = FALSE; strmaxcpy(str2,confrecord->rootdir,PATH_MAX); splitstring(spary,str2,':',MAXARGS); for (n=0; spary[n]!=NULL; n++) { if (strstr(realpath,spary[n]) == realpath) { cdok = TRUE; break; } } if (cdok) { rootchg = TRUE; strcpy(oldchrootdir,chrootrecord->root); strcpy(oldrootname,chrootrecord->rootname); strmaxcat(chrootrecord->rootname,"/",PATH_MAX); strmaxcat(chrootrecord->rootname,ndir,PATH_MAX); stripslashes(chrootrecord->rootname); strmaxcpy(chrootrecord->root,realpath,PATH_MAX); getrealdir(chrootrecord->root,confrecord); } else { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_cd", msg("do_cd",0,confrecord->userrecord.lang)); } } } } } if (cdok && chdir(args[0]) < 0) { if (rootchg) { strcpy(chrootrecord->root,oldchrootdir); strcpy(chrootrecord->rootname,oldrootname); } errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_cd","chdir %s: %m", getchrootpath(str,chrootrecord->root)); } getchrootcwd(chrootrecord); #ifdef AUTOLISTFILE if (checkfileperms(AUTOLISTFILE,geteuid(),getegid()) == 0) { do_showfile(AUTOLISTFILE,NULL,chrootrecord->cwd,chrootrecord->root, confrecord); } #endif } void do_get(const char params[], const chrootrecordtyp *chrootrecord, const char *protokollnamen[], const int protokoll, const confrecordtyp *confrecord) { UID_T euid; GID_T egid; int k, p; char *args[MAXARGS+1], *inargs[MAXARGS+1], *files[MAXARGS+1], str[ARG_MAX+1], path[PATH_MAX+1], kermrcpath[PATH_MAX+1]; strmaxcpy(str,params,ARG_MAX); euid = geteuid(); egid = getegid(); bbslogn(LOG_FILE,confrecord,"%s: %s",protokollnamen[protokoll],str); splitparams(inargs,str); p = 0; for (k=0;inargs[k]!=NULL;k++) { if (*inargs[k]!='-') { strmaxcpy(path,inargs[k],PATH_MAX); chrootpath(path,chrootrecord->cwd,chrootrecord->root); switch (checkfileperms(path,euid,egid)) { case -EACCES: case -ENOENT: errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_get", msg("do_get",0,confrecord->userrecord.lang), getchrootpath(path,chrootrecord->root)); break; case EFAULT: errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_get", msg("do_get",1,confrecord->userrecord.lang), getchrootpath(path,chrootrecord->root)); break; case EACCES: errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_get", msg("do_get",2,confrecord->userrecord.lang), getchrootpath(path,chrootrecord->root)); break; default: files[p] = (char *)malloc((SIZE_T)PATH_MAX); strcpy(files[p],path); p++; } } } files[p] = NULL; if (p == 0) return; strcpy(path,"."); chrootpath(path,chrootrecord->cwd,chrootrecord->root); p = 0; switch (protokoll) { case KERMITPROTO: if ((errno=checkfileperms(confrecord->kermrcpath,euid,egid)) != 0) { if (errno < 0) errno = -errno; errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_get", "cannot access kermit configuration file\n%s:\n%m", confrecord->kermrcpath); break; } args[p++] = "kermit"; args[p++] = "-y"; strcpy(kermrcpath,confrecord->kermrcpath); args[p++] = kermrcpath; args[p++] = "-s"; for (k=0;files[k]!=NULL;k++) { getchrootpath(files[k],path); args[p++] = &(files[k][1]); /* wegen dem fuehrenden '/' */ } args[p] = NULL; execute(KERMIT,args,confrecord->userrecord.loglevel,confrecord); break; case ZMODEMPROTO: args[p++] = "sz"; args[p++] = "-b"; for (k=0;files[k]!=NULL;k++) { getchrootpath(files[k],path); args[p++] = &(files[k][1]); /* wegen dem fuehrenden '/' */ } args[p] = NULL; execute(SZ,args,confrecord->userrecord.loglevel,confrecord); break; } for (k=0;files[k]!=NULL;k++) { free((void *)files[k]); } } void do_home(const char params[], const chrootrecordtyp *chrootrecord, userrecordtyp *userrecord, const confrecordtyp *confrecord) { char *args[MAXARGS+1], path[PATH_MAX+1], fullpath[PATH_MAX+1], wdir[PATH_MAX+1]; strmaxcpy(path,params,PATH_MAX); splitparams(args,path); if (args[0]!=(char *)NULL) { strcpy(fullpath,args[0]); chrootpath(fullpath,chrootrecord->cwd,chrootrecord->root); getcwd(wdir,PATH_MAX); if (chdir(fullpath)<0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_home", msg("do_home",0,confrecord->lang)); } else if (userrecord->seclevel == HIGHSECURITY) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_home", msg("do_home",1,confrecord->lang)); } else { mdefenv("HOME",fullpath); chrootpath(args[0],chrootrecord->cwd,(char *)NULL); strcpy(userrecord->home,args[0]); } chdir(wdir); } writetouser(confrecord,"Home: %s\n",userrecord->home); } void do_ls(const char params[], const chrootrecordtyp *chrootrecord, const confrecordtyp *confrecord) { UID_T euid; GID_T egid; int n, anz; char *args[MAXARGS+1], dir[PATH_MAX+1], tstr[ASCIITIMESTRLEN], str[PATH_MAX+1], *sp, *sp2; DIR *dp; struct dirent *dirp; struct stat stats; tlistetyp *tliste; strmaxcpy(str,params,PATH_MAX); anz = splitparams(args,str); if (anz == 0) { strcpy(dir,"."); } else { strcpy(dir,args[0]); } chrootpath(dir,chrootrecord->cwd,chrootrecord->root); if (stat(dir,&stats) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_ls","stat %s: %m",dir); return; } if (! S_ISDIR(stats.st_mode)) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_ls", "%s is not a directory",dir); return; } if ((dp=opendir(dir)) == NULL) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_ls","opendir %s: %m",dir); return; } euid = geteuid(); egid = getegid(); tliste = (tlistetyp *)0; /* addstrtoliste(&tliste,TRUE,0,TL_BLOCKLEN,"",confrecord); */ anz = 0; while ((dirp=readdir(dp)) != NULL) { if (strcmp(dirp->d_name,".") == 0) continue; if (strcmp(dirp->d_name,"..") == 0) continue; if (stat(dirp->d_name,&stats) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_ls","stat %s: %m", dirp->d_name); continue; } n = getperms(&stats,euid,egid); if (!(PERM_R & n)) continue; if (S_ISREG(stats.st_mode)) { strcpy(tstr,ctime(&(stats.st_mtime))); tstr[7] = '\0'; tstr[10] = '\0'; tstr[19] = '\0'; tstr[24] = '\0'; sprintf(str,"%s\t%s %s %s %8ld",dirp->d_name, &(tstr[8]),&(tstr[4]),&(tstr[20]),(long)stats.st_size); addstrtoliste(&tliste,TRUE,anz,TL_BLOCKLEN,str,confrecord); anz++; } else if (S_ISDIR(stats.st_mode) && (PERM_X & n)) { strcpy(str,dirp->d_name); strcat(str,"\t (Directory) "); addstrtoliste(&tliste,TRUE,anz,TL_BLOCKLEN,str,confrecord); anz++; } else { continue; } } sortliste(tliste,TL_BLOCKLEN,anz,confrecord); for (n=0; n<anz; n++) { readliste(&tliste,FALSE,n,TL_BLOCKLEN,&sp,confrecord); sp2 = sp; for (; *sp!='\t'; sp++) ; *sp++ = '\0'; sprintf(str,"%s %s",sp,sp2); addstrtoliste(&tliste,TRUE,n,TL_BLOCKLEN,str,confrecord); } tlpager(tliste,anz," Datum Bytes Name","dir",confrecord); removeliste(&tliste,TRUE,TL_BLOCKLEN); return; } void do_protokoll(const char params[], const char *protokollnamen[], int *protokoll, confrecordtyp *confrecord) { char c; c = params[0]; c = tolower(c); if (c=='k') { if (confrecord->userrecord.kermitok) { *protokoll = KERMITPROTO; mputenv("PROTOKOLL=KERMIT"); } else { writetouser(confrecord,msg("do_protokoll",0, confrecord->userrecord.lang)); return; } } else if (c=='z') { *protokoll = ZMODEMPROTO; mputenv("PROTOKOLL=ZMODEM"); } confrecord->userrecord.protokoll = *protokoll; writetouser(confrecord,"Protokoll: %s\n",protokollnamen[*protokoll]); } void do_put(const char params[], const chrootrecordtyp *chrootrecord, const int protokoll, confrecordtyp *confrecord) { int p, rw = -1; char *args[MAXARGS+1], *inargs[MAXARGS+1], str[PATH_MAX+1], path[PATH_MAX+1]; getcwd(path,PATH_MAX); strmaxcpy(str,confrecord->userrecord.uploaddir,PATH_MAX); chrootpath(str,chrootrecord->cwd,chrootrecord->root); if (chdir(str) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_put","chdir %s: %m", confrecord->userrecord.uploaddir); return; } if (access(".",W_OK) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_put", msg("do_put",0,confrecord->lang), chrootrecord->cwd); if (chdir(path) < 0) { errormsg(E_LOGFILE,confrecord,"bbs","do_put","chdir (r) %s: %m",path); } return; } strcpy(str,params); splitparams(inargs,str); p = 0; switch (protokoll) { case KERMITPROTO: if ((errno=checkfileperms(confrecord->kermrcpath,geteuid(),getegid())) != 0) { if (errno < 0) errno = -errno; errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_put", "cannot access kermit configuration file\n%s:\n%m", confrecord->kermrcpath); break; } args[p++] = "kermit"; args[p++] = "-y"; args[p++] = confrecord->kermrcpath; args[p++] = "-r"; args[p] = NULL; rw = execute(KERMIT,args,confrecord->userrecord.loglevel,confrecord); break; case ZMODEMPROTO: args[p++] = "rz"; #ifndef NO_RZ_BFLAG args[p++] = "-b"; #endif args[p] = NULL; rw = execute(RZ,args,confrecord->userrecord.loglevel,confrecord); break; } if (chdir(path) < 0) { errormsg(E_LOGFILE,confrecord,"bbs","do_put","chdir (r) %s: %m",path); } if (rw == 0) { writetouser(confrecord,msg("do_put",1,confrecord->lang), confrecord->userrecord.uploaddir); } else { writetouser(confrecord,msg("do_put",2,confrecord->lang), confrecord->userrecord.uploaddir); } return; } void do_pwd(const char *chrootcwd, const confrecordtyp *confrecord) { writetouser(confrecord,"Directory: %s",chrootcwd); } void do_showenv(const userrecordtyp *userrecord, const confrecordtyp *confrecord) { char str[STRLEN+1], str1[STRLEN+1]; sprintf(str1,"Username: %s\n", userrecord->name); strmaxcpy(str,str1,STRLEN); sprintf(str1,"Securitylevel: %d\n", userrecord->seclevel); strmaxcat(str,str1,STRLEN); sprintf(str1,"Protokoll: %s\n", protokollnamen[userrecord->protokoll]); strmaxcat(str,str1,STRLEN); sprintf(str1,"Auto-Z-Modem: %s\n", userrecord->autozmodem ? "on":"off"); strmaxcat(str,str1,STRLEN); sprintf(str1,"Fullist on cd: %s\n", userrecord->fullist_on_cd ? "yes":"no"); strmaxcat(str,str1,STRLEN); sprintf(str1,"Home: %s\n", userrecord->home); strmaxcat(str,str1,STRLEN); if (strcmp(userrecord->shell,NOSHELL)==0) { sprintf(str1,"No shell\n"); } else if (strcmp(userrecord->shell,RESHELL)==0) { sprintf(str1,"'restricted' shell (%s)\n", RESHELL); } else { sprintf(str1,"Shell: %s\n", userrecord->shell); } strmaxcat(str,str1,STRLEN); if (userrecord->seclevel>=MEDIUMSECURITY) { sprintf(str1,"Path: %s\n", userrecord->path); strmaxcat(str,str1,STRLEN); } sprintf(str1,"Term: %s\n", userrecord->term); strmaxcat(str,str1,STRLEN); sprintf(str1,"Lines: %d\n", userrecord->lines); strmaxcat(str,str1,STRLEN); sprintf(str1,"Columns: %d\n", userrecord->columns); strmaxcat(str,str1,STRLEN); sprintf(str1,"Charset: %s\n", userrecord->charset); strmaxcat(str,str1,STRLEN); sprintf(str1,"Language: %s\n", sprachennamen[userrecord->lang]); strmaxcat(str,str1,STRLEN); sprintf(str1,"Permittions: %s\n", userrecord->permittions); strmaxcat(str,str1,STRLEN); writetouser(confrecord,str); } char do_showfile(const char *filepath, const char *header, const char *chrootcwd, const char *chrootdir, const confrecordtyp *confrecord) { int fd, pfds[2], maxz, k, offset, zeilen, zstep, lang, cntrlchars, status; PID_T pid = 0; SIZE_T len, stsize; SSIZE_T bytes; char str[PATH_MAX+1], prompt[S_STRLEN+1], buf[BUFSIZE], *mmp, *cp, key, cascii; char cset[] = {SPACE_KEY,BACKSPACE_KEY,DELETE_KEY,QUIT_KEY,'\0'}; char cset2[] = {'Y','J','N','\0'}; struct stat stats; tlistetyp *tliste; lang = confrecord->userrecord.lang; strmaxcpy(str,filepath,PATH_MAX); if (chrootcwd != NULL) { chrootpath(str,chrootcwd,chrootdir); } switch (checkfileperms(str,geteuid(),getegid())) { case -EACCES: case -ENOENT: errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", msg("do_showfile",0,lang),filepath); return '\0'; break; case EFAULT: errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", msg("do_showfile",1,lang),filepath); return '\0'; break; case EACCES: errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", msg("do_showfile",2,lang),filepath); return '\0'; break; } #ifdef GUNZIP len = strlen(str) - 1; if ((len>2 && str[len]=='z' && str[len-1]=='g' && str[len-2]=='.') || (len>1 && str[len]=='Z' && str[len-1]=='.')) { pipe(pfds); if ((pid = fork()) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile","fork: %m"); return '\0'; } if (pid == 0) { close(pfds[0]); dup2(pfds[1],STDOUT_FILENO); execl(GUNZIP,"gunzip","-c",str,(char *)0); errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", "execl GUNZIP -c %s: %m",str); exit(1); } close(pfds[1]); sprintf(str,"%s/gunzip.%ld",confrecord->scratchdir,(long)getpid()); if ((fd=open(str,O_RDWR|O_CREAT|O_EXCL,0600)) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", "open %s: %m",str); return '\0'; } bytes = 0; while (bytes >= 0 && (bytes=read(pfds[0],(void *)buf,(SIZE_T)BUFSIZE)) > 0) { bytes = writen(fd,buf,bytes); } close(pfds[0]); close(fd); while (wait(&status) != pid); if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "gunzip exited with status %d",WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "gunzip got signal %d",WTERMSIG(status)); if (WCOREDUMP(status)) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_sendmail", "gunzip dumped core"); } } } #endif if ((fd=open(str,O_RDONLY)) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", "open %s: %m",str); return '\0'; } if (pid > 0) unlink(str); if (fstat(fd,&stats) < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", "fstat %s: %m",str); return '\0'; } stsize = stats.st_size; #ifdef NO_MMAP # ifdef NeXT mmp = (char *)0; if (map_fd(fd,(vm_offset_t)0,(vm_offset_t *)&mmp,TRUE, (vm_size_t)stsize) != KERN_SUCCESS) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", "map_fd: failed"); return '\0'; } # else if ((mmp=(char *)malloc(stsize)) == NULL) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", "malloc: %m"); return '\0'; } if (readn(fd,(void *)mmp,stsize) != stsize) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", "read %s: %m",str); return '\0'; } # endif #else if ((mmp=(char *)mmap(0,stsize,PROT_READ,MAP_FILE|MAP_SHARED,fd,0)) == (CADDR_T) -1) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", "mmap %s: %m",str); return '\0'; } #endif key = 'N'; for (k=0, cp=mmp, cntrlchars=0; k<stsize; k++) { if (!(isprint(*cp) || isspace(*cp))) cntrlchars++; cp++; } if (cntrlchars*BINARYFACTOR > stsize) { key = getkeyonprompt(msg("do_showfile",7,lang),cset2,TRUE,FALSE, "showfile",confrecord); } if (key == 'N') { cascii = 'U'; if (cntrlchars > 0) { if (strcmp(confrecord->userrecord.charset,"?") == 0) { key = getkeyonprompt(msg("do_showfile",8,lang),cset2,TRUE,FALSE, "showfile",confrecord); } if (key == 'J' || key == 'Y' || strcasecmp(confrecord->userrecord.charset,"ascii") == 0) { cascii = 'A'; } else if (strcasecmp(confrecord->userrecord.charset,"next") == 0) { cascii = 'N'; } } cp = mmp; tliste = (tlistetyp *)0; zeilen = 0; do { addstrtoliste(&tliste,FALSE,zeilen++,TL_BLOCKLEN,cp,confrecord); for (k=0; *cp!='\n' && k<COLS && (OFF_T)(cp-mmp)<stsize; cp++) { k += strlen(recode(str,*cp,cascii)); } if (*cp=='\n' && (OFF_T)(cp-mmp)<stsize) { cp++; } } while ((OFF_T)(cp-mmp)<stsize); move(0,0); clear(); if (header != NULL) { maxz = confrecord->userrecord.lines - 2; standout(); addstr_withmargin(header); standend(); } else { maxz = confrecord->userrecord.lines - 1; } zstep = maxz - 2; offset = 0; do { if (header != NULL) { move(1,0); clrtobot(); } else { move(0,0); clear(); } for (k=offset; k<offset+maxz && k<zeilen; k++) { readliste(&tliste,FALSE,k,TL_BLOCKLEN,&cp,confrecord); linerecodeout(cp,mmp,stsize,cascii,COLS); } if (zeilen > maxz) { if (offset+maxz < zeilen) { if (offset == 0) { strcpy(prompt,msg("do_showfile",4,lang)); } else { sprintf(prompt,msg("do_showfile",5,lang),offset); } } else { strcpy(prompt,msg("do_showfile",3,lang)); } } else { strcpy(prompt,msg("do_showfile",6,lang)); } key = getkeyonprompt(prompt,cset,TRUE,FALSE,"showfile",confrecord); if (pagerstep(key) < 0) { offset -= zstep; } else if (pagerstep(key) > 0) { offset += zstep; } if (offset > zeilen-maxz) offset = zeilen-maxz; if (offset < 0) offset = 0; } while (pagerquit(key) == 0); removeliste(&tliste,FALSE,TL_BLOCKLEN); } #ifdef NO_MMAP # ifdef NeXT if (vm_deallocate(task_self(),(vm_address_t)mmp,(vm_size_t)stsize) != KERN_SUCCESS) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_showfile", "vm_deallocate: failed"); } # else free(mmp); # endif #else munmap(mmp,stsize); #endif close(fd); return key; } int do_term(const char params[], userrecordtyp *userrecord, confrecordtyp *confrecord) { int n; boolean size_changed=FALSE; char *args[MAXARGS+1], str[PATH_MAX+1]; #ifdef TIOCGWINSZ char tgetentbuf[TGETENTBUF]; struct winsize termsize; #endif strmaxcpy(str,params,PATH_MAX); splitparams(args,str); if (args[0]!=(char *)NULL) { if (strcmp(args[0],"*")!=0) { if (! termexists(args[0])) { errormsg(E_LOGFILE|E_USER|E_CONSOLE,confrecord,NULL,"do_term", "Terminaltype %s does not exist",args[0]); return(-1); } strmaxcpy(userrecord->term,args[0],S_STRLEN); mdefenv("TERM",args[0]); } if (args[1]!=(char *)NULL) { if (isdigit(args[1][0])) { n = atoi(args[1]); if (n>0 && n<1000) { userrecord->lines = n; mdefenv("LINES","%d",n); size_changed = TRUE; } } if (args[2]!=(char *)NULL) { if (isdigit(args[2][0])) { n = atoi(args[2]); if (n>0 && n<1000) { userrecord->columns = n; mdefenv("COLUMNS","%d",n); size_changed = TRUE; } } } } } if (confrecord->curses_on) { #ifdef TIOCGWINSZ if (size_changed) { ioctl(STDIN_FILENO,TIOCGWINSZ, (char *)&termsize); termsize.ws_row = userrecord->lines; termsize.ws_col = userrecord->columns; ioctl(STDIN_FILENO,TIOCSWINSZ, (char *)&termsize); tgetent(tgetentbuf,userrecord->term); endwin(); confrecord->curses_on = FALSE; window_on(&save_termios,&ttystate,confrecord); } #endif writetouser(confrecord,"Term: %s\nLines: %d\nColumns: %d\nCharset: %s\n", userrecord->term,userrecord->lines, userrecord->columns, userrecord->charset); } return(0); } int do_newpasswd(const char params[], userrecordtyp *userrecord, const confrecordtyp *confrecord) { boolean passwdchanged=FALSE; char *args[MAXARGS+1], str[S_STRLEN+PASS_MAX+2], salt[9]; userrecordtyp urec; #ifndef NO_CRYPT void to64(char *, long, int); #endif strmaxcpy(str,params,S_STRLEN+PASS_MAX+1); if (splitparams(args,str) != 2) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_newpasswd", "wrong number of args"); return(-1); } if (strlen(args[1]) > PASS_MAX) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_newpasswd", "password too long"); return(-1); } if (userrecord->seclevel != HIGHSECURITY) { #ifndef NO_CRYPT SRANDOM(time((TIME_T)0)); # ifdef NEWSALT salt[0] = _PASSWORD_EFMT1; to64(&salt[1], (long)(29 * 25), 4); to64(&salt[5], RANDOM(), 4); # else to64(&salt[0], RANDOM(), 2); # endif #endif if (strcmp(userrecord->name,args[0]) == 0) { strmaxcpy(userrecord->passwd,CRYPTFUNC(args[1],salt),PASSCRYPTED_LEN); saveuserrecord(userrecord,confrecord); passwdchanged = TRUE; } else if (strcmp(userrecord->name,confrecord->sysop) == 0) { if (! getuserrecord(&urec,args[0],confrecord)) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","do_newpasswd", msg("do_newpasswd",0,userrecord->lang),args[0]); return(-1); } strmaxcpy(urec.passwd,CRYPTFUNC(args[1],salt),PASSCRYPTED_LEN); saveuserrecord(&urec,confrecord); passwdchanged = TRUE; } } if (passwdchanged) { bbslog(LOG_FILE,confrecord,msg("do_newpasswd",1,userrecord->lang), args[0],userrecord->name); writetouser(confrecord,msg("do_newpasswd",2,userrecord->lang)); } else { writetouser(confrecord,msg("do_newpasswd",3,userrecord->lang)); } return(0); } #ifndef NO_CRYPT void to64(char *s, long v, int n) { static U_CHAR itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; while (--n >= 0) { *s++ = itoa64[v&0x3f]; v >>= 6; } } #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.