137660Sbostic /* 237660Sbostic * Copyright (c) 1989 The Regents of the University of California. 337660Sbostic * All rights reserved. 437660Sbostic * 540027Sbostic * This code is derived from software contributed to Berkeley by 640027Sbostic * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. 740027Sbostic * 8*42731Sbostic * %sccs.include.redist.c% 937660Sbostic */ 1037660Sbostic 1137660Sbostic #ifndef lint 12*42731Sbostic static char sccsid[] = "@(#)util.c 5.12 (Berkeley) 06/01/90"; 1337660Sbostic #endif /* not lint */ 1437660Sbostic 1537660Sbostic #include <sys/param.h> 1637660Sbostic #include <sys/stat.h> 1737660Sbostic #include <sys/file.h> 1837660Sbostic #include <stdio.h> 1937660Sbostic #include <ctype.h> 2042053Sbostic #include <string.h> 2137660Sbostic #include "finger.h" 2237660Sbostic #include "pathnames.h" 2337660Sbostic 2437664Sedward find_idle_and_ttywrite(w) 2537664Sedward register WHERE *w; 2637660Sbostic { 2737660Sbostic extern time_t now; 2837660Sbostic extern int errno; 2937660Sbostic struct stat sb; 3037660Sbostic char *strerror(); 3137660Sbostic 3237664Sedward (void)sprintf(tbuf, "%s/%s", _PATH_DEV, w->tty); 3337660Sbostic if (stat(tbuf, &sb) < 0) { 3437660Sbostic (void)fprintf(stderr, 3537660Sbostic "finger: %s: %s\n", tbuf, strerror(errno)); 3637660Sbostic exit(1); 3737660Sbostic } 3837664Sedward w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime; 3937660Sbostic 4037660Sbostic #define TALKABLE 0220 /* tty is writable if 220 mode */ 4137664Sedward w->writable = ((sb.st_mode & TALKABLE) == TALKABLE); 4237660Sbostic } 4337660Sbostic 4437660Sbostic userinfo(pn, pw) 4537660Sbostic register PERSON *pn; 4637660Sbostic register struct passwd *pw; 4737660Sbostic { 4837660Sbostic register char *p, *t; 4941568Smarc char *bp, name[1024]; 5037660Sbostic 5137660Sbostic pn->realname = pn->office = pn->officephone = pn->homephone = NULL; 5237660Sbostic 5337660Sbostic pn->uid = pw->pw_uid; 5437660Sbostic pn->name = strdup(pw->pw_name); 5537660Sbostic pn->dir = strdup(pw->pw_dir); 5637660Sbostic pn->shell = strdup(pw->pw_shell); 5737660Sbostic 5837660Sbostic /* why do we skip asterisks!?!? */ 5941553Smarc (void)strcpy(bp = tbuf, pw->pw_gecos); 6041553Smarc if (*bp == '*') 6141553Smarc ++bp; 6237660Sbostic 6337660Sbostic /* ampersands get replaced by the login name */ 6441553Smarc if (!(p = strsep(&bp, ","))) 6537660Sbostic return; 6637660Sbostic for (t = name; *t = *p; ++p) 6737660Sbostic if (*t == '&') { 6837660Sbostic (void)strcpy(t, pw->pw_name); 6937660Sbostic if (islower(*t)) 7037660Sbostic *t = toupper(*t); 7137660Sbostic while (*++t); 7237660Sbostic } 7337660Sbostic else 7437660Sbostic ++t; 7537660Sbostic pn->realname = strdup(name); 7641553Smarc pn->office = ((p = strsep(&bp, ",")) && *p) ? 7738600Sbostic strdup(p) : NULL; 7841553Smarc pn->officephone = ((p = strsep(&bp, ",")) && *p) ? 7938600Sbostic strdup(p) : NULL; 8041553Smarc pn->homephone = ((p = strsep(&bp, ",")) && *p) ? 8138600Sbostic strdup(p) : NULL; 8237660Sbostic } 8337660Sbostic 8437660Sbostic match(pw, user) 8537660Sbostic struct passwd *pw; 8637660Sbostic char *user; 8737660Sbostic { 8837660Sbostic register char *p, *t; 8941568Smarc char name[1024]; 9037660Sbostic 9137660Sbostic /* why do we skip asterisks!?!? */ 9237660Sbostic (void)strcpy(p = tbuf, pw->pw_gecos); 9337660Sbostic if (*p == '*') 9437660Sbostic ++p; 9537660Sbostic 9637660Sbostic /* ampersands get replaced by the login name */ 9737660Sbostic if (!(p = strtok(p, ","))) 9837660Sbostic return(0); 9937660Sbostic for (t = name; *t = *p; ++p) 10037660Sbostic if (*t == '&') { 10137660Sbostic (void)strcpy(t, pw->pw_name); 10237660Sbostic while (*++t); 10337660Sbostic } 10437660Sbostic else 10537660Sbostic ++t; 10637660Sbostic for (t = name; p = strtok(t, "\t "); t = (char *)NULL) 10737660Sbostic if (!strcasecmp(p, user)) 10837660Sbostic return(1); 10937660Sbostic return(0); 11037660Sbostic } 11137660Sbostic 11237664Sedward enter_lastlog(pn) 11337660Sbostic register PERSON *pn; 11437660Sbostic { 11537664Sedward register WHERE *w; 11637683Sedward static int opened, fd; 11737660Sbostic struct lastlog ll; 11837664Sedward char doit = 0; 11937660Sbostic off_t lseek(); 12037660Sbostic 12137665Sbostic /* some systems may not maintain lastlog, don't report errors. */ 12237665Sbostic if (!opened) { 12337664Sedward fd = open(_PATH_LASTLOG, O_RDONLY, 0); 12437665Sbostic opened = 1; 12537660Sbostic } 12637665Sbostic if (fd == -1 || 12737665Sbostic lseek(fd, (long)pn->uid * sizeof(ll), L_SET) != 12837665Sbostic (long)pn->uid * sizeof(ll) || 12937665Sbostic read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) { 13037665Sbostic /* as if never logged in */ 13137665Sbostic ll.ll_line[0] = ll.ll_host[0] = NULL; 13237665Sbostic ll.ll_time = 0; 13337665Sbostic } 13437664Sedward if ((w = pn->whead) == NULL) 13537664Sedward doit = 1; 13637683Sedward else if (ll.ll_time != 0) { 13737664Sedward /* if last login is earlier than some current login */ 13837664Sedward for (; !doit && w != NULL; w = w->next) 13937664Sedward if (w->info == LOGGEDIN && w->loginat < ll.ll_time) 14037664Sedward doit = 1; 14137664Sedward /* 14237664Sedward * and if it's not any of the current logins 14337664Sedward * can't use time comparison because there may be a small 14437664Sedward * discrepency since login calls time() twice 14537664Sedward */ 14637664Sedward for (w = pn->whead; doit && w != NULL; w = w->next) 14737664Sedward if (w->info == LOGGEDIN && 14837664Sedward strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0) 14937664Sedward doit = 0; 15037660Sbostic } 15137664Sedward if (doit) { 15237664Sedward w = walloc(pn); 15337664Sedward w->info = LASTLOG; 15437664Sedward bcopy(ll.ll_line, w->tty, UT_LINESIZE); 15537664Sedward w->tty[UT_LINESIZE] = 0; 15637664Sedward bcopy(ll.ll_host, w->host, UT_HOSTSIZE); 15737664Sedward w->host[UT_HOSTSIZE] = 0; 15837664Sedward w->loginat = ll.ll_time; 15937664Sedward } 16037660Sbostic } 16137660Sbostic 16237664Sedward enter_where(ut, pn) 16337660Sbostic struct utmp *ut; 16437660Sbostic PERSON *pn; 16537660Sbostic { 16637664Sedward register WHERE *w = walloc(pn); 16737664Sedward 16837664Sedward w->info = LOGGEDIN; 16937664Sedward bcopy(ut->ut_line, w->tty, UT_LINESIZE); 17037664Sedward w->tty[UT_LINESIZE] = 0; 17137664Sedward bcopy(ut->ut_host, w->host, UT_HOSTSIZE); 17237664Sedward w->host[UT_HOSTSIZE] = 0; 17337664Sedward w->loginat = (time_t)ut->ut_time; 17437664Sedward find_idle_and_ttywrite(w); 17537660Sbostic } 17637664Sedward 17737664Sedward PERSON * 17837664Sedward enter_person(pw) 17937664Sedward register struct passwd *pw; 18037664Sedward { 18137664Sedward register PERSON *pn, **pp; 18237664Sedward 18337664Sedward for (pp = htab + hash(pw->pw_name); 18437664Sedward *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0; 18537664Sedward pp = &(*pp)->hlink) 18637664Sedward ; 18737664Sedward if ((pn = *pp) == NULL) { 18837664Sedward pn = palloc(); 18937664Sedward entries++; 19037664Sedward if (phead == NULL) 19137664Sedward phead = ptail = pn; 19237664Sedward else { 19337664Sedward ptail->next = pn; 19437664Sedward ptail = pn; 19537664Sedward } 19637664Sedward pn->next = NULL; 19737664Sedward pn->hlink = NULL; 19837664Sedward *pp = pn; 19937664Sedward userinfo(pn, pw); 20037664Sedward pn->whead = NULL; 20137664Sedward } 20237664Sedward return(pn); 20337664Sedward } 20437664Sedward 20537664Sedward PERSON * 20637664Sedward find_person(name) 20737664Sedward char *name; 20837664Sedward { 20937664Sedward register PERSON *pn; 21037664Sedward 21137664Sedward /* name may be only UT_NAMESIZE long and not terminated */ 21237664Sedward for (pn = htab[hash(name)]; 21337664Sedward pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0; 21437664Sedward pn = pn->hlink) 21537664Sedward ; 21637664Sedward return(pn); 21737664Sedward } 21837664Sedward 21937664Sedward hash(name) 22037664Sedward register char *name; 22137664Sedward { 22237664Sedward register int h, i; 22337664Sedward 22437664Sedward h = 0; 22537664Sedward /* name may be only UT_NAMESIZE long and not terminated */ 22637664Sedward for (i = UT_NAMESIZE; --i >= 0 && *name;) 22737664Sedward h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK; 22837664Sedward return(h); 22937664Sedward } 23037664Sedward 23137664Sedward PERSON * 23237664Sedward palloc() 23337664Sedward { 23437664Sedward PERSON *p; 23537664Sedward 23637664Sedward if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) { 23737664Sedward (void)fprintf(stderr, "finger: out of space.\n"); 23837664Sedward exit(1); 23937664Sedward } 24037664Sedward return(p); 24137664Sedward } 24237664Sedward 24337664Sedward WHERE * 24437664Sedward walloc(pn) 24537664Sedward register PERSON *pn; 24637664Sedward { 24737664Sedward register WHERE *w; 24837664Sedward 24937664Sedward if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) { 25037664Sedward (void)fprintf(stderr, "finger: out of space.\n"); 25137664Sedward exit(1); 25237664Sedward } 25337664Sedward if (pn->whead == NULL) 25437664Sedward pn->whead = pn->wtail = w; 25537664Sedward else { 25637664Sedward pn->wtail->next = w; 25737664Sedward pn->wtail = w; 25837664Sedward } 25937664Sedward w->next = NULL; 26037664Sedward return(w); 26137664Sedward } 26238052Sbostic 26338052Sbostic char * 26438052Sbostic prphone(num) 26538052Sbostic char *num; 26638052Sbostic { 26738052Sbostic register char *p; 26838052Sbostic int len; 26938052Sbostic static char pbuf[15]; 27038052Sbostic 27138052Sbostic /* don't touch anything if the user has their own formatting */ 27238052Sbostic for (p = num; *p; ++p) 27338052Sbostic if (!isdigit(*p)) 27438052Sbostic return(num); 27538052Sbostic len = p - num; 27638052Sbostic p = pbuf; 27738052Sbostic switch(len) { 27838052Sbostic case 11: /* +0-123-456-7890 */ 27938052Sbostic *p++ = '+'; 28038052Sbostic *p++ = *num++; 28138052Sbostic *p++ = '-'; 28238052Sbostic /* FALLTHROUGH */ 28338052Sbostic case 10: /* 012-345-6789 */ 28438052Sbostic *p++ = *num++; 28538052Sbostic *p++ = *num++; 28638052Sbostic *p++ = *num++; 28738052Sbostic *p++ = '-'; 28838052Sbostic /* FALLTHROUGH */ 28938052Sbostic case 7: /* 012-3456 */ 29038052Sbostic *p++ = *num++; 29138052Sbostic *p++ = *num++; 29238052Sbostic *p++ = *num++; 29338052Sbostic break; 29438052Sbostic case 5: /* x0-1234 */ 29538052Sbostic *p++ = 'x'; 29638052Sbostic *p++ = *num++; 29738052Sbostic break; 29838052Sbostic default: 29938052Sbostic return(num); 30038052Sbostic } 30138052Sbostic *p++ = '-'; 30238052Sbostic *p++ = *num++; 30338052Sbostic *p++ = *num++; 30438052Sbostic *p++ = *num++; 30538052Sbostic *p++ = *num++; 30638052Sbostic *p = '\0'; 30738052Sbostic return(pbuf); 30838052Sbostic } 309