#include "buddies.h" char* bud_expand_fmt(const bud_utrec_t *bud, const char *fmt_string); static int bud_hash_buddy(void *o){ char *c=((buddy_t*)o)->name; int i, hash=0; for(i=0;iu->ut_line; int i,hash=0; for(i=0;iname, ((buddy_t*)o2)->name, __UT_NAMESIZE); } static int bud_comp_login(void *o1, void *o2){ bud_utrec_t *b1=(bud_utrec_t*)o1, *b2=(bud_utrec_t*)o2; return strncmp(b1->u->ut_line, b2->u->ut_line, __UT_LINESIZE); } htable_t *bud_init_budtable(void){ return ht_init(BUDDY_HT_SIZE, bud_hash_buddy, bud_comp_buddy); } int bud_load(const char *fn, htable_t *ht){ char *line_buf=NULL; int line_buf_size=4, buf_offset=0, len=0; buddy_t *next_buddy=NULL; wuzzah_config_t *bconf=NULL; FILE *buds=NULL; // initialize the hashtable of buddies if (g_config.noloadfile) return 0; else if(strcmp(fn, "-")==0) buds=stdin; else buds=fopen(fn, "r"); if(!buds){ fprintf(stderr, "unable to open %s! (%s)\n", fn, strerror(errno)); next_buddy=bud_create_buddy(g_config.whoami); fprintf(stderr, "defaulting to just watching yourself...\n"); ht_insert(next_buddy, ht); return 0; } line_buf=(char*)malloc(sizeof(char)*line_buf_size); while(!feof(buds)){ // first make sure we get a whole line if(!fgets(line_buf+buf_offset, line_buf_size-len, buds))break; len=strlen(line_buf); if(strcspn(line_buf, "\n") == len && !feof(buds)){ buf_offset=len; line_buf_size *= 2; line_buf=(char*)realloc(line_buf, line_buf_size); continue; } next_buddy=bud_create_buddy(line_buf); if(ht_find(next_buddy, ht)){ fprintf(stderr, "%s: warning: duplicate buddy %s\n", g_config.progname, next_buddy->name); } else ht_insert(next_buddy, ht); // reset some variables len=buf_offset=0; bconf=NULL; } return 0; } void bud_load_every_user(htable_t *ht){ struct passwd *pw=NULL; buddy_t *next_buddy=NULL; setpwent(); pw=getpwent(); while(pw){ next_buddy=bud_create_buddy(pw->pw_name); ht_insert(next_buddy, ht); pw=getpwent(); } endpwent(); } // what's going on: // // - for each buddy in ht // - for each bud_utrec_t in buddy's login ht // - set the 'verify' field to logged out // // - initialize the utmpx records // - for each record in utmpx // - if it's a USER_PROCESS // - if ut_user is in buddy ht // - if buddy's login ht already has ut_line // - set verify field to logged in // - else (they've logged in) // - add the record, with verify=logged in // // - for each buddy in ht // - for each bud_utrec_t in buddy's login ht // - if verify == logged out (they've logged out) // - remove from login ht // // void bud_chk_utmpx(htable_t *buddy_table, short write_users){ ht_list_t *budlist_root,*budlist, *utlist_root,*utlist; STRUCT_UTMPX *u; // below are for quick lookups in the respective ht's // (all i need to do is fill in the fields that are used // for the hash and comp functions) buddy_t *budptr=NULL, tmpbud; bud_utrec_t *recptr=NULL, tmprec; budlist_root=ht_iter(buddy_table); budlist=budlist_root; while(budlist){ utlist_root=ht_iter(((buddy_t*)budlist->info)->logins); utlist=utlist_root; while(utlist){ ((bud_utrec_t*)utlist->info)->verified=B_LOGGED_OUT; utlist=utlist->lptr; } ht_free_iter(utlist_root); budlist=budlist->lptr; } ht_free_iter(budlist_root); SETUTXENT(); u=GETUTXENT(); while(u){ if(IS_USER_PROCESS(u)){ tmpbud.name=u->ut_user; budptr=ht_find(&tmpbud, buddy_table); if(budptr){ tmprec.u=u; recptr=NULL; recptr=ht_find(&tmprec, budptr->logins); if(recptr){ recptr->verified=B_UNCHANGED; } else { recptr=MSTRUCT(bud_utrec_t); recptr->u=MSTRUCT(STRUCT_UTMPX); memcpy(recptr->u, u, sizeof(STRUCT_UTMPX)); recptr->verified=B_LOGGED_IN; ht_insert(recptr, budptr->logins); } } } u=GETUTXENT(); } ENDUTXENT(); budlist_root=ht_iter(buddy_table); budlist=budlist_root; while(budlist){ budptr=(buddy_t*)budlist->info; utlist_root=ht_iter(budptr->logins); utlist=utlist_root; while(utlist){ recptr=(bud_utrec_t*)utlist->info; event(budptr, recptr, write_users); if(recptr->verified==B_LOGGED_OUT) ht_remove(recptr, budptr->logins); utlist=utlist->lptr; } ht_free_iter(utlist_root); budlist=budlist->lptr; } ht_free_iter(budlist_root); return; } char* bud_expand_fmt(const bud_utrec_t *bud, const char *fmt_string){ int buf_fd[2], buf_size=0, amt=0, i, h_len=0; char *hname=NULL, *out_str=NULL; time_t tp; struct tm *tm_p; FILE *buf; struct hostent *hent; struct in_addr in; if(!bud || !fmt_string) return NULL; if(pipe(buf_fd)!=0){ perror("unable to alloc pipe in bud_expand_fmt"); return NULL; } buf=fdopen(buf_fd[1], "w"); if(!buf){ perror("unable to attach file ptr in bud_expand_fmt"); return NULL; } tp=time(NULL); tm_p=localtime(&tp); for(i=0;iu->ut_user); break; case 'd': amt=fprintf(buf, "%02d:%02d:%02d", tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec); break; case 'h': h_len=UTMPX_HOSTLEN(bud->u); if(h_len == 0){ amt=fprintf(buf, "localhost"); } else { hname=(char*)malloc(sizeof(char*)*(h_len+1)); memcpy(hname, UTMPX_HOSTNAME(bud->u), h_len); hname[h_len] = '\0'; amt=fprintf(buf, "%s", hname); free(hname); } break; case 'H': h_len=UTMPX_HOSTLEN(bud->u); if(h_len == 0){ amt=fprintf(buf, "127.0.0.1"); } else { hname=(char*)malloc(sizeof(char*)*(h_len+1)); memcpy(hname, UTMPX_HOSTNAME(bud->u), h_len); hname[h_len] = '\0'; hent=gethostbyname(hname); if(!hent) amt=fprintf(buf, "n/a"); else { memcpy(&in, hent->h_addr_list[0], sizeof(struct in_addr)); hname=inet_ntoa(in); amt=fprintf(buf, "%s", hname); } free(hname); } break; case 'l': amt=fprintf(buf, "%-8s", bud->u->ut_line); break; case 'm': if(g_config.write_users) amt=fprintf(buf, "messaging"); else amt=fprintf(buf, "not messaging"); break; case 'n': amt=fprintf(buf, "\n"); break; case 'o': if(bud->verified==B_LOGGED_IN) amt=fprintf(buf, "logged on "); else if(bud->verified==B_LOGGED_OUT) amt=fprintf(buf, "logged off"); else amt=fprintf(buf, "bummin'"); break; case 'u': amt=fprintf(buf, "%s", g_config.whoami); break; default: amt=fprintf(buf, "%c", fmt_string[i]); break; } } if(amt>0) buf_size+=amt; else if(amt==-1) perror("error writing to pipe"); } if(!g_config.no_newline) { amt=fprintf(buf, "\n"); if(amt>0) buf_size+=amt; else if(amt==-1) perror("error writing to pipe"); } if(fclose(buf)!=0) perror("error closing pipe"); out_str=(char*)malloc(sizeof(char)*(buf_size+2)); amt=read(buf_fd[0], out_str, sizeof(char)*(buf_size)); out_str[amt]='\0'; if(close(buf_fd[0])!=0) perror("error closing pipe"); return out_str; } int argvify(int *cmd_argc, char **cmd_argv[], const char *cmdline){ int i=0, num_args=1, cmd_len=strlen(cmdline); char **argv=NULL, *next_arg=NULL, *cmd_copy=strdup(cmdline); if(strtok(cmd_copy, " \t\n")) num_args++; else { fprintf(stderr, "argvify: unable to parse string!\n"); return -1; } while(strtok(NULL, " \t\n")) num_args++; argv=(char **)malloc(sizeof(char*)*(num_args+1)); if(!argv) { perror("argvify"); return -1; } else memset(argv, 0, sizeof(char*)*(num_args+1)); argv[0]=strdup(g_config.progname); next_arg=cmd_copy; for(i=1; iname=strdup(line_buf); next_buddy->conf=bconf; next_buddy->logins=ht_init(BUDDY_HT_SIZE, bud_hash_login, bud_comp_login); free(line_buf); return next_buddy; }