/* users.c -- handles: testing and enforcing bans and ignores adding and removing bans and ignores listing bans and ignores auto-linking bots sending and receiving a userfile from a bot listing users ('.whois' and '.match') reading the user file dprintf'ized, 9nov95 */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include "eggdrop.h" #include "users.h" #include "proto.h" extern char botname[]; extern char botuser[]; extern char botuserhost[]; extern int serv; extern char curchan[]; extern struct dcc_t dcc[]; extern int dcc_total; extern int noshare; extern struct userrec *userlist,*lastuser,*banu,*ignu; extern char cx_file[]; extern int cx_line; extern int perm_bans; extern char origbotname[]; extern char SBUF[]; /* where the user records are stored */ char userfile[121]=""; /* how many minutes will bans last? */ int ban_time=60; /* how many minutes will ignores last? */ int ignore_time=10; /* ignores are stored as 'hostmask:timer' */ int match_ignore(user) char *user; { struct userrec *u; struct eggqueue *q; char hst[121],s[161]; u=get_user_by_handle(userlist,IGNORE_NAME); if (u==NULL) return 0; q=u->host; while (q!=NULL) { strcpy(s,q->item); splitc(hst,s,':'); if (wild_match(hst,user)) return 1; q=q->next; } return 0; } /* returns 1 if temporary ban, 2 if permban, 0 if not a ban at all */ int equals_ban(user) char *user; { struct userrec *u; struct eggqueue *q; char hst[121],s[256]; u=get_user_by_handle(userlist,BAN_NAME); if (u==NULL) return 0; q=u->host; while (q!=NULL) { strcpy(s,q->item); splitc(hst,s,':'); if (!hst[0]) strcpy(hst,s); if (strcasecmp(hst,user)==0) { if (atol(s)>0) return 1; else return 2; } q=q->next; } return 0; /* not equal */ } int match_ban(user) char *user; { struct userrec *u; struct eggqueue *q; char hst[121],s[256]; u=get_user_by_handle(userlist,BAN_NAME); if (u==NULL) return 0; q=u->host; while (q!=NULL) { strcpy(s,q->item); splitc(hst,s,':'); if (!hst[0]) strcpy(hst,s); if (wild_match(hst,user)) return 1; q=q->next; } return 0; } /* if any bans match this wildcard expression, refresh them on the channel */ void refresh_ban_kick(user,nick) char *user,*nick; { struct userrec *u; struct eggqueue *q; char hst[121],s[256],*p; u=get_user_by_handle(userlist,BAN_NAME); if (u==NULL) return; q=u->host; while (q!=NULL) { strcpy(s,q->item); splitc(hst,s,':'); if (!hst[0]) { strcpy(hst,s); s[0]=0; } if (wild_match(hst,user)) { add_mode('+','b',hst); flush_mode(); /* do it IMMEDIATELY */ if ((s[0]) && (strchr(s,'~')!=NULL) && (strchr(s,':')!=NULL)) { /* ban reason stored */ splitc(NULL,s,'~'); /* crafty Fred1 method to dispose of nick */ p=strchr(s,'~'); while (p!=NULL) { *p=' '; p=strchr(s,'~'); } p=strchr(s,'`'); while (p!=NULL) { *p=','; p=strchr(s,'`'); } tprintf(serv,"KICK %s %s :banned: %s\n",curchan,nick,s); } else tprintf(serv,"KICK %s %s :You are banned.\n",curchan,nick); } q=q->next; } } int unprog_ban(who) char *who; { struct userrec *u; int i,j; struct eggqueue *q; char s[256],hst[121]; context; u=get_user_by_handle(userlist,BAN_NAME); i=0; if (u==NULL) return 0; if (atoi(who)) { j=atoi(who)-1; q=u->host; while ((j>0) && (q!=NULL)) { if (q!=NULL) q=q->next; j--; } if (q!=NULL) { strcpy(s,q->item); splitc(who,s,':'); if (!who[0]) strcpy(who,s); u->host=del_q(q->item,u->host,&i); } else return j-atoi(who); } else { /* find matching host, if there is one */ q=u->host; while ((q!=NULL) && (!i)) { strcpy(s,q->item); splitc(hst,s,':'); if (!hst[0]) strcpy(hst,s); if (strcasecmp(who,hst)==0) u->host=del_q(q->item,u->host,&i); q=q->next; } } if (i) { if (u->host==NULL) deluser(BAN_NAME); if (!noshare) shareout("-ban %s\n",who); } return i; } int unprog_ignore(who) char *who; { struct userrec *u; int i,j; struct eggqueue *q; char s[161],hst[121]; context; u=get_user_by_handle(userlist,IGNORE_NAME); i=0; if (u==NULL) return 0; if (atoi(who)) { j=atoi(who)-1; q=u->host; while (j>0) { if (q!=NULL) q=q->next; j--; } if (q!=NULL) { strcpy(s,q->item); splitc(who,s,':'); u->host=del_q(q->item,u->host,&i); } } else { /* find the matching host, if there is one */ q=u->host; while ((q!=NULL) && (!i)) { strcpy(s,q->item); splitc(hst,s,':'); context; if (strcasecmp(who,hst)==0) u->host=del_q(q->item,u->host,&i); q=q->next; } } if (i) { if (u->host == NULL) deluser(IGNORE_NAME); if (!noshare) shareout("-ignore %s\n",who); } return i; } void prog_ban(who,t,note) char *who,*note; time_t t; { struct userrec *u; char s[121],*p,oldnote[121]; time_t now=time(NULL); context; sprintf(s,"%s!%s",botname,botuserhost); /* choke check: fix broken bans (must have '!' and '@') */ if ((strchr(who,'!')==NULL) && (strchr(who,'@')==NULL)) { strcat(who,"!*@*"); } else if (strchr(who,'@')==NULL) { strcat(who,"@*"); } else if (strchr(who,'!')==NULL) { char *p=strchr(who,'@'),s1[161]; strcpy(s1,p); *p=0; strcat(who,"!*"); strcat(who,s1); } if (wild_match(who,s)) { log(LOG_MISC,"Wanted to ban myself: deflected."); return; } if (equals_ban(who)) unprog_ban(who); /* remove old ban */ u=get_user_by_handle(userlist,BAN_NAME); sprintf(s,"%s:%lu",who,t); if (note[0]) { strcpy(oldnote,note); /* remove spaces & commas */ p=strchr(note,' '); while (p!=NULL) { *p='~'; p=strchr(note,' '); } p=strchr(note,','); while (p!=NULL) { *p='`'; p=strchr(note,','); } strcat(s,":"); strcat(s,note); } else oldnote[0]=0; if (t!=0) { t=(now-t); if (t==0) t=1; } if (u==NULL) { userlist=adduser(userlist,BAN_NAME,s,"nopass",0); if (!noshare) shareout("+ban %s %lu %s\n",who,t,oldnote); strcpy(note,oldnote); return; } u->host=add_q(s,u->host); if (!noshare) shareout("+ban %s %lu %s\n",who,t,oldnote); strcpy(note,oldnote); } void prog_ignore(who,t) char *who; time_t t; { struct userrec *u; char s[161]; time_t now=time(NULL); context; u=get_user_by_handle(userlist,IGNORE_NAME); sprintf(s,"%s:%lu",who,t); if (t!=0) { t=(now-t); if (t==0) t=1; } if (u==NULL) { userlist=adduser(userlist,IGNORE_NAME,s,"nopass",0); if (!noshare) shareout("+ignore %s %lu\n",who,t); return; } u->host=add_q(s,u->host); if (!noshare) shareout("+ignore %s %lu\n",who,t); } void tell_bans(idx,show_inact,match) int idx,show_inact; char *match; { struct userrec *u; struct eggqueue *q; int i,j,k=1; time_t tt,ti; char s[256],hst[121],note[121],*p; int hidn=0; if (show_inact) dprintf(idx,"Channel bans: (! = not on channel, * = not placed by bot)\n"); else dprintf(idx,"Channel bans: (* = not placed by bot)\n"); u=get_user_by_handle(userlist,BAN_NAME); tt=time(NULL); if (u!=NULL) { q=u->host; while (q!=NULL) { strcpy(s,q->item); splitc(hst,s,':'); note[0]=0; if (!hst[0]) { strcpy(hst,s); ti=0L; } else { splitc(note,s,':'); if (note[0]) { ti=atoi(note); strcpy(note,s); } else ti=atol(s); } if (ti==0) strcpy(s,"(perm)"); else { i=tt-ti; j=(i/60); i=i%60; s[0]=0; sprintf(s,"(active %d:%02d)",j,i); } if (note[0]) { /* fix spaces & commas */ p=strchr(note,'~'); while (p!=NULL) { *p=' '; p=strchr(note,'~'); } p=strchr(note,'`'); while (p!=NULL) { *p=','; p=strchr(note,'`'); } sprintf(&s[strlen(s)]," (%s)",note); } if (match[0]) { if ((wild_match(match,hst)) || (wild_match(match,note))) { if (isbanned(hst)) dprintf(idx," [%2d] %s %s\n",k,hst,s); else dprintf(idx,"! [%2d] %s %s\n",k,hst,s); } k++; } else { if (isbanned(hst)) dprintf(idx," [%2d] %s %s\n",k++,hst,s); else { if (show_inact) dprintf(idx,"! [%2d] %s %s\n",k++,hst,s); else { k++; hidn=1; } /* skip it */ } } q=q->next; } } tell_chanbans(idx,k,match); if ((!show_inact) && (hidn)) dprintf(idx,"Use '.bans all' to see the total list.\n"); } /* list the ignores and how long they've been active */ void tell_ignores(idx) int idx; { struct userrec *u; struct eggqueue *q; int i,j,k=1; time_t tt,ti; char s[161],hst[121]; u=get_user_by_handle(userlist,IGNORE_NAME); tt=time(NULL); if (u==NULL) { dprintf(idx,"No ignores.\n"); return; } q=u->host; if (q==NULL) dprintf(idx,"No ignores.\n"); dprintf(idx,"Currently ignoring:\n"); while (q!=NULL) { strcpy(s,q->item); splitc(hst,s,':'); ti=atol(s); if (ti==0) strcpy(s,"(perm)"); else { i=tt-ti; j=(i/60); i=i%60; s[0]=0; sprintf(s,"(active %d:%02d)",j,i); } dprintf(idx," [%2d] %s %s\n",k++,hst,s); q=q->next; } } /* check for expired timed-ignores */ void check_expired_ignores() { struct userrec *u; struct eggqueue *q; char s[161],hst[121]; time_t tt,ti; context; u=get_user_by_handle(userlist,IGNORE_NAME); tt=time(NULL); if (u==NULL) return; q=u->host; if (q==NULL) return; while (q!=NULL) { strcpy(s,q->item); splitc(hst,s,':'); ti=atol(s); if (ti!=0L) if (tt-ti >= 60*ignore_time) { /* expired */ log(LOG_MISC,"No longer ignoring %s (automatically expired)",hst); unprog_ignore(hst); u=get_user_by_handle(userlist,IGNORE_NAME); if (u!=NULL) q=u->host; /* start over, check for more */ } if ((u!=NULL) && (q!=NULL)) q=q->next; else q=NULL; } } /* check for expired timed-bans */ void check_expired_bans() { struct userrec *u; struct eggqueue *q; char s[256],hst[121]; time_t tt,ti; char note[41]; context; u=get_user_by_handle(userlist,BAN_NAME); tt=time(NULL); if (u==NULL) return; q=u->host; if (q==NULL) return; while (q!=NULL) { strcpy(s,q->item); splitc(hst,s,':'); if (!hst[0]) { strcpy(hst,s); ti=0L; } else { splitc(note,s,':'); if (note[0]) ti=atoi(note); else ti=atol(s); } if ((ti!=0L) && (tt-ti >= 60*ban_time)) { /* expired: 1 hr later */ log(LOG_MISC,"No longer banning %s (automatically expired)",hst); add_mode('-','b',hst); unprog_ban(hst); u=get_user_by_handle(userlist,BAN_NAME); if (u!=NULL) q=u->host; /* start over, check for more */ else q=NULL; } else q=q->next; } } /* see if there are any bots that need to be linked */ void auto_link_tandem(start) char *start; { struct userrec *u=userlist,*autc=NULL; int i,j,ok=0,got_hub=0; context; if (start==NULL) ok=1; while (u!=NULL) { if (((u->flags&USER_BOT) && (u->flags&BOT_AUTO))) { j=0; for (i=0; ihandle)==0) { if (dcc[i].type==DCC_TANDEM) j=1; if (dcc[i].type==DCC_TANDEM_NEW) j=1; if (dcc[i].type==DCC_FORK) if (dcc[i].u.fork->type==DCC_TANDEM) j=1; } /* check for possibility that share-bot IS linked in... but not to me */ if ((!j) && (in_chain(u->handle)) && (u->flags&BOT_SHARE) && (strcasecmp(origbotname,u->handle)!=0)) { int q=nextbot(u->handle); tprintf(dcc[q].sock,"unlink %s %s %s\n",origbotname,lastbot(u->handle), u->handle); /* once unlinking is done, i'll try to autoconnect later */ } if ((!j) && (in_chain(u->handle))) j=1; if (u->flags&BOT_HUB) { if (j) { got_hub=1; /* a hub is connected out there somewhere */ if ((autc!=NULL) && (autc->flags&BOT_HUB)) { /* great... already have a hub bot in line to be linked */ /* start over from there */ u=autc; j=1; autc=NULL; } } else if (got_hub) j=1; /* don't want this one cos we have a hub */ } if ((!j) && (ok)) { if (autc==NULL) autc=u; else if ((u->flags&BOT_SHARE) && (!(autc->flags&BOT_SHARE))) autc=u; /* share bots get priority */ } /* did we make it where we're supposed to start? yay! */ if (!ok) if (strcasecmp(u->handle,start)==0) ok=1; } if ((u->flags&USER_BOT) && (u->flags&BOT_REJECT)) if (in_chain(u->handle)) { /* get rid of nasty reject bot */ reject_bot(u->handle); } u=u->next; } if (autc!=NULL) tandem_link("",-1,autc->handle); /* try autoconnect */ } /* erase old user list, switch to new one */ void use_new_buf(idx) int idx; { clear_userlist(userlist); userlist=dcc[idx].u.tand->user; dcc[idx].u.tand->user=NULL; clear_chanlist(); lastuser=banu=ignu=NULL; } void store_new_user(idx,s) int idx; char *s; { int f=0; char handle[20],host[181],pass[20]; split(handle,s); split(host,s); split(pass,s); f=str2flags(s); dcc[idx].u.tand->user=(void *) adduser((struct userrec *)dcc[idx].u.tand->user,handle,host,pass,f); } void send_tandem_user(z,u) int z; struct userrec *u; { char f[20]; struct eggqueue *q; char h[181]; context; flags2str((u->flags & USER_MASK),f); /* for user-created flags that could have any name, depending: */ if (u->flags & USER_FLAG1) strcat(f,"1"); if (u->flags & USER_FLAG2) strcat(f,"2"); if (u->flags & USER_FLAG3) strcat(f,"3"); if (u->flags & USER_FLAG4) strcat(f,"4"); if (u->flags & USER_FLAG5) strcat(f,"5"); if (u->flags & USER_FLAG5) strcat(f,"6"); if (u->flags & USER_FLAG5) strcat(f,"7"); if (u->host==NULL) strcpy(h,"none"); else strcpy(h,u->host->item); tprintf(z,"user %s %s %s %s\n",u->handle,h,u->pass,f); tprintf(z,"laston %lu\n",u->laston); q=u->host->next; while (q!=NULL) { tprintf(z,"host %s\n",q->item); q=q->next; } if (u->email!=NULL) tprintf(z,"email %s\n",u->email); if (u->dccdir!=NULL) tprintf(z,"dccdir %s\n",u->dccdir); if (u->comment!=NULL) tprintf(z,"comment %s\n",u->comment); if (u->info!=NULL) tprintf(z,"info %s\n",u->info); if (u->xtra!=NULL) tprintf(z,"xtra %s\n",u->xtra); tprintf(z,"*user\n"); } /* begin the user transfer process */ void start_sending_users(idx) int idx; { struct userrec *u=userlist; context; if (u==NULL) { tprintf(dcc[idx].sock,"*userlist"); return; } dcc[idx].u.tand->user=(void *)dup_userlist(0); /* only non-bots */ if (dcc[idx].u.tand->user == NULL) { tprintf(dcc[idx].sock,"*userlist"); return; } dcc[idx].u.tand->status|=STAT_SENDING; u=(struct userrec *)dcc[idx].u.tand->user; send_tandem_user(dcc[idx].sock,u); } /* resend user in case of error */ void resend_user(idx) int idx; { struct userrec *u; u=(struct userrec *)dcc[idx].u.tand->user; send_tandem_user(dcc[idx].sock,u); } /* send next user (return 1 if end of list) */ int send_next_user(idx) int idx; { struct userrec *u,*u1; context; u=(struct userrec *)dcc[idx].u.tand->user; if (u==NULL) { tprintf(dcc[idx].sock,"*userlist\n"); dcc[idx].u.tand->status&=~STAT_SENDING; return 1; } u1=u; u=u->next; freeuser(u1); if (u==NULL) { tprintf(dcc[idx].sock,"*userlist\n"); dcc[idx].u.tand->user=NULL; dcc[idx].u.tand->status&=~STAT_SENDING; return 1; } dcc[idx].u.tand->user=(void *)u; send_tandem_user(dcc[idx].sock,u); return 0; } char *cursend(idx) int idx; { struct userrec *u; u=(struct userrec *)dcc[idx].u.tand->user; if (u!=NULL) return (u->handle); else return "[EOF]"; } /* update a user's last signon, by host */ void update_laston(host) char *host; { struct userrec *u; u=get_user_by_host(host); if (u==NULL) return; u->laston=time(NULL); } /* return laston time */ void get_handle_laston(nick,n) char *nick; time_t *n; { struct userrec *u; u=get_user_by_handle(userlist,nick); if (u==NULL) *n=0L; else *n = u->laston; } void set_handle_laston(nick,n) char *nick; time_t n; { struct userrec *u; u=get_user_by_handle(userlist,nick); if (u==NULL) return; u->laston=n; } void set_handle_laston2(bu,nick,n) struct userrec *bu; char *nick; time_t n; { struct userrec *u; u=get_user_by_handle(bu,nick); if (u==NULL) return; u->laston=n; } /* since i was getting a ban list, i assume i'm chop */ /* recheck_bans makes sure that all who are 'banned' on the userlist are actually in fact banned on the channel */ void recheck_bans() { struct userrec *u=userlist; struct eggqueue *q; char s[256],hst[121]; context; if (!perm_bans) return; u=get_user_by_handle(userlist,BAN_NAME); if (u==NULL) return; q=u->host; while (q!=NULL) { strcpy(s,q->item); splitc(hst,s,':'); if (!hst[0]) strcpy(hst,s); if (!isbanned(hst)) add_mode('+','b',hst); q=q->next; } } /* find info line for a user and display it if there is one */ void showinfo(who,nick) char *who,*nick; { char s[121],s1[121]; if (get_attr_handle(who) & USER_BOT) return; get_handle_info(who,s1); strcpy(s,s1); if (s[0]=='@') strcpy(s,&s[1]); if (s[0]) { if (stristr(s,nick)==NULL) { sprintf(s1,"[%s] %s",nick,s); strcpy(s,s1); } mprintf(serv,"PRIVMSG %s :%s\n",curchan,s); } } void tell_user(idx,u,master) int idx; struct userrec *u; int master; { char s[81],s1[81],host[81]; struct eggqueue *q; time_t now; if (strcmp(u->handle,BAN_NAME)==0) { dprintf(idx,"[ban list] -> use '.bans'\n"); return; } if (strcmp(u->handle,IGNORE_NAME)==0) { dprintf(idx,"[ignore list] -> use '.ignores'\n"); return; } flags2str(u->flags,s); if (u->laston == 0L) strcpy(s1,"never"); else { now=time(NULL)-(u->laston); strcpy(s1,ctime(&(u->laston))); if (now>86400) { s1[7]=0; strcpy(&s1[11],&s1[4]); strcpy(s1,&s1[8]); } else { s1[16]=0; strcpy(s1,&s1[11]); } } strcpy(host,u->host->item); if (strlen(host)>33) { strcpy(host,"(see below)"); q=u->host; } else q=u->host->next; dprintf(idx,"%-10s%-35s%-5s%-18s%s\n",u->handle,host,(strcasecmp(u->pass, "nopass")==0)?"no":"yes",s,s1); s[0]=0; while (q!=NULL) { if (!s[0]) sprintf(s," %s",q->item); else { if (strlen(s)+strlen(q->item)+2>70) { dprintf(idx,"%s\n",s); sprintf(s," %s",q->item); } else { strcat(s,", "); strcat(s,q->item); } } q=q->next; } if (s[0]) dprintf(idx,"%s\n",s); if ((master) && (u->comment!=NULL)) dprintf(idx," COMMENT: %s\n",u->comment); if (u->email!=NULL) dprintf(idx," EMAIL: %s\n",u->email); if (u->flags&USER_BOT) { if (u->info!=NULL) dprintf(idx," ADDRESS: %s\n",u->info); } else { if (u->info!=NULL) dprintf(idx," INFO: %s\n",u->info); } } /* show user by ident */ void tell_user_ident(idx,id,master) int idx; char *id; int master; { struct userrec *u; u=get_user_by_handle(userlist,id); if (u==NULL) u=get_user_by_host(id); if (u==NULL) { dprintf(idx,"Can't find anyone matching that.\n"); return; } dprintf(idx,"HANDLE HOSTMASK(S) PASS ATTR LAST\n"); tell_user(idx,u,master); } /* match string: wildcard to match nickname or hostmasks */ /* +attr to find all with attr */ void tell_users_match(idx,mtch,start,limit,master) int idx; char *mtch; int start,limit,master; { struct userrec *u=userlist; int fnd=0,cnt; struct eggqueue *q; dprintf(idx,"*** Matching '%s':\n",mtch); cnt=0; dprintf(idx,"HANDLE HOSTMASK(S) PASS ATTR LAST\n"); if (start>1) dprintf(idx,"(skipping first %d)\n",start-1); while (u!=NULL) { if (mtch[0]=='+') { fnd=str2flags(&mtch[1]); if ((u->flags&fnd)==fnd) { cnt++; if ((cnt<=limit) && (cnt>=start)) tell_user(idx,u,master); if (cnt==limit+1) dprintf(idx,"(more than %d matches; list truncated)\n",limit); } } else if (wild_match(mtch,u->handle)) { cnt++; if ((cnt<=limit) && (cnt>=start)) tell_user(idx,u,master); if (cnt==limit+1) dprintf(idx,"(more than %d matches; list truncated)\n",limit); } else { fnd=0; q=u->host; while (q!=NULL) { if ((wild_match(mtch,q->item)) && (!fnd)) { cnt++; fnd=1; if ((cnt<=limit) && (cnt>=start)) tell_user(idx,u,master); if (cnt==limit+1) dprintf(idx,"(more than %d matches; list truncated)\n",limit); } q=q->next; } } u=u->next; } dprintf(idx,"--- Found %d match%s.\n",cnt,cnt==1?"":"es"); } int readuserfile(file) char *file; { char *p,s[181],lasthand[20],host[181],attr[181],pass[181],code[181]; FILE *f; int flags; context; clear_chanlist(); lastuser=banu=ignu=NULL; lasthand[0]=0; f=fopen(file,"r"); if (f==NULL) return 0; noshare=1; while (!feof(f)) { fgets(s,180,f); if (!feof(f)) { rmspace(s); if ((s[0]!='#') && (s[0]!=';') && (s[0])) { nsplit(code,s); rmspace(code); rmspace(s); if (strcasecmp(code,"-")==0) { if (lasthand[0]) { p=strchr(s,','); while (p!=NULL) { splitc(code,s,','); rmspace(code); rmspace(s); if (code[0]) addhost_by_handle(lasthand,code); p=strchr(s,','); } if (s[0]) addhost_by_handle(lasthand,s); } } else if (strcasecmp(code,"+")==0) { if (lasthand[0]) { set_handle_email(userlist,lasthand,s); } } else if (strcasecmp(code,"*")==0) { if (lasthand[0]) { set_handle_dccdir(userlist,lasthand,s); } } else if (strcasecmp(code,"=")==0) { if (lasthand[0]) { set_handle_comment(userlist,lasthand,s); } } else if (strcasecmp(code,":")==0) { if (lasthand[0]) { set_handle_info(userlist,lasthand,s); } } else if (strcasecmp(code,".")==0) { if (lasthand[0]) { char xxx[513]; get_handle_xtra(lasthand,xxx); if (xxx[0]) strcat(xxx," "); strcat(xxx,s); set_handle_xtra(userlist,lasthand,xxx); } } else { nsplit(host,s); rmspace(host); rmspace(s); nsplit(pass,s); rmspace(pass); rmspace(s); nsplit(attr,s); rmspace(attr); rmspace(s); if ((!s[0]) || (!attr[0]) || (!pass[0]) || (!host[0])) { log(LOG_MISC,"* Corrupt user record '%s'!",code); lasthand[0]=0; } else if (is_user(code)) { log(LOG_MISC,"* Duplicate user record '%s'!",code); lasthand[0]=0; } else { flags=str2flags(attr); strcpy(lasthand,code); if (strcasecmp(host,"$placeholder$")==0) host[0]=0; if (strcasecmp(host,"none")==0) host[0]=0; if (strlen(code)>9) code[9]=0; if (strlen(pass)>9) pass[9]=0; userlist=adduser(userlist,code,host,pass,flags); set_handle_laston(code,atol(s)); } } } } } noshare=0; fclose(f); return 1; }