/* See the file wizshell.c, wizshell.h or the files in docs/ for information */ #include <time.h> #include <signal.h> #include "wizshell.h" /* to make a new one */ #define MK_WLIST(wlist) {if((wlist=(who_t *) MALLOC(sizeof(who_t)))==NULL) \ FATAL("Could not allocate memory for who list") \ wlist->next=NULL;} /* inserts line in utmp of the form: "pid:tty:who:real name:access:login@" */ /* also, inserts line in wtmp of the form: "who:access:ip:login@" */ /* can't do ip_number yet.. */ /* Assumes that there are no ":" in any of these fields */ /* Assumes that if there is no $NETHOST then it must be localhost */ void add_uwtmp() { pid_t p; time_t t; FILE *fp; char *ip; struct stat status; int size,removed=0; p=getpid(); time(&t); if(!(fp=fopen(UTMP_FILE,"a"))) { fprintf(stderr,"Could not open utmp file: %s\n",UTMP_FILE); fprintf(stderr,"Not adding to 'who' list.\n"); } else { fprintf(fp,"%d:%s:%s:%s:%s:%d:%d\n", p,ttyname(0),envir.login,envir.access,envir.real_name,t,envir.mesg); fclose(fp); } if(!stat(WTMP_FILE,&status)) size=status.st_size; else size=0; if(size>(MAX_WTMP_SIZE*1024)) { removed=1; unlink(WTMP_FILE); } if(!(fp=fopen(WTMP_FILE,"a"))) { fprintf(stderr,"Could not open wtmp file: %s\n",WTMP_FILE); fprintf(stderr,"Not adding to 'last' list.\n"); } else { if(removed) fprintf(fp,"old wtmp file removed (over %dKb) on %s\n", MAX_WTMP_SIZE,ctime(&t)); if(!(ip=getenv("NETHOST"))) ip="127.0.0.1"; fprintf(fp,"%-15.15s %-10.10s %-26.26s %s", envir.login,envir.access,ip,ctime(&t)); fclose(fp); } } /*rewrite is used for if we changed our envir.mesg setting and need to save it*/ who_t *read_utmp(rewrite) int rewrite; { FILE *fp; pid_t p; time_t t; char buf[MAX_BUF],*tp; who_t *wlist,*t1,*t2; int changed=rewrite,c; if(!(fp=fopen(UTMP_FILE,"r"))) { MK_WLIST(wlist) return wlist; } rewind(fp); if(rewrite) tp=ttyname(0); /* so we know which is ours */ MK_WLIST(wlist) t1=wlist; while(!feof(fp)) { MK_WLIST(t2) /* process id */ get_field(fp,buf); if(buf[0]) t2->num1=atol(buf); if(!t2->num1) { FREE(t2); continue; } if(kill(t2->num1,0)==-1) { /* fprintf(stderr,"Process: %d doesn't exist anymore\n",t2->num1); */ changed++; while((c=fgetc(fp))!=EOF && c!='\n') ; FREE(t2); continue; } /* ttyname */ get_field(fp,buf); MK_STR(t2->str1,strlen(buf)+1) strcpy(t2->str1,buf); /* login name */ get_field(fp,buf); MK_STR(t2->str2,strlen(buf)+1) strcpy(t2->str2,buf); /* access type */ get_field(fp,buf); MK_STR(t2->str3,strlen(buf)+1) strcpy(t2->str3,buf); /* real name */ get_field(fp,buf); MK_STR(t2->str4,strlen(buf)+1) strcpy(t2->str4,buf); /* login time */ get_field(fp,buf); if(buf[0]) t2->num2=atol(buf); /* mesg setting */ get_field(fp,buf); if(buf[0]) t2->num3=atol(buf); if(rewrite && !strcmp(t2->str1,tp)) /* if rewrite and this is ours */ t2->num3=envir.mesg; t1->next=t2; t1=t2; } fclose(fp); /* This could cause a problem if someone calls add_uwtmp between * the reading of the utmp file and this write to utmp -oh well * maybe I'll make a lockfile for it later -- semaphores are difficult * (the worst case is that someone will be logged in without being in 'who') */ if(changed) write_utmp(wlist); return wlist; } #ifdef MAX_USERS int count_users(who) who_t *who; { int i; i=0; who=read_utmp(0); who=who->next; while(who && who->num1) { i++; who=who->next; } return i; } #endif void write_utmp(who) who_t *who; { FILE *fp; who_t *t; if(!(fp=fopen(UTMP_FILE,"w"))) { fprintf(stderr,"Couldn't find utmp file: %s\n",UTMP_FILE); return; } rewind(fp); t=who->next; while(t && t->num1) { fprintf(fp,"%d:%s:%s:%s:%s:%d:%d\n", t->num1,t->str1,t->str2,t->str3,t->str4,t->num2,t->num3); t=t->next; } fclose(fp); } /* How long before we actually print the idle time (seconds) */ #define IDLE 30 /* returns 'who' so you can free_who(print_utmp(read_utmp())) ;-) */ who_t *print_utmp(who,args) who_t *who; char *args; /* currently ignored */ { who_t *t; int i=0; struct stat status; time_t now; int idle; time(&now); t=who->next; fprintf(stdout, "login tty acc real name mesg idle\n"); while(t && t->num1) { i++; fprintf(stdout, "%-13.13s %-10.10s %-6.6s %-23.23s %c", t->str2,t->str1+5,t->str3,t->str4,(t->num3?'y':'n'), ctime((time_t *) &(t->num2)) ); /* not used by format string */ if(stat(t->str1,&status)==-1) { fprintf(stdout," error "); } else { idle=now-status.st_atime; if(!stat(t->str1,&status)) idle=now-status.st_atime; else idle=0; if(idle<IDLE) idle=0; if(idle>60*60) { fprintf(stdout,"%2dh",idle/(60*60)); idle=idle%(60*60); } else fprintf(stdout," "); if(idle>60) { fprintf(stdout,"%2dm",idle/60); idle=idle%60; } else fprintf(stdout," "); if(idle>0) fprintf(stdout,"%2ds",idle); else fprintf(stdout," "); fprintf(stdout,"\n"); } t=t->next; } fprintf(stdout,"Number of users: %d\n",i); return who; } void free_who(who) who_t *who; { who_t *t; while(who) { t=who->next; FREE(who->str1); FREE(who->str2); FREE(who->str3); FREE(who); who=t; } }