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 * 837660Sbostic * Redistribution and use in source and binary forms are permitted 937660Sbostic * provided that the above copyright notice and this paragraph are 1037660Sbostic * duplicated in all such forms and that any documentation, 1137660Sbostic * advertising materials, and other materials related to such 1237660Sbostic * distribution and use acknowledge that the software was developed 1337660Sbostic * by the University of California, Berkeley. The name of the 1437660Sbostic * University may not be used to endorse or promote products derived 1537660Sbostic * from this software without specific prior written permission. 1637660Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1737660Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1837660Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1937660Sbostic */ 2037660Sbostic 2137660Sbostic #ifndef lint 22*41553Smarc static char sccsid[] = "@(#)util.c 5.9 (Berkeley) 05/10/90"; 2337660Sbostic #endif /* not lint */ 2437660Sbostic 2537660Sbostic #include <sys/param.h> 2637660Sbostic #include <sys/stat.h> 2737660Sbostic #include <sys/file.h> 2837660Sbostic #include <stdio.h> 2937660Sbostic #include <ctype.h> 3037660Sbostic #include <strings.h> 3137660Sbostic #include "finger.h" 3237660Sbostic #include "pathnames.h" 3337660Sbostic 3437664Sedward find_idle_and_ttywrite(w) 3537664Sedward register WHERE *w; 3637660Sbostic { 3737660Sbostic extern time_t now; 3837660Sbostic extern int errno; 3937660Sbostic struct stat sb; 4037660Sbostic char *strerror(); 4137660Sbostic 4237664Sedward (void)sprintf(tbuf, "%s/%s", _PATH_DEV, w->tty); 4337660Sbostic if (stat(tbuf, &sb) < 0) { 4437660Sbostic (void)fprintf(stderr, 4537660Sbostic "finger: %s: %s\n", tbuf, strerror(errno)); 4637660Sbostic exit(1); 4737660Sbostic } 4837664Sedward w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime; 4937660Sbostic 5037660Sbostic #define TALKABLE 0220 /* tty is writable if 220 mode */ 5137664Sedward w->writable = ((sb.st_mode & TALKABLE) == TALKABLE); 5237660Sbostic } 5337660Sbostic 5437660Sbostic userinfo(pn, pw) 5537660Sbostic register PERSON *pn; 5637660Sbostic register struct passwd *pw; 5737660Sbostic { 5837660Sbostic register char *p, *t; 59*41553Smarc char *bp, name[256]; 6037660Sbostic 6137660Sbostic pn->realname = pn->office = pn->officephone = pn->homephone = NULL; 6237660Sbostic 6337660Sbostic pn->uid = pw->pw_uid; 6437660Sbostic pn->name = strdup(pw->pw_name); 6537660Sbostic pn->dir = strdup(pw->pw_dir); 6637660Sbostic pn->shell = strdup(pw->pw_shell); 6737660Sbostic 6837660Sbostic /* why do we skip asterisks!?!? */ 69*41553Smarc (void)strcpy(bp = tbuf, pw->pw_gecos); 70*41553Smarc if (*bp == '*') 71*41553Smarc ++bp; 7237660Sbostic 7337660Sbostic /* ampersands get replaced by the login name */ 74*41553Smarc if (!(p = strsep(&bp, ","))) 7537660Sbostic return; 7637660Sbostic for (t = name; *t = *p; ++p) 7737660Sbostic if (*t == '&') { 7837660Sbostic (void)strcpy(t, pw->pw_name); 7937660Sbostic if (islower(*t)) 8037660Sbostic *t = toupper(*t); 8137660Sbostic while (*++t); 8237660Sbostic } 8337660Sbostic else 8437660Sbostic ++t; 8537660Sbostic pn->realname = strdup(name); 86*41553Smarc pn->office = ((p = strsep(&bp, ",")) && *p) ? 8738600Sbostic strdup(p) : NULL; 88*41553Smarc pn->officephone = ((p = strsep(&bp, ",")) && *p) ? 8938600Sbostic strdup(p) : NULL; 90*41553Smarc pn->homephone = ((p = strsep(&bp, ",")) && *p) ? 9138600Sbostic strdup(p) : NULL; 9237660Sbostic } 9337660Sbostic 9437660Sbostic match(pw, user) 9537660Sbostic struct passwd *pw; 9637660Sbostic char *user; 9737660Sbostic { 9837660Sbostic register char *p, *t; 9937660Sbostic char name[256]; 10037660Sbostic 10137660Sbostic /* why do we skip asterisks!?!? */ 10237660Sbostic (void)strcpy(p = tbuf, pw->pw_gecos); 10337660Sbostic if (*p == '*') 10437660Sbostic ++p; 10537660Sbostic 10637660Sbostic /* ampersands get replaced by the login name */ 10737660Sbostic if (!(p = strtok(p, ","))) 10837660Sbostic return(0); 10937660Sbostic for (t = name; *t = *p; ++p) 11037660Sbostic if (*t == '&') { 11137660Sbostic (void)strcpy(t, pw->pw_name); 11237660Sbostic while (*++t); 11337660Sbostic } 11437660Sbostic else 11537660Sbostic ++t; 11637660Sbostic for (t = name; p = strtok(t, "\t "); t = (char *)NULL) 11737660Sbostic if (!strcasecmp(p, user)) 11837660Sbostic return(1); 11937660Sbostic return(0); 12037660Sbostic } 12137660Sbostic 12237664Sedward enter_lastlog(pn) 12337660Sbostic register PERSON *pn; 12437660Sbostic { 12537664Sedward register WHERE *w; 12637683Sedward static int opened, fd; 12737660Sbostic struct lastlog ll; 12837664Sedward char doit = 0; 12937660Sbostic off_t lseek(); 13037660Sbostic 13137665Sbostic /* some systems may not maintain lastlog, don't report errors. */ 13237665Sbostic if (!opened) { 13337664Sedward fd = open(_PATH_LASTLOG, O_RDONLY, 0); 13437665Sbostic opened = 1; 13537660Sbostic } 13637665Sbostic if (fd == -1 || 13737665Sbostic lseek(fd, (long)pn->uid * sizeof(ll), L_SET) != 13837665Sbostic (long)pn->uid * sizeof(ll) || 13937665Sbostic read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) { 14037665Sbostic /* as if never logged in */ 14137665Sbostic ll.ll_line[0] = ll.ll_host[0] = NULL; 14237665Sbostic ll.ll_time = 0; 14337665Sbostic } 14437664Sedward if ((w = pn->whead) == NULL) 14537664Sedward doit = 1; 14637683Sedward else if (ll.ll_time != 0) { 14737664Sedward /* if last login is earlier than some current login */ 14837664Sedward for (; !doit && w != NULL; w = w->next) 14937664Sedward if (w->info == LOGGEDIN && w->loginat < ll.ll_time) 15037664Sedward doit = 1; 15137664Sedward /* 15237664Sedward * and if it's not any of the current logins 15337664Sedward * can't use time comparison because there may be a small 15437664Sedward * discrepency since login calls time() twice 15537664Sedward */ 15637664Sedward for (w = pn->whead; doit && w != NULL; w = w->next) 15737664Sedward if (w->info == LOGGEDIN && 15837664Sedward strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0) 15937664Sedward doit = 0; 16037660Sbostic } 16137664Sedward if (doit) { 16237664Sedward w = walloc(pn); 16337664Sedward w->info = LASTLOG; 16437664Sedward bcopy(ll.ll_line, w->tty, UT_LINESIZE); 16537664Sedward w->tty[UT_LINESIZE] = 0; 16637664Sedward bcopy(ll.ll_host, w->host, UT_HOSTSIZE); 16737664Sedward w->host[UT_HOSTSIZE] = 0; 16837664Sedward w->loginat = ll.ll_time; 16937664Sedward } 17037660Sbostic } 17137660Sbostic 17237664Sedward enter_where(ut, pn) 17337660Sbostic struct utmp *ut; 17437660Sbostic PERSON *pn; 17537660Sbostic { 17637664Sedward register WHERE *w = walloc(pn); 17737664Sedward 17837664Sedward w->info = LOGGEDIN; 17937664Sedward bcopy(ut->ut_line, w->tty, UT_LINESIZE); 18037664Sedward w->tty[UT_LINESIZE] = 0; 18137664Sedward bcopy(ut->ut_host, w->host, UT_HOSTSIZE); 18237664Sedward w->host[UT_HOSTSIZE] = 0; 18337664Sedward w->loginat = (time_t)ut->ut_time; 18437664Sedward find_idle_and_ttywrite(w); 18537660Sbostic } 18637664Sedward 18737664Sedward PERSON * 18837664Sedward enter_person(pw) 18937664Sedward register struct passwd *pw; 19037664Sedward { 19137664Sedward register PERSON *pn, **pp; 19237664Sedward 19337664Sedward for (pp = htab + hash(pw->pw_name); 19437664Sedward *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0; 19537664Sedward pp = &(*pp)->hlink) 19637664Sedward ; 19737664Sedward if ((pn = *pp) == NULL) { 19837664Sedward pn = palloc(); 19937664Sedward entries++; 20037664Sedward if (phead == NULL) 20137664Sedward phead = ptail = pn; 20237664Sedward else { 20337664Sedward ptail->next = pn; 20437664Sedward ptail = pn; 20537664Sedward } 20637664Sedward pn->next = NULL; 20737664Sedward pn->hlink = NULL; 20837664Sedward *pp = pn; 20937664Sedward userinfo(pn, pw); 21037664Sedward pn->whead = NULL; 21137664Sedward } 21237664Sedward return(pn); 21337664Sedward } 21437664Sedward 21537664Sedward PERSON * 21637664Sedward find_person(name) 21737664Sedward char *name; 21837664Sedward { 21937664Sedward register PERSON *pn; 22037664Sedward 22137664Sedward /* name may be only UT_NAMESIZE long and not terminated */ 22237664Sedward for (pn = htab[hash(name)]; 22337664Sedward pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0; 22437664Sedward pn = pn->hlink) 22537664Sedward ; 22637664Sedward return(pn); 22737664Sedward } 22837664Sedward 22937664Sedward hash(name) 23037664Sedward register char *name; 23137664Sedward { 23237664Sedward register int h, i; 23337664Sedward 23437664Sedward h = 0; 23537664Sedward /* name may be only UT_NAMESIZE long and not terminated */ 23637664Sedward for (i = UT_NAMESIZE; --i >= 0 && *name;) 23737664Sedward h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK; 23837664Sedward return(h); 23937664Sedward } 24037664Sedward 24137664Sedward PERSON * 24237664Sedward palloc() 24337664Sedward { 24437664Sedward PERSON *p; 24537664Sedward 24637664Sedward if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) { 24737664Sedward (void)fprintf(stderr, "finger: out of space.\n"); 24837664Sedward exit(1); 24937664Sedward } 25037664Sedward return(p); 25137664Sedward } 25237664Sedward 25337664Sedward WHERE * 25437664Sedward walloc(pn) 25537664Sedward register PERSON *pn; 25637664Sedward { 25737664Sedward register WHERE *w; 25837664Sedward 25937664Sedward if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) { 26037664Sedward (void)fprintf(stderr, "finger: out of space.\n"); 26137664Sedward exit(1); 26237664Sedward } 26337664Sedward if (pn->whead == NULL) 26437664Sedward pn->whead = pn->wtail = w; 26537664Sedward else { 26637664Sedward pn->wtail->next = w; 26737664Sedward pn->wtail = w; 26837664Sedward } 26937664Sedward w->next = NULL; 27037664Sedward return(w); 27137664Sedward } 27238052Sbostic 27338052Sbostic char * 27438052Sbostic prphone(num) 27538052Sbostic char *num; 27638052Sbostic { 27738052Sbostic register char *p; 27838052Sbostic int len; 27938052Sbostic static char pbuf[15]; 28038052Sbostic 28138052Sbostic /* don't touch anything if the user has their own formatting */ 28238052Sbostic for (p = num; *p; ++p) 28338052Sbostic if (!isdigit(*p)) 28438052Sbostic return(num); 28538052Sbostic len = p - num; 28638052Sbostic p = pbuf; 28738052Sbostic switch(len) { 28838052Sbostic case 11: /* +0-123-456-7890 */ 28938052Sbostic *p++ = '+'; 29038052Sbostic *p++ = *num++; 29138052Sbostic *p++ = '-'; 29238052Sbostic /* FALLTHROUGH */ 29338052Sbostic case 10: /* 012-345-6789 */ 29438052Sbostic *p++ = *num++; 29538052Sbostic *p++ = *num++; 29638052Sbostic *p++ = *num++; 29738052Sbostic *p++ = '-'; 29838052Sbostic /* FALLTHROUGH */ 29938052Sbostic case 7: /* 012-3456 */ 30038052Sbostic *p++ = *num++; 30138052Sbostic *p++ = *num++; 30238052Sbostic *p++ = *num++; 30338052Sbostic break; 30438052Sbostic case 5: /* x0-1234 */ 30538052Sbostic *p++ = 'x'; 30638052Sbostic *p++ = *num++; 30738052Sbostic break; 30838052Sbostic default: 30938052Sbostic return(num); 31038052Sbostic } 31138052Sbostic *p++ = '-'; 31238052Sbostic *p++ = *num++; 31338052Sbostic *p++ = *num++; 31438052Sbostic *p++ = *num++; 31538052Sbostic *p++ = *num++; 31638052Sbostic *p = '\0'; 31738052Sbostic return(pbuf); 31838052Sbostic } 319