void checkmail (void) { int i; int gold, taxes; if (readboard () < 0) return; /* can't find scoreboard */ for (i = 0; i < SCORESIZE; i++) /* search through winners scoreboard */ if (strcmp (winr[i].who, logname) == 0 && winr[i].score > 0 && winr[i].hasmail) { winr[i].hasmail = 0; gold = taxes = winr[i].taxes; writeboard (); /* Intuit the amount of gold -- should have changed * the score file, but ... TAXRATE is an fraction. */ while ((gold * TAXRATE) < taxes) gold += taxes; readmail (gold); } }
//Client-Handle void * runclient(void *arg) { args *arg2 = arg; //Argumente casten int new_socket = arg2->socket; //Socket struct sockaddr_in client = arg2->address; //IP und Port short attempt = 0; //Login-Versuche char buffer[BUF]; char *username = NULL; //Benutzername int quit = 0; int size = 0; //Client mit Server verbunden, Willkommennachricht senden if (new_socket > 0) { printf ("Client connected from %s:%d...\n", inet_ntoa (client.sin_addr),ntohs(client.sin_port)); strcpy(buffer,"Welcome to our Mail-Server, Please enter your command:\n"); send(new_socket, buffer, strlen(buffer),0); } do { size = readline(new_socket, buffer, BUF-1); if( size > 0) { buffer[size] = '\0'; switch(findcom(buffer)) //Auswahl welcher Befehl eingegeben wurde { case 0: //QUIT free(username); quit = 1; break; case 1: //SEND if(sendmail(new_socket, spool, username) == 0) strcpy(buffer,"OK\n"); else strcpy(buffer,"ERR\n"); send(new_socket, buffer, strlen(buffer),0); break; case 2: //LIST if(listmail(new_socket, spool, username) == 0) strcpy(buffer,"OK\n"); else strcpy(buffer,"ERR\n"); send(new_socket, buffer, strlen(buffer),0); break; case 3: //READ if(readmail(new_socket, spool, username) == 0) strcpy(buffer,"OK\n"); else strcpy(buffer,"ERR\n");; send(new_socket, buffer, strlen(buffer),0); break; case 4: //DEL if(delmail(new_socket, spool, username) == 0) strcpy(buffer,"OK\n"); else strcpy(buffer,"ERR\n"); send(new_socket, buffer, strlen(buffer),0); break; case 5: //LOGIN if(loginuser(new_socket, &username) == 0) { strcpy(buffer,"OK\n"); } else { attempt++; strcpy(buffer,"ERR\n"); } send(new_socket, buffer, strlen(buffer),0); break; default: //Andere Eingabe -> Fehler strcpy(buffer,"Server: Undefinded command\n"); send(new_socket, buffer, strlen(buffer),0); break; } //Client in Liste speichern if(attempt >= 3) { struct host *tmp; if(locked == NULL) { locked = malloc(sizeof(struct host)); locked->ip = strdup(inet_ntoa (client.sin_addr)); locked->time = time(NULL); locked->next = NULL; } else { tmp = locked; while(tmp->next != NULL) tmp = tmp->next; tmp->next = malloc(sizeof(struct host)); tmp = tmp->next; tmp->ip = strdup(inet_ntoa (client.sin_addr)); tmp->time = time(NULL); tmp->next = NULL; } //Nachricht an Server senden strcpy(buffer, "lock\n"); send(new_socket, buffer, strlen(buffer),0); printf("Client locked\n"); quit = 1; } } else if (size == 0) { printf("Client closed remote socket\n"); free(username); break; } else { perror("recv error"); free(username); return EXIT_FAILURE; } } while (quit == 0); close (new_socket); }
int doread() { struct obj *scroll; boolean confused = (Confusion != 0); boolean known = FALSE; scroll = getobj("?", "read"); if(!scroll) return(0); if(!scroll->dknown && Blind) { pline("Being blind, you cannot read the formula on the scroll."); return(0); } if(Blind) pline("As you pronounce the formula on it, the scroll disappears."); else pline("As you read the scroll, it disappears."); if(confused) pline("Being confused, you mispronounce the magic words ... "); switch(scroll->otyp) { #ifdef MAIL case SCR_MAIL: readmail(/* scroll */); break; #endif /* MAIL */ case SCR_ENCHANT_ARMOR: { struct obj *otmp = some_armor(); if(!otmp) { strange_feeling(scroll,"Your skin glows then fades."); return(1); } if(confused) { pline("Your %s glows silver for a moment.", objects[otmp->otyp].oc_name); otmp->rustfree = 1; break; } if(otmp->spe > 3 && rn2(otmp->spe)) { pline("Your %s glows violently green for a while, then evaporates.", objects[otmp->otyp].oc_name); useup(otmp); break; } pline("Your %s glows green for a moment.", objects[otmp->otyp].oc_name); otmp->cursed = 0; otmp->spe++; break; } case SCR_DESTROY_ARMOR: if(confused) { struct obj *otmp = some_armor(); if(!otmp) { strange_feeling(scroll,"Your bones itch."); return(1); } pline("Your %s glows purple for a moment.", objects[otmp->otyp].oc_name); otmp->rustfree = 0; break; } if(uarm) { pline("Your armor turns to dust and falls to the floor!"); useup(uarm); } else if(uarmh) { pline("Your helmet turns to dust and is blown away!"); useup(uarmh); } else if(uarmg) { pline("Your gloves vanish!"); useup(uarmg); selftouch("You"); } else { strange_feeling(scroll,"Your skin itches."); return(1); } break; case SCR_CONFUSE_MONSTER: if(confused) { pline("Your hands begin to glow purple."); Confusion += rnd(100); } else { pline("Your hands begin to glow blue."); u.umconf = 1; } break; case SCR_SCARE_MONSTER: { int ct = 0; struct monst *mtmp; for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(cansee(mtmp->mx,mtmp->my)) { if(confused) mtmp->mflee = mtmp->mfroz = mtmp->msleep = 0; else mtmp->mflee = 1; ct++; } if(!ct) { if(confused) pline("You hear sad wailing in the distance."); else pline("You hear maniacal laughter in the distance."); } break; } case SCR_BLANK_PAPER: if(confused) pline("You see strange patterns on this scroll."); else pline("This scroll seems to be blank."); break; case SCR_REMOVE_CURSE: { struct obj *obj; if(confused) pline("You feel like you need some help."); else pline("You feel like someone is helping you."); for(obj = invent; obj ; obj = obj->nobj) if(obj->owornmask) obj->cursed = confused; if(Punished && !confused) { Punished = 0; freeobj(uchain); unpobj(uchain); free(uchain); uball->spe = 0; uball->owornmask &= ~W_BALL; uchain = uball = (struct obj *) 0; } break; } case SCR_CREATE_MONSTER: { int cnt = 1; if(!rn2(73)) cnt += rnd(4); if(confused) cnt += 12; while(cnt--) (void) makemon(confused ? PM_ACID_BLOB : (struct permonst *) 0, u.ux, u.uy); break; } case SCR_ENCHANT_WEAPON: if(uwep && confused) { pline("Your %s glows silver for a moment.", objects[uwep->otyp].oc_name); uwep->rustfree = 1; } else if(!chwepon(scroll, 1)) /* tests for !uwep */ return(1); break; case SCR_DAMAGE_WEAPON: if(uwep && confused) { pline("Your %s glows purple for a moment.", objects[uwep->otyp].oc_name); uwep->rustfree = 0; } else if(!chwepon(scroll, -1)) /* tests for !uwep */ return(1); break; case SCR_TAMING: { int i,j; int bd = confused ? 5 : 1; struct monst *mtmp; for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) if ((mtmp = m_at(u.ux+i, u.uy+j))) (void) tamedog(mtmp, NULL); break; } case SCR_GENOCIDE: { extern char genocided[], fut_geno[]; char buf[BUFSZ]; struct monst *mtmp, *mtmp2; pline("You have found a scroll of genocide!"); known = TRUE; if(confused) *buf = u.usym; else do { pline("What monster do you want to genocide (Type the letter)? "); getlin(buf); } while(strlen(buf) != 1 || !monstersym(*buf)); if(!strchr(fut_geno, *buf)) charcat(fut_geno, *buf); if(!strchr(genocided, *buf)) charcat(genocided, *buf); else { pline("Such monsters do not exist in this world."); break; } for(mtmp = fmon; mtmp; mtmp = mtmp2){ mtmp2 = mtmp->nmon; if(mtmp->data->mlet == *buf) mondead(mtmp); } pline("Wiped out all %c's.", *buf); if(*buf == u.usym) { killer = "scroll of genocide"; u.uhp = -1; } break; } case SCR_LIGHT: if(!Blind) known = TRUE; litroom(!confused); break; case SCR_TELEPORTATION: if(confused) level_tele(); else { #ifdef QUEST int oux = u.ux, ouy = u.uy; tele(); if(dist(oux, ouy) > 100) known = TRUE; #else /* QUEST */ int uroom = inroom(u.ux, u.uy); tele(); if(uroom != inroom(u.ux, u.uy)) known = TRUE; #endif /* QUEST */ } break; case SCR_GOLD_DETECTION: /* Unfortunately this code has become slightly less elegant, now that gold and traps no longer are of the same type. */ if(confused) { struct trap *ttmp; if(!ftrap) { strange_feeling(scroll, "Your toes stop itching."); return(1); } else { for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) if(ttmp->tx != u.ux || ttmp->ty != u.uy) goto outtrapmap; /* only under me - no separate display required */ pline("Your toes itch!"); break; outtrapmap: cls(); for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) at(ttmp->tx, ttmp->ty, '$'); prme(); pline("You feel very greedy!"); } } else { struct gold *gtmp; if(!fgold) { strange_feeling(scroll, "You feel materially poor."); return(1); } else { known = TRUE; for(gtmp = fgold; gtmp; gtmp = gtmp->ngold) if(gtmp->gx != u.ux || gtmp->gy != u.uy) goto outgoldmap; /* only under me - no separate display required */ pline("You notice some gold between your feet."); break; outgoldmap: cls(); for(gtmp = fgold; gtmp; gtmp = gtmp->ngold) at(gtmp->gx, gtmp->gy, '$'); prme(); pline("You feel very greedy, and sense gold!"); } } /* common sequel */ more(); docrt(); break; case SCR_FOOD_DETECTION: { int ct = 0, ctu = 0; struct obj *obj; char foodsym = confused ? POTION_SYM : FOOD_SYM; for(obj = fobj; obj; obj = obj->nobj) if(obj->olet == FOOD_SYM) { if(obj->ox == u.ux && obj->oy == u.uy) ctu++; else ct++; } if(!ct && !ctu) { strange_feeling(scroll,"Your nose twitches."); return(1); } else if(!ct) { known = TRUE; pline("You smell %s close nearby.", confused ? "something" : "food"); } else { known = TRUE; cls(); for(obj = fobj; obj; obj = obj->nobj) if(obj->olet == foodsym) at(obj->ox, obj->oy, FOOD_SYM); prme(); pline("Your nose tingles and you smell %s!", confused ? "something" : "food"); more(); docrt(); } break; } case SCR_IDENTIFY: /* known = TRUE; */ if(confused) pline("You identify this as an identify scroll."); else pline("This is an identify scroll."); useup(scroll); objects[SCR_IDENTIFY].oc_name_known = 1; if(!confused) while( !ggetobj("identify", identify, rn2(5) ? 1 : rn2(5)) && invent ); return(1); case SCR_MAGIC_MAPPING: { struct rm *lev; int num, zx, zy; known = TRUE; pline("On this scroll %s a map!", confused ? "was" : "is"); for(zy = 0; zy < ROWNO; zy++) for(zx = 0; zx < COLNO; zx++) { if(confused && rn2(7)) continue; lev = &(levl[zx][zy]); if((num = lev->typ) == 0) continue; if(num == SCORR) { lev->typ = CORR; lev->scrsym = CORR_SYM; } else if(num == SDOOR) { lev->typ = DOOR; lev->scrsym = '+'; /* do sth in doors ? */ } else if(lev->seen) continue; #ifndef QUEST if(num != ROOM) #endif /* QUEST */ { lev->seen = lev->new = 1; if(lev->scrsym == ' ' || !lev->scrsym) newsym(zx,zy); else on_scr(zx,zy); } } break; } case SCR_AMNESIA: { int zx, zy; known = TRUE; for(zx = 0; zx < COLNO; zx++) for(zy = 0; zy < ROWNO; zy++) if(!confused || rn2(7)) if(!cansee(zx,zy)) levl[zx][zy].seen = 0; docrt(); pline("Thinking of Maud you forget everything else."); break; } case SCR_FIRE: { int num; struct monst *mtmp; known = TRUE; if(confused) { pline("The scroll catches fire and you burn your hands."); losehp(1, "scroll of fire"); } else { pline("The scroll erupts in a tower of flame!"); if(Fire_resistance) pline("You are uninjured."); else { num = rnd(6); u.uhpmax -= num; losehp(num, "scroll of fire"); } } num = (2*num + 1)/3; for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { if(dist(mtmp->mx,mtmp->my) < 3) { mtmp->mhp -= num; if(strchr("FY", mtmp->data->mlet)) mtmp->mhp -= 3*num; /* this might well kill 'F's */ if(mtmp->mhp < 1) { killed(mtmp); break; /* primitive */ } } } break; } case SCR_PUNISHMENT: known = TRUE; if(confused) { pline("You feel guilty."); break; } pline("You are being punished for your misbehaviour!"); if(Punished){ pline("Your iron ball gets heavier."); uball->owt += 15; break; } Punished = INTRINSIC; setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN); setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL); uball->spe = 1; /* special ball (see save) */ break; default: impossible("What weird language is this written in? (%u)", scroll->otyp); }
bool sbbs_t::logon() { char str[256],c; char tmp[512]; int file; uint i,j,mailw; long kmode; ulong totallogons; node_t node; struct tm tm; now=time(NULL); if(localtime_r(&now,&tm)==NULL) return(false); if(!useron.number) return(false); client.user=useron.alias; client_on(client_socket,&client,TRUE /* update */); #ifdef JAVASCRIPT js_create_user_objects(); #endif if(useron.rest&FLAG('Q')) qwklogon=1; if(SYSOP && !(cfg.sys_misc&SM_R_SYSOP)) return(false); if(useron.rest&FLAG('G')) { /* Guest account */ useron.misc=(cfg.new_misc&(~ASK_NSCAN)); useron.rows=0; useron.misc&=~(ANSI|RIP|WIP|NO_EXASCII|COLOR|HTML); useron.misc|=autoterm; if(!(useron.misc&ANSI) && text[AnsiTerminalQ][0] && yesno(text[AnsiTerminalQ])) useron.misc|=ANSI; if(useron.misc&(RIP|WIP|HTML) || (useron.misc&ANSI && text[ColorTerminalQ][0] && yesno(text[ColorTerminalQ]))) useron.misc|=COLOR; if(text[ExAsciiTerminalQ][0] && !yesno(text[ExAsciiTerminalQ])) useron.misc|=NO_EXASCII; for(i=0;i<cfg.total_xedits;i++) if(!stricmp(cfg.xedit[i]->code,cfg.new_xedit) && chk_ar(cfg.xedit[i]->ar,&useron,&client)) break; if(i<cfg.total_xedits) useron.xedit=i+1; else useron.xedit=0; useron.prot=cfg.new_prot; useron.shell=cfg.new_shell; } if(!chk_ar(cfg.node_ar,&useron,&client)) { bputs(text[NoNodeAccess]); sprintf(str,"(%04u) %-25s Insufficient node access" ,useron.number,useron.alias); logline(LOG_NOTICE,"+!",str); return(false); } getnodedat(cfg.node_num,&thisnode,1); if(thisnode.misc&NODE_LOCK) { putnodedat(cfg.node_num,&thisnode); /* must unlock! */ if(!SYSOP && !(useron.exempt&FLAG('N'))) { bputs(text[NodeLocked]); sprintf(str,"(%04u) %-25s Locked node logon attempt" ,useron.number,useron.alias); logline(LOG_NOTICE,"+!",str); return(false); } if(yesno(text[RemoveNodeLockQ])) { getnodedat(cfg.node_num,&thisnode,1); logline("S-","Removed Node Lock"); thisnode.misc&=~NODE_LOCK; } else getnodedat(cfg.node_num,&thisnode,1); } if(useron.exempt&FLAG('H')) console|=CON_NO_INACT; if((useron.exempt&FLAG('Q') && useron.misc&QUIET)) thisnode.status=NODE_QUIET; else thisnode.status=NODE_INUSE; action=thisnode.action=NODE_LOGN; thisnode.connection=node_connection; thisnode.misc&=~(NODE_ANON|NODE_INTR|NODE_MSGW|NODE_POFF|NODE_AOFF); if(useron.chat&CHAT_NOACT) thisnode.misc|=NODE_AOFF; if(useron.chat&CHAT_NOPAGE) thisnode.misc|=NODE_POFF; thisnode.useron=useron.number; putnodedat(cfg.node_num,&thisnode); getusrsubs(); getusrdirs(); if(useron.misc&CURSUB && !(useron.rest&FLAG('G'))) { for(i=0;i<usrgrps;i++) { for(j=0;j<usrsubs[i];j++) { if(!strcmp(cfg.sub[usrsub[i][j]]->code,useron.cursub)) break; } if(j<usrsubs[i]) { curgrp=i; cursub[i]=j; break; } } for(i=0;i<usrlibs;i++) { for(j=0;j<usrdirs[i];j++) if(!strcmp(cfg.dir[usrdir[i][j]]->code,useron.curdir)) break; if(j<usrdirs[i]) { curlib=i; curdir[i]=j; break; } } } if(useron.misc&AUTOTERM) { useron.misc&=~(ANSI|RIP|WIP|HTML); useron.misc|=autoterm; } if(!chk_ar(cfg.shell[useron.shell]->ar,&useron,&client)) { useron.shell=cfg.new_shell; if(!chk_ar(cfg.shell[useron.shell]->ar,&useron,&client)) { for(i=0;i<cfg.total_shells;i++) if(chk_ar(cfg.shell[i]->ar,&useron,&client)) break; if(i==cfg.total_shells) useron.shell=0; } } logon_ml=useron.level; logontime=time(NULL); starttime=logontime; useron.logontime=(time32_t)logontime; last_ns_time=ns_time=useron.ns_time; // ns_time-=(useron.tlast*60); /* file newscan time == last logon time */ delfiles(cfg.temp_dir,ALLFILES); sprintf(str,"%smsgs/n%3.3u.msg",cfg.data_dir,cfg.node_num); remove(str); /* remove any pending node messages */ sprintf(str,"%smsgs/n%3.3u.ixb",cfg.data_dir,cfg.node_num); remove(str); /* remove any pending node message indices */ if(!SYSOP && online==ON_REMOTE && !qwklogon) { rioctl(IOCM|ABORT); /* users can't abort anything */ rioctl(IOCS|ABORT); } CLS; if(useron.rows) rows=useron.rows; unixtodstr(&cfg,(time32_t)logontime,str); if(!strncmp(str,useron.birth,5) && !(useron.rest&FLAG('Q'))) { bputs(text[HappyBirthday]); pause(); CLS; user_event(EVENT_BIRTHDAY); } useron.ltoday++; gettimeleft(); sprintf(str,"%sfile/%04u.dwn",cfg.data_dir,useron.number); batch_add_list(str); if(!qwklogon) { /* QWK Nodes don't go through this */ if(cfg.sys_pwdays && (ulong)logontime>(useron.pwmod+((ulong)cfg.sys_pwdays*24UL*60UL*60UL))) { bprintf(text[TimeToChangePw],cfg.sys_pwdays); c=0; while(c<LEN_PASS) { /* Create random password */ str[c]=sbbs_random(43)+'0'; if(isalnum(str[c])) c++; } str[c]=0; bprintf(text[YourPasswordIs],str); if(cfg.sys_misc&SM_PWEDIT && yesno(text[NewPasswordQ])) while(online) { bputs(text[NewPassword]); getstr(str,LEN_PASS,K_UPPER|K_LINE); truncsp(str); if(chkpass(str,&useron,true)) break; CRLF; } while(online) { if(cfg.sys_misc&SM_PWEDIT) { CRLF; bputs(text[VerifyPassword]); } else bputs(text[NewUserPasswordVerify]); console|=CON_R_ECHOX; getstr(tmp,LEN_PASS*2,K_UPPER); console&=~(CON_R_ECHOX|CON_L_ECHOX); if(strcmp(str,tmp)) { bputs(text[Wrong]); continue; } break; } strcpy(useron.pass,str); useron.pwmod=time32(NULL); putuserrec(&cfg,useron.number,U_PWMOD,8,ultoa((ulong)useron.pwmod,str,16)); bputs(text[PasswordChanged]); pause(); } if(useron.ltoday>cfg.level_callsperday[useron.level] && !(useron.exempt&FLAG('L'))) { bputs(text[NoMoreLogons]); sprintf(str,"(%04u) %-25s Out of logons" ,useron.number,useron.alias); logline(LOG_NOTICE,"+!",str); hangup(); return(false); } if(useron.rest&FLAG('L') && useron.ltoday>1) { bputs(text[R_Logons]); sprintf(str,"(%04u) %-25s Out of logons" ,useron.number,useron.alias); logline(LOG_NOTICE,"+!",str); hangup(); return(false); } kmode=(cfg.uq&UQ_NOEXASC); if(!(cfg.uq&UQ_NOUPRLWR)) kmode|=K_UPRLWR; if(!(useron.rest&FLAG('G'))) { if(!useron.name[0] && ((cfg.uq&UQ_ALIASES && cfg.uq&UQ_REALNAME) || cfg.uq&UQ_COMPANY)) while(online) { if(cfg.uq&UQ_ALIASES && cfg.uq&UQ_REALNAME) bputs(text[EnterYourRealName]); else bputs(text[EnterYourCompany]); getstr(useron.name,LEN_NAME,kmode); if(cfg.uq&UQ_ALIASES && cfg.uq&UQ_REALNAME) { if(trashcan(useron.name,"name") || !useron.name[0] || !strchr(useron.name,' ') || strchr(useron.name,0xff) || (cfg.uq&UQ_DUPREAL && userdatdupe(useron.number,U_NAME,LEN_NAME ,useron.name,0,0))) bputs(text[YouCantUseThatName]); else break; } else break; } if(cfg.uq&UQ_HANDLE && !useron.handle[0]) { sprintf(useron.handle,"%.*s",LEN_HANDLE,useron.alias); while(online) { bputs(text[EnterYourHandle]); if(!getstr(useron.handle,LEN_HANDLE ,K_LINE|K_EDIT|K_AUTODEL|(cfg.uq&UQ_NOEXASC)) || strchr(useron.handle,0xff) || (cfg.uq&UQ_DUPHAND && userdatdupe(useron.number,U_HANDLE,LEN_HANDLE ,useron.handle,0,0)) || trashcan(useron.handle,"name")) bputs(text[YouCantUseThatName]); else break; } } if(cfg.uq&UQ_LOCATION && !useron.location[0]) while(online) { bputs(text[EnterYourCityState]); if(getstr(useron.location,LEN_LOCATION,kmode)) break; } if(cfg.uq&UQ_ADDRESS && !useron.address[0]) while(online) { bputs(text[EnterYourAddress]); if(getstr(useron.address,LEN_ADDRESS,kmode)) break; } if(cfg.uq&UQ_ADDRESS && !useron.zipcode[0]) while(online) { bputs(text[EnterYourZipCode]); if(getstr(useron.zipcode,LEN_ZIPCODE,K_UPPER|(cfg.uq&UQ_NOEXASC))) break; } if(cfg.uq&UQ_PHONE && !useron.phone[0]) { if(text[CallingFromNorthAmericaQ][0]) i=yesno(text[CallingFromNorthAmericaQ]); else i=0; while(online) { bputs(text[EnterYourPhoneNumber]); if(i) { if(gettmplt(useron.phone,cfg.sys_phonefmt ,K_LINE|(cfg.uq&UQ_NOEXASC))<strlen(cfg.sys_phonefmt)) continue; } else { if(getstr(useron.phone,LEN_PHONE ,K_UPPER|(cfg.uq&UQ_NOEXASC))<5) continue; } if(!trashcan(useron.phone,"phone")) break; } } if(!(cfg.uq&UQ_NONETMAIL) && !useron.netmail[0]) { while(online) { bputs(text[EnterNetMailAddress]); if(getstr(useron.netmail,LEN_NETMAIL,K_EDIT|K_AUTODEL|K_LINE) && !trashcan(useron.netmail,"email")) break; } if(useron.netmail[0] && cfg.sys_misc&SM_FWDTONET && !noyes(text[ForwardMailQ])) useron.misc|=NETMAIL; else useron.misc&=~NETMAIL; } if(cfg.new_sif[0]) { sprintf(str,"%suser/%4.4u.dat",cfg.data_dir,useron.number); if(flength(str)<1L) create_sif_dat(cfg.new_sif,str); } } } if(!online) { sprintf(str,"(%04u) %-25s Unsuccessful logon" ,useron.number,useron.alias); logline(LOG_NOTICE,"+!",str); return(false); } SAFECOPY(useron.modem,connection); useron.logons++; putuserdat(&cfg,&useron); getmsgptrs(); sys_status|=SS_USERON; /* moved from further down */ if(useron.rest&FLAG('Q')) { sprintf(str,"(%04u) %-25s QWK Network Connection" ,useron.number,useron.alias); logline("++",str); return(true); } /********************/ /* SUCCESSFUL LOGON */ /********************/ totallogons=logonstats(); sprintf(str,"(%04u) %-25s Logon %lu - %u" ,useron.number,useron.alias,totallogons,useron.ltoday); logline("++",str); if(!qwklogon && cfg.logon_mod[0]) exec_bin(cfg.logon_mod,&main_csi); if(thisnode.status!=NODE_QUIET && (!REALSYSOP || cfg.sys_misc&SM_SYSSTAT)) { sprintf(str,"%slogon.lst",cfg.data_dir); if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) { errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_CREAT|O_APPEND); return(false); } getuserrec(&cfg,useron.number,U_NOTE,LEN_NOTE,useron.note); getuserrec(&cfg,useron.number,U_LOCATION,LEN_LOCATION,useron.location); sprintf(str,text[LastFewCallersFmt],cfg.node_num ,totallogons,useron.alias ,cfg.sys_misc&SM_LISTLOC ? useron.location : useron.note ,tm.tm_hour,tm.tm_min ,connection,useron.ltoday > 999 ? 999 : useron.ltoday); write(file,str,strlen(str)); close(file); } if(cfg.sys_logon[0]) /* execute system logon event */ external(cmdstr(cfg.sys_logon,nulstr,nulstr,NULL),EX_STDOUT); /* EX_SH */ if(qwklogon) return(true); sys_status|=SS_PAUSEON; /* always force pause on during this section */ mailw=getmail(&cfg,useron.number,0); if(!(cfg.sys_misc&SM_NOSYSINFO)) { bprintf(text[SiSysName],cfg.sys_name); //bprintf(text[SiNodeNumberName],cfg.node_num,cfg.node_name); bprintf(text[LiUserNumberName],useron.number,useron.alias); bprintf(text[LiLogonsToday],useron.ltoday ,cfg.level_callsperday[useron.level]); bprintf(text[LiTimeonToday],useron.ttoday ,cfg.level_timeperday[useron.level]+useron.min); bprintf(text[LiMailWaiting],mailw); strcpy(str,text[LiSysopIs]); if(startup->options&BBS_OPT_SYSOP_AVAILABLE || (cfg.sys_chat_ar[0] && chk_ar(cfg.sys_chat_ar,&useron,&client))) strcat(str,text[LiSysopAvailable]); else strcat(str,text[LiSysopNotAvailable]); bprintf("%s\r\n\r\n",str); } if(sys_status&SS_EVENT) bprintf(text[ReducedTime],timestr(event_time)); getnodedat(cfg.node_num,&thisnode,1); thisnode.misc&=~(NODE_AOFF|NODE_POFF); if(useron.chat&CHAT_NOACT) thisnode.misc|=NODE_AOFF; if(useron.chat&CHAT_NOPAGE) thisnode.misc|=NODE_POFF; putnodedat(cfg.node_num,&thisnode); getsmsg(useron.number); /* Moved from further down */ SYNC; c=0; for(i=1;i<=cfg.sys_nodes;i++) if(i!=cfg.node_num) { getnodedat(i,&node,0); if(!(cfg.sys_misc&SM_NONODELIST) && (node.status==NODE_INUSE || ((node.status==NODE_QUIET || node.errors) && SYSOP))) { if(!c) bputs(text[NodeLstHdr]); printnodedat(i,&node); c=1; } if(node.status==NODE_INUSE && i!=cfg.node_num && node.useron==useron.number && !SYSOP && !(useron.exempt&FLAG('G'))) { SAFEPRINTF2(str,"(%04u) %-25s On two nodes at the same time" ,useron.number,useron.alias); logline(LOG_NOTICE,"+!",str); bputs(text[UserOnTwoNodes]); hangup(); return(false); } if(thisnode.status!=NODE_QUIET && (node.status==NODE_INUSE || node.status==NODE_QUIET) && !(node.misc&NODE_AOFF) && node.useron!=useron.number) { sprintf(str,text[NodeLoggedOnAtNbps] ,cfg.node_num ,thisnode.misc&NODE_ANON ? text[UNKNOWN_USER] : useron.alias ,connection); putnmsg(&cfg,i,str); } } if(cfg.sys_exp_warn && useron.expire && useron.expire>now /* Warn user of coming */ && (useron.expire-now)/(1440L*60L)<=cfg.sys_exp_warn) /* expiration */ bprintf(text[AccountWillExpireInNDays],(useron.expire-now)/(1440L*60L)); if(criterrs && SYSOP) bprintf(text[CriticalErrors],criterrs); if((i=getuserxfers(0,useron.number,0))!=0) bprintf(text[UserXferForYou],i,i>1 ? "s" : nulstr); if((i=getuserxfers(useron.number,0,0))!=0) bprintf(text[UnreceivedUserXfer],i,i>1 ? "s" : nulstr); SYNC; sys_status&=~SS_PAUSEON; /* Turn off the pause override flag */ if(online==ON_REMOTE) rioctl(IOSM|ABORT); /* Turn abort ability on */ if(text[ReadYourMailNowQ][0] && mailw) { if(yesno(text[ReadYourMailNowQ])) readmail(useron.number,MAIL_YOUR); } if(usrgrps && useron.misc&ASK_NSCAN && text[NScanAllGrpsQ][0] && yesno(text[NScanAllGrpsQ])) scanallsubs(SCAN_NEW); if(usrgrps && useron.misc&ASK_SSCAN && text[SScanAllGrpsQ][0] && yesno(text[SScanAllGrpsQ])) scanallsubs(SCAN_TOYOU); return(true); }
namespace wfc { namespace { static CursesWindow* CreateBoxedWindow(const std::string& title, int nlines, int ncols, int y, int x) { unique_ptr<CursesWindow> window(new CursesWindow(out->window(), out->color_scheme(), nlines, ncols, y, x)); window->SetColor(SchemeId::WINDOW_BOX); window->Box(0, 0); window->SetTitle(title); window->SetColor(SchemeId::WINDOW_TEXT); return window.release(); } } auto noop = [](){}; static void wfc_command(int instance_location_id, std::function<void()> f, std::function<void()> f2 = noop, std::function<void()> f3 = noop, std::function<void()> f4 = noop) { session()->reset_local_io(new CursesLocalIO(out->window()->GetMaxY())); wfc_cls(); write_inst(instance_location_id, 0, INST_FLAGS_NONE); f(); f2(); f3(); f4(); write_inst(INST_LOC_WFC, 0, INST_FLAGS_NONE); } auto send_email_f = []() { session()->usernum = 1; bout << "|#1Send Email:"; send_email(); session()->WriteCurrentUser(1); }; auto view_sysop_log_f = []() { unique_ptr<WStatus> pStatus(session()->status_manager()->GetStatus()); const string sysop_log_file = GetSysopLogFileName(date()); print_local_file(sysop_log_file); }; auto view_yesterday_sysop_log_f = []() { unique_ptr<WStatus> pStatus(session()->status_manager()->GetStatus()); print_local_file(pStatus->GetLogFileName(1)); }; auto read_mail_f = []() { session()->usernum = 1; readmail(0); session()->WriteCurrentUser(1); }; auto getkey_f = []() { getkey(); }; ControlCenter::ControlCenter() { const string title = StringPrintf("WWIV %s%s Server.", wwiv_version, beta_version); CursesIO::Init(title); // take ownership of out. out_scope_.reset(out); session()->SetWfcStatus(0); } ControlCenter::~ControlCenter() {} static void DrawCommands(CursesWindow* commands) { commands->SetColor(SchemeId::WINDOW_TEXT); commands->PutsXY(1, 1, "[B]oardEdit [C]hainEdit"); commands->PutsXY(1, 2, "[D]irEdit [E]mail [G]-FileEdit"); commands->PutsXY(1, 3, "[I]nit Voting Data [J] ConfEdit"); commands->PutsXY(1, 4, "Sysop[L]og Read [M]ail [N]etLog"); commands->PutsXY(1, 5, "[P]ending Net Data [/] Net Callout"); commands->PutsXY(1, 6, "[R]ead all email [S]ystem Status"); commands->PutsXY(1, 7, "[U]serEdit [Y]-Log [Z]-Log"); } static void DrawStatus(CursesWindow* statusWindow) { statusWindow->SetColor(SchemeId::WINDOW_TEXT); statusWindow->PutsXY(2, 1, "Today:"); statusWindow->PutsXY(2, 2, "Calls: XXXXX Minutes: XXXXX"); statusWindow->PutsXY(2, 3, "M: XXX L: XXX E: XXX F: XXX FW: XXX"); statusWindow->PutsXY(2, 4, "Totals:"); statusWindow->PutsXY(2, 5, "Users: XXXXX Calls: XXXXX"); statusWindow->PutsXY(2, 6, "Last User:"******"XXXXXXXXXXXXXXXXXXXXXXXXXX"); } static string GetLastUserName(int inst_num) { instancerec ir; get_inst_info(inst_num, &ir); if (ir.flags & INST_FLAGS_ONLINE) { return session()->names()->UserName(ir.user); } else { return "Nobody"; } } static void UpdateStatus(CursesWindow* statusWindow) { statusWindow->SetColor(SchemeId::WINDOW_DATA); std::unique_ptr<WStatus> pStatus(session()->status_manager()->GetStatus()); statusWindow->PrintfXY(9, 2, "%-5d", pStatus->GetNumCallsToday()); statusWindow->PrintfXY(24, 2, "%-5d", pStatus->GetMinutesActiveToday()); statusWindow->PrintfXY(5, 3, "%-3u", pStatus->GetNumMessagesPostedToday()); statusWindow->PrintfXY(12, 3, "%-3u", pStatus->GetNumLocalPosts()); statusWindow->PrintfXY(19, 3, "%-3u", pStatus->GetNumEmailSentToday()); statusWindow->PrintfXY(26, 3, "%-3u", pStatus->GetNumFeedbackSentToday()); fwaiting = session()->user()->GetNumMailWaiting(); statusWindow->PrintfXY(34, 3, "%-3d", fwaiting); statusWindow->PrintfXY(9, 5, "%-5d", pStatus->GetNumUsers()); statusWindow->PrintfXY(22, 5, "%-6lu", pStatus->GetCallerNumber()); // TODO(rushfan): Need to know the last used node number // then call GetLastUserName. // statusWindow->PutsXY(2, 7, "XXXXXXXXXXXXXXXXXXXXXXXXXX"); } static void CleanNetIfNeeded() { static int mult_time = 0; if (session()->IsCleanNetNeeded() || std::abs(timer1() - mult_time) > 1000L) { cleanup_net(); mult_time = timer1(); } } static void RunEventsIfNeeded() { unique_ptr<WStatus> pStatus(session()->status_manager()->GetStatus()); if (!IsEquals(date(), pStatus->GetLastDate())) { if ((session()->GetBeginDayNodeNumber() == 0) || (session()->instance_number() == session()->GetBeginDayNodeNumber())) { cleanup_events(); beginday(true); } } if (!do_event) { check_event(); } while (do_event) { run_event(do_event - 1); check_event(); } session()->SetCurrentSpeed("KB"); static time_t last_time_c = 0; time_t lCurrentTime = time(nullptr); if ((((rand() % 8000) == 0) || (lCurrentTime - last_time_c > 1200)) && net_sysnum) { lCurrentTime = last_time_c; attempt_callout(); } } void ControlCenter::Initialize() { // Initialization steps that have to happen before we // have a functional WFC system. This also supposes that // session()->InitializeBBS has been called. out->Cls(ACS_CKBOARD); const int logs_y_padding = 1; const int logs_start = 11; const int logs_length = out->window()->GetMaxY() - logs_start - logs_y_padding; log_.reset(new WfcLog(logs_length - 2)); commands_.reset(CreateBoxedWindow("Commands", 9, 38, 1, 1)); status_.reset(CreateBoxedWindow("Status", 9, 39, 1, 40)); logs_.reset(CreateBoxedWindow("Logs", logs_length, 78, 11, 1)); DrawCommands(commands_.get()); DrawStatus(status_.get()); vector<HelpItem> help_items0 = { { "?", "All Commands" },}; vector<HelpItem> help_items1 = { {"Q", "Quit" } }; out->footer()->ShowHelpItems(0, help_items0); out->footer()->ShowHelpItems(1, help_items1); session()->ReadCurrentUser(1); read_qscn(1, qsc, false); session()->ResetEffectiveSl(); session()->usernum = 1; fwaiting = session()->user()->GetNumMailWaiting(); session()->SetWfcStatus(1); } void ControlCenter::Run() { Initialize(); bool need_refresh = false; for (bool done = false; !done;) { if (need_refresh) { // refresh the window since we call endwin before invoking bbs code. RefreshAll(); need_refresh = false; } wtimeout(commands_->window(), 500); int key = commands_->GetChar(); if (key == ERR) { // we have a timeout. process other events need_refresh = false; UpdateLog(); UpdateStatus(status_.get()); CleanNetIfNeeded(); RunEventsIfNeeded(); continue; } need_refresh = true; session()->SetWfcStatus(2); // Call endwin since we'll be out of curses IO endwin(); switch (toupper(key)) { case 'B': wfc_command(INST_LOC_BOARDEDIT, boardedit, cleanup_net); log_->Put("Ran BoardEdit"); break; case 'C': wfc_command(INST_LOC_CHAINEDIT, chainedit); log_->Put("Ran ChainEdit"); break; case 'D': wfc_command(INST_LOC_DIREDIT, dlboardedit); log_->Put("Ran DirEdit"); break; case 'E': wfc_command(INST_LOC_EMAIL, send_email_f, cleanup_net); break; case 'G': wfc_command(INST_LOC_GFILEEDIT, gfileedit); break; case 'H': wfc_command(INST_LOC_EVENTEDIT, eventedit); break; case 'I': wfc_command(INST_LOC_VOTEEDIT, ivotes); break; case 'J': wfc_command(INST_LOC_CONFEDIT, edit_confs); break; case 'L': wfc_command(INST_LOC_WFC, view_sysop_log_f); break; case 'M': wfc_command(INST_LOC_EMAIL, read_mail_f, cleanup_net); break; case 'N': wfc_command(INST_LOC_WFC, []() { print_local_file("net.log"); }); break; case 'P': wfc_command(INST_LOC_WFC, print_pending_list); break; case 'R': wfc_command(INST_LOC_MAILR, mailr); break; case 'S': wfc_command(INST_LOC_WFC, prstatus, getkey_f); break; case 'U': wfc_command(INST_LOC_UEDIT, []() { uedit(1, UEDIT_NONE); } ); break; case 'Y': wfc_command(INST_LOC_WFC, view_yesterday_sysop_log_f); break; case 'Z': wfc_command(INST_LOC_WFC, zlog, getkey_f); break; case 'Q': done=true; break; // ansicallout doesn't work due to arrow keys and other drawing problems with it under curses. // case '/': wfc_command(INST_LOC_NET, []() { force_callout(0); }); log_->Put("Ran Network Callout"); break; case ' ': log_->Put("Not Implemented Yet"); break; } TouchAll(); } } void ControlCenter::TouchAll() { out->window()->TouchWin(); commands_->TouchWin(); status_->TouchWin(); logs_->TouchWin(); } void ControlCenter::RefreshAll() { out->window()->Refresh(); commands_->Refresh(); status_->Refresh(); logs_->Refresh(); UpdateStatus(status_.get()); } void ControlCenter::UpdateLog() { if (!log_->dirty()) { return; } vector<string> lines; if (!log_->Get(lines)) { return; } int start = 1; const int width = logs_->GetMaxX() - 4; for (const auto& line : lines) { logs_->PutsXY(1, start, line); logs_->PutsXY(1 + line.size(), start, string(width - line.size(), ' ')); start++; } } }