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