/**************************************************************** * User edit/add routines for Metal/Z-MSG * * FILE: MEUSER.C * * Copyright (c) 1984, 1985, 1986 Tim Gary * All rights reserved * **************************************************************** * * 1.50xx 08/13/86 Added support for user.phon kludge * 1.50xx 03/12/86 Allow group access code changes.. * 1.40xx 02/10/86 External help files (lib members) used.. * 1.40xx 02/04/86 Mods for use with hashed users file.. * 1.40xx 01/26/86 Fixed for new format of things.. * 1.31a 10/13/85 Release version. Minor bug fixes in scan to user * number and if user not found. * 1.30xx 6/29/85 Packed down to under 8k.. must stay this way * 1.30xx 5/26/85 Minor cosmetic bugs fixed (prompt mode, etc) * 1.30xx 5/15/85 Edit user function made simpler. * 1.30xx 5/01/85 Split Add function to other overlay (space) * 1.30xx 4/25/85 Edit user fixed... was wiping previous user * 1.30xx 4/08/85 Fixed so selective read user funcs work * 1.30xx 4/04/85 Few bug fixes (won't re-delete users) * 1.20c 04/01/85 Not an April Fools joke.. mass stuff added * 1.20c 03/29/85 Still more mass user stuff added * 1.20c 03/23/85 More advanced mass-user delete method.. * 1.20a 11/07/84 More work on the ADD command (gcntrs change) * 1.10e 11/03/84 # calls initialized in ADD * 1.10e 10/30/84 User width initialized. * 1.10a 9/12/84 Cosmetic fixes. * 1.10a 9/08/84 Cosmetic fixes. * 1.10a 9/01/84 Split from mutil for overlay Metal. * * 1.01a 6/10/84 Fixed for Aztec C 1.06. * * 1.0b 4/13/84 Fixed for upper/lower case names. * ****************************************************************/ #include "xpm.h" /* CPMIO header file for i/o operations.*/ #include "megen.h" /* general defines */ #include "meglob.h" /* global variable definitions */ #include "meovfn.h" /* overlay function numbers */ #include "mefiles.h" /* file names */ #include "ctype.h" #define EDITHLP "EDITMAINHLP" /* must be exactly 11 chars */ #define STATHLP "EDITSTATHLP" /* mass function time help */ #define DATEHLP "EDITDATEHLP" /* mass function date help */ #define CALLHLP "EDITCALLHLP" /* mass function calls help */ static int dead_rec_no=0; /* for deleted user */ static int dead_user_no=0; /* main program */ ovmain(func,parm) int func; char *parm; { if (user.status==SYSOP) { if (func==EDITUSER) { init_tags(); user_sweep(parm); } else { /* delete user */ char temp[NAMELEN+2]; users=open(USERFILE,1); if (del_user(parm)==ERROR) send("\n[User not found]\n"); else send("\n[Deleted]"); close(users); } } } /* main */ edituser() { register int cfast; char temp[50]; usr *up; up=bufloc(users); /********************************** * begin editing user * *********************************/ send("\n[Edit]\n\nHit return if no change.\n"); do { sprintf(buffer,"Name: %s : ",up->name); ask(buffer,temp,NAMELEN,UPLOW); if (*temp!='\0') { capstr(temp); if (isdigit(*temp)) { send("First char can't be numeric!"); continue; } else { usr *tbuf; tbuf=malloc(128); movmem(up,tbuf,128); del_user(tbuf->name); /* delete old user */ strcpy(tbuf->name,temp); add_user(tbuf); up=bufloc(users); movmem(tbuf,up,128); free(tbuf); break; } } } while (*temp!='\0'); sprintf(buffer,"City: %s : ",up->city); ask(buffer,temp,CITYLEN,UPLOW); capstr(temp); if (*temp!='\0') strcpy(up->city,temp); do { sprintf(buffer,"Password: %s : ",up->pass); ask(buffer,temp,PASSLEN,UP); if (*temp!='\0') { if (isdigit(*temp)) { send("First char can't be numeric!"); continue; } else { strcpy(up->pass,temp); break; } } } while (*temp!='\0'); sprintf(buffer,"Answer to Sysop question:: %s : ",up->phone); ask(buffer,temp,12,UP); if (*temp!='\0') strcpy(up->phone,temp); do { sprintf(buffer,"Status: '%c' (%s) :",up->status,up->status==SYSOP ? "SYSOP" : up->status==SPECIAL ? "SPECIAL" : up->status==NORMAL ? "NORMAL" : up->status==NOCPM ? "NO OS" : up->status==TWIT ? "*TWIT*" : "OTHER"); ask(buffer,temp,10,UPLOW); if (*temp=='\0') continue; if (!index("+snxXabcde",*temp)) { send("Bad status. Try:\n'+' for SYSOP\n's' for SPECIAL\ \n'n' for NORMAL\n'x' for NO Operating System\n'X' for TWIT\ \nor 'a','b' or 'c' for user defined types\n"); continue; } else { up->status=*temp; break; } } while (*temp!='\0'); do { printf("Group read flag is currently %4x hex.\n", up->group_flags); ask("Enter new flag (in hex): ",temp,5,UP); if (isxdigit(*temp)) up->group_flag=xtou(temp); } while (*temp!='\0'); write(users,0); /* write new version */ send("[Saved]\n"); } /* edituser */ user_sweep(name) char *name; { register int flag; /* to abort do loop */ int offset,c,all; char temp[MAXLINE]; usr *up; all=FALSE; flag=TRUE; users=open(USERFILE,0); if (name) strcpy(temp,name); else *temp='\0'; if (strloc && !(*temp)) ask("",temp,NAMELEN,UPLOW); /* fudge to get parm */ if (*temp) { /* if name passed, then it's from the selective read */ if (find_user(temp)>=0) edituser(); else send("\n[User not found]\n"); close(users); return TRUE; } offset=0; up=bufloc(users); do { setrrec(users,offset); if (read(users,0)!=128) { putchar('\n'); /* mark end of file */ setarec(users,0); offset=0; continue; } if (!all && (up->file_info&DEADUSER)) { if (offset==0) offset=1; continue; /* skip deleted users */ } offset=0; /* clear this afterwards */ out_user(); send("--> "); switch(c=tolower(getchar())) { case ' ': case '\n': case '\r': offset=1; /* advance */ break; case 'b': case '-': /* backup one user */ case '\b': offset=-1; break; case 'd': /* delete? */ purge_user(); offset=1; /* and bump past him */ break; case 'u': unpurge_user(); /* undelete this user... */ break; case 'a': /* show all users (deleted ones too..) */ all= all ? FALSE : TRUE; if (all) send("\n[All users]"); else send("\n[Only active Users]"); break; case 'z': /* to eof */ toeof(users); offset=-1; /* so next read will backup */ break; case 'm': /* mass delete from current position */ mass_func(); break; case 't': tag_users(); break; case 'i': printf("\nPass: %s\nCity: %s\nAnswer to Sysop question: %s",up->pass,up->city,up->phone); break; case 'e': /* edit this user */ edituser(); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': sprintf(temp,"%c",(char)c); /* start of number */ while ( isdigit(c=getchar()) && strlen(temp) ",temp,NAMELEN,UPLOW); if (*temp) { unsigned sav_seek; sav_seek=getrec(users); if (find_user(temp)<0) { setarec(users,sav_seek); if (!finduser(temp)) setarec(users,sav_seek); } } break; case 'x': /* abort this mode */ flag=FALSE; break; default: ltype(METHELP,EDITHLP); /* sweep_help(); */ } /* switch */ putchar('\n'); /* goto next line */ } while (flag); /* do... */ close(users); return NULL; } /* deleteuser */ out_user() { char temp[8]; usr *up; up=bufloc(users); if (up->file_info&DEADUSER) strcpy(temp,"[dead]"); else sprintf(temp,"%3u",getrec(users)+1); printf("%s (%c - group %04x) %4u calls. %8s %-26s",temp,up->status, up->group_flags,up->calls,ascdate(up->date),up->name); } purge_user() /* delete user at current location */ { usr *up; register unsigned tu; up=bufloc(users); if (up->file_info&DEADUSER) return; /* ignore already deleted users */ send("\n[User deleted]"); up->file_info|=DEADUSER; /* zap him.. */ write(users,0); /* and do this... */ } unpurge_user() /* restore user at current location */ { usr *up; up=bufloc(users); if ( !(up->file_info&DEADUSER) ) return; /* not dead to start with */ send("\n[User restored]"); up->file_info^=DEADUSER; /* reset status.. */ write(users,0); /* and do this... */ } /* To free a bit of room in compiling, zap a few unused defines */ #undef OSCOM #undef BYECOM #undef WELCOME #define LT 3 #define GT 2 #define EQ 1 #define NOT 256 static char date_pat[10]; /* date pattern */ static int date_flag; /* flag if date < or > or == */ static char stat_pat[10]; /* status matchers */ static int stat_flag; /* flag if status == or != */ static int calls_num; /* # of calls matcher */ static int calls_flag; /* if < or > or == */ static int prompt_flag; /* wether or not prompted mode */ init_tags() { *date_pat=*stat_pat='\0'; /* clear date/status flags */ date_flag=stat_flag=calls_flag=prompt_flag=calls_num=0; } show_tags() { printf("\n\nDate: %s %s Status: %s %s Calls: %s %u\n", date_flag==GT ? ">" : date_flag==LT ? "<" : date_flag==EQ ? "=" : "(none)",date_pat, stat_flag==EQ ? "=" : stat_flag==NOT ? "NOT" : "(none)",stat_pat, calls_flag==GT ? ">" : calls_flag==LT ? "<" : calls_flag==EQ ? "=" : "(none)",calls_num); } /* show pat */ mass_func() { unsigned start_rec; /* initial record #, and one to change */ int flag; char temp[MAXLINE+1]; if ( !(calls_flag+stat_flag+date_flag) ) { send("\nNo 'Tags' set. Use the 'T' function to set them.\n\n"); return; } show_tags(); send("\nNote: function starts scanning at the CURRENT location,\n\ NOT at the start of the users file!!\n\n"); ask("Perform mass delete function (y/n)? ",temp,2,UP); if (*temp!='Y') return; sprintf(temp,"Prompted mode (RETURN=%s)? ",prompt_flag ? "YES" : "NO"); ask(temp,temp,2,UP); switch (*temp) { case 'N': prompt_flag = !prompt_flag; break; case 'Y': prompt_flag = YES; break; case '\0': break; default: send("[aborted]\n"); return; } /* switch */ start_rec=getrec(users); /* save starting place */ while (read(users,0)==128) { usr *up; up=bufloc(users); flag=match_date(); /* check for date match */ flag&=match_calls(); /* check for calls match */ flag&=match_stat(); /* see if status matches */ if (flag && !(up->file_info&DEADUSER)) /* if not already gone, and a match.. */ { if (prompt_flag) { out_user(); send("Delete? "); *temp=tolower(getchar()); if (*temp=='y') purge_user(); if ( ((*temp)&0x0b) == 0x0b) /* ^k to abort */ { send("[Purge aborted]"); break; } else send("\n[User REMAINS]"); putchar('\n'); } else purge_user(); } setrrec(users,1); /* goto next record location for read */ if (breakkey()) { send("\n[Mass deletion aborted!]\n"); break; } } /* while */ setarec(users,start_rec); /* back to where we began */ read(users,0); /* and read */ } /* mass function */ match_date() { int flag; usr *up; char td_pat[9],td_usr[9]; up=bufloc(users); if (!date_flag) return TRUE; /* fake match if no date pattern */ strncpy(td_pat,date_pat+6,2); strncpy(td_pat+2,date_pat,2); strncpy(td_pat+4,date_pat+2,2); td_pat[6]='\0'; strncpy(td_usr,ascdate(up->date)+6,2); strncpy(td_usr+2,ascdate(up->date),2); strncpy(td_usr+4,ascdate(up->date)+2,2); td_usr[6]='\0'; if (date_flag==EQ && !strcmp(td_usr,td_pat)) return TRUE; if (date_flag==LT && (strcmp(td_usr,td_pat)==-1)) return TRUE; if (date_flag==GT && (strcmp(td_usr,td_pat)==1)) return TRUE; return FALSE; } match_stat() { usr *up; int flag; up=bufloc(users); if (!stat_flag) return TRUE; /* fake match if no status pattern */ flag=index(stat_pat,up->status); if (stat_flag==EQ && flag) return TRUE; /* match */ if (stat_flag==NOT && !flag) return TRUE; /* also a match */ return FALSE; /* otherwise no match */ } match_calls() { usr *up; up=bufloc(users); if (!calls_flag) return TRUE; /* fake match if no calls pattern */ if (calls_flag==EQ && up->calls==calls_num) return TRUE; if (calls_flag==LT && up->callscalls>calls_num) return TRUE; return FALSE; /* otherwise no match */ } tag_users() { char temp[MAXLINE+1]; /* parm holder */ show_tags(); ask("\nChange current tags (y/n)? ",temp,2,UP); if (*temp!='Y') return; send("\nReturn alone at a prompt CLEARS that match string!\n"); do { *date_pat='\0'; /* clear this */ date_flag=0; /* and this */ ask("\nDate match string (? for help) -> ",temp,13,UP); if (*temp=='?') { ltype(METHELP,DATEHLP); continue; } switch (*temp) { case '\0': break; case '>': date_flag=GT; /* Greater than flag */ strcpy(date_pat,temp+1); break; case '<': date_flag=LT; strcpy(date_pat,temp+1); break; case '=': date_flag=EQ; strcpy(date_pat,temp+1); break; default: if (isdigit(*temp)) { date_flag=EQ; strcpy(date_pat,temp); break; } else { *temp='?'; send("\nBad Match string.\n"); } break; } /* switch */ } while (*temp && (strlen(temp)!=9) ); /* date match question */ do { *stat_pat='\0'; stat_flag=0; ask("\nUser Status match string (? for help) -> ",temp,10+3,UPLOW); if (*temp=='?') { ltype(METHELP,STATHLP); continue; } switch (*temp) { case '\0': break; case '=': stat_flag=EQ; strcpy(stat_pat,temp+1); break; case '!': stat_flag=NOT; strcpy(stat_pat,temp+1); break; default: if (index("+snxXabcde",*temp)) { stat_flag=EQ; strcpy(stat_pat,temp); break; } else { *temp='?'; send("\n[Bad Match String]\n"); } break; } /* switch */ } while (*temp && (strlen(temp)<2) ); /* match question */ do { calls_num=0; calls_flag=0; ask("\nTimes user has called match string (? for help) -> ",temp,10,UPLOW); if (*temp=='?') { ltype(METHELP,CALLHLP); continue; } switch (*temp) { case '\0': break; case '=': calls_flag=EQ; calls_num=atoi(temp+1); break; case '>': calls_flag=GT; calls_num=atoi(temp+1); break; case '<': calls_flag=LT; calls_num=atoi(temp+1); break; default: if (isdigit(*temp)) { calls_flag=EQ; calls_num=atoi(temp); break; } else { *temp='?'; send("\n[Bad Match String]\n"); } break; } /* switch */ } while (*temp && (strlen(temp)<2) ); /* match question */ show_tags(); } /* tag_users */ finduser(name) char *name; { register int cfast; char temp[MAXLINE+1]; usr *up; if (!name) { ask("Enter full or partial user name? ",temp,MAXLINE,UP); if (*temp=='\0') return FALSE; /* exit to main */ } else strcpy(temp,name); up=bufloc(users); send("\n[Searching.."); while ((cfast=read(users,1))==128) { if (!(getrec(users)%25)) putchar('.'); cfast=128; if (!(up->file_info&DEADUSER)) if (usindex(temp,up->name) || usindex(temp,up->phone)) break; /* found him */ /* I know.. the index func. looks backwards.. */ } if (cfast!=128) { send("]\n[Not found]"); return FALSE; } setrrec(users,-1); /* back to where user was actually read */ putchar(']'); /* make things look neato */ return TRUE; } /* End Of File */