// Filename: User.c // Contents: the methods for the User object // Author: Greg Shaw // Created: 6/1/93 /* This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. In addition to the permissions in the GNU General Public License, the Free Software Foundation gives you unlimited permission to link the compiled version of this file with other programs, and to distribute those programs without any restriction coming from the use of this file. (The General Public License restrictions do apply in other respects; for example, they cover modification of the file, and distribution when not linked into another program.) This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _USER_C_ #define _USER_C_ #include "bbshdr.h" // Function: append // Purpose: append a new user record to the user file // Input: object attributes // Output: (file is written) // Author: Greg Shaw // Created: 7/20/93 int User::append(void) { FILE *ofile; char finame[255]; // filename char line[255]; // one line in file (255 max) char bbspath[225]; // bbs path if (strcpy(bbspath,getenv("BBSDIR")), bbspath == NULL) { sprintf(finame,"user.save: BBSDIR env var not set for %s",login_name); ap_log(finame); return(-1); } strcpy(line,bbspath); strcat(line,"/admin/userlog"); if (ofile = bopen(line,"a"), ofile == NULL) { sprintf(line,"user.save: Unable to open userlog file "); ap_log(line); return(-1); } //[A login_name firstname lastname state city] fprintf(ofile,"[A %s %s %s %s %s %s ]\n", login_name, fname, lname, alias, state, city); //[B terminal_type last_logon #_logins downloads uploads card_color] fprintf(ofile,"[B %s %ld %d %d %d %s ]\n", uterm, last_login, logins, downloads, uploads, card->colr); //[C private_msgs public_msgs credited_time has_color editor lines cols] fprintf(ofile,"[C %d %d %d %d %s %d %d ]\n",priv_msgs,pub_msgs, credited, has_color, editor, lines, cols); //[D flags access_level timelimit timeused_last_call anniversary kused ] fprintf(ofile,"[D %lx %d %d %d %ld %d ]\n",flags, acl, timelimit, timeused, anniversary, kused); bclose(ofile); return(0); }; // Function: change_acl // Purpose: change the user's access level (possibly permanently) // Input: acl - the timlit to change to // perm - permanent or not // Output: none // Author: Greg Shaw // Created: 6/8/93 int User::change_acl(int acl, char perm) { if (perm) acl = acl; else tmpacl = acl; return(0); } // Function: change_flags // Purpose: change the user's timelimit (possibly permanently) // Input: flags - the flags to change to // perm - permanent or not // or - or into user flags or and into user flags // Output: none // Author: Greg Shaw // Created: 6/9/93 int User::change_flags(unsigned long fl, char perm, char or) { if (perm) if (or) flags |= fl; else flags &= fl; else if (or) tmpflags |= fl; else tmpflags &= fl; return(0); } // Function: change_tl // Purpose: change the user's timelimit (possibly permanently) // Input: tl - the timlit to change to // perm - permanent or not // Output: none // Author: Greg Shaw // Created: 6/8/93 int User::change_tl(int tl, char perm) { if (perm) timelimit = tl; else tmptl = tl; return(0); } // Function: check_card // Purpose: check the user's access information vs. the card color he has // Input: none // Output: (user may be changed) // Author: Greg Shaw int User::check_card(void) { if (card = cardinfo(card_color), card == NULL) return(-1); if (acl < card->acl) // only update info if card better acl = card->acl; if (timelimit < card->tl) timelimit = card->tl; flags |= card->flags; return(0); }; // Function: delete_user // Purpose: delete a user from the BBS // Input: name - the login name of the user to delete // Output: none // Author: Greg Shaw // Created: 4/11/94 int User::delete_user(char *name) { }; // Function: display_info // Purpose: display the user's information // Input: logon - has the user just logged on? (it gives 'welcome' message // Output: user information is formatted and printed. // Author: Greg Shaw // Created: 7/2793 int User::display_info(int logon) { char tmpstr[255]; // string char *str2; // used for time double udratio; // upload/download ratio clear(); if (logon) sprintf(tmpstr,WELCOMEBACK,fname,lname,city,state); else sprintf(tmpstr,YOUARE,fname,lname,city,state); sstrcr(tmpstr); str2 = ctime(&login_time); str2[strlen(str2)-1] = 0; // chop \n cr(); sstrcr(USERINFORMATION); sstr(" "); sprintf(tmpstr,ONSINCE,str2); sstrcr(tmpstr); str2 = ctime(&last_login); str2[strlen(str2)-1] = 0; // chop \n sstr(" "); sprintf(tmpstr,LOGINSLAST,logins,str2); sstrcr(tmpstr); sstr(" "); sprintf(tmpstr,ALIASEDITOR,alias,editor); sstrcr(tmpstr); sstr(" "); sprintf(tmpstr,TERMINALINFO,uterm,has_color?COLOR:MONOCHROME,lines,cols); sstrcr(tmpstr); cr(); sprintf(tmpstr,CARDINFORMATION,card->colr); sstrcr(tmpstr); sstr(" "); sprintf(tmpstr,TIMELIMITINFO,timelimit,waittime()); sstrcr(tmpstr); sstr(" "); sprintf(tmpstr,CREDITEDTIME,credited); sstrcr(tmpstr); sstr(" "); if (card->kbytes < 0) // unlimited download? sprintf(tmpstr,DOWNLOADCAPACITY1); else sprintf(tmpstr,DOWNLOADCAPACITY2,card->kbytes); sstrcr(tmpstr); cr(); sstrcr(FILETRANSFERS); sstr(" "); sprintf(tmpstr,PRIORDOWNLOADS,downloads); sstrcr(tmpstr); sstr(" "); sprintf(tmpstr,PRIORUPLOADS,uploads); sstrcr(tmpstr); if (downloads > 0) udratio = (double)uploads/downloads; else udratio = uploads; sstr(" "); sprintf(tmpstr,RESULTRATIO,udratio); sstrcr(tmpstr); cr(); sstrcr(LASTCALL); sstr(" "); sprintf(tmpstr,TIMEUSED,timeused); sstrcr(tmpstr); sstr(" "); sprintf(tmpstr,DOWNLOADSIZE,kused); sstrcr(tmpstr); waitcr(); return(0); }; // Function: export // Purpose: export the user's environment variables // Input: none // Output: (environment vars are exported) // Author: Greg Shaw // Created: 7/2793 int User::export(void) { char tmpmsg[100]; char *outmsg; sprintf(tmpmsg,"EDITOR=%s",editor); if (outmsg = (char *) malloc(strlen(tmpmsg)+1), outmsg == NULL) { ap_log("Unable to malloc more environment space."); } strcpy(outmsg,tmpmsg); if (putenv(outmsg) != 0) ap_log("Unable to export variable."); sprintf(tmpmsg,"VISUAL=%s",editor); if (outmsg = (char *) malloc(strlen(tmpmsg)+1), outmsg == NULL) { ap_log("Unable to malloc more environment space."); } strcpy(outmsg,tmpmsg); if (putenv(outmsg) != 0) ap_log("Unable to export variable."); sprintf(tmpmsg,"TERM=%s",uterm); if (outmsg = (char *) malloc(strlen(tmpmsg)+1), outmsg == NULL) { ap_log("Unable to malloc more environment space."); } strcpy(outmsg,tmpmsg); if (putenv(outmsg) != 0) ap_log("Unable to export variable."); sprintf(tmpmsg,"LINES=%s",lines); if (outmsg = (char *) malloc(strlen(tmpmsg)+1), outmsg == NULL) { ap_log("Unable to malloc more environment space."); } strcpy(outmsg,tmpmsg); if (putenv(outmsg) != 0) ap_log("Unable to export variable."); sprintf(tmpmsg,"COLUMNS=%s",cols); if (outmsg = (char *) malloc(strlen(tmpmsg)+1), outmsg == NULL) { ap_log("Unable to malloc more environment space."); } strcpy(outmsg,tmpmsg); if (putenv(outmsg) != 0) ap_log("Unable to export variable."); return(0); }; // Function: get // Purpose: get the user's info from the user list // Input: none // Output: object is loaded or an error is returned // Author: Greg Shaw // Created: 7/13/93 // Notes: the user file is a plain text file (to allow editing). // its format is such: // [A login_name firstname lastname] // [B terminal_type last_logon #_logins downloads uploads card color] // [C private_msgs public_msgs credited_time has_color editor lines cols] // [D flags access_level timelimit timeused_last_call] // the above format includes the brackets and lines (for reference) int User::get(char *name) { FILE *ufile; char *u; char finame[255]; // filename char line[255]; // one line in file (255 max) char logname[10]; // user login name char found; // user found? char linenum; // used to look for appropriate line char c; // input char unsigned char of; // offset into line int x; struct passwd *userent; // user entry in password file if (name == NULL) strcpy(logname,username()); // get user's login information else strcpy(logname,name); if (strcpy(finame,getenv("BBSDIR")), fname == NULL) { sprintf(finame,"user.get: BBSDIR environment variable not set for %s",logname); ap_log(finame); return(-1); } strcat(finame,"/admin/userlog"); linenum = 0; // look for first line first if (ufile = bopen(finame,"r"), ufile != NULL) { found = 0; while (!found && !feof(ufile)) { of = 0; while (c = fgetc(ufile), c != '\r' && c != '\n' && !feof(ufile)) if (c != ']') // skip trailing left bracket line[of++] = c; line[of] = 0; // add null switch(linenum) { case 0: // first line if (line[0] == '[' && line[1] == 'A') // got line 1? { x = sscanf(&line[2],"%s %s %s %s %s %s",login_name, fname, lname, alias, state, city); if (u = strchr(city,']'), u != NULL) { // convert any left brackets to null u++; u[0] = 0; } if (strcmp(login_name,logname) == 0) { linenum++; // get next line } } break; case 1: // second line if (line[0] == '[' && line[1] == 'B') // got line 2? { if (sscanf(&line[2],"%s %ld %d %d %d %s",uterm, &last_login, &logins, &downloads, &uploads, card->colr) != 6) { ap_log("user.get: bad read from user file. Corrupted?"); sprintf(finame,"user.get: bad user record was %s, line B",login_name); ap_log(finame); return(-1); } linenum++; // get next line if (!strcmp(card->colr,"red")) card_color = 0; if (!strcmp(card->colr,"blue")) card_color = 1; if (!strcmp(card->colr,"green")) card_color = 2; if (!strcmp(card->colr,"white")) card_color = 3; if (!strcmp(card->colr,"grey")) card_color = 4; if (!strcmp(card->colr,"pink")) card_color = 5; if (!strcmp(card->colr,"yellow")) card_color = 6; if (!strcmp(card->colr,"black")) card_color = 7; } break; case 2: // third line if (line[0] == '[' && line[1] == 'C') // got line 3? { if (sscanf(&line[2],"%d %d %d %d %s %d %d",&priv_msgs,&pub_msgs, &credited, &has_color, editor, &lines, &cols) != 7) { ap_log("user.get: bad read from user file. Corrupted?"); sprintf(finame,"user.get: bad user record was %s, line C",login_name); ap_log(finame); return(-1); } linenum++; // get next line } break; case 3: // fourth line if (line[0] == '[' && line[1] == 'D') // got line 4? { if (sscanf(&line[2],"%lx %d %d %d %ld %d",&flags, &acl, &timelimit, &timeused, &anniversary,&kused) != 6) { ap_log("user.get: bad read from user file. Corrupted?"); sprintf(finame,"user.get: bad user record was %s, line D",login_name); ap_log(finame); return(-1); } linenum++; // get next line } break; } if (linenum == 4) // got him. { found++; bclose(ufile); logins++; if (name != NULL && (login_time - last_login)/60 < waittime()) { if ((timelimit - timeused) < 5) { clear(); sstrcr(NOUNUSEDTIME); sprintf(finame,TOOSOONERROR,waittime()); sstrcr(finame); cr(); cr(); waitcr(); sstrcr(THANKSFORCALLING); exit(0); } } else { kused = 0; // start all counters over timeused = 0; credited = 0; } tmpflags = flags; tmpacl = acl; tmptl = timelimit; if (name == NULL) { sprintf(line,"Logon for %s %s",fname,lname); ap_log(line); export(); // export his environment variables check_card(); // check his access level vs. card } return(1); // return 1 for new user only } } } bclose(ufile); // close just in case // didn't find him in user file. Need to get his information if (name != NULL) // error - unable to find user in userlog { sprintf(line,"Unable to find %s in userlog.",name); ap_log(line); return(0); } strcpy(login_name,logname); // get login name sstrcr(UNABLETOFINDUSER); sstr(WOULDLIKETOREGISTER); if (!yesno()) { fflush(stdout); sprintf(finame,"user.get: %s decided not to register for bbs.",logname); ap_log(finame); return(-1); } cr(); if (userent = getpwnam((char *)username()), userent == NULL) { sprintf(finame,"user.get: Unable to get user %s's password entry!",logname); ap_log(finame); return(-1); } sscanf(userent->pw_gecos,"%s %s",fname,lname); // get user name getinfo(1); // get user information export(); // export his environment variables check_card(); // check his access level vs. card append(); sprintf(line,"Logon for %s %s",fname,lname); ap_log(line); return(0); } // Function: getinfo // Purpose: prompt the user for information to setup the user object // Input: firsttime - is this the first logon by user? // Output: (user questions) // Author: Greg Shaw // Created: 7/25/93 int User::getinfo(char firsttime) { char loop; // loop counter char done; // loop counter char entered; // entered anything? char tmpstr[255]; char anotherstr[50]; // another string char finame[255]; // filename char logname[10]; // user login name loop = 1; entered = 0; while (loop) { clear(); // clear screen if (!firsttime || entered) { cr(); cr(); cr(); sstrcr(ENTERFOLLOWING); cr(); sprintf(finame,LOGINNAME,login_name); sstrcr(finame); sprintf(finame,REALNAME,fname,lname); sstrcr(finame); sprintf(finame,ALIASNAME,alias); sstrcr(finame); sprintf(finame,CALLINGFROM,city,state); sstrcr(finame); sprintf(finame,TERMINALTYPE,uterm); sstrcr(finame); sprintf(finame,TERMINALCAPABILITIES,has_color?YES:NO); sstrcr(finame); sprintf(finame,EDITOR,editor); sstrcr(finame); sprintf(finame,LINESCOLUMNS,lines,cols); sstrcr(finame); cr(); sstr(CORRECT); if (yesno()) loop = 0; } if (loop) // still looping? { if (!firsttime) sstrcr(XTOKEEPENTRY); strcpy(logname,username()); // get user's login information done = 0; while (!done) { sstrcr(USERINFOCITY0); sstrcr(USERINFOCITY1); sstr(USERINFOCITY2); if (gstr(tmpstr,20), strcmp(tmpstr,"") == 0) continue; if (!strcmp(tmpstr,"x")) { if (firsttime) // no empty entries for first time continue; } else strcpy(city,tmpstr); done++; } cr(); done = 0; while (!done) { sstrcr(USERINFOSTATE0); sstr(USERINFOSTATE1); if (gstr(tmpstr,2), strcmp(tmpstr,"") == 0) continue; if (!strcmp(tmpstr, "x")) { if (firsttime) // no empty entries for first time continue; } else strcpy(state,tmpstr); done++; } cr(); done = 0; while (!done) { sstrcr(USERINFOTERM0); sstrcr(USERINFOTERM1); sstrcr(USERINFOTERM2); sstrcr(USERINFOTERM3); cr(); sstrcr(USERINFOTERM4); sstrcr(USERINFOTERM5); sstrcr(USERINFOTERM6); sstrcr(USERINFOTERM7); sstrcr(USERINFOTERM8); cr(); sstrcr(USERINFOTERM9); sstrcr(USERINFOTERM10); sstrcr(USERINFOTERM11); sstrcr(USERINFOTERM12); sstrcr(USERINFOTERM13); cr(); sstrcr(USERINFOTERM14); sstr(USERINFOTERM15); if (gstr(tmpstr,20), strcmp(tmpstr,"") == 0) continue; if (!strcmp(tmpstr,"x")) { if (firsttime) // no empty entries for first time continue; } else strcpy(uterm,tmpstr); done++; } cr(); cr(); sstr(USERINFOCOLOR0); if (yesno()) has_color = 1; else has_color = 0; cr(); cr(); if (strcpy(finame,getenv("BBSDIR")), finame == NULL) { sprintf(finame,"user.get: BBSDIR env var not set for %s",logname); ap_log(finame); return(-1); } strcat(finame,"/text/editors"); sprintf(tmpstr,"Viewing %s",finame); sysopstrcr(tmpstr); display_file(finame,1); // display file with paging cr(); cr(); done = 0; while (!done) { sstrcr(USERINFOEDITOR0); sstr(USERINFOEDITOR1); if (gstr(tmpstr,14), strcmp(tmpstr,"") == 0) continue; if (!strcmp(tmpstr,"x")) { if (firsttime) // no empty entries for first time continue; } else strcpy(editor,tmpstr); done++; } cr(); cr(); sstrcr(USERINFOALIAS0); sstrcr(USERINFOALIAS1); sstr(USERINFOALIAS2); if (yesno()) strcpy(alias,logname); else { done = 0; while (!done) { sstrcr(USERINFOALIAS3); sstr(USERINFOALIAS4); if (gstr(tmpstr,20), strcmp(tmpstr,"") == 0) continue; if (!strcmp(tmpstr,"x")) { if (firsttime) // no empty entries for first time continue; } else if (sscanf(tmpstr,"%s%s",alias,anotherstr) != 1) continue; done++; } } cr(); cr(); done = 0; while (!done) { sstrcr(USERINFOLINES0); sstrcr(USERINFOLINES1); sstr(USERINFOLINES2); if (gstr(tmpstr,5), strcmp(tmpstr,"") == 0) continue; if (tmpstr[0] == 'x') { lines = 24; } else sscanf(tmpstr,"%d",&lines); done++; } cr(); cr(); done = 0; while (!done) { sstrcr(USERINFOCOLUMNS0); sstrcr(USERINFOCOLUMNS1); sstr(USERINFOCOLUMNS2); if (gstr(tmpstr,5), strcmp(tmpstr,"") == 0) continue; if (tmpstr[0] == 'x') { cols = 80; } else sscanf(tmpstr,"%d",&cols); done++; } entered++; } } export(); return(0); }; // Function: inactive_list // Purpose: list the inactive (people who haven't called lately) users // Input: none // Output: A list of users who haven't called in a specified time // Author: Greg Shaw // Created: 4/3/94 int User::inactive_list(void) { char tmpstr[255]; char line[150]; char c; char key[MAX_FILENAMELENGTH+1]; char uname[10]; char fullname[50]; char fname[15]; char lname[15]; char tmp[2][15]; char state[50]; char city[50]; char llogon[10]; char from[50]; char *sptr; int logins; int uls,dls; time_t laston; time_t today; struct tm *tmdata; int off; int found; int days; FILE *infile; clear(); time(&today); // get number of days inactive to search for sstrcr(USERSEARCH1); sstrcr(USERSEARCH2); sstrcr(USERSEARCH3); cr(); sstr(USERSEARCH4); gstr(key,MAX_FILENAMELENGTH); if (key[0] == 0 || sscanf(key,"%d",&days) != 1) return(0); sprintf(tmpstr,"%s/admin/userlog",getenv("BBSDIR")); if (infile = bopen(tmpstr,"r"), infile == NULL) { ap_log("Unable to open userlog for read."); return(0); } found = 0; sstr(USERSEARCH5); while (!feof(infile)) { off = 0; while (c = fgetc(infile), c != '\n' && c != '\r' && !feof(infile)) line[off++] = c; line[off] = 0; if (line[0] == '[') { if (line[1] == 'A') { sscanf(&line[2],"%s %s %s %s %s %s %s %s", uname, fname, lname, alias, state, city,tmp[0], tmp[1]); strcat(city,tmp[0]); strcat(city,tmp[1]); if (sptr = strchr(city,']'), sptr != NULL) sptr[0] = 0; } else if (line[1] == 'B') { sscanf(&line[2],"%*s %ld %d %d %d %*s",&laston, &logins,&uls,&dls); sprintf(fullname,"%s %s",fname,lname); sprintf(from,"%s, %s",city,state); tmdata = localtime(&laston); strftime(llogon, 12, "%b %d,%Y", tmdata); if ((today - laston)/86400 >= days) { sprintf(tmpstr,"%-15s %-15s %s %d %d",fullname,from,llogon,uls,dls); sstrcr(tmpstr); found++; } if (found == 17) { found = 0; waitcr(); sstr(CONTINUELISTING); if (!yesno()) { bclose(infile); return(0); } } } } } cr(); sstrcr(NOMOREFOUND); bclose(infile); waitcr(); return(0); }; // Function: inactive_delete // Purpose: delete inactive users on the BBS // Input: none // Output: A list of users who haven't called in a specified time // Author: Greg Shaw // Created: 4/21/94 int User::inactive_delete(void) { char tmpstr[255]; char line[150]; char c,b; char key[MAX_FILENAMELENGTH+1]; char uname[10]; char fullname[50]; char fname[15]; char lname[15]; char tmp[2][15]; char state[50]; char city[50]; char llogon[10]; char from[50]; char *sptr; int x; int logins; int uls,dls; time_t laston; time_t today; struct tm *tmdata; int off; int found; int days; FILE *infile; FILE *outfile; clear(); time(&today); // get number of days inactive to search for sstrcr(SEARCHTODELETE1); sstrcr(SEARCHTODELETE2); sstrcr(SEARCHTODELETE3); cr(); sstr(SEARCHTODELETE4); gstr(key,MAX_FILENAMELENGTH); if (key[0] == 0 || sscanf(key,"%d",&days) != 1) return(0); sprintf(tmpstr,"Will delete users %d days.",days); sstrcr(tmpstr); cr(); sstrcr(SEARCHTODELETE5); sstr(SEARCHTODELETE6); while (b = tolower(gch(1)), b != 'a' && b != 'i'); cr(); if (b == 'i') // interactively { sstrcr(PROMPTENABLED); waitcr(); } sprintf(tmpstr,"%s/admin/userlog",getenv("BBSDIR")); if (infile = bopen(tmpstr,"r"), infile == NULL) { ap_log("Unable to open userlog for read."); sstrcr(NOOPENREAD); waitcr(); return(0); } strcat(tmpstr,".new"); // get 'new' filename if (outfile = bopen(tmpstr,"w"), outfile == NULL) { ap_log("Unable to open userlog.new for write."); sstrcr(NOOPENWRITE); waitcr(); return(0); } found = 0; while (!feof(infile)) { off = 0; while (c = fgetc(infile), c != '\n' && c != '\r' && !feof(infile)) line[off++] = c; line[off] = 0; if (line[0] == '[') { if (line[1] == 'A') { sscanf(&line[2],"%s %s %s %s %s %s %s %s", uname, fname, lname, alias, state, city,tmp[0], tmp[1]); strcat(city,tmp[0]); strcat(city,tmp[1]); if (sptr = strchr(city,']'), sptr != NULL) sptr[0] = 0; } else if (line[1] == 'B') { if (sscanf(&line[2],"%s %ld %d %d %d %s",uterm, &laston, &logins,&uls,&dls,card->colr) != 6) { sprintf(tmpstr,"Error found in line B userlog in entry %s %s",fname,lname); ap_log(tmpstr); sstrcr("Error found in userlog. Clean aborted."); waitcr(); return(0); } sprintf(fullname,"%s %s",fname,lname); sprintf(from,"%s, %s",city,state); tmdata = localtime(&laston); strftime(llogon, 12, "%b %d,%Y", tmdata); if ((today - laston)/86400 >= days) { sprintf(tmpstr,"%-15s %-15s %s %d %d",fullname,from,llogon,uls,dls); sstrcr(tmpstr); if (b == 'i') // interactive? { sstr(DELETEUSER); if (yesno()) continue; } else continue; } for (x=0; x<2; x++) if (strlen(tmp[x]) < 2) tmp[x][0] = 0; // save info and next two lines fprintf(outfile,"[A %s %s %s %s %s %s %s %s ]\n", uname, fname, lname, alias, state, city, tmp[0], tmp[1]); fprintf(outfile,"%s\n",line); x = 0; while (x < 2) { if (c = fgetc(infile), c == '\n' || c == '\r') x++; fputc(c,outfile); } } } } cr(); bclose(outfile); sprintf(tmpstr,"%s/admin/userlog",getenv("BBSDIR")); sprintf(line,"%s/admin/userlog.old",getenv("BBSDIR")); rename(tmpstr,line); sprintf(tmpstr,"%s/admin/userlog.new",getenv("BBSDIR")); sprintf(line,"%s/admin/userlog",getenv("BBSDIR")); rename(tmpstr,line); waitcr(); return(0); }; // Function: list // Purpose: return a user record // Input: path - the path to the user file // Output: a list of users on the bbs - // Author: Greg Shaw // Created: 6/8/93 int User::list(int search, int sysop) { char tmpstr[255]; char line[150]; char c; char key[MAX_FILENAMELENGTH+1]; char uname[10]; char alias[25]; char fname[15]; char lname[15]; char tmp[2][15]; char state[50]; char city[50]; char *sptr; int logins; time_t laston; int off; int found; FILE *infile; clear(); sprintf(tmpstr,"%s/admin/userlog",getenv("BBSDIR")); if (infile = bopen(tmpstr,"r"), infile == NULL) { ap_log("Unable to open userlog for read."); return(0); } if (search) { sstrcr(SEARCHFORUSER); cr(); sstr(SEARCHFORCHARS); gstr(key,MAX_FILENAMELENGTH); if (key[0] == 0) return(0); // search for characters in userlog found = 0; while (!feof(infile)) { off = 0; while (c = fgetc(infile), c != '\n' && c != '\r' && !feof(infile)) line[off++] = c; line[off] = 0; if (line[0] == '[') { if (line[1] == 'A') { sscanf(&line[2],"%s %s %s %s %s %s %s %s", uname, fname, lname, alias, state, city,tmp[0], tmp[1]); strcat(city,tmp[0]); strcat(city,tmp[1]); if (sptr = strchr(city,']'), sptr != NULL) sptr[0] = 0; if (strstr(line,key) != NULL) { sprintf(tmpstr,NAMEFROM,fname,lname,city,state); sstrcr(tmpstr); sprintf(tmpstr,LOGINALIAS,uname,alias); sstrcr(tmpstr); found++; } } else if (found && line[1] == 'B') { sscanf(&line[2],"%*s %ld %d %*d %*d %*s",&laston, &logins); sptr = ctime(&laston); sptr[strlen(sptr)-1] = 0; // chop \n sprintf(tmpstr,NUMLOGONS,logins,sptr); sstrcr(tmpstr); waitcr(); if (sysop) { sstr(CONTINUEEDITDELETE); while (c = toupper(gch(1)), c != 'D' && c != 'C' && c != 'E'); if (c == 'D') { bclose(infile); delete_user(uname); return(0); } else if (c == 'E') { bclose(infile); if (get(uname)) { check_card(); sysop_edit(); } else { sprintf(tmpstr,"Unable to get %s for sysop edit.",uname); ap_log(tmpstr); } return(0); } } else { sstr(CONTINUESEARCH); if (!yesno()) { bclose(infile); return(0); } } found = 0; } } } bclose(infile); } else { found = 0; while (!feof(infile)) { off = 0; while (c = fgetc(infile), c != '\n' && c != '\r' && !feof(infile)) line[off++] = c; if (line[0] == '[') { if (line[1] == 'A') { sscanf(&line[2],"%s %s %s %s %s %s %s %s", uname, fname, lname, alias, state, city,tmp[0], tmp[1]); strcat(city,tmp[0]); strcat(city,tmp[1]); if (sptr = strchr(city,']'), sptr != NULL) sptr[0] = 0; sprintf(tmpstr,"%s %s from %s, %s",fname,lname,city,state); sstrcr(tmpstr); sprintf(tmpstr,LOGINALIAS,uname,alias); sstrcr(tmpstr); } else if (line[1] == 'B') { sscanf(&line[2],"%*s %ld %d %*d %*d %*s",&laston, &logins); sptr = ctime(&laston); sptr[strlen(sptr)-1] = 0; // chop \n sprintf(tmpstr,NUMLOGONS,logins,sptr); sstrcr(tmpstr); cr(); if (found == 6) { found = 0; waitcr(); sstr(CONTINUELISTING); if (!yesno()) { bclose(infile); return(0); } } found++; } } } cr(); } cr(); sstrcr(NOMOREFOUND); waitcr(); return(0); } // Function: mailavail // Purpose: return true if mail for the user is available // Input: none // Output: 1 for mail. 0 for no mail // Author: Greg Shaw // Created: 8/10/93 int User::mailavail(void) { struct stat fistat; // file status record char tmpstr[255]; // tmpstr time_t now = 0L; // current time static time_t then = 0L; // previous check time if (!checkmail()) // check? return(0); // no, just exit time(&now); if (abs(now - then) > mailchecktime()) // seconds elapsed? { sprintf(tmpstr,"%s/%s",mailspool(),login_name); if (stat(tmpstr,&fistat) == 0 && S_ISREG(fistat.st_mode)) { if (mail_check == 0) // just check size the first time { mail_check = fistat.st_mtime;// save modification time if (mail_size = fistat.st_size, mail_size > 0) return(1); } else // check date of last mail update { if (fistat.st_mtime != mail_check && fistat.st_size > mail_size) // new mail (mailbox bigger) { return(1); } mail_check = fistat.st_mtime; mail_size = fistat.st_size; } } } return(0); }; // Function: save // Purpose: save the current User to the User file // Input: path - the path to the User file // Output: returns non-zero on failure // Author: Greg Shaw // Created: 6/5/93 int User::save(char *name) { FILE *ufile; FILE *ofile; char finame[255]; // filename char line[255]; // one line in file (255 max) char bbspath[225]; // bbs path char logname[10]; // user login name char found; // user found? char linenum; // used to look for appropriate line char c; // input character char *u; unsigned char of; // offset into line int x; time_t now; last_login = login_time; // set to new login time time(&now); timeused += (now - login_time)/60; // update time used field. if (name == NULL) strcpy(logname,username()); // get user's log information else strcpy(logname,name); if (strcpy(bbspath,getenv("BBSDIR")), bbspath == NULL) { sprintf(finame,"user.save: BBSDIR env var not set for %s",logname); ap_log(finame); return(-1); } strcpy(line,bbspath); strcat(line,"/admin/nuserlog"); if (ofile = bopen(line,"w"), ofile == NULL) { sprintf(line,"user.save: Unable to open new userlog file: %s",logname); ap_log(line); return(-1); } chmod(line,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH); // change permissions strcpy(finame,bbspath); strcat(finame,"/admin/userlog"); linenum = 0; // look for first line first if (ufile = bopen(finame,"r"), ufile == NULL) { // create the bugger so that you can continue ufile = bopen(finame,"w"); bclose(ufile); if (ufile = bopen(finame,"r"), ufile == NULL) { // still can't open the file! AARGH! sprintf(line,"user.save: Unable to open userlog file.",logname); ap_log(line); return(-1); } } else { found = 0; while (!found && !feof(ufile)) { // get first line of = 0; while (c = fgetc(ufile), c != '\r' && c != '\n' && !feof(ufile)) if (c != ']') // skip trailing left bracket line[of++] = c; line[of] = 0; // add null if (!feof(ufile) && of > 1) // end of file, skip. { switch(linenum) { case 0: // first line if (line[0] == '[' && line[1] == 'A') // got line 1? { x = sscanf(&line[2],"%s %s %s %s %s %s",login_name, fname, lname, alias, state, city); if (u = strchr(city,']'), u != NULL) { // convert any left brackets to null u++; u[0] = 0; } if (strcmp(login_name,logname) == 0) { linenum++; // get next line fprintf(ofile,"[A %s %s %s %s %s %s ]\n", login_name, fname, lname, alias, state, city); } else fprintf(ofile,"%s]\n",line); // [A login_name firstname lastname state city] } else fprintf(ofile,"%s]\n",line); break; case 1: // second line if (line[0] == '[' && line[1] == 'B') // got line 2? { fprintf(ofile,"[B %s %ld %d %d %d %s ]\n", uterm, last_login, logins, downloads, uploads, card->colr); // [B terminal_type last_logon #_logins downloads uploads] linenum++; // get next line } else fprintf(ofile,"%s]\n",line); break; case 2: // third line if (line[0] == '[' && line[1] == 'C') // got line 3? { fprintf(ofile,"[C %d %d %d %d %s %d %d]\n",priv_msgs, pub_msgs, credited, has_color, editor, lines, cols); linenum++; // save next line // [C private_msgs public_msgs credited_time has_color editor lines cols] } else fprintf(ofile,"%s]\n",line); break; case 3: // fourth line if (line[0] == '[' && line[1] == 'D') // got line 4? { fprintf(ofile,"[D %lx %d %d %d %ld %d ]\n", flags, acl, timelimit, timeused,anniversary,kused); // [D flags access_level timelimit timeused_last_call anniversary kused ] linenum++; // save next line } else fprintf(ofile,"%s]\n",line); break; } if (linenum == 4) // got him. { found++; } } } // Ok, got the guy. copy the rest of the file while (!feof(ufile)) { c = fgetc(ufile); if (!feof(ufile)) fputc(c,ofile); } } // now rename the userfile to old userfile bclose(ufile); bclose(ofile); strcpy(line,bbspath); strcat(line,"/admin/userlog.old"); if (rename(finame, line) != 0) { sprintf(finame,"user.save: unable to rename userlog to userlog.old"); ap_log(finame); return(-1); } strcpy(line,bbspath); strcat(line,"/admin/nuserlog"); strcpy(finame,bbspath); strcat(finame,"/admin/userlog"); if (rename(line, finame) != 0) { sprintf(finame,"user.save: unable to rename new userlog to userlog",logname); ap_log(finame); return(-1); } chmod(finame,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH); // change permissions return(0); } // Function: sysop_edit // Purpose: allow the sysop to edit a user // Input: firsttime - is this the first logon by user? // Output: (user questions) // Author: Greg Shaw // Created: 4/11/94 int User::sysop_edit(void) { char c; char loop; // loop counter char changed; // changed anything? char tmpstr[255]; char str1[50], str2[50]; int selected; // which selected? int tmp; int x; struct tm *tmdata; // time stuff loop = 1; changed = 0; while (loop) { clear(); // clear screen cr(); cr(); cr(); sstrcr(CURRENTUSER); cr(); sprintf(tmpstr,LOGINFULLNAME,login_name,fname,lname,city,state); sstrcr(tmpstr); sprintf(tmpstr,ALIASDOWNLOADS,alias, downloads, uploads, logins); sstrcr(tmpstr); sprintf(tmpstr,ACLFLAGS,acl, flags, timelimit); sstrcr(tmpstr); sprintf(tmpstr,TERMTYPECOLOR,uterm,card->colr,lines,cols); sstrcr(tmpstr); tmdata = localtime(&anniversary); strftime(str1,49,"%c",tmdata); tmdata = localtime(&last_login); strftime(str2,49,"%c",tmdata); sprintf(tmpstr,FIRSTLOGON,str1); sstrcr(tmpstr); sprintf(tmpstr,LASTLOGON,str2,timeused); sstrcr(tmpstr); sstr(ISTHISCORRECT); if (yesno()) { if (changed) { sstrcr(SAVEUSERINFO); save(login_name); } return(0); } cr(); clear(); sstrcr(EDITFOLLOWING); sstrcr(EDITUSER1); sstrcr(EDITUSER2); sstrcr(EDITUSER3); sstrcr(EDITUSER4); sstrcr(EDITUSER5); sstrcr(EDITUSER6); sstrcr(EDITUSER7); sstrcr(EDITUSER8); sstrcr(RETURNTOEXIT); cr(); sstr("Edit which? "); gstr(str1,3); selected = 0; if (sscanf(str1,"%d",&selected) != 1 || (selected < 1 || selected > 15)) continue; switch(selected) { case 1: // get login name sstrcr(LOGINERROR); sstrcr(SECURITYHOLE); sstrcr(RETURNTOEXIT); waitcr(); break; // not done at this time (requires // modification of passwd file) case 2: // get first name sprintf(tmpstr,CURRENTFIRSTNAME,fname); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGEFIRSTNAME); gstr(str1,20); if (sscanf(str1,"%s",str2) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } strcpy(fname,str2); changed++; break; case 3: // get last name sprintf(tmpstr,CURRENTLASTNAME,lname); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGELASTNAME); gstr(str1,20); if (sscanf(str1,"%s",str2) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } strcpy(lname,str2); changed++; break; case 4: // get city sprintf(tmpstr,CURRENTCITY,city); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGECITY); gstr(str1,20); if (sscanf(str1,"%s",str2) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } strcpy(city,str2); changed++; break; case 5: // get state sprintf(tmpstr,CURRENTSTATE,state); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGESTATE); gstr(str1,14); if (sscanf(str1,"%s",str2) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } strcpy(state,str2); changed++; break; case 6: // get alias sprintf(tmpstr,CURRENTALIAS,alias); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGEALIAS); gstr(str1,20); if (sscanf(str1,"%s",str2) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } strcpy(alias,str2); changed++; break; case 7: // get downloads sprintf(tmpstr,CURRENTDOWNLOADS,downloads); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGEDOWNLOADS); gstr(str1,4); if (sscanf(str1,"%d",&tmp) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } downloads = tmp; changed++; break; case 8: // get uploads sprintf(tmpstr,CURRENTUPLOADS,uploads); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGEUPLOADS); gstr(str1,4); if (sscanf(str1,"%d",&tmp) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } uploads = tmp; changed++; break; case 9: // get access level sprintf(tmpstr,CURRENTACL,acl); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGEACL); gstr(str1,5); if (sscanf(str1,"%d",&tmp) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } acl = tmp; changed++; break; case 10: // get flags sstrcr(CURRENTFLAGS); for (x=0; x<32; x++) { if (x%8 == 0 && x != 0) cr(); sprintf(tmpstr,"%.2d:%d ",x,flags&1< 31)) { sstrcr(NOTCHANGED); waitcr(); continue; } flags |= 1< 31)) { sstrcr(NOTCHANGED); waitcr(); continue; } flags &= ~(1<colr); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGECOLOR); gstr(str1,10); if (sscanf(str1,"%s",str2) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } for (c = 0; c < strlen(str2); c++) // convert to lower case str2[c] = tolower(str2[c]); if (!strcmp(str2,"red")) card_color = 0; else if (!strcmp(str2,"blue")) card_color = 1; else if (!strcmp(str2,"green")) card_color = 2; else if (!strcmp(str2,"white")) card_color = 3; else if (!strcmp(str2,"grey")) card_color = 4; else if (!strcmp(str2,"pink")) card_color = 5; else if (!strcmp(str2,"yellow")) card_color = 6; else if (!strcmp(str2,"black")) card_color = 7; else { sstrcr(COLORBAD); sstrcr(NOTCHANGED); waitcr(); continue; } check_card(); changed++; break; case 14: // get lines sprintf(tmpstr,CURRENTLINES,lines); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGELINES); gstr(str1,4); if (sscanf(str1,"%d",&tmp) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } lines = tmp; changed++; break; case 15: // get columns sprintf(tmpstr,CURRENTCOLUMNS,cols); sstrcr(tmpstr); cr(); sstrcr(RETURNTOEXIT); cr(); sstr(CHANGECOLUMNS); gstr(str1,4); if (sscanf(str1,"%d",&tmp) != 1) { sstrcr(NOTCHANGED); waitcr(); continue; } cols = tmp; changed++; break; } } return(0); }; // Function: constructor // Purpose: initialize all object variables // Input: none // Output: (object is initialized) // Author: Greg Shaw // Created: 6/1/93 User::User() { card = NULL; if (card_color = def_card(), card_color == -1) ap_log("Unable to get default card color."); if (card_color != -1 && (card = cardinfo(card_color), card == NULL)) ap_log("Unable to get card information."); fname[0] = 0; lname[0] = 0; alias[0] = 0; login_name[0] = 0; editor[0] = 0; city[0] = 0; state[0] = 0; uterm[0] = 0; time(&last_login); time(&login_time); time(&anniversary); mail_check = 0; logins = 1; lines = 24; cols = 80; downloads = 0; uploads = 0; priv_msgs = 0; pub_msgs = 0; credited = 0; flags = 0; tmpflags = 0; acl = card->acl; tmpacl = acl; timelimit = card->tl; tmptl = timelimit; credited = 0; timeused = 0; kused = 0; has_color = 0; } // Function: destructor // Purpose: clean up the object // Input: none // Output: none ( null destructor at this point ) // Author: Greg Shaw // Created: 6/1/93 User::~User() { } #endif // _USER_C_