/**************i**************************************************************** * * Awsome NUTS v. 0.1 - (c) Mind Booster Noori (marado@student.dei.uc.pt) * - This is LICENSED! Read the LICENSE file to know more about it! - * * Awsome NUTS v. 0.1 is a code based upon SAMNUTS v. 0.3, which header follows: *******************************************************************************/ /***************************************************************************** SAMNUTS v. 0.3 - (c) Mind Booster Noori (marado@student.dei.uc.pt) - This is an "internal version", not licensed (yet) - *****************************************************************************/ /* For glibc's intl/ instead of the old one: */ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <string.h> #include <unistd.h> /* If those defined upwards doesn't make sense to you, forget it... it's all * because of the new libraries version... */ #define VERSION "2.3.0" //NUTS version #include <stdio.h> #ifdef _AIX #include <sys/select.h> #endif #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <fcntl.h> #include <netdb.h> #include <netinet/in.h> #include <signal.h> #include <time.h> #include "openssl/bio.h" #include "openssl/err.h" #include "openssl/ssl.h" /* file and directory definitions */ #define DATADIR "datadir" #define INITFILE "init_data" #define MESSDIR "messboards" #define NEWSFILE "newsfile" #define MOTD1 "motd1" #define MOTD2 "motd2" #define SYSTEM_LOG "syslog" #define PASSFILE "passfile" #define USERDATADIR "userdata" #define HELPDIR "helpfiles" #define WHOFILE "whofile" #define BANFILE "banfile" #define MAPFILE "mapfile" #define GENFILE "general" /* level defs */ #define GOD 3 #define WIZARD 2 #define USER 1 #define NEWBIE 0 /* other definitions */ #ifndef FD_SETSIZE #define FD_SETSIZE 256 #endif #define ARR_SIZE 2000 #define MAX_USERS 30 /* MAX_USERS must NOT be greater than FD_SETSIZE - 1 */ #define MAX_AREAS 26 #define ALARM_TIME 30 /* alarm time in seconds (must not exceed 60) */ #define TIME_OUT 180 /* time out in seconds at login - can't be less than ALARM_TIME */ #define IDLE_MENTION 30 /* Used in check_timeout(). Is in minutes */ #define TOPIC_LEN 35 #define DESC_LEN 29 #define NAME_LEN 16 #define NUM_LINES 15 /* number of lines of conv. to store in areas */ #define PRO_LINES 15 /* number of lines of profile user can store */ #define PRINUM 2 /* no. of users in area befor it can be made private */ #define PASSWORD_ECHO 1 /* set this to 1 if you want passwords echoed */ #define CHAR_MODE_ECHO 0 /* see README about this */ #define SALT "AB" /* for password encryption */ void sigcall(); char *timeline(); /** Far too many bloody global declarations **/ char *command[]={ ".quit",".who",".shout",".tell",".listen",".ignore",".look",".go", ".private",".public",".invite",".emote",".areas",".letmein",".write",".read", ".wipe",".topic",".demote",".map",".kill",".shutdown",".search", ".review",".help",".bcast",".news",".prompt",".move",".access",".log", ".semote",".pemote",".desc",".newusers",".version",".entpro",".examine",".passwd", ".dmail",".rmail",".smail",".wake",".promote","*" }; /* Alter this data to suit. It is the level of user that can run each command in the above string array. */ int com_level[]={ 0,0,2,1,1,1,0, 1,2, 2,2,0,2,1,1,1,2, 2,3,1,3,3,2,1,0, 2,1,0,2,3,3,2,1, 0,3,0,0,1,1,1,0, 1,2,2 }; char *syserror="Sorry - a system error has occured"; char mess[ARR_SIZE]; /* functions use mess to send output */ char mess2[ARR_SIZE]; /* for event functions output */ char conv[MAX_AREAS][NUM_LINES][161]; /* stores lines of conversation in area*/ char start_time[30]; /* startup time */ int PORT,NUM_AREAS,num_of_users=0; int MESS_LIFE=7; /* message lifetime in days */ int noprompt,atmos_on,allow_new,com_num; int syslog_on=1; int shutd=-1; int sys_access=1; int checked=1; /* see if messages have been checked */ /* user structure */ struct { char buff[ARR_SIZE],name[NAME_LEN],desc[DESC_LEN]; char login_name[NAME_LEN],login_pass[NAME_LEN]; char site[80],page_file[80]; char *pro_start,*pro_end; int area,listen,level,file_posn,pro_enter; int buffpos,sock,time,vis,invite,last_input; int idle_mention,logging_in,attleft,prompt; } ustr[MAX_USERS]; /* area structure */ struct { char name[NAME_LEN],topic[TOPIC_LEN+1],move[MAX_AREAS]; int private,status,mess_num,conv_line; } astr[MAX_AREAS]; /**** START OF FUNCTIONS ****/ /**************************************************************************** Main function - Sets up TCP sockets, ignores signals, accepts user input and acts as the switching centre for speach output. *****************************************************************************/ main() { struct sockaddr_in bind_addr,acc_addr; struct hostent *host; fd_set readmask; /* readmask for select() */ unsigned int addr; int listen_sock,accept_sock; int l,len,area,size,user,new_user,on; char inpstr[ARR_SIZE],filename[80],site_num[80]; char *inet_ntoa(); /* socket library function */ printf("\n *** Talker booting ***\n\n"); /* Make old system log backup */ sprintf(filename,"%s.bak",SYSTEM_LOG); if (rename(SYSTEM_LOG,filename)==-1) printf("SAMNUTS: Warning: Couldn't make old system log backup\n\n"); write_syslog("*** Talker BOOTING ***\n",0); /* read system data */ read_init_data(); /* initialize sockets */ printf("Initialising sockets on port %d\n",PORT); size=sizeof(struct sockaddr_in); if ((listen_sock=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("\nSAMNUTS: Couldn't open listen socket"); write_syslog("BOOT FAILED: Couldn't open listen socket\n",0); exit(1); } /* Allow reboots even with TIME_WAITS etc on port */ on=1; setsockopt(listen_sock,SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof(on)); bind_addr.sin_family=AF_INET; bind_addr.sin_addr.s_addr=INADDR_ANY; bind_addr.sin_port=htons(PORT); if (bind(listen_sock,(struct sockaddr *)&bind_addr,size)==-1) { perror("\nSAMNUTS: Couldn't bind to port"); write_syslog("BOOT FAILED: Couldn't bind to port\n",0); exit(1); } if (listen(listen_sock,20)==-1) { perror("\nSAMNUTS: Listen error"); write_syslog("BOOT FAILED: Listen error",0); exit(1); } /* initialize functions */ puts("Initialising structures"); init_structures(); puts("Checking for out of date messages"); check_mess(1); messcount(); /* Set socket to non-blocking. Not really needed but it does no harm. */ fcntl(listen_sock,F_SETFL,O_NDELAY); /* Set to run in background automatically - no '&' needed */ switch(fork()) { case -1: perror("\nSAMNUTS: Fork failed"); write_syslog("BOOT FAILED: Fork failed\n",0); exit(1); case 0: break; /* child becomes server */ default: sleep(1); exit(0); /* kill parent */ } /* log startup */ sprintf(mess,"*** Talker BOOTED (PID %d) on %s ***\n",getpid(),timeline(1)); write_syslog(mess,0); strcpy(start_time,timeline(1)); /* record boot time */ unlink(WHOFILE); printf("Process ID: %d\n\n*** Server running ***\n\n",getpid()); /* close stdin, out & err to free up some descriptors */ close(0); close(1); close(2); /* Set up alarm & ignore all possible signals. Ok so we shouldnt really ignore signals but I can't think of any usefull trap function to write. */ reset_alarm(); signal(SIGILL,SIG_IGN); signal(SIGTRAP,SIG_IGN); signal(SIGIOT,SIG_IGN); signal(SIGBUS,SIG_IGN); signal(SIGSEGV,SIG_IGN); signal(SIGTSTP,SIG_IGN); signal(SIGCONT,SIG_IGN); signal(SIGHUP,SIG_IGN); signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); signal(SIGABRT,SIG_IGN); signal(SIGFPE,SIG_IGN); signal(SIGTERM,SIG_IGN); signal(SIGURG,SIG_IGN); signal(SIGPIPE,SIG_IGN); signal(SIGTTIN,SIG_IGN); signal(SIGTTOU,SIG_IGN); signal(SIGXCPU,SIG_IGN); /**** Main program loop. Its a bit too long but what the hell... *****/ while(1) { noprompt=0; FD_ZERO(&readmask); /* set up readmask */ for (user=0;user<MAX_USERS;++user) { if (ustr[user].sock==-1) continue; FD_SET(ustr[user].sock,&readmask); } FD_SET(listen_sock,&readmask); /* wait */ if (select(FD_SETSIZE,&readmask,0,0,0)==-1) continue; /* check for connection to listen socket */ if (FD_ISSET(listen_sock,&readmask)) { accept_sock=accept(listen_sock,(struct sockaddr *)&acc_addr,&size); more(-1,accept_sock,MOTD1); /* send first message of the day */ if (!sys_access) { strcpy(mess,"\n\rDesculpa, neste momento a Selva IV nao esta' a aceitar novas ligacoes...\n\n\rAte' la' aconselhamos a que te ligues (por telnet) a um dos outros talkers:\n\rA nossa preferencia: LoveNest - spunge.org 6969\n\n\r"); write(accept_sock,mess,strlen(mess)); close(accept_sock); continue; } if ((new_user=find_free_slot())==-1) { strcpy(mess,"\n\rDesculpa, neste momento a Selva IV esta' cheia...\n\n\rAte' la' aconselhamos a que te ligues (por telnet) a um dos outros talkers:\n\rA nossa preferencia: LoveNest - spunge.org 6969\n\n\r"); write(accept_sock,mess,strlen(mess)); close(accept_sock); continue; } /* get new user internet site */ strcpy(site_num,inet_ntoa(acc_addr.sin_addr)); /* get number addr. */ addr=inet_addr(site_num); if ((host=gethostbyaddr((char *)&addr,4,AF_INET))) strcpy(ustr[new_user].site,host->h_name); /* copy name addr. */ else strcpy(ustr[new_user].site,site_num); ustr[new_user].sock=accept_sock; ustr[new_user].last_input=time((time_t *)0); ustr[new_user].logging_in=3; ustr[new_user].attleft=3; echo_on(user); write_user(new_user,"\n\rDiz-me o teu nome: "); } /** cycle through users **/ for (user=0;user<MAX_USERS;++user) { if (ustr[user].sock==-1) continue; area=ustr[user].area; /* see if any data on socket else continue */ if (!FD_ISSET(ustr[user].sock,&readmask)) continue; inpstr[0]=0; if (!(len=read(ustr[user].sock,inpstr,sizeof(inpstr)))) { user_quit(user); continue; } /* ignore control code replies */ if ((unsigned char)inpstr[0]==255) continue; /* see if delete key pressed in char. mode */ if (inpstr[0]==8 || inpstr[0]==127) { if (ustr[user].buffpos) { ustr[user].buffpos--; write_user(user,"\b \b"); ustr[user].buff[ustr[user].buffpos]=0; } continue; } /* copy input into buffer - allows line or char. mode clients */ for(l=0;l<len;++l) { ustr[user].buff[ustr[user].buffpos+l]=inpstr[l]; if (inpstr[l]<32 || ustr[user].buffpos+l+2==ARR_SIZE) { if (ustr[user].buffpos) write_user(user,"\n\r"); goto GOT_LINE; } } if (CHAR_MODE_ECHO && (!ustr[user].logging_in || ustr[user].logging_in==3 || PASSWORD_ECHO)) write(ustr[user].sock,inpstr,len); ustr[user].buffpos=ustr[user].buffpos+l; continue; GOT_LINE: /* copy buffer back into inpstr */ strcpy(inpstr,ustr[user].buff); terminate(inpstr); ustr[user].buff[0]=0; ustr[user].buffpos=0; ustr[user].last_input=time((time_t *)0); /* ie now */ ustr[user].idle_mention=0; /* see if user is logging in */ if (ustr[user].logging_in) { login(user,inpstr); continue; } /* see if user is reading a file */ if (ustr[user].file_posn) { if (inpstr[0]=='q' || inpstr[0]=='Q') { ustr[user].file_posn=0; prompt(user); continue; } if (more(user,ustr[user].sock,ustr[user].page_file)==2) prompt(user); continue; } /* see if input is answer to shutdown query */ if (shutd==user && inpstr[0]!='y') { shutd=-1; prompt(user); continue; } if (shutd==user && inpstr[0]=='y') shutdown_talker(user,listen_sock); if (!inpstr[0] || nospeech(inpstr)) continue; /* see if user is entering profile data */ if (ustr[user].pro_enter) { enter_pro(user,inpstr); continue; } /* deal with any commands */ com_num=get_com_num(inpstr); if (com_num==-1 && inpstr[0]=='.') { write_user(user,"Comando desconhecido!"); prompt(user); continue; } if (com_num!=-1) { exec_com(user,inpstr,ustr[user].sock); if (!com_num || noprompt) continue; /* com 0 is quit */ prompt(user); continue; } /* send speech to speaker & everyone else in same area */ if (!instr(inpstr,"help")) write_user(user,"* Ta's a precisar de ajuda... Faz .help. *\n\r"); say_speech(user,inpstr); prompt(user); } } /* end while */ } /************************* MISCELLANIOUS FUNCTIONS ***************************/ /*** Say user speech ***/ say_speech(user,inpstr) int user; char *inpstr; { char type[10]; switch(inpstr[strlen(inpstr)-1]) { case '?': strcpy(type,"perguntas"); break; case '!': strcpy(type,"exclamas"); break; default : strcpy(type,"dizes"); } sprintf(mess,"Tu %s: %s",type,inpstr); write_user(user,mess); if (!ustr[user].vis) sprintf(mess,"Uma voz animalesca diz: %s\n\r",inpstr); else sprintf(mess,"%s diz: %s\n\r",ustr[user].name,inpstr); write_alluser(user,mess,0,0); record(mess,ustr[user].area); } /*** Print prompt ***/ prompt(user) int user; { int mins,hours; time_t tm_num; char timestr[30]; if (ustr[user].prompt) { time(&tm_num); midcpy(ctime(&tm_num),timestr,11,15); mins=((int)tm_num-ustr[user].time)/60; hours=mins/60; mins=mins%60; sprintf(mess,"\n\r[SELVA IV: %s, %02d:%02d]\n\r",timestr,hours,mins); write_user(user,mess); return; } write_user(user,"\n\r"); } /*** Record speech and emotes ***/ record(string,area) char *string; int area; { string[160]=0; strcpy(conv[area][astr[area].conv_line],string); astr[area].conv_line=(++astr[area].conv_line)%NUM_LINES; } /*** Put string terminate char. at first char < 32 ***/ terminate(str) char *str; { int u; for (u=0;u<ARR_SIZE;++u) { if (*(str+u)<32) { *(str+u)=0; return; } } str[u-1]=0; } /*** convert string to lower case ***/ strtolower(str) char *str; { while(*str) { *str=tolower(*str); str++; } } /*** check for empty string ***/ nospeech(str) char *str; { while(*str) { if (*str>32) return 0; str++; } return 1; } /** read in initialize data **/ read_init_data() { char filename[80],line[80],status[10]; char *initerror="BOOT FAILED: Error in init file\n"; int a; FILE *fp; printf("Reading init data from file ./%s/%s\n",DATADIR,INITFILE); sprintf(filename,"%s/%s",DATADIR,INITFILE); if (!(fp=fopen(filename,"r"))) { perror("\nSAMNUTS: Couldn't read init file"); write_syslog("BOOT FAILED: Couldn't read init file\n",0); exit(1); } fgets(line,80,fp); /* read in important system data & do a check of some of it */ atmos_on=-1; syslog_on=-1; MESS_LIFE=-1; allow_new=-1; sscanf(line,"%d %d %d %d %d %d",&PORT,&NUM_AREAS,&atmos_on,&syslog_on,&allow_new,&MESS_LIFE); if (PORT<1 || PORT>65535 || NUM_AREAS>MAX_AREAS || atmos_on<0 || atmos_on>1 || syslog_on<0 || syslog_on>1 || MESS_LIFE<1 || allow_new<0 || allow_new>1) { fprintf(stderr,"\nSAMNUTS: Error in init file on line 1\n"); write_syslog(initerror,0); exit(1); } /* read in descriptions and joinings */ for (a=0;a<NUM_AREAS;++a) { fgets(line,80,fp); astr[a].name[0]=0; astr[a].move[0]=0; status[0]=0; sscanf(line,"%s %s %s",astr[a].name,astr[a].move,status); astr[a].status=atoi(status); if (!astr[a].name[0] || !astr[a].move[0] || !status[0] || astr[a].status<0 || astr[a].status>2) { fprintf(stderr,"\nSAMNUTS: Error in init file on line %d\n",a+2); write_syslog(initerror,0); exit(1); } if (astr[a].status==2) astr[a].private=1; else astr[a].private=0; } fclose(fp); } /*** Init user & area structures ***/ init_structures() { int a,n,u; for (u=0;u<MAX_USERS;++u) { ustr[u].area=-1; ustr[u].listen=1; ustr[u].invite=-1; ustr[u].level=0; ustr[u].vis=1; ustr[u].logging_in=0; ustr[u].buffpos=0; ustr[u].sock=-1; ustr[u].buff[0]=0; } for (a=0;a<NUM_AREAS;++a) { for (n=0;n<NUM_LINES;++n) conv[a][n][0]=0; astr[a].conv_line=0; astr[a].topic[0]=0; } } /*** count no. of messages (counts no. of newlines in message files) ***/ messcount() { FILE *fp; char c,filename[40]; int a; puts("A contar mensagens..."); for(a=0;a<NUM_AREAS;++a) { astr[a].mess_num=0; sprintf(filename,"%s/board%d",MESSDIR,a); if (!(fp=fopen(filename,"r"))) continue; while(!feof(fp)) { c=getc(fp); if (c=='\n') astr[a].mess_num++; } fclose(fp); } } /*** This is login function - first part of prog users encounter ***/ login(user,inpstr) int user; char *inpstr; { char line[81],name[ARR_SIZE],passwd[ARR_SIZE]; char name2[NAME_LEN],passwd2[NAME_LEN]; int f=0; FILE *fp; passwd[0]=0; passwd2[0]=0; switch(ustr[user].logging_in) { case 1: check_pass(user,inpstr); return; case 2: /* See if user entering password ... */ passwd[0]=0; sscanf(inpstr,"%s",passwd); if (strlen(passwd)>NAME_LEN-1) { write_user(user,"\n\rPassword muito grande...\n\n\r"); attempts(user); return; } if (strlen(passwd)<4) { write_user(user,"\n\rPassword muito pequena...\n\n\r"); attempts(user); return; } /* convert name to lowercase with first letter uppercase */ strtolower(ustr[user].login_name); ustr[user].login_name[0]=toupper(ustr[user].login_name[0]); /* open password file to read */ if (!(fp=fopen(PASSFILE,"r"))) { write_syslog("WARNING: Couldn't open password file to read in login()\n",0); goto NEW_USER; } /* search for login */ while(!feof(fp)) { fgets(line,80,fp); sscanf(line,"%s %s",name2,passwd2); if (/*0 !=*/ !strcmp(ustr[user].login_name,name2) && strcmp(crypt(passwd,SALT),passwd2) /*== 0*/) { write_user(user,"\n\rLogin incorrecto!\n\n\r"); attempts(user); fclose(fp); return; } if (!strcmp(ustr[user].login_name,name2) && !strcmp(crypt(passwd,SALT),passwd2)) { fclose(fp); echo_on(user); add_user(user); return; } } /** deal with new user **/ fclose(fp); NEW_USER: if (!allow_new) { write_user(user,"\n\rLogin incorrecto!\r\n\n"); attempts(user); return; } write_user(user,"\n\rNovo animal...\n\rVolta a introduzir a password: "); strcpy(ustr[user].login_pass,passwd); ustr[user].logging_in=1; return; case 3: /* User has entered his login name... */ name[0]=0; sscanf(inpstr,"%s",name); if (!strcmp(name,"quit")) { write_user(user,"\n\rAbandonando a Selva...\n\n\r"); user_quit(user); return; } /* This allows someone to see who's on from the login prompt so they needn't bother to log in if their mates arn't on. I think its a nice idea, you may find it intrusive , remove it if you must */ if (!strcmp(name,"who")) { who(user,0); write_user(user,"\n\rDiz ai' um nome: "); return; } if (name[0]<32 || !strlen(name)) { write_user(user,"\n\rDiz ai' um nome: "); return; } if (strlen(name)<3) { write_user(user,"Isso e' um nome muito pequeno!\n\n\r"); attempts(user); return; } if (strlen(name)>NAME_LEN-1) { write_user(user,"Nome demasiado grande...\n\n\r"); attempts(user); return; } if (!strcmp(name,"Someone") || !strcmp(name,"someone")) { write_user(user,"Esse nome nao e' va'lido!\n\n\r"); attempts(user); return; } /* see if only letters in login */ for (f=0;f<strlen(name);++f) { if (!isalpha(name[f])) { write_user(user,"Desculpa, mas so' aceitamos letras nos nomes...\n\n\r"); attempts(user); return; } } strcpy(ustr[user].login_name,name); ustr[user].logging_in=2; write_user(user,"Diz a password: "); } } /*** Check user password ***/ check_pass(user,inpstr) int user; char *inpstr; { FILE *fp; char passwd[ARR_SIZE]; sscanf(inpstr,"%s",passwd); if (strcmp(ustr[user].login_pass,passwd)) { write_user(user,"\n\rPassword errada\n\n\r"); ustr[user].login_pass[0]=0; attempts(user); return; } if (!(fp=fopen(PASSFILE,"a"))) { echo_on(user); sprintf(mess,"\n\r%s : Actualmente estamos com problemas... Tenta mais tarde.\n\n\r",syserror); write_user(user,mess); write_syslog("ERROR: Couldn't open password file to append in check_pass()\n",0); user_quit(user); return; } fprintf(fp,"%s %s\n",ustr[user].login_name,crypt(passwd,SALT)); echo_on(user); sprintf(mess,"Nova id \"%s\" criada\n",ustr[user].login_name); write_syslog(mess,1); add_user(user); fclose(fp); } /*** check to see if user has had max login attempts ***/ attempts(user) int user; { echo_on(user); if (!--ustr[user].attleft) { write_user(user,"\n\rAtingiste o numero maximo de tentativas...\n\n\r"); user_quit(user); return; } ustr[user].logging_in=3; write_user(user,"Da'-me um nome: "); } /*** Tell telnet not to echo characters - for password entry ***/ echo_off(user) int user; { char seq[4]; if (PASSWORD_ECHO) return; sprintf(seq,"%c%c%c",255,251,1); write_user(user,seq); } /*** Tell telnet to echo characters ***/ echo_on(user) int user; { char seq[4]; if (PASSWORD_ECHO) return; sprintf(seq,"%c%c%c",255,252,1); write_user(user,seq); } /*** Return a time string ***/ char *timeline(len) { time_t tm_num; static char timestr[30]; time(&tm_num); if (len) { strcpy(timestr,ctime(&tm_num)); timestr[strlen(timestr)-1]=0; /* get rid of nl */ } else midcpy(ctime(&tm_num),timestr,4,15); return timestr; } /*** Send a string to system log ***/ write_syslog(str,write_time) char *str; int write_time; { FILE *fp; time_t tm_num; char timestr[15],line[160]; if (!syslog_on || !(fp=fopen(SYSTEM_LOG,"a"))) return; if (write_time) { time(&tm_num); midcpy(ctime(&tm_num),timestr,4,15); sprintf(line,"%s: %s",timestr,str); fputs(line,fp); } else fputs(str,fp); fclose(fp); } /*** write user sends string down socket ***/ write_user(user,str) char *str; int user; { write(ustr[user].sock,str,strlen(str)); } /*** finds next free user number ***/ find_free_slot() { int u; if (num_of_users==MAX_USERS) return -1; for (u=0;u<MAX_USERS;++u) if (ustr[u].sock==-1) return u; return -1; } /*** set up data for new user if he can get on ***/ add_user(user) int user; { int i,u; char filename[80],timestr[31],sitestr[81],levstr[3],type[10]; FILE *fp; timestr[0]=0; /* see if already logged on */ if ((u=get_user_num(ustr[user].login_name))!=-1 && u!=user) { write_user(user,"\n\rJa' esta's ligado - a trocar de sessao...\n\n\r"); /* switch user instances */ close(ustr[u].sock); ustr[u].sock=ustr[user].sock; ustr[user].name[0]=0; ustr[user].area=-1; ustr[user].sock=-1; ustr[user].logging_in=0; look(u); prompt(u); return; } /* reset user structure */ strcpy(ustr[user].name,ustr[user].login_name); ustr[user].area=0; ustr[user].listen=1; ustr[user].vis=1; ustr[user].time=time((time_t *)0); ustr[user].invite=-1; ustr[user].last_input=time((time_t *)0); ustr[user].logging_in=0; ustr[user].file_posn=0; ustr[user].pro_enter=0; ustr[user].prompt=1; num_of_users++; /* Set socket to non-blocking. Not really needed but it does no harm. */ fcntl(ustr[user].sock,F_SETFL,O_NDELAY); /* Load user data */ sprintf(filename,"%s/%s.D",USERDATADIR,ustr[user].name); if (!(fp=fopen(filename,"r"))) { ustr[user].level=NEWBIE; strcpy(ustr[user].desc,"- um novo animal..."); } else { /* load data */ fgets(timestr,30,fp); fgets(sitestr,80,fp); fgets(ustr[user].desc,80,fp); fgets(levstr,2,fp); fclose(fp); ustr[user].level=atoi(levstr); /* remove newlines */ timestr[strlen(timestr)-1]=0; ustr[user].desc[strlen(ustr[user].desc)-1]=0; } /* send intro stuff */ if (PASSWORD_ECHO) { for(i=0;i<6;++i) write_user(user,"\n\n\n\n\n\n\n\n\n\n\r"); } switch(ustr[user].level) { case NEWBIE: strcpy(type,"TARTARUGA "); break; case USER : strcpy(type,"GIBOIA "); break; case WIZARD: strcpy(type,"LEAO "); break; case GOD : strcpy(type,"DEUS "); } sprintf(mess,"\n\n\n\rBenvindo %s%s\n\n\r",type,ustr[user].name); write_user(user,mess); if (timestr[0]) { sprintf(mess,"Ligado pela ultima vez em %s de %s\n\r",timestr,sitestr); write_user(user,mess); } /* send 2nd message of the day */ more(-1,ustr[user].sock,MOTD2); /* check for mail */ sprintf(filename,"%s/%s.M",USERDATADIR,ustr[user].name); look(user); if (fp=fopen(filename,"r")) { write_user(user,"\n\r** TENS MAIL !!! **"); fclose(fp); } if (ustr[user].level==NEWBIE){ write_user(user,"\n\r** Faz .entpro e regista-te na Selva !!! **\n\r"); } prompt(user); /* send message to other users and to file */ if (ustr[user].name[0]!='?') { sprintf(mess,"ACABADINHO DE ENTRAR: %s %s\n\r",ustr[user].name,ustr[user].desc); write_alluser(user,mess,1,0); sprintf(mess,"%s LIGOU-SE A SELVA...\n",ustr[user].name); write_syslog(mess,1); } whowrite(); } /*** Page a file out to user like unix "more" command ***/ more(user,socket,filename) int user,socket; char *filename; { int i,num_chars=0,lines=0,retval=1; FILE *fp; if (!(fp=fopen(filename,"r"))) { ustr[user].file_posn=0; return 0; } /* jump to reading posn in file */ if (user!=-1) fseek(fp,ustr[user].file_posn,0); /* loop until end of file or end of page reached */ mess[0]=0; while(!feof(fp) && lines<23) { lines+=strlen(mess)/80+1; num_chars+=strlen(mess); for (i=0;i<strlen(mess);++i) { if (mess[i]=='\n') write(socket,"\n\r",2); else write(socket,&mess[i],1); } fgets(mess,sizeof(mess)-1,fp); } if (user==-1) goto SKIP; if (feof(fp)) { ustr[user].file_posn=0; noprompt=0; retval=2; } else { /* store file position and file name */ ustr[user].file_posn+=num_chars; strcpy(ustr[user].page_file,filename); write_user(user,"*** CARREGA NO ENTER, OU Q PARA FAZER QUIT: "); noprompt=1; } SKIP: fclose(fp); return retval; } /*** get user number using name ***/ get_user_num(name) char *name; { int u; for (u=0;u<MAX_USERS;++u) if (!strcmp(ustr[u].name,name) && ustr[u].area!=-1) return u; return -1; } /*** return pos. of second word in inpstr ***/ char *remove_first(inpstr) char *inpstr; { char *pos=inpstr; while(*pos<33 && *pos) ++pos; while(*pos>32) ++pos; while(*pos<33 && *pos) ++pos; return pos; } /*** sends output to all areas if area==1, else only users in same area ***/ write_alluser(user,str,area,send_to_user) char *str; int user,area,send_to_user; { int u; str[0]=toupper(str[0]); for (u=0;u<MAX_USERS;++u) { /* com_num 26 is bcast command ,30 is close , 31 is open */ if (!ustr[u].listen && com_num!=26 && com_num!=30 && com_num!=31) continue; if ((!send_to_user && user==u) || ustr[u].area==-1) continue; if (ustr[u].area==ustr[user].area || area) write_user(u,str); } } /*** gets number of command entered (if any) ***/ get_com_num(inpstr) char *inpstr; { char comstr[ARR_SIZE]; int com; sscanf(inpstr,"%s",comstr); /*Place to code command aliases... */ if (!strcmp(comstr,";") || !strcmp(comstr,":")) strcpy(comstr,".emote"); if (!strcmp(comstr,"!")) strcpy(comstr,".semote"); if (!strcmp(comstr,">")) strcpy(comstr,".tell"); com=0; while(command[com][0]!='*') { if (!instr(command[com],comstr) && strlen(comstr)>1) return com; ++com; } return -1; } /*** alter who file (used by who daemon) ***/ whowrite() { int u; FILE *fp; unlink(WHOFILE); if (!num_of_users) return; if (!(fp=fopen(WHOFILE,"w"))) { write_syslog("ERROR: Couldn't open whofile to write in whowrite()\n",0); return; } /* write user names and descriptions to the file */ for (u=0;u<MAX_USERS;++u) { if (ustr[u].area==-1) continue; sprintf(mess,"%s %s\n",ustr[u].name,ustr[u].desc); fputs(mess,fp); } fclose(fp); } /**** mid copy copies chunk from string strf to string strt (used in write_board & prompt) ***/ midcpy(strf,strt,fr,to) char *strf,*strt; int fr,to; { int f; for (f=fr;f<=to;++f) { if (!strf[f]) { strt[f-fr]='\0'; return; } strt[f-fr]=strf[f]; } strt[f-fr]='\0'; } /*** searches string ss for string sf ***/ instr(ss,sf) char *ss,*sf; { int f,g; for (f=0;*(ss+f);++f) { for (g=0;;++g) { if (*(sf+g)=='\0' && g>0) return f; if (*(sf+g)!=*(ss+f+g)) break; } } return -1; } /*** Finds number or users in given area ***/ find_num_in_area(area) int area; { int u,num=0; for (u=0;u<MAX_USERS;++u) if (ustr[u].area==area) ++num; return num; } /*** See if user exists in password file ***/ user_exists(user,name) int user; char *name; { char line[80],name2[NAME_LEN]; FILE *fp; if (!(fp=fopen(PASSFILE,"r"))) { sprintf(mess,"%s : Nao consigo abrir o teu fixeiro de password...",syserror); write_user(user,mess); write_syslog("ERROR: Couldn't open password file to read in user_exists()\n",0); return 0; } while(!feof(fp)) { fgets(line,80,fp); sscanf(line,"%s ",name2); if (!strcmp(name,name2)) { fclose(fp); return 1; } } fclose(fp); return 0; } /*** Save user stats ***/ save_stats(user) int user; { time_t tm_num; char timestr[30],filename[80]; FILE *fp; if (!strcmp(ustr[user].name,"?")) return 1; sprintf(filename,"%s/%s.D",USERDATADIR,ustr[user].name); if (!(fp=fopen(filename,"w"))) return 0; time(&tm_num); strcpy(timestr,ctime(&tm_num)); fprintf(fp,"%s%s\n%s\n%d\n",timestr,ustr[user].site,ustr[user].desc,ustr[user].level); fclose(fp); return 1; } /**************************** COMMAND FUNCTIONS *******************************/ /*** Call command function or execute command directly ***/ exec_com(user,inpstr) int user; char *inpstr; { /* see if superuser command */ if (ustr[user].level<com_level[com_num]) { write_user(user,"Ainda nao es grande o suficiente para fazer isso..."); return; } inpstr=remove_first(inpstr); /* get rid of commmand word */ switch(com_num) { case 0 : user_quit(user); break; case 1 : who(user,0); break; /* who */ case 2 : shout(user,inpstr); break; case 3 : tell(user,inpstr); break; case 4 : if (ustr[user].listen) { write_user(user,"Mas tu ja' esta's a ouvir!"); return; } write_user(user,"Passas a ouvir tudo..."); sprintf(mess,"%s passou a ouvir tudo.\n\r",ustr[user].name); write_alluser(user,mess,0,0); ustr[user].listen=1; break; case 5 : if (!ustr[user].listen) { write_user(user,"Tu ja' esta's a ser um antisocial!"); return; } write_user(user,"Passas a ignorar esta cambada de animais..."); sprintf(mess,"%s esta' a ignorar tudo...\n\r",ustr[user].name); write_alluser(user,mess,0,0); ustr[user].listen=0; break; case 6 : look(user); break; case 7 : go(user,inpstr,0); break; case 8 : area_access(user,1); break; /* private */ case 9 : area_access(user,0); break; /* public */ case 10: invite_user(user,inpstr); break; case 11: emote(user,inpstr); break; case 12: areas(user); break; case 13: go(user,inpstr,1); break; /* letmein */ case 14: write_board(user,inpstr); break; case 15: read_board(user); break; case 16: wipe_board(user,inpstr); break; case 17: set_topic(user,inpstr); break; case 20: kill_user(user,inpstr); break; case 21: shutdown_talker(user,0); break; case 22: search(user,inpstr); break; case 23: review(user); break; case 24: help(user,inpstr); break; case 25: broadcast(user,inpstr); break; case 26: write_user(user,"\n\r*** Novidades ***\n\n\r"); if (!more(user,ustr[user].sock,NEWSFILE)) write_user(user,"Nao ha' novidades... Avisa o MindBooster!"); break; case 28: move(user,inpstr); break; case 29: if (sys_access) { write_area(-1,"*** A SELVA ESTA' FEXADA A NOVOS LOGINS ***\n\r"); sprintf(mess,"%s CLOSED the system\n",ustr[user].name); write_syslog(mess,1); sys_access=0; break; } write_area(-1,"*** A SELVA ESTA' ABERTA A NOVOS LOGINS ***\n\r"); sprintf(mess,"%s ABRIU a Selva IV!\r\n",ustr[user].name); write_syslog(mess,1); sys_access=1; break; case 30: if (syslog_on) { write_user(user,"Sistema de logging OFF"); sprintf(mess,"%s turned logging OFF\n",ustr[user].name); write_syslog(mess,1); syslog_on=0; break; } write_user(user,"Sistema de logging ON"); syslog_on=1; sprintf(mess,"%s turned logging ON\n",ustr[user].name); write_syslog(mess,1); break; case 33: set_desc(user,inpstr); break; case 34: if (allow_new) { write_user(user,"Novos utilizadores? NAO!"); allow_new=0; sprintf(mess,"%s DISALLOWED new users\n",ustr[user].name); write_syslog(mess,1); break; } write_user(user,"Abres a Selva a novos utilizadores..."); sprintf(mess,"%s ALLOWED new users\n",ustr[user].name); write_syslog(mess,1); allow_new=1; break; case 35: sprintf(mess,"awnuts version 0.1 (c) Mind Booster Noori. awnuts is Awsome NUTS, a code based on SAMNUTS version 0.3: Secured and Modified NUTS. (c) Mind Booster Noori\r\n SAMNUTS is Based on some codes that are still present in Awsome NUTS, those being:\r\nNUTS version %s\r\nAlpha Server Project v0.2 (c) Mind Booster Noori && Brain Harper\r\n",VERSION); write_user(user,mess); break; case 36: enter_pro(user,inpstr); break; case 37: exa_pro(user,inpstr); break; case 39: dmail(user,inpstr); break; case 40: rmail(user); break; case 41: smail(user,inpstr); break; case 42: wake(user,inpstr); break; case 43: promote(user,inpstr); break; case 18: demote(user,inpstr); break; case 19: if (!more(user,ustr[user].sock,MAPFILE)) write_user(user,"Parece que nao 'a mapa... Avisa o MindBooster!"); break; case 38: change_pass(user,inpstr); break; case 32: pemote(user,inpstr); break; case 31: semote(user,inpstr); break; case 27: if (ustr[user].prompt) { write_user(user,"Prompt OFF"); ustr[user].prompt=0; break; } write_user(user,"Prompt ON"); ustr[user].prompt=1; break; default: write_user(user,"O que?"); break; } } /*** closes socket & does relevant output to other users & files ***/ user_quit(user) int user; { int area=ustr[user].area; /* see is user has quit befor he logged in */ if (ustr[user].logging_in) { close(ustr[user].sock); ustr[user].logging_in=0; ustr[user].sock=-1; ustr[user].area=-1; return; } /* save stats */ if (!save_stats(user)) { sprintf(mess,"%s : Nao consegui gravar a tua informacao...\n\r",syserror); write_user(user,mess); sprintf(mess,"ERROR: Couldn't save %s's stats in user_quit()\n",ustr[user].name); write_syslog(mess,0); } write_user(user,"\n\rA voltar para o mundo real...\n\n\r"); close(ustr[user].sock); /* send message to other users & conv file & reset some vars */ if (ustr[user].name[0]!='?') { sprintf(mess,"BAZOU: %s %s\n\r",ustr[user].name,ustr[user].desc); write_alluser(user,mess,1,0); sprintf(mess,"%s signed off\n\r",ustr[user].name); write_syslog(mess,1); } if (astr[area].private && astr[area].status!=2 && find_num_in_area(area)<=PRINUM) { write_alluser(user,"Sala voltou a ser publica\n\r",0,0); astr[area].private=0; } num_of_users--; ustr[user].area=-1; ustr[user].sock=-1; ustr[user].logging_in=0; ustr[user].name[0]=0; if (ustr[user].pro_enter) free(ustr[user].pro_start); whowrite(); } /*** Displays who's on ***/ who(user,people) int user,people; { int u,tm,idle,min,invis=0; char *yesno[]={ "NO","YES" }; char *levstr[]={ "TARTARUGA","GIBOIA","LEAO","DEUS" }; char timestr[30],temp[80]; /* display current time */ time((long *)&tm); strcpy(timestr,ctime((long *)&tm)); timestr[strlen(timestr)-1]=0; sprintf(mess,"\n\r*** Animais ligados actualmente %s ***\n\n\r",timestr); write_user(user,mess); /* display user list */ for (u=0;u<MAX_USERS;++u) { if (ustr[u].area!=-1) { if (!ustr[u].vis && ustr[user].level<ustr[u].level && ustr[u].level>USER) { invis++; continue; } min=(tm-ustr[u].time)/60; idle=(tm-ustr[u].last_input)/60; sprintf(temp,"%s %s",ustr[u].name,ustr[u].desc); sprintf(mess,"%-40s : %-9s : %s : %d mins.\n\r",temp,levstr[ustr[u].level],astr[ustr[u].area].name,min); write_user(user,mess); } if (ustr[u].area==-1 && ustr[u].logging_in && people) { sprintf(mess,"LOGIN de %s na linha %d\n\r",ustr[u].site,ustr[u].sock); write_user(user,mess); } } if (invis) { sprintf(mess,"\n\rExistem %d animais invisiveis aos teus olhos...",invis); write_user(user,mess); } sprintf(mess,"\n\rTotal de %d animais ligados\n\r",num_of_users); write_user(user,mess); } /*** shout sends speech to all users regardless of area ***/ shout(user,inpstr) int user; char *inpstr; { if (!inpstr[0]) { write_user(user,"Gritas, mas gritas o que?"); return; } sprintf(mess,"%s grita: %s\n\r",ustr[user].name,inpstr); if (!ustr[user].vis) sprintf(mess,"Um animal grita: %s\n\r",inpstr); write_alluser(user,mess,1,0); sprintf(mess,"Tu gritas: %s",inpstr); write_user(user,mess); } /*** tells another user something without anyone else hearing ***/ tell(user,inpstr) int user; char *inpstr; { char other_user[ARR_SIZE],name[ARR_SIZE]; int user2,temp; sscanf(inpstr,"%s ",other_user); other_user[0]=toupper(other_user[0]); inpstr=remove_first(inpstr); if (!inpstr[0]) { write_user(user,"Modo de utilizacao: .tell <animal> <mensagem>"); return; } if ((user2=get_user_num(other_user))==-1) { sprintf(mess,"%s nao esta' na Selva!",other_user); write_user(user,mess); return; } if (user2==user) { write_user(user,"Isto nao e' um manico'mio, se queres falar contigo proprio tas no sitio errado!"); return; } if (!ustr[user2].listen) { sprintf(mess,"%s nao esta' a ouvir...",other_user); write_user(user,mess); return; } if (ustr[user].vis) strcpy(name,ustr[user].name); else strcpy(name,"Um animal"); switch(inpstr[strlen(inpstr)-1]) { case '?': sprintf(mess,"Tu perguntas a %s: %s",ustr[user2].name,inpstr); write_user(user,mess); sprintf(mess,"%s pergunta-te: %s\n\r",name,inpstr); write_user(user2,mess); break; case '!': sprintf(mess,"Tu exclamas a %s: %s",ustr[user2].name,inpstr); write_user(user,mess); sprintf(mess,"%s exclama para ti: %s\n\r",name,inpstr); write_user(user2,mess); break; default: sprintf(mess,"Tu dizes a %s: %s",ustr[user2].name,inpstr); write_user(user,mess); sprintf(mess,"%s diz-te: %s\n\r",name,inpstr); write_user(user2,mess); } if (ustr[user].vis && ustr[user2].vis && ustr[user].area==ustr[user2].area) { sprintf(mess,"%s sussurra algo a %s...\n\r",name,ustr[user2].name); temp=ustr[user2].area; ustr[user2].area=-1; write_alluser(user,mess,0,0); ustr[user2].area=temp; } } /*** look decribes the surrounding scene **/ look(user) int user; { int f,u,area,occupied=0; char filename[80]; area=ustr[user].area; sprintf(mess,"\n\rLocal: %s\n\n\r",astr[area].name); write_user(user,mess); /* open and read area description file */ sprintf(filename,"%s/%s",DATADIR,astr[area].name); more(user,ustr[user].sock,filename); /* show exits from area */ write_user(user,"\n\rSaidas: "); for (f=0;f<strlen(astr[area].move);++f) { write_user(user,astr[astr[area].move[f]-65].name); write_user(user," "); } write_user(user,"\n\n\r"); for (u=0;u<MAX_USERS;++u) { if (ustr[u].area!=area || u==user || !ustr[u].vis) continue; if (!occupied) write_user(user,"Consegues ver:\n\r"); sprintf(mess," %s %s\n\r",ustr[u].name,ustr[u].desc); write_user(user,mess); occupied++; } if (!occupied) write_user(user,"Nao esta' aqui mais ninguem...\n\r"); write_user(user,"\n\rEste local esta' "); if (astr[ustr[user].area].private) write_user(user,"privado\n\r"); else write_user(user,"publico\n\r"); sprintf(mess,"Existem %d mensagens no quadro.\n\r",astr[area].mess_num); write_user(user,mess); if (!strlen(astr[area].topic)) write_user(user,"Este local nao tem topico..."); else { sprintf(mess,"Topico actual: %s",astr[area].topic); write_user(user,mess); } } /*** go moves user into different area ***/ go(user,inpstr,user_letin) int user,user_letin; char *inpstr; { int f,new_area,teleport=0; int area=ustr[user].area; char area_char,area_name[ARR_SIZE]; char entmess[30]; if (!inpstr[0]) { if (user_letin) write_user(user,"Modo de utilizacao: .letmein <local>"); else write_user(user,"Modo de utilizacao: .go <local>"); return; } sscanf(inpstr,"%s ",area_name); /* see if area exists */ for (new_area=0;new_area<NUM_AREAS;++new_area) if (!instr(astr[new_area].name,area_name)) goto AREA_EXISTS; write_user(user,"Esse local nao existe!"); return; AREA_EXISTS: if (ustr[user].area==new_area) { write_user(user,"Tu ja' la' esta's!!!"); return; } /* see if user can get to area from current area */ area_char=new_area+65; /* get char. repr. of area to move to (A-I) */ /* see if new area is joined to current one */ strcpy(entmess,"entra."); for (f=0;f<strlen(astr[area].move);++f) if (astr[area].move[f]==area_char) goto JOINED; if (ustr[user].level>USER) { strcpy(entmess,"aparece!"); teleport=1; goto JOINED; } write_user(user,"Esse sitio nao esta ligado a este..."); return; JOINED: if (user_letin) { letmein(user,new_area); return; } if (astr[new_area].private && ustr[user].invite!=new_area && ustr[user].level<WIZARD) { write_user(user,"Desculpa, mas esse local e' actualmente privado..."); return; } /* output to old area */ if (teleport && ustr[user].vis) { sprintf(mess,"=> %s desaparece magicamente!\n\r",ustr[user].name); write_alluser(user,mess,0,0); } if (!teleport && ustr[user].vis) { sprintf(mess,"=> %s foi para um local de nome %s\n\r",ustr[user].name,astr[new_area].name); write_alluser(user,mess,0,0); } /* gods dont show any entry message, wizards show this */ if (!ustr[user].vis && ustr[user].level==WIZARD) { write_alluser(user,"Sentes algo magico a passar por ti...\n\r",0,0); } if (astr[area].private && astr[area].status!=2 && find_num_in_area(area)<=PRINUM) { write_alluser(user,"Local passou a ser outra vez publico.\n\r",0,0); astr[area].private=0; } /* send output to new area */ ustr[user].area=new_area; if (!ustr[user].vis) { if (ustr[user].level==WIZARD) write_alluser(user,"Sentes algo magico a passar por ti...\n\r",0,0); } else { sprintf(mess,"=> %s %s\n\r",ustr[user].name,entmess); write_alluser(user,mess,0,0); } /* deal with user */ if (ustr[user].invite==new_area) ustr[user].invite=-1; look(user); } /*** Subsid func of go ***/ letmein(user,new_area) int user,new_area; { char name[ARR_SIZE]; if (!astr[new_area].private) { write_user(user,"Isso ja' era publico de qualquer forma..."); return; } sprintf(mess,"Gritas desesperadamente para os lados da %s pedindo para entrar!",astr[new_area].name); write_user(user,mess); sprintf(mess,"%s esta' a gritar, pedindo para entrar!\n\r",ustr[user].name); if (!ustr[user].vis) sprintf(mess,"Um animal esta' a gritar, pedindo para entrar!\n\r"); write_area(new_area,mess); /* send message to users in current area */ if (!ustr[user].vis) strcpy(name,"Um animal"); else strcpy(name,ustr[user].name); sprintf(mess,"%s grita para o local %s pedindo para entrar!\n\r",name,astr[new_area].name); write_alluser(user,mess,0,0); } /*** area_access sets area to private or public ***/ area_access(user,priv) int user,priv; { int area; char *noset="Nada disso, aqui tu nao mexes..."; char *pripub[]={ "public","private" }; area=ustr[user].area; /* see if areas access can be set */ if (astr[area].status) { write_user(user,noset); return; } /* see if access already set to user request */ if (priv==astr[area].private) { sprintf(mess,"Esse local ja' e' %s!",pripub[priv]); write_user(user,mess); return; } /* set to public */ if (!priv) { write_user(user,"Local passa a ser publico."); sprintf(mess,"%s colocou este lugar publico...\n\r",ustr[user].name); if (!ustr[user].vis) sprintf(mess,"Alguem colocou este lugar publico...\n\r"); write_alluser(user,mess,0,0); astr[area].private=0; return; } /* need at least PRINUM people to set area to private unless are superuser */ if (find_num_in_area(area)<PRINUM && ustr[user].level<WIZARD) { sprintf(mess,"Precisas pelo menos de %d pessoas para isso...",PRINUM); write_user(user,mess); return; }; write_user(user,"Pronto, isto ja' esta' privado."); sprintf(mess,"%s fez com que este fosse um lugar privado.\n\r",ustr[user].name); if (!ustr[user].vis) sprintf(mess,"Um animal fez com que este fosse um lugar privado.\n\r"); write_alluser(user,mess,0,0); astr[area].private=1; } /*** invite someone into private area ***/ invite_user(user,inpstr) int user; char *inpstr; { int u,area=ustr[user].area; char other_user[ARR_SIZE]; if (!inpstr[0]) { write_user(user,"Uso: .invite <animal>"); return; } if (!astr[area].private) { write_user(user,"Esta area e' publica!"); return; } sscanf(inpstr,"%s ",other_user); other_user[0]=toupper(other_user[0]); /* see if other user exists */ if ((u=get_user_num(other_user))==-1) { sprintf(mess,"%s nem sequer esta' na Selva...",other_user); write_user(user,mess); return; } if (!strcmp(other_user,ustr[user].name)) { write_user(user,"Tu es um tipo bue da fixe, a convidar-te a ti proprio..."); return; } if (ustr[u].area==ustr[user].area) { sprintf(mess,"Mas... %s esta' aqui!",ustr[u].name); write_user(user,mess); return; } write_user(user,"OK! "); if (!ustr[user].vis) sprintf(mess,"Foste convidado para %s\n\r",astr[area].name); else sprintf(mess,"%s convidou-te para %s\n\r",ustr[user].name,astr[area].name); write_user(u,mess); ustr[u].invite=area; } /*** emote func used for expressing emotional or visual stuff ***/ emote(user,inpstr) int user; char *inpstr; { if (!inpstr[0]) { write_user(user,"Uso: .emote <texto>"); return; } if (!ustr[user].vis) sprintf(mess,"Um animal %s",inpstr); else sprintf(mess,"%s %s",ustr[user].name,inpstr); /* write & record output */ write_user(user,mess); strcat(mess,"\n\r"); write_alluser(user,mess,0,0); record(mess,ustr[user].area); } /*** Gives current status of areas */ areas(user) int user; { int area; char *pripub[]={ "publico","privado" }; char *yesno[]={ "NAO","SIM" }; write_user(user,"\n\rLocal : Pri/Pub Fixo Anim Msgs Topico\n\n\r"); for (area=0;area<NUM_AREAS;++area) { sprintf(mess,"%-15s : %-7s %3s %2d %3d ",astr[area].name,pripub[astr[area].private],yesno[(astr[area].status>0)],find_num_in_area(area),astr[area].mess_num); if (!strlen(astr[area].topic)) strcat(mess,"<sem topico>"); else strcat(mess,astr[area].topic); strcat(mess,"\n\r"); mess[0]=toupper(mess[0]); write_user(user,mess); } sprintf(mess,"\n\rUm total de %d locais.\n\r",NUM_AREAS); write_user(user,mess); } /*** save message to area message board file ***/ write_board(user,inpstr) int user; char *inpstr; { FILE *fp; char filename[30],name[NAME_LEN]; if (!inpstr[0]) { write_user(user,"Uso: .write <mensagem>"); return; } /* open board file */ sprintf(filename,"%s/board%d",MESSDIR,ustr[user].area); if (!(fp=fopen(filename,"a"))) { sprintf(mess,"%s : mensagem nao pode ser escrita.",syserror); write_user(user,mess); sprintf(mess,"ERROR: Couldn't open %s message board file to write in write_board()\n",astr[ustr[user].area].name); write_syslog(mess,0); return; } /* write message - alter nums. in midcpy to suit */ strcpy(name,ustr[user].name); if (!ustr[user].vis) strcpy(name,"Um animal"); sprintf(mess,"(%s) De %s: %s\n",timeline(0),name,inpstr); fputs(mess,fp); fclose(fp); /* send output */ write_user(user,"Tu escreves uma mensagem na board!"); sprintf(mess,"=> %s escreve uma mensagem na board.\n\r",ustr[user].name); if (!ustr[user].vis) sprintf(mess,"Ves uma mao fantasma a escrever uma mensagem na board - spooky...\n\r"); write_alluser(user,mess,0,0); astr[ustr[user].area].mess_num++; } /*** read the message board ***/ read_board(user) int user; { char filename[30]; /* send output to user */ sprintf(filename,"%s/board%d",MESSDIR,ustr[user].area); sprintf(mess,"\n\r*** A board da %s ***\n\n\r",astr[ustr[user].area].name); write_user(user,mess); if (!more(user,ustr[user].sock,filename) || !astr[ustr[user].area].mess_num) write_user(user,"Nao existem mensagens na board.\n\r"); /* send output to others */ sprintf(mess,"=> %s le a board.\n\r",ustr[user].name); if (ustr[user].vis) write_alluser(user,mess,0,0); } /*** wipe board (erase file) ***/ wipe_board(user,inpstr) int user; char *inpstr; { int lines,cnt=0; char c,filename[20],temp[20]; char *nocando="Nao consigo apagar tanta coisa..."; FILE *bfp,*tfp; lines=atoi(inpstr); if (lines<1) { write_user(user,"Uso: .wipe <numero de escritos a apagar>"); return; } sprintf(filename,"%s/board%d",MESSDIR,ustr[user].area); if (!(bfp=fopen(filename,"r"))) { write_user(user,nocando); return; } sprintf(temp,"%s/temp",MESSDIR); if (!(tfp=fopen(temp,"w"))) { write_user(user,"Eh pa' desculpa mas a Selva esta' com dificuldades em fazer isso..."); write_syslog("ERROR: Couldn't open temporary file to write in wipe_board()\n",0); fclose(bfp); return; } /* find start of where to copy */ while(cnt<lines) { c=getc(bfp); if (feof(bfp)) { write_user(user,nocando); fclose(bfp); fclose(tfp); return; } if (c=='\n') cnt++; } /* copy rest of board file into temp file & erase board file */ c=getc(bfp); while(!feof(bfp)) { putc(c,tfp); c=getc(bfp); } fclose(bfp); fclose(tfp); unlink(filename); /* rename temp file to new board file */ if (rename(temp,filename)==-1) { write_user(user,"Eh pa', desculpa mas a Selva esta' com dificuldades em fazer isso..."); write_syslog("ERROR: Couldn't rename temp file to board file in wipe_board()\n",0); astr[ustr[user].area].mess_num=0; return; } astr[ustr[user].area].mess_num-=lines; /* print messages */ write_user(user,"Ok"); sprintf(mess,"=> %s apaga algumas mensagens da board.\n\r",ustr[user].name); if (!ustr[user].vis) sprintf(mess,"Uma mao fantasma apaga uma mensagem do quadro... SPOOKY!\n\r"); write_alluser(user,mess,0,0); } /*** sets area topic ***/ set_topic(user,inpstr) int user; char *inpstr; { if (!inpstr[0]) { if (!strlen(astr[ustr[user].area].topic)) { write_user(user,"Ta's maluco? Aqui nao ha' topico!"); return; } else { sprintf(mess,"O topico actual e': %s",astr[ustr[user].area].topic); write_user(user,mess); return; } } if (strlen(inpstr)>TOPIC_LEN) { write_user(user,"Isso e' grande de mais para topico..."); return; } strcpy(astr[ustr[user].area].topic,inpstr); /* send output to users */ sprintf(mess,"Pronto, o topico passa a ser %s",inpstr); write_user(user,mess); sprintf(mess,"%s mudou o topico para %s\n\r",ustr[user].name,inpstr); if (!ustr[user].vis) sprintf(mess,"Um animal mudou o topico para %s\n\r",inpstr); write_alluser(user,mess,0,0); } /*** sets superuser to visible or invisible ***/ visible(user,vis) int user,vis; { if (ustr[user].vis && vis) { write_user(user,"Tu ja' esta's visivel!"); return; } if (!ustr[user].vis && !vis) { write_user(user,"Tu ja' esta's invisivel!"); return; } ustr[user].vis=vis; if (vis) { write_user(user,"POP! Tu voltas a aparecer!"); sprintf(mess,"BOO! %s aparece mesmo ao teu lado!\n\r",ustr[user].name); write_alluser(user,mess,0,0); } else { write_user(user,"Um ritual antigo ecoa, e tu desapareces..."); sprintf(mess,"%s desaparece ao som de um antigo ritual...\n\r",ustr[user].name); write_alluser(user,mess,0,0); } } /*** Throw off an annoying bastard (or throw off someone for a laugh) ***/ kill_user(user,inpstr) int user; char *inpstr; { char name[ARR_SIZE]; int victim; if (!inpstr[0]) { write_user(user,"Uso: .kill <animal>"); return; } sscanf(inpstr,"%s ",name); name[0]=toupper(name[0]); if ((victim=get_user_num(name))==-1) { sprintf(mess,"%s nao esta' ligado!",name); write_user(user,mess); return; } if (victim==user) { write_user(user,"Ta's armado em suicida ou que?"); return; } /* can't kill god */ if (ustr[victim].level==GOD) { write_user(user,"MAS QUEM RAIO PENSAS TU QUE E'S??? A MATAR UM DEUS?"); sprintf(mess,"%s passa-se: tentou matar-te!\n\r",ustr[user].name); write_user(victim,mess); return; } /* record killing */ sprintf(mess,"%s MATOU %s!\n\r",ustr[user].name,ustr[victim].name); write_syslog(mess,1); /* kill user */ sprintf(mess,"Um monitor cai em cima da tola de %s, e ele MORRE!!\n\r",ustr[victim].name); write_alluser(victim,mess,0,0); write_user(victim,"Olhas para o ceu e ves algo a cair... Sera' um piano? sera' um monitor?\n\rNao tens tempo de descobrir. O super-homem nao era...\n\r"); user_quit(victim); write_area(-1,".oO( Menos um PC com Windoze... )Oo.\n\r"); write_user(user,"Mauzinho! ;)"); } /*** shutdown talk server ***/ shutdown_talker(user,ls) int user,ls; { int u; char name[NAME_LEN]; if (shutd==-1) { write_user(user,"\n\rTens a certeza disso? (y/n)? "); shutd=user; noprompt=1; return; } write_user(user,"A aniquilar todos os animais...\n\r"); for (u=0;u<MAX_USERS;++u) { if (ustr[u].area==-1 || u==user) continue; write_user(u,"\n\r*** Selva a auto-destruir-se! ***\n\r"); user_quit(u); } write_user(user,"\n\rAdeusinho, volta em breve...\n\r"); strcpy(name,ustr[user].name); user_quit(user); sprintf(mess,"*** Talker SHUTDOWN by %s on %s ***\n",name,timeline(1)); write_syslog(mess,0); /* close listen socket */ close(ls); exit(0); } /*** search for specific word in the message files ***/ search(user,inpstr) int user; char *inpstr; { int b,occured=0; char word[ARR_SIZE],filename[20],line[ARR_SIZE]; FILE *fp; if (!inpstr[0]) { write_user(user,"Uso: .search <palavra(s)>"); return; } sscanf(inpstr,"%s ",word); /* look through boards */ for (b=0;b<NUM_AREAS;++b) { sprintf(filename,"%s/board%d",MESSDIR,b); if (!(fp=fopen(filename,"r"))) continue; fgets(line,300,fp); while(!feof(fp)) { if (instr(line,word)==-1) { fgets(line,300,fp); continue; } sprintf(mess,"%s : %s\r",astr[b].name,line); mess[0]=toupper(mess[0]); write_user(user,mess); ++occured; fgets(line,300,fp); } fclose(fp); } if (!occured) write_user(user,"Nao foram encontradas ocorrencias..."); else { sprintf(mess,"\n\r%d ocurrencias encontradas!\n\r",occured); write_user(user,mess); } } /*** review last five lines of conversation in area ***/ review(user) int user; { int area=ustr[user].area; int pos=astr[area].conv_line%NUM_LINES; int f; for (f=0;f<NUM_LINES;++f) { write_user(user,conv[area][pos++]); pos=pos%NUM_LINES; } } /*** help function ***/ help(user,inpstr) int user; char *inpstr; { int com,nl=0; char *levstr[]={ "TARTARUGA","GIBOIA","LEAO","DEUS" }; char filename[ARR_SIZE],word[ARR_SIZE],word2[ARR_SIZE]; /* help for one command */ if (strlen(inpstr)) { sscanf(inpstr,"%s",word); sprintf(word2,".%s\n",word); if (get_com_num(word2)==-1) { write_user(user,"Esse comando nao existe!"); return; } sprintf(filename,"%s/%s",HELPDIR,word); if (!more(user,ustr[user].sock,filename)) write_user(user,"Desculpa mais ainda nao existe ajuda para esse comando :("); return; } /* general help */ sprintf(mess,"\n\r*** Comandos existentes para animais do nivel %s ***\n\n\r",levstr[ustr[user].level]); write_user(user,mess); com=0; while(command[com][0]!='*') { if (ustr[user].level<com_level[com]) { ++com; continue; } sprintf(mess,".%-10s ",command[com]); mess[0]=' '; write_user(user,mess); ++nl; ++com; if (nl==5) { write_user(user,"\n\r"); nl=0; } } write_user(user,"\n\rPara saber para que serve um comando faz .help <comando>.\n\r"); } /*** Broadcast message to everyone without the "X shouts:" bit ***/ broadcast(user,inpstr) int user; char *inpstr; { if (!inpstr[0]) { write_user(user,"Uso: .bcast <mensagem>"); return; } sprintf(mess,"*** %s ***\n\r",inpstr); write_area(-1,mess); } /*** Move user somewhere else ***/ move(user,inpstr) int user; char *inpstr; { char other_user[ARR_SIZE],area_name[260]; int area,user2; /* do checks */ sscanf(inpstr,"%s %s",other_user,area_name); other_user[0]=toupper(other_user[0]); inpstr=remove_first(inpstr); if (!inpstr[0]) { write_user(user,"Uso: .move <animal> <area>"); return; } if ((user2=get_user_num(other_user))==-1) { sprintf(mess,"%s nao esta na Selva",other_user); write_user(user,mess); return; } /* see if user is moving himself */ if (user==user2) { write_user(user,"Ja nao te chega o .go? Boa tentativa..."); return; } /* see if user to be moved is god */ if (ustr[user2].level==GOD) { write_user(user,"Mover um DEUS... Has-de ter sorte :P"); sprintf(mess,"%s tentou mover-te... Brincalhao!\n\r",ustr[user].name); write_user(user2,mess); return; } /* check area */ for (area=0;area<NUM_AREAS;++area) if (!strcmp(astr[area].name,area_name)) goto FOUND; write_user(user,"Vais aonde? Isso nao existe!"); return; FOUND: if (area==ustr[user2].area) { sprintf(mess,"%s ja' esta' ao pe' de ti!!",ustr[user2].name); write_user(user,mess); return; } /** send output **/ write_user(user2,"\n\rAlguem pega em ti e atira-te para outro lugar!!!\n\r"); /* to old area */ sprintf(mess,"%s e atirado para outro lado!\n\r",ustr[user2].name); write_alluser(user2,mess,0,0); if (astr[ustr[user2].area].private && astr[ustr[user2].area].status!=2 && find_num_in_area(ustr[user2].area)<=PRINUM) { write_alluser(user2,"Este lugar voltou a ficar publico...\n\r",0,0); astr[ustr[user2].area].private=0; } ustr[user2].area=area; look(user2); prompt(user2); /* to new area */ sprintf(mess,"%s aparece aqui de repente!\n\r",ustr[user2].name); write_alluser(user2,mess,0,0); write_user(user,"Ok"); } /*** Set system access to allow or disallow further logins ***/ system_access(user,co) int user,co; { if (!co) { write_area(-1,"*** A Selva IV esta' agora fechada a novos logins ***\n\r"); sys_access=0; return; } write_area(-1,"*** A Selva IV esta' agora aberta a novos logins ***\n\r"); sys_access=1; } /*** Set user description ***/ set_desc(user,inpstr) int user; char *inpstr; { if (!inpstr[0]) { sprintf(mess,"A tua descricao e': %s",ustr[user].desc); write_user(user,mess); return; } if (strlen(inpstr)>=DESC_LEN) { write_user(user,"Essa descricao e muito grande!"); return; } strcpy(ustr[user].desc,inpstr); save_stats(user); write_user(user,"Tasse ;)"); } /*** Enter profile ***/ enter_pro(user,inpstr) int user; char *inpstr; { char *c; int ret_val; /* get memory */ if (!ustr[user].pro_enter) { if (!(ustr[user].pro_start=(char *)malloc(82*PRO_LINES))) { write_syslog("ERROR: Couldn't allocate mem. in enter_pro()\n",0); sprintf(mess,"%s : a jungle esta' com problemas de memoria... Avisa os DEUSES!\n\r",syserror); write_user(user,mess); return; } ustr[user].pro_enter=1; ustr[user].pro_end=ustr[user].pro_start; sprintf(mess,"%s comeceu a escrever um profile...\n\r",ustr[user].name); write_alluser(user,mess,0,0); sprintf(mess,"\n\r** A escrever o profile **\n\n\rTens um maximo de %d linhas. Escreve um '.' numa linha vazia para saires daqui...\n\n\rLinha 1: ",PRO_LINES); write_user(user,mess); noprompt=1; ustr[user].listen=0; return; } inpstr[80]=0; c=inpstr; /* check for dot terminator */ ret_val=0; if (*c=='.' && *(c+1)==0) { if (ustr[user].pro_enter!=1) ret_val=write_pro(user); if (ret_val) write_user(user,"\n\rProfile gravado\n\r"); else write_user(user,"\n\rProfile nao gravado\n\r"); free(ustr[user].pro_start); ustr[user].pro_enter=0; ustr[user].listen=1; noprompt=0; prompt(user); sprintf(mess,"%s acabou de escrever o profile\n\r",ustr[user].name); write_alluser(user,mess,0,0); return; } /* write string to mem */ while(*c) *ustr[user].pro_end++=*c++; *ustr[user].pro_end++='\n'; /* end of lines */ if (ustr[user].pro_enter==PRO_LINES) { ret_val=write_pro(user); free(ustr[user].pro_start); if (ret_val) write_user(user,"\n\rProfile gravado\n\r"); else write_user(user,"\n\rProfile nao gravado\n\r"); ustr[user].pro_enter=0; ustr[user].listen=1; noprompt=0; prompt(user); sprintf(mess,"%s acabou de escrever o profile\n\r",ustr[user].name); write_alluser(user,mess,0,0); return; } sprintf(mess,"Linha %d: ",++ustr[user].pro_enter); write_user(user,mess); } /*** Write profile in buffer to file ***/ write_pro(user) int user; { FILE *fp; char *c,filename[80]; sprintf(filename,"%s/%s.P",USERDATADIR,ustr[user].name); if (!(fp=fopen(filename,"w"))) { sprintf(mess,"ERROR: Couldn't open %s's profile file to write in write_pro()\n",ustr[user].name); write_syslog(mess,0); sprintf(mess,"%s : nao consigo escrever no ficheiro...\n\r",syserror); write_user(user,mess); return 0; } for (c=ustr[user].pro_start;c<ustr[user].pro_end;++c) putc(*c,fp); fclose(fp); /* Code for auto promotion: if user is level 0 ... */ if (ustr[user].level==NEWBIE){ ustr[user].level=USER; sprintf(mess,"\n\rParabens, foste promovido a GIBOIA!\n\r"); write_user(user,mess); sprintf(mess,"\n\rO %s registou-se e foi promovido a GIBOIA!\n\r",ustr[user].name); write_alluser(user,mess,0,0); } return 1; } /*** show profile ***/ exa_pro(user,inpstr) int user; char *inpstr; { int u; char filename[80],user2[20],line[81]; FILE *fp; if (!inpstr[0]) { write_user(user,"Uso: .examine <user>"); return; } sscanf(inpstr,"%s",user2); user2[0]=toupper(user2[0]); if (!user_exists(user,user2)) { write_user(user,"Esse animal nao existe"); return; } if ((u=get_user_num(user2))!=-1 && u!=user) { sprintf(mess,"%s examina-te...\n\r",ustr[user].name); write_user(u,mess); } sprintf(filename,"%s/%s.P",USERDATADIR,user2); sprintf(mess,"\n\r** Profile do %s **\n\n\r",user2); write_user(user,mess); if (!more(user,ustr[user].sock,filename)) write_user(user,"Sem profile.\n\r"); sprintf(filename,"%s/%s.D",USERDATADIR,user2); if (get_user_num(user2)!=-1) { sprintf(mess,"\n\r%s esta ligado na Selva!!\n\r",user2); write_user(user,mess); return; } if (!(fp=fopen(filename,"r"))) return; fgets(line,80,fp); sprintf(mess,"\n\r%s ligou-se pela ultima vez em %s\r",user2,line); write_user(user,mess); fclose(fp); } /*** Delete mail ***/ dmail(user,inpstr) int user; char *inpstr; { char c,filename[80]; char *nocando="Nao podes apagar isso tudo! Nao abuses..."; int lines,cnt,any_left; FILE *fp,*tfp; lines=atoi(inpstr); if (lines<1 && strcmp(inpstr,"todas")) { write_user(user,"Uso: .dmail <numero de linhas a apagar>/todas"); return; } sprintf(filename,"%s/%s.M",USERDATADIR,ustr[user].name); if (!(fp=fopen(filename,"r"))) { write_user(user,"Tu nao tens nenhum mail para apagar!"); return; } if (!strcmp(inpstr,"todas")) { unlink(filename); write_user(user,"Todo o teu mail foi apagado!"); return; } if (!(tfp=fopen("tempfile","w"))) { write_user(user,"Desculpa mas nao consegui abrir o ficheiro temporario..."); write_syslog("ERROR: Couldn't open temporary file to write in dmail()\n",0); fclose(fp); return; } /* go through file */ cnt=0; while(cnt<lines) { c=getc(fp); if (feof(fp)) { write_user(user,nocando); fclose(fp); return; } if (c=='\n') cnt++; } /* copy to temp */ any_left=0; c=getc(fp); while(!feof(fp)) { any_left=1; putc(c,tfp); c=getc(fp); } fclose(fp); fclose(tfp); unlink(filename); if (!any_left) { sprintf(mess,"Foram apagadas %d linhas de mail",lines); write_user(user,mess); unlink("tempfile"); return; } /* rename temp file to new board file */ if (rename("tempfile",filename)==-1) { write_user(user,"He pa' isto nao correu bem... Conta ao MindBoosteR!"); write_syslog("ERROR: Couldn't rename temp file to board file in dmail()\n",0); return; } sprintf(mess,"Apaguei %d linhas de mail",lines); write_user(user,mess); } /*** Read mail ***/ rmail(user) int user; { FILE *fp; char filename[80]; sprintf(filename,"%s/%s.M",USERDATADIR,ustr[user].name); if (!(fp=fopen(filename,"r"))) { write_user(user,"Tu nao tens mail nenhum!"); return; } fclose(fp); write_user(user,"\n\r*** Os teus mails ***\n\n\r"); more(user,ustr[user].sock,filename); } /*** Send mail ***/ smail(user,inpstr) int user; char *inpstr; { char filename[80],name[NAME_LEN],name2[NAME_LEN]; int user2; FILE *fp; sscanf(inpstr,"%s ",name); name[0]=toupper(name[0]); inpstr=remove_first(inpstr); if (!inpstr[0]) { write_user(user,"Uso: .smail <user> <mensagem>"); return; } if (!strcmp(name,ustr[user].name)) { write_user(user,"Qual mandar mails para ti proprio qual que... Isso e que era bom!"); return; } /* see if user exists at all .. */ if (!user_exists(user,name)) { write_user(user,"Esse animal nao existe"); return; } sprintf(filename,"%s/%s.M",USERDATADIR,name); if (!(fp=fopen(filename,"a"))) { sprintf(mess,"%s : Nao consigo abrir a tua caixa de correio... :(",syserror); write_user(user,mess); sprintf(mess,"ERROR: Couldn't open %s's mailbox file to append in smail()\n",name); write_syslog(mess,0); return; } /* send the mail & record mailing */ if (!ustr[user].vis) strcpy(name2,"alguem"); else strcpy(name2,ustr[user].name); sprintf(mess,"(%s) De %s: %s\n",timeline(0),name2,inpstr); fputs(mess,fp); fclose(fp); write_user(user,"Mail enviado"); sprintf(mess,"%s mailed %s\n",ustr[user].name,name); write_syslog(mess,1); /* if recipient is logged on at the moment notify them */ if ((user2=get_user_num(name))!=-1) write_user(user2,"TENS MAIL NOVO!!!\n\r"); } /*** Send wakeup message to a user ***/ wake(user,inpstr) int user; char *inpstr; { int user2; char name[NAME_LEN]; if (!inpstr[0]) { write_user(user,"Uso: .wake <user>"); return; } sscanf(inpstr,"%s",name); name[0]=toupper(name[0]); if ((user2=get_user_num(name))==-1) { sprintf(mess,"%s nao esta ligado!",name); write_user(user,mess); return; } if (user==user2) { write_user(user,"Tu ja' estas acordado!"); return; } write_user(user2,"*** WAKE UP!! *** ACORDA!! ***\07\07\07\n\r"); write_user(user,"Ja tentaste acorda-lo, vamos ver se resultou..."); } /*** Advance a user a level ***/ promote(user,inpstr) int user; char *inpstr; { int user2; char name[NAME_LEN]; char *levstr[]={ "","GIBOIA","LEAO","DEUS" }; if (!inpstr[0]) { write_user(user,"Uso: .promote <user>"); return; } sscanf(inpstr,"%s",name); name[0]=toupper(name[0]); if ((user2=get_user_num(name))==-1) { sprintf(mess,"%s nao esta ligado!",name); write_user(user,mess); return; } if (ustr[user2].level>=ustr[user].level) { write_user(user,"Nao podes promover animais de rank igual ou superior ao teu :P"); return; } ustr[user2].level++; sprintf(mess,"%s promoveu-te a %s!\n\r",ustr[user].name,levstr[ustr[user2].level]); write_user(user2,mess); sprintf(mess,"%s PROMOTED %s to %s\n",ustr[user].name,ustr[user2].name,levstr[ustr[user2].level]); write_syslog(mess,1); save_stats(user2); write_user(user,"Ja' ta'!"); } /*** Demote a user ***/ demote(user,inpstr) int user; char *inpstr; { int user2; char name[NAME_LEN]; if (!inpstr[0]) { write_user(user,"Uso: .demote <user>"); return; } sscanf(inpstr,"%s",name); name[0]=toupper(name[0]); if ((user2=get_user_num(name))==-1) { sprintf(mess,"%s nao esta ligado!",name); write_user(user,mess); return; } if (ustr[user2].level<USER || ustr[user2].level>WIZARD) { write_user(user,"O' ve la bem o rank desse animal e diz-me se faz sentido despromove-lo..."); return; } sprintf(mess,"%s despromoveu-te!!\n\r",ustr[user].name); write_user(user2,mess); sprintf(mess,"%s DEMOTED %s\n",ustr[user].name,ustr[user2].name); write_syslog(mess,1); ustr[user2].level--; save_stats(user2); write_user(user,"Ja ta', mauzinho! ;)"); } /*** Change users password ***/ change_pass(user,inpstr) int user; char *inpstr; { char line[81],name[NAME_LEN],passwd[NAME_LEN],word[2][ARR_SIZE]; int found; FILE *fpi,*fpo; word[0][0]=0; word[1][0]=0; sscanf(inpstr,"%s %s",word[0],word[1]); if (!word[0][0] || !word[1][0]) { write_user(user,"Uso: passwd <password antiga> <nova password>"); return; } if (strlen(word[1])>NAME_LEN-1) { write_user(user,"Essa password e' grande de mais..."); return; } if (strlen(word[1])<4) { write_user(user,"Essa password e' pequena de mais..."); return; } if (!strcmp(word[0],word[1])) { write_user(user,"Entao estas a mudar o que?"); return; } /* search though password file */ if (!(fpi=fopen(PASSFILE,"r"))) { sprintf(mess,"%s : Nao consegui abrir o ficheiro de passwords :(",syserror); write_user(user,mess); write_syslog("ERROR: Couldn't open password file to read in change_pass()\n",0); return; } if (!(fpo=fopen("tempfile","w"))) { sprintf(mess,"%s : Nao consegui abrir o ficheiro de passwords :(",syserror); write_user(user,mess); write_syslog("ERROR: Couldn't open tempfile to write in change_pass()\n",0); fclose(fpi); return; } /* go through password file */ found=0; fgets(line,80,fpi); while(!feof(fpi)) { if (found) { fputs(line,fpo); fgets(line,80,fpi); continue; } sscanf(line,"%s %s",name,passwd); if (!strcmp(name,ustr[user].name) && strcmp(passwd,crypt(word[0],SALT))) { write_user(user,"Password incorrecta!!!"); fclose(fpi); fclose(fpo); unlink("tempfile"); return; } if (!strcmp(name,ustr[user].name) && !strcmp(passwd,crypt(word[0],SALT))) { sprintf(mess,"%s %s\n",ustr[user].name,crypt(word[1],SALT)); fputs(mess,fpo); found=1; } else fputs(line,fpo); fgets(line,80,fpi); } fclose(fpi); fclose(fpo); /* this shouldn't happen */ if (!found) { sprintf(mess,"%s : leitura errada.",syserror); write_user(user,mess); write_syslog("ERROR: Bad read of password file in change_pass()\n",0); return; } /* Make the temp file the password file. */ if (rename("tempfile",PASSFILE)==-1) { sprintf(mess,"%s : falha de leitura",syserror); write_user(user,mess); write_syslog("ERROR: Couldn't rename temp file to password file in change_pass()\n",0); return; } /* Output fact of changed password. We save to syslog in case change is not done by accounts owner and the owner complains and so we know the time it occured */ write_user(user,"A password foi mudada com sucesso."); sprintf(mess,"User %s changed their password\n",ustr[user].name); write_syslog(mess,1); } /*** Do a private emote ***/ pemote(user,inpstr) int user; char *inpstr; { char other_user[ARR_SIZE]; int user2; sscanf(inpstr,"%s ",other_user); other_user[0]=toupper(other_user[0]); inpstr=remove_first(inpstr); if (!inpstr[0]) { write_user(user,"Uso: .pemote <user> <mensagem>"); return; } if ((user2=get_user_num(other_user))==-1) { sprintf(mess,"%s nao esta' ligado",other_user); write_user(user,mess); return; } if (user2==user) { write_user(user,"Acho que sim, entao, fazeres emocoes para ti proprio..."); return; } if (ustr[user].vis) sprintf(mess,"-> %s %s\n\r",ustr[user].name,inpstr); else sprintf(mess,"-> Um animal %s\n\r",inpstr); write_user(user2,mess); if (ustr[user].vis) sprintf(mess,"-> Para %s: %s %s",ustr[user2].name,ustr[user].name,inpstr); else sprintf(mess,"-> Para %s: Um animal %s",ustr[user2].name,inpstr); write_user(user,mess); } /*** Do a shout emote ***/ semote(user,inpstr) int user; char *inpstr; { if (!inpstr[0]) { write_user(user,"Uso: .semote <texto>"); return; } if (!ustr[user].vis) sprintf(mess,"!! Um animal %s",inpstr); else sprintf(mess,"!! %s %s",ustr[user].name,inpstr); write_user(user,mess); strcat(mess,"\n\r"); write_alluser(user,mess,1,0); } /***************************** EVENT FUNCTIONS *****************************/ /*** switching function ***/ void sigcall() { check_mess(0); check_timeout(); /* reset alarm */ reset_alarm(); } /*** reset alarm - first called from add_user ***/ reset_alarm() { signal(SIGALRM,sigcall); alarm(ALARM_TIME); } /*** write to areas - if area=-1 write to all areas ***/ write_area(area,inpstr) int area; char *inpstr; { int u; for (u=0;u<MAX_USERS;++u) { if (ustr[u].area==-1 || !ustr[u].listen) continue; if (ustr[u].area!=area && area!=-1) continue; write_user(u,inpstr); } } /*** check to see if messages are out of date ***/ check_mess(startup) int startup; { int b,tm,day,day2; char line[ARR_SIZE+1],datestr[30],timestr[7],boardfile[20],tempfile[20]; char daystr[3],daystr2[3],month[4],month2[4]; FILE *bfp,*tfp; time((long *)&tm); strcpy(datestr,ctime((long *)&tm)); midcpy(datestr,timestr,11,15); midcpy(datestr,daystr,8,9); midcpy(datestr,month,4,6); day=atoi(daystr); /* see if its time to check (midnight) */ if (!startup) { if (!strcmp(timestr,"00:01")) { checked=0; return; } if (strcmp(timestr,"00:00") || checked) return; checked=1; } /* cycle through files */ sprintf(tempfile,"%s/temp",MESSDIR); for(b=0;b<NUM_AREAS;++b) { sprintf(boardfile,"%s/board%d",MESSDIR,b); if (!(bfp=fopen(boardfile,"r"))) continue; if (!(tfp=fopen(tempfile,"w"))) { write_syslog("ERROR: Couldn't open temp file to write in check_mess()\n",0); fclose(bfp); return; } /* go through board and write valid messages to temp file */ fgets(line,ARR_SIZE,bfp); while(!feof(bfp)) { if (line[0]!='=') { midcpy(line,daystr2,5,6); midcpy(line,month2,1,3); day2=atoi(daystr2); if (strcmp(month,month2)) day2-=30; /* if mess from prev. month */ } if (line[0]=='=' || day2>=day-MESS_LIFE) fputs(line,tfp); else astr[b].mess_num--; fgets(line,ARR_SIZE,bfp); } fclose(bfp); fclose(tfp); unlink(boardfile); /* rename temp file to boardfile */ if (rename(tempfile,boardfile)==-1) { write_syslog("ERROR: Couldn't rename temp file to board file in check_mess()\n",0); astr[b].mess_num=0; } } } /*** Boot off users who idle too long at login prompt ***/ check_timeout() { int secs,user,idle; for (user=0;user<MAX_USERS;++user) { if (ustr[user].sock==-1) continue; idle=((int)time((time_t *)0)-ustr[user].last_input)/60; if (!ustr[user].logging_in && !ustr[user].idle_mention && idle>=IDLE_MENTION) { sprintf(mess2,"%s entra em IDLE...\n\r",ustr[user].name); write_alluser(user,mess2,0,0); write_user(user,"Entraste em IDLE...\n\r"); ustr[user].idle_mention=1; } if (!ustr[user].logging_in || ustr[user].sock==-1) continue; secs=(int)time((time_t *)0)-ustr[user].last_input; if (secs>=TIME_OUT) { echo_on(user); write_user(user,"\n\n\rTime out\n\n\r"); user_quit(user); } } }