17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*06e1a714Sraf * Common Development and Distribution License (the "License"). 6*06e1a714Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*06e1a714Sraf 227c478bd9Sstevel@tonic-gate /* 23*06e1a714Sraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * Copyright (c) 1982, 1986, 1988 327c478bd9Sstevel@tonic-gate * The Regents of the University of California 337c478bd9Sstevel@tonic-gate * All Rights Reserved 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * Portions of this document are derived from 367c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 377c478bd9Sstevel@tonic-gate * contributors. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate * This is a finger program. It prints out useful information about users 447c478bd9Sstevel@tonic-gate * by digging it up from various system files. 457c478bd9Sstevel@tonic-gate * 467c478bd9Sstevel@tonic-gate * There are three output formats, all of which give login name, teletype 477c478bd9Sstevel@tonic-gate * line number, and login time. The short output format is reminiscent 487c478bd9Sstevel@tonic-gate * of finger on ITS, and gives one line of information per user containing 497c478bd9Sstevel@tonic-gate * in addition to the minimum basic requirements (MBR), the user's full name, 507c478bd9Sstevel@tonic-gate * idle time and location. 517c478bd9Sstevel@tonic-gate * The quick style output is UNIX who-like, giving only name, teletype and 527c478bd9Sstevel@tonic-gate * login time. Finally, the long style output give the same information 537c478bd9Sstevel@tonic-gate * as the short (in more legible format), the home directory and shell 547c478bd9Sstevel@tonic-gate * of the user, and, if it exits, a copy of the file .plan in the users 557c478bd9Sstevel@tonic-gate * home directory. Finger may be called with or without a list of people 567c478bd9Sstevel@tonic-gate * to finger -- if no list is given, all the people currently logged in 577c478bd9Sstevel@tonic-gate * are fingered. 587c478bd9Sstevel@tonic-gate * 597c478bd9Sstevel@tonic-gate * The program is validly called by one of the following: 607c478bd9Sstevel@tonic-gate * 617c478bd9Sstevel@tonic-gate * finger {short form list of users} 627c478bd9Sstevel@tonic-gate * finger -l {long form list of users} 637c478bd9Sstevel@tonic-gate * finger -b {briefer long form list of users} 647c478bd9Sstevel@tonic-gate * finger -q {quick list of users} 657c478bd9Sstevel@tonic-gate * finger -i {quick list of users with idle times} 667c478bd9Sstevel@tonic-gate * finger -m {matches arguments against only username} 677c478bd9Sstevel@tonic-gate * finger -f {suppress header in non-long form} 687c478bd9Sstevel@tonic-gate * finger -p {suppress printing of .plan file} 697c478bd9Sstevel@tonic-gate * finger -h {suppress printing of .project file} 707c478bd9Sstevel@tonic-gate * finger -i {forces "idle" output format} 717c478bd9Sstevel@tonic-gate * finger namelist {long format list of specified users} 727c478bd9Sstevel@tonic-gate * finger -s namelist {short format list of specified users} 737c478bd9Sstevel@tonic-gate * finger -w namelist {narrow short format list of specified users} 747c478bd9Sstevel@tonic-gate * 757c478bd9Sstevel@tonic-gate * where 'namelist' is a list of users login names. 767c478bd9Sstevel@tonic-gate * The other options can all be given after one '-', or each can have its 777c478bd9Sstevel@tonic-gate * own '-'. The -f option disables the printing of headers for short and 787c478bd9Sstevel@tonic-gate * quick outputs. The -b option briefens long format outputs. The -p 797c478bd9Sstevel@tonic-gate * option turns off plans for long format outputs. 807c478bd9Sstevel@tonic-gate */ 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate #include <sys/types.h> 837c478bd9Sstevel@tonic-gate #include <sys/stat.h> 847c478bd9Sstevel@tonic-gate #include <utmpx.h> 857c478bd9Sstevel@tonic-gate #include <sys/signal.h> 867c478bd9Sstevel@tonic-gate #include <pwd.h> 877c478bd9Sstevel@tonic-gate #include <stdio.h> 887c478bd9Sstevel@tonic-gate #include <lastlog.h> 897c478bd9Sstevel@tonic-gate #include <ctype.h> 907c478bd9Sstevel@tonic-gate #include <sys/time.h> 917c478bd9Sstevel@tonic-gate #include <time.h> 927c478bd9Sstevel@tonic-gate #include <sys/socket.h> 937c478bd9Sstevel@tonic-gate #include <netinet/in.h> 947c478bd9Sstevel@tonic-gate #include <netdb.h> 957c478bd9Sstevel@tonic-gate #include <locale.h> 967c478bd9Sstevel@tonic-gate #include <sys/select.h> 977c478bd9Sstevel@tonic-gate #include <stdlib.h> 987c478bd9Sstevel@tonic-gate #include <strings.h> 997c478bd9Sstevel@tonic-gate #include <fcntl.h> 1007c478bd9Sstevel@tonic-gate #include <curses.h> 1017c478bd9Sstevel@tonic-gate #include <unctrl.h> 1027c478bd9Sstevel@tonic-gate #include <maillock.h> 1037c478bd9Sstevel@tonic-gate #include <deflt.h> 1047c478bd9Sstevel@tonic-gate #include <unistd.h> 1057c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 1067c478bd9Sstevel@tonic-gate #include <macros.h> 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static char gecos_ignore_c = '*'; /* ignore this in real name */ 1097c478bd9Sstevel@tonic-gate static char gecos_sep_c = ','; /* separator in pw_gecos field */ 1107c478bd9Sstevel@tonic-gate static char gecos_samename = '&'; /* repeat login name in real name */ 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate #define TALKABLE 0220 /* tty is writable if this mode */ 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate #define NMAX sizeof (((struct utmpx *)0)->ut_name) 1157c478bd9Sstevel@tonic-gate #define LMAX sizeof (((struct utmpx *)0)->ut_line) 1167c478bd9Sstevel@tonic-gate #define HMAX sizeof (((struct utmpx *)0)->ut_host) 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate struct person { /* one for each person fingered */ 1197c478bd9Sstevel@tonic-gate char *name; /* name */ 1207c478bd9Sstevel@tonic-gate char tty[LMAX+1]; /* null terminated tty line */ 1217c478bd9Sstevel@tonic-gate char host[HMAX+1]; /* null terminated remote host name */ 1227c478bd9Sstevel@tonic-gate char *ttyloc; /* location of tty line, if any */ 1237c478bd9Sstevel@tonic-gate time_t loginat; /* time of (last) login */ 1247c478bd9Sstevel@tonic-gate time_t idletime; /* how long idle (if logged in) */ 1257c478bd9Sstevel@tonic-gate char *realname; /* pointer to full name */ 1267c478bd9Sstevel@tonic-gate struct passwd *pwd; /* structure of /etc/passwd stuff */ 1277c478bd9Sstevel@tonic-gate char loggedin; /* person is logged in */ 1287c478bd9Sstevel@tonic-gate char writable; /* tty is writable */ 1297c478bd9Sstevel@tonic-gate char original; /* this is not a duplicate entry */ 1307c478bd9Sstevel@tonic-gate struct person *link; /* link to next person */ 1317c478bd9Sstevel@tonic-gate }; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate char LASTLOG[] = "/var/adm/lastlog"; /* last login info */ 1347c478bd9Sstevel@tonic-gate char PLAN[] = "/.plan"; /* what plan file is */ 1357c478bd9Sstevel@tonic-gate char PROJ[] = "/.project"; /* what project file */ 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate int unbrief = 1; /* -b option default */ 1387c478bd9Sstevel@tonic-gate int header = 1; /* -f option default */ 1397c478bd9Sstevel@tonic-gate int hack = 1; /* -h option default */ 1407c478bd9Sstevel@tonic-gate int idle = 0; /* -i option default */ 1417c478bd9Sstevel@tonic-gate int large = 0; /* -l option default */ 1427c478bd9Sstevel@tonic-gate int match = 1; /* -m option default */ 1437c478bd9Sstevel@tonic-gate int plan = 1; /* -p option default */ 1447c478bd9Sstevel@tonic-gate int unquick = 1; /* -q option default */ 1457c478bd9Sstevel@tonic-gate int small = 0; /* -s option default */ 1467c478bd9Sstevel@tonic-gate int wide = 1; /* -w option default */ 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * RFC 1288 says that system administrators should have the option of 1507c478bd9Sstevel@tonic-gate * separately allowing ASCII characters less than 32 or greater than 1517c478bd9Sstevel@tonic-gate * 126. The termpass variable keeps track of this. 1527c478bd9Sstevel@tonic-gate */ 1537c478bd9Sstevel@tonic-gate char defaultfile[] = "/etc/default/finger"; 1547c478bd9Sstevel@tonic-gate char passvar[] = "PASS="; 1557c478bd9Sstevel@tonic-gate int termpass = 0; /* default is ASCII only */ 1567c478bd9Sstevel@tonic-gate char *termopts[] = { 1577c478bd9Sstevel@tonic-gate #define TERM_LOW 0 1587c478bd9Sstevel@tonic-gate "low", 1597c478bd9Sstevel@tonic-gate #define TERM_HIGH 1 1607c478bd9Sstevel@tonic-gate "high", 1617c478bd9Sstevel@tonic-gate (char *)NULL 1627c478bd9Sstevel@tonic-gate }; 1637c478bd9Sstevel@tonic-gate #define TS_LOW (1 << TERM_LOW) /* print characters less than 32 */ 1647c478bd9Sstevel@tonic-gate #define TS_HIGH (1 << TERM_HIGH) /* print characters greater than 126 */ 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate int unshort; 1687c478bd9Sstevel@tonic-gate FILE *lf; /* LASTLOG file pointer */ 1697c478bd9Sstevel@tonic-gate struct person *person1; /* list of people */ 1707c478bd9Sstevel@tonic-gate time_t tloc; /* current time */ 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate char usagestr[] = "Usage: " 1737c478bd9Sstevel@tonic-gate "finger [-bfhilmpqsw] [name1 [name2 ...] ]\n"; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate int AlreadyPrinted(uid_t uid); 1767c478bd9Sstevel@tonic-gate void AnyMail(char *name); 1777c478bd9Sstevel@tonic-gate void catfile(char *s, mode_t mode, int trunc_at_nl); 1787c478bd9Sstevel@tonic-gate void decode(struct person *pers); 1797c478bd9Sstevel@tonic-gate void doall(void); 1807c478bd9Sstevel@tonic-gate void donames(char **argv); 1817c478bd9Sstevel@tonic-gate void findidle(struct person *pers); 1827c478bd9Sstevel@tonic-gate void findwhen(struct person *pers); 1837c478bd9Sstevel@tonic-gate void fwclose(void); 1847c478bd9Sstevel@tonic-gate void fwopen(void); 1857c478bd9Sstevel@tonic-gate void initscreening(void); 1867c478bd9Sstevel@tonic-gate void ltimeprint(char *before, time_t *dt, char *after); 1877c478bd9Sstevel@tonic-gate int matchcmp(char *gname, char *login, char *given); 1887c478bd9Sstevel@tonic-gate int namecmp(char *name1, char *name2); 1897c478bd9Sstevel@tonic-gate int netfinger(char *name); 1907c478bd9Sstevel@tonic-gate void personprint(struct person *pers); 1917c478bd9Sstevel@tonic-gate void print(void); 1927c478bd9Sstevel@tonic-gate struct passwd *pwdcopy(const struct passwd *pfrom); 1937c478bd9Sstevel@tonic-gate void quickprint(struct person *pers); 1947c478bd9Sstevel@tonic-gate void shortprint(struct person *pers); 1957c478bd9Sstevel@tonic-gate void stimeprint(time_t *dt); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate int 1997c478bd9Sstevel@tonic-gate main(int argc, char **argv) 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate int c; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2047c478bd9Sstevel@tonic-gate /* parse command line for (optional) arguments */ 2057c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "bfhilmpqsw")) != EOF) 2067c478bd9Sstevel@tonic-gate switch (c) { 2077c478bd9Sstevel@tonic-gate case 'b': 2087c478bd9Sstevel@tonic-gate unbrief = 0; 2097c478bd9Sstevel@tonic-gate break; 2107c478bd9Sstevel@tonic-gate case 'f': 2117c478bd9Sstevel@tonic-gate header = 0; 2127c478bd9Sstevel@tonic-gate break; 2137c478bd9Sstevel@tonic-gate case 'h': 2147c478bd9Sstevel@tonic-gate hack = 0; 2157c478bd9Sstevel@tonic-gate break; 2167c478bd9Sstevel@tonic-gate case 'i': 2177c478bd9Sstevel@tonic-gate idle = 1; 2187c478bd9Sstevel@tonic-gate unquick = 0; 2197c478bd9Sstevel@tonic-gate break; 2207c478bd9Sstevel@tonic-gate case 'l': 2217c478bd9Sstevel@tonic-gate large = 1; 2227c478bd9Sstevel@tonic-gate break; 2237c478bd9Sstevel@tonic-gate case 'm': 2247c478bd9Sstevel@tonic-gate match = 0; 2257c478bd9Sstevel@tonic-gate break; 2267c478bd9Sstevel@tonic-gate case 'p': 2277c478bd9Sstevel@tonic-gate plan = 0; 2287c478bd9Sstevel@tonic-gate break; 2297c478bd9Sstevel@tonic-gate case 'q': 2307c478bd9Sstevel@tonic-gate unquick = 0; 2317c478bd9Sstevel@tonic-gate break; 2327c478bd9Sstevel@tonic-gate case 's': 2337c478bd9Sstevel@tonic-gate small = 1; 2347c478bd9Sstevel@tonic-gate break; 2357c478bd9Sstevel@tonic-gate case 'w': 2367c478bd9Sstevel@tonic-gate wide = 0; 2377c478bd9Sstevel@tonic-gate break; 2387c478bd9Sstevel@tonic-gate default: 2397c478bd9Sstevel@tonic-gate (void) fprintf(stderr, usagestr); 2407c478bd9Sstevel@tonic-gate exit(1); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate if (unquick || idle) 2437c478bd9Sstevel@tonic-gate tloc = time(NULL); 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate /* find out what filtering on .plan/.project files we should do */ 2467c478bd9Sstevel@tonic-gate initscreening(); 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * optind == argc means no names given 2507c478bd9Sstevel@tonic-gate */ 2517c478bd9Sstevel@tonic-gate if (optind == argc) 2527c478bd9Sstevel@tonic-gate doall(); 2537c478bd9Sstevel@tonic-gate else 2547c478bd9Sstevel@tonic-gate donames(&argv[optind]); 2557c478bd9Sstevel@tonic-gate if (person1) 2567c478bd9Sstevel@tonic-gate print(); 2577c478bd9Sstevel@tonic-gate return (0); 2587c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate void 2627c478bd9Sstevel@tonic-gate doall(void) 2637c478bd9Sstevel@tonic-gate { 2647c478bd9Sstevel@tonic-gate struct person *p; 2657c478bd9Sstevel@tonic-gate struct passwd *pw; 2667c478bd9Sstevel@tonic-gate struct utmpx *u; 2677c478bd9Sstevel@tonic-gate char name[NMAX + 1]; 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate unshort = large; 2707c478bd9Sstevel@tonic-gate setutxent(); 2717c478bd9Sstevel@tonic-gate if (unquick) { 2727c478bd9Sstevel@tonic-gate setpwent(); 2737c478bd9Sstevel@tonic-gate fwopen(); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate while (u = getutxent()) { 2767c478bd9Sstevel@tonic-gate if (u->ut_name[0] == 0 || 2777c478bd9Sstevel@tonic-gate nonuserx(*u) || 2787c478bd9Sstevel@tonic-gate u->ut_type != USER_PROCESS) 2797c478bd9Sstevel@tonic-gate continue; 2807c478bd9Sstevel@tonic-gate if (person1 == 0) 2817c478bd9Sstevel@tonic-gate p = person1 = malloc(sizeof (*p)); 2827c478bd9Sstevel@tonic-gate else { 2837c478bd9Sstevel@tonic-gate p->link = malloc(sizeof (*p)); 2847c478bd9Sstevel@tonic-gate p = p->link; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate bcopy(u->ut_name, name, NMAX); 2877c478bd9Sstevel@tonic-gate name[NMAX] = 0; 2887c478bd9Sstevel@tonic-gate bcopy(u->ut_line, p->tty, LMAX); 2897c478bd9Sstevel@tonic-gate p->tty[LMAX] = 0; 2907c478bd9Sstevel@tonic-gate bcopy(u->ut_host, p->host, HMAX); 2917c478bd9Sstevel@tonic-gate p->host[HMAX] = 0; 2927c478bd9Sstevel@tonic-gate p->loginat = u->ut_tv.tv_sec; 2937c478bd9Sstevel@tonic-gate p->pwd = 0; 2947c478bd9Sstevel@tonic-gate p->loggedin = 1; 2957c478bd9Sstevel@tonic-gate if (unquick && (pw = getpwnam(name))) { 2967c478bd9Sstevel@tonic-gate p->pwd = pwdcopy(pw); 2977c478bd9Sstevel@tonic-gate decode(p); 2987c478bd9Sstevel@tonic-gate p->name = p->pwd->pw_name; 2997c478bd9Sstevel@tonic-gate } else 3007c478bd9Sstevel@tonic-gate p->name = strdup(name); 3017c478bd9Sstevel@tonic-gate p->ttyloc = NULL; 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate if (unquick) { 3047c478bd9Sstevel@tonic-gate fwclose(); 3057c478bd9Sstevel@tonic-gate endpwent(); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate endutxent(); 3087c478bd9Sstevel@tonic-gate if (person1 == 0) { 3097c478bd9Sstevel@tonic-gate (void) printf("No one logged on\n"); 3107c478bd9Sstevel@tonic-gate return; 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate p->link = 0; 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate void 3167c478bd9Sstevel@tonic-gate donames(char **argv) 3177c478bd9Sstevel@tonic-gate { 3187c478bd9Sstevel@tonic-gate struct person *p; 3197c478bd9Sstevel@tonic-gate struct passwd *pw; 3207c478bd9Sstevel@tonic-gate struct utmpx *u; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * get names from command line and check to see if they're 3247c478bd9Sstevel@tonic-gate * logged in 3257c478bd9Sstevel@tonic-gate */ 3267c478bd9Sstevel@tonic-gate unshort = !small; 3277c478bd9Sstevel@tonic-gate for (; *argv != 0; argv++) { 3287c478bd9Sstevel@tonic-gate if (netfinger(*argv)) 3297c478bd9Sstevel@tonic-gate continue; 3307c478bd9Sstevel@tonic-gate if (person1 == 0) 3317c478bd9Sstevel@tonic-gate p = person1 = malloc(sizeof (*p)); 3327c478bd9Sstevel@tonic-gate else { 3337c478bd9Sstevel@tonic-gate p->link = malloc(sizeof (*p)); 3347c478bd9Sstevel@tonic-gate p = p->link; 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate p->name = *argv; 3377c478bd9Sstevel@tonic-gate p->loggedin = 0; 3387c478bd9Sstevel@tonic-gate p->original = 1; 3397c478bd9Sstevel@tonic-gate p->pwd = 0; 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate if (person1 == 0) 3427c478bd9Sstevel@tonic-gate return; 3437c478bd9Sstevel@tonic-gate p->link = 0; 3447c478bd9Sstevel@tonic-gate /* 3457c478bd9Sstevel@tonic-gate * if we are doing it, read /etc/passwd for the useful info 3467c478bd9Sstevel@tonic-gate */ 3477c478bd9Sstevel@tonic-gate if (unquick) { 3487c478bd9Sstevel@tonic-gate setpwent(); 3497c478bd9Sstevel@tonic-gate if (!match) { 3507c478bd9Sstevel@tonic-gate for (p = person1; p != 0; p = p->link) { 3517c478bd9Sstevel@tonic-gate if (pw = getpwnam(p->name)) 3527c478bd9Sstevel@tonic-gate p->pwd = pwdcopy(pw); 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate } else { 3557c478bd9Sstevel@tonic-gate while ((pw = getpwent()) != 0) { 3567c478bd9Sstevel@tonic-gate for (p = person1; p != 0; p = p->link) { 3577c478bd9Sstevel@tonic-gate if (!p->original) 3587c478bd9Sstevel@tonic-gate continue; 3597c478bd9Sstevel@tonic-gate if (strcmp(p->name, pw->pw_name) != 0 && 3607c478bd9Sstevel@tonic-gate !matchcmp(pw->pw_gecos, pw->pw_name, 3617c478bd9Sstevel@tonic-gate p->name)) { 3627c478bd9Sstevel@tonic-gate continue; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate if (p->pwd == 0) { 3657c478bd9Sstevel@tonic-gate p->pwd = pwdcopy(pw); 3667c478bd9Sstevel@tonic-gate } else { 3677c478bd9Sstevel@tonic-gate struct person *new; 3687c478bd9Sstevel@tonic-gate /* 3697c478bd9Sstevel@tonic-gate * Handle multiple login names. 3707c478bd9Sstevel@tonic-gate * Insert new "duplicate" entry 3717c478bd9Sstevel@tonic-gate * behind. 3727c478bd9Sstevel@tonic-gate */ 3737c478bd9Sstevel@tonic-gate new = malloc(sizeof (*new)); 3747c478bd9Sstevel@tonic-gate new->pwd = pwdcopy(pw); 3757c478bd9Sstevel@tonic-gate new->name = p->name; 3767c478bd9Sstevel@tonic-gate new->original = 1; 3777c478bd9Sstevel@tonic-gate new->loggedin = 0; 3787c478bd9Sstevel@tonic-gate new->ttyloc = NULL; 3797c478bd9Sstevel@tonic-gate new->link = p->link; 3807c478bd9Sstevel@tonic-gate p->original = 0; 3817c478bd9Sstevel@tonic-gate p->link = new; 3827c478bd9Sstevel@tonic-gate p = new; 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate endpwent(); 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate /* Now get login information */ 3907c478bd9Sstevel@tonic-gate setutxent(); 3917c478bd9Sstevel@tonic-gate while (u = getutxent()) { 3927c478bd9Sstevel@tonic-gate if (u->ut_name[0] == 0 || u->ut_type != USER_PROCESS) 3937c478bd9Sstevel@tonic-gate continue; 3947c478bd9Sstevel@tonic-gate for (p = person1; p != 0; p = p->link) { 3957c478bd9Sstevel@tonic-gate p->ttyloc = NULL; 3967c478bd9Sstevel@tonic-gate if (p->loggedin == 2) 3977c478bd9Sstevel@tonic-gate continue; 3987c478bd9Sstevel@tonic-gate if (strncmp(p->pwd ? p->pwd->pw_name : p->name, 3997c478bd9Sstevel@tonic-gate u->ut_name, NMAX) != 0) 4007c478bd9Sstevel@tonic-gate continue; 4017c478bd9Sstevel@tonic-gate if (p->loggedin == 0) { 4027c478bd9Sstevel@tonic-gate bcopy(u->ut_line, p->tty, LMAX); 4037c478bd9Sstevel@tonic-gate p->tty[LMAX] = 0; 4047c478bd9Sstevel@tonic-gate bcopy(u->ut_host, p->host, HMAX); 4057c478bd9Sstevel@tonic-gate p->host[HMAX] = 0; 4067c478bd9Sstevel@tonic-gate p->loginat = u->ut_tv.tv_sec; 4077c478bd9Sstevel@tonic-gate p->loggedin = 1; 4087c478bd9Sstevel@tonic-gate } else { /* p->loggedin == 1 */ 4097c478bd9Sstevel@tonic-gate struct person *new; 4107c478bd9Sstevel@tonic-gate new = malloc(sizeof (*new)); 4117c478bd9Sstevel@tonic-gate new->name = p->name; 4127c478bd9Sstevel@tonic-gate bcopy(u->ut_line, new->tty, LMAX); 4137c478bd9Sstevel@tonic-gate new->tty[LMAX] = 0; 4147c478bd9Sstevel@tonic-gate bcopy(u->ut_host, new->host, HMAX); 4157c478bd9Sstevel@tonic-gate new->host[HMAX] = 0; 4167c478bd9Sstevel@tonic-gate new->loginat = u->ut_tv.tv_sec; 4177c478bd9Sstevel@tonic-gate new->pwd = p->pwd; 4187c478bd9Sstevel@tonic-gate new->loggedin = 1; 4197c478bd9Sstevel@tonic-gate new->original = 0; 4207c478bd9Sstevel@tonic-gate new->link = p->link; 4217c478bd9Sstevel@tonic-gate p->loggedin = 2; 4227c478bd9Sstevel@tonic-gate p->link = new; 4237c478bd9Sstevel@tonic-gate p = new; 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate endutxent(); 4287c478bd9Sstevel@tonic-gate if (unquick) { 4297c478bd9Sstevel@tonic-gate fwopen(); 4307c478bd9Sstevel@tonic-gate for (p = person1; p != 0; p = p->link) 4317c478bd9Sstevel@tonic-gate decode(p); 4327c478bd9Sstevel@tonic-gate fwclose(); 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate void 4377c478bd9Sstevel@tonic-gate print(void) 4387c478bd9Sstevel@tonic-gate { 4397c478bd9Sstevel@tonic-gate struct person *p; 4407c478bd9Sstevel@tonic-gate char *s; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* 4437c478bd9Sstevel@tonic-gate * print out what we got 4447c478bd9Sstevel@tonic-gate */ 4457c478bd9Sstevel@tonic-gate if (header) { 4467c478bd9Sstevel@tonic-gate if (unquick) { 4477c478bd9Sstevel@tonic-gate if (!unshort) { 4487c478bd9Sstevel@tonic-gate if (wide) { 4497c478bd9Sstevel@tonic-gate (void) printf("Login " 4507c478bd9Sstevel@tonic-gate "Name TTY " 4517c478bd9Sstevel@tonic-gate "Idle When Where\n"); 4527c478bd9Sstevel@tonic-gate } else { 4537c478bd9Sstevel@tonic-gate (void) printf("Login TTY Idle " 4547c478bd9Sstevel@tonic-gate "When Where\n"); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate } else { 4587c478bd9Sstevel@tonic-gate (void) printf("Login TTY When"); 4597c478bd9Sstevel@tonic-gate if (idle) 4607c478bd9Sstevel@tonic-gate (void) printf(" Idle"); 4617c478bd9Sstevel@tonic-gate (void) putchar('\n'); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate for (p = person1; p != 0; p = p->link) { 4657c478bd9Sstevel@tonic-gate if (!unquick) { 4667c478bd9Sstevel@tonic-gate quickprint(p); 4677c478bd9Sstevel@tonic-gate continue; 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate if (!unshort) { 4707c478bd9Sstevel@tonic-gate shortprint(p); 4717c478bd9Sstevel@tonic-gate continue; 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate personprint(p); 4747c478bd9Sstevel@tonic-gate if (p->pwd != 0 && !AlreadyPrinted(p->pwd->pw_uid)) { 4757c478bd9Sstevel@tonic-gate AnyMail(p->pwd->pw_name); 4767c478bd9Sstevel@tonic-gate if (hack) { 4777c478bd9Sstevel@tonic-gate struct stat sbuf; 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate s = malloc(strlen(p->pwd->pw_dir) + 4807c478bd9Sstevel@tonic-gate sizeof (PROJ)); 4817c478bd9Sstevel@tonic-gate if (s) { 4827c478bd9Sstevel@tonic-gate (void) strcpy(s, p->pwd->pw_dir); 4837c478bd9Sstevel@tonic-gate (void) strcat(s, PROJ); 4847c478bd9Sstevel@tonic-gate if (stat(s, &sbuf) != -1 && 4857c478bd9Sstevel@tonic-gate (S_ISREG(sbuf.st_mode) || 4867c478bd9Sstevel@tonic-gate S_ISFIFO(sbuf.st_mode)) && 4877c478bd9Sstevel@tonic-gate (sbuf.st_mode & S_IROTH)) { 4887c478bd9Sstevel@tonic-gate (void) printf("Project: "); 4897c478bd9Sstevel@tonic-gate catfile(s, sbuf.st_mode, 1); 4907c478bd9Sstevel@tonic-gate (void) putchar('\n'); 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate free(s); 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate if (plan) { 4967c478bd9Sstevel@tonic-gate struct stat sbuf; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate s = malloc(strlen(p->pwd->pw_dir) + 4997c478bd9Sstevel@tonic-gate sizeof (PLAN)); 5007c478bd9Sstevel@tonic-gate if (s) { 5017c478bd9Sstevel@tonic-gate (void) strcpy(s, p->pwd->pw_dir); 5027c478bd9Sstevel@tonic-gate (void) strcat(s, PLAN); 5037c478bd9Sstevel@tonic-gate if (stat(s, &sbuf) == -1 || 5047c478bd9Sstevel@tonic-gate (!S_ISREG(sbuf.st_mode) && 5057c478bd9Sstevel@tonic-gate !S_ISFIFO(sbuf.st_mode)) || 5067c478bd9Sstevel@tonic-gate ((sbuf.st_mode & S_IROTH) == 0)) 5077c478bd9Sstevel@tonic-gate (void) printf("No Plan.\n"); 5087c478bd9Sstevel@tonic-gate else { 5097c478bd9Sstevel@tonic-gate (void) printf("Plan:\n"); 5107c478bd9Sstevel@tonic-gate catfile(s, sbuf.st_mode, 0); 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate free(s); 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate if (p->link != 0) 5177c478bd9Sstevel@tonic-gate (void) putchar('\n'); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate /* 5227c478bd9Sstevel@tonic-gate * Duplicate a pwd entry. 5237c478bd9Sstevel@tonic-gate * Note: Only the useful things (what the program currently uses) are copied. 5247c478bd9Sstevel@tonic-gate */ 5257c478bd9Sstevel@tonic-gate struct passwd * 5267c478bd9Sstevel@tonic-gate pwdcopy(const struct passwd *pfrom) 5277c478bd9Sstevel@tonic-gate { 5287c478bd9Sstevel@tonic-gate struct passwd *pto; 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate pto = malloc(sizeof (*pto)); 5317c478bd9Sstevel@tonic-gate pto->pw_name = strdup(pfrom->pw_name); 5327c478bd9Sstevel@tonic-gate pto->pw_uid = pfrom->pw_uid; 5337c478bd9Sstevel@tonic-gate pto->pw_gecos = strdup(pfrom->pw_gecos); 5347c478bd9Sstevel@tonic-gate pto->pw_dir = strdup(pfrom->pw_dir); 5357c478bd9Sstevel@tonic-gate pto->pw_shell = strdup(pfrom->pw_shell); 5367c478bd9Sstevel@tonic-gate return (pto); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate /* 5407c478bd9Sstevel@tonic-gate * print out information on quick format giving just name, tty, login time 5417c478bd9Sstevel@tonic-gate * and idle time if idle is set. 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate void 5447c478bd9Sstevel@tonic-gate quickprint(struct person *pers) 5457c478bd9Sstevel@tonic-gate { 5467c478bd9Sstevel@tonic-gate (void) printf("%-8.8s ", pers->name); 5477c478bd9Sstevel@tonic-gate if (pers->loggedin) { 5487c478bd9Sstevel@tonic-gate if (idle) { 5497c478bd9Sstevel@tonic-gate findidle(pers); 5507c478bd9Sstevel@tonic-gate (void) printf("%c%-12s %-16.16s", 5517c478bd9Sstevel@tonic-gate pers->writable ? ' ' : '*', 5527c478bd9Sstevel@tonic-gate pers->tty, ctime(&pers->loginat)); 5537c478bd9Sstevel@tonic-gate ltimeprint(" ", &pers->idletime, ""); 5547c478bd9Sstevel@tonic-gate } else { 5557c478bd9Sstevel@tonic-gate (void) printf(" %-12s %-16.16s", 5567c478bd9Sstevel@tonic-gate pers->tty, ctime(&pers->loginat)); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate (void) putchar('\n'); 5597c478bd9Sstevel@tonic-gate } else { 5607c478bd9Sstevel@tonic-gate (void) printf(" Not Logged In\n"); 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate /* 5657c478bd9Sstevel@tonic-gate * print out information in short format, giving login name, full name, 5667c478bd9Sstevel@tonic-gate * tty, idle time, login time, and host. 5677c478bd9Sstevel@tonic-gate */ 5687c478bd9Sstevel@tonic-gate void 5697c478bd9Sstevel@tonic-gate shortprint(struct person *pers) 5707c478bd9Sstevel@tonic-gate { 5717c478bd9Sstevel@tonic-gate char *p; 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate if (pers->pwd == 0) { 5747c478bd9Sstevel@tonic-gate (void) printf("%-15s ???\n", pers->name); 5757c478bd9Sstevel@tonic-gate return; 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate (void) printf("%-8s", pers->pwd->pw_name); 5787c478bd9Sstevel@tonic-gate if (wide) { 5797c478bd9Sstevel@tonic-gate if (pers->realname) { 5807c478bd9Sstevel@tonic-gate (void) printf(" %-20.20s", pers->realname); 5817c478bd9Sstevel@tonic-gate } else { 5827c478bd9Sstevel@tonic-gate (void) printf(" ??? "); 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate (void) putchar(' '); 5867c478bd9Sstevel@tonic-gate if (pers->loggedin && !pers->writable) { 5877c478bd9Sstevel@tonic-gate (void) putchar('*'); 5887c478bd9Sstevel@tonic-gate } else { 5897c478bd9Sstevel@tonic-gate (void) putchar(' '); 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate if (*pers->tty) { 5927c478bd9Sstevel@tonic-gate (void) printf("%-11.11s ", pers->tty); 5937c478bd9Sstevel@tonic-gate } else { 5947c478bd9Sstevel@tonic-gate (void) printf(" "); /* 12 spaces */ 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate p = ctime(&pers->loginat); 5977c478bd9Sstevel@tonic-gate if (pers->loggedin) { 5987c478bd9Sstevel@tonic-gate stimeprint(&pers->idletime); 5997c478bd9Sstevel@tonic-gate (void) printf(" %3.3s %-5.5s ", p, p + 11); 6007c478bd9Sstevel@tonic-gate } else if (pers->loginat == 0) { 6017c478bd9Sstevel@tonic-gate (void) printf(" < . . . . >"); 6027c478bd9Sstevel@tonic-gate } else if (tloc - pers->loginat >= 180 * 24 * 60 * 60) { 6037c478bd9Sstevel@tonic-gate (void) printf(" <%-6.6s, %-4.4s>", p + 4, p + 20); 6047c478bd9Sstevel@tonic-gate } else { 6057c478bd9Sstevel@tonic-gate (void) printf(" <%-12.12s>", p + 4); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate if (*pers->host) { 6087c478bd9Sstevel@tonic-gate (void) printf(" %-20.20s", pers->host); 6097c478bd9Sstevel@tonic-gate } else { 6107c478bd9Sstevel@tonic-gate if (pers->ttyloc != NULL) 6117c478bd9Sstevel@tonic-gate (void) printf(" %-20.20s", pers->ttyloc); 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate (void) putchar('\n'); 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate /* 6187c478bd9Sstevel@tonic-gate * print out a person in long format giving all possible information. 6197c478bd9Sstevel@tonic-gate * directory and shell are inhibited if unbrief is clear. 6207c478bd9Sstevel@tonic-gate */ 6217c478bd9Sstevel@tonic-gate void 6227c478bd9Sstevel@tonic-gate personprint(struct person *pers) 6237c478bd9Sstevel@tonic-gate { 6247c478bd9Sstevel@tonic-gate if (pers->pwd == 0) { 6257c478bd9Sstevel@tonic-gate (void) printf("Login name: %-10s\t\t\tIn real life: ???\n", 6267c478bd9Sstevel@tonic-gate pers->name); 6277c478bd9Sstevel@tonic-gate return; 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate (void) printf("Login name: %-10s", pers->pwd->pw_name); 6307c478bd9Sstevel@tonic-gate if (pers->loggedin && !pers->writable) { 6317c478bd9Sstevel@tonic-gate (void) printf(" (messages off) "); 6327c478bd9Sstevel@tonic-gate } else { 6337c478bd9Sstevel@tonic-gate (void) printf(" "); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate if (pers->realname) { 6367c478bd9Sstevel@tonic-gate (void) printf("In real life: %s", pers->realname); 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate if (unbrief) { 6397c478bd9Sstevel@tonic-gate (void) printf("\nDirectory: %-25s", pers->pwd->pw_dir); 6407c478bd9Sstevel@tonic-gate if (*pers->pwd->pw_shell) 6417c478bd9Sstevel@tonic-gate (void) printf("\tShell: %-s", pers->pwd->pw_shell); 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate if (pers->loggedin) { 6447c478bd9Sstevel@tonic-gate char *ep = ctime(&pers->loginat); 6457c478bd9Sstevel@tonic-gate if (*pers->host) { 6467c478bd9Sstevel@tonic-gate (void) printf("\nOn since %15.15s on %s from %s", 6477c478bd9Sstevel@tonic-gate &ep[4], pers->tty, pers->host); 6487c478bd9Sstevel@tonic-gate ltimeprint("\n", &pers->idletime, " Idle Time"); 6497c478bd9Sstevel@tonic-gate } else { 6507c478bd9Sstevel@tonic-gate (void) printf("\nOn since %15.15s on %-12s", 6517c478bd9Sstevel@tonic-gate &ep[4], pers->tty); 6527c478bd9Sstevel@tonic-gate ltimeprint("\n", &pers->idletime, " Idle Time"); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate } else if (pers->loginat == 0) { 6557c478bd9Sstevel@tonic-gate (void) printf("\nNever logged in."); 6567c478bd9Sstevel@tonic-gate } else if (tloc - pers->loginat > 180 * 24 * 60 * 60) { 6577c478bd9Sstevel@tonic-gate char *ep = ctime(&pers->loginat); 6587c478bd9Sstevel@tonic-gate (void) printf("\nLast login %10.10s, %4.4s on %s", 6597c478bd9Sstevel@tonic-gate ep, ep+20, pers->tty); 6607c478bd9Sstevel@tonic-gate if (*pers->host) { 6617c478bd9Sstevel@tonic-gate (void) printf(" from %s", pers->host); 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate } else { 6647c478bd9Sstevel@tonic-gate char *ep = ctime(&pers->loginat); 6657c478bd9Sstevel@tonic-gate (void) printf("\nLast login %16.16s on %s", ep, pers->tty); 6667c478bd9Sstevel@tonic-gate if (*pers->host) { 6677c478bd9Sstevel@tonic-gate (void) printf(" from %s", pers->host); 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate (void) putchar('\n'); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate /* 6757c478bd9Sstevel@tonic-gate * decode the information in the gecos field of /etc/passwd 6767c478bd9Sstevel@tonic-gate */ 6777c478bd9Sstevel@tonic-gate void 6787c478bd9Sstevel@tonic-gate decode(struct person *pers) 6797c478bd9Sstevel@tonic-gate { 6807c478bd9Sstevel@tonic-gate char buffer[256]; 6817c478bd9Sstevel@tonic-gate char *bp, *gp, *lp; 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate pers->realname = 0; 6847c478bd9Sstevel@tonic-gate if (pers->pwd == 0) 6857c478bd9Sstevel@tonic-gate return; 6867c478bd9Sstevel@tonic-gate gp = pers->pwd->pw_gecos; 6877c478bd9Sstevel@tonic-gate bp = buffer; 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate if (gecos_ignore_c != '\0' && 6907c478bd9Sstevel@tonic-gate *gp == gecos_ignore_c) { 6917c478bd9Sstevel@tonic-gate gp++; 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate while (*gp != '\0' && 6947c478bd9Sstevel@tonic-gate *gp != gecos_sep_c) { /* name */ 6957c478bd9Sstevel@tonic-gate if (*gp == gecos_samename) { 6967c478bd9Sstevel@tonic-gate lp = pers->pwd->pw_name; 6977c478bd9Sstevel@tonic-gate if (islower(*lp)) 6987c478bd9Sstevel@tonic-gate *bp++ = toupper(*lp++); 6997c478bd9Sstevel@tonic-gate while (*bp++ = *lp++) 7007c478bd9Sstevel@tonic-gate ; 7017c478bd9Sstevel@tonic-gate bp--; 7027c478bd9Sstevel@tonic-gate gp++; 7037c478bd9Sstevel@tonic-gate } else { 7047c478bd9Sstevel@tonic-gate *bp++ = *gp++; 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate *bp++ = 0; 7087c478bd9Sstevel@tonic-gate if (bp > (buffer + 1)) 7097c478bd9Sstevel@tonic-gate pers->realname = strdup(buffer); 7107c478bd9Sstevel@tonic-gate if (pers->loggedin) 7117c478bd9Sstevel@tonic-gate findidle(pers); 7127c478bd9Sstevel@tonic-gate else 7137c478bd9Sstevel@tonic-gate findwhen(pers); 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate /* 7177c478bd9Sstevel@tonic-gate * find the last log in of a user by checking the LASTLOG file. 7187c478bd9Sstevel@tonic-gate * the entry is indexed by the uid, so this can only be done if 7197c478bd9Sstevel@tonic-gate * the uid is known (which it isn't in quick mode) 7207c478bd9Sstevel@tonic-gate */ 7217c478bd9Sstevel@tonic-gate void 7227c478bd9Sstevel@tonic-gate fwopen(void) 7237c478bd9Sstevel@tonic-gate { 7247c478bd9Sstevel@tonic-gate if ((lf = fopen(LASTLOG, "r")) == (FILE *)NULL) 7257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "finger: %s open error\n", LASTLOG); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate void 7297c478bd9Sstevel@tonic-gate findwhen(struct person *pers) 7307c478bd9Sstevel@tonic-gate { 7317c478bd9Sstevel@tonic-gate struct lastlog ll; 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate if (lf != (FILE *)NULL) { 7347c478bd9Sstevel@tonic-gate if (fseeko(lf, (off_t)pers->pwd->pw_uid * (off_t)sizeof (ll), 7357c478bd9Sstevel@tonic-gate SEEK_SET) == 0) { 7367c478bd9Sstevel@tonic-gate if (fread((char *)&ll, sizeof (ll), 1, lf) == 1) { 7377c478bd9Sstevel@tonic-gate int l_max, h_max; 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate l_max = min(LMAX, sizeof (ll.ll_line)); 7407c478bd9Sstevel@tonic-gate h_max = min(HMAX, sizeof (ll.ll_host)); 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate bcopy(ll.ll_line, pers->tty, l_max); 7437c478bd9Sstevel@tonic-gate pers->tty[l_max] = '\0'; 7447c478bd9Sstevel@tonic-gate bcopy(ll.ll_host, pers->host, h_max); 7457c478bd9Sstevel@tonic-gate pers->host[h_max] = '\0'; 7467c478bd9Sstevel@tonic-gate pers->loginat = ll.ll_time; 7477c478bd9Sstevel@tonic-gate } else { 7487c478bd9Sstevel@tonic-gate if (ferror(lf)) 7497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7507c478bd9Sstevel@tonic-gate "finger: %s read error\n", LASTLOG); 7517c478bd9Sstevel@tonic-gate pers->tty[0] = 0; 7527c478bd9Sstevel@tonic-gate pers->host[0] = 0; 7537c478bd9Sstevel@tonic-gate pers->loginat = 0L; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate } else { 7567c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "finger: %s fseeko error\n", 7577c478bd9Sstevel@tonic-gate LASTLOG); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate } else { 7607c478bd9Sstevel@tonic-gate pers->tty[0] = 0; 7617c478bd9Sstevel@tonic-gate pers->host[0] = 0; 7627c478bd9Sstevel@tonic-gate pers->loginat = 0L; 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate void 7677c478bd9Sstevel@tonic-gate fwclose(void) 7687c478bd9Sstevel@tonic-gate { 7697c478bd9Sstevel@tonic-gate if (lf != (FILE *)0) 7707c478bd9Sstevel@tonic-gate (void) fclose(lf); 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate /* 7747c478bd9Sstevel@tonic-gate * find the idle time of a user by doing a stat on /dev/tty??, 7757c478bd9Sstevel@tonic-gate * where tty?? has been gotten from UTMPX_FILE, supposedly. 7767c478bd9Sstevel@tonic-gate */ 7777c478bd9Sstevel@tonic-gate void 7787c478bd9Sstevel@tonic-gate findidle(struct person *pers) 7797c478bd9Sstevel@tonic-gate { 7807c478bd9Sstevel@tonic-gate struct stat ttystatus; 7817c478bd9Sstevel@tonic-gate #ifdef sun 7827c478bd9Sstevel@tonic-gate struct stat inputdevstatus; 7837c478bd9Sstevel@tonic-gate #endif 7847c478bd9Sstevel@tonic-gate #define TTYLEN (sizeof ("/dev/") - 1) 7857c478bd9Sstevel@tonic-gate static char buffer[TTYLEN + LMAX + 1] = "/dev/"; 7867c478bd9Sstevel@tonic-gate time_t t; 7877c478bd9Sstevel@tonic-gate time_t lastinputtime; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate (void) strcpy(buffer + TTYLEN, pers->tty); 7907c478bd9Sstevel@tonic-gate buffer[TTYLEN+LMAX] = 0; 7917c478bd9Sstevel@tonic-gate if (stat(buffer, &ttystatus) < 0) { 7927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "finger: Can't stat %s\n", buffer); 7937c478bd9Sstevel@tonic-gate exit(4); 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate lastinputtime = ttystatus.st_atime; 7967c478bd9Sstevel@tonic-gate #ifdef sun 7977c478bd9Sstevel@tonic-gate if (strcmp(pers->tty, "console") == 0) { 7987c478bd9Sstevel@tonic-gate /* 7997c478bd9Sstevel@tonic-gate * On the console, the user may be running a window system; if 8007c478bd9Sstevel@tonic-gate * so, their activity will show up in the last-access times of 8017c478bd9Sstevel@tonic-gate * "/dev/kbd" and "/dev/mouse", so take the minimum of the idle 8027c478bd9Sstevel@tonic-gate * times on those two devices and "/dev/console" and treat that 8037c478bd9Sstevel@tonic-gate * as the idle time. 8047c478bd9Sstevel@tonic-gate */ 8057c478bd9Sstevel@tonic-gate if (stat("/dev/kbd", &inputdevstatus) == 0) { 8067c478bd9Sstevel@tonic-gate if (lastinputtime < inputdevstatus.st_atime) 8077c478bd9Sstevel@tonic-gate lastinputtime = inputdevstatus.st_atime; 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate if (stat("/dev/mouse", &inputdevstatus) == 0) { 8107c478bd9Sstevel@tonic-gate if (lastinputtime < inputdevstatus.st_atime) 8117c478bd9Sstevel@tonic-gate lastinputtime = inputdevstatus.st_atime; 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate } 8147c478bd9Sstevel@tonic-gate #endif 8157c478bd9Sstevel@tonic-gate t = time(NULL); 8167c478bd9Sstevel@tonic-gate if (t < lastinputtime) 8177c478bd9Sstevel@tonic-gate pers->idletime = (time_t)0; 8187c478bd9Sstevel@tonic-gate else 8197c478bd9Sstevel@tonic-gate pers->idletime = t - lastinputtime; 8207c478bd9Sstevel@tonic-gate pers->writable = (ttystatus.st_mode & TALKABLE) == TALKABLE; 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate /* 8247c478bd9Sstevel@tonic-gate * print idle time in short format; this program always prints 4 characters; 8257c478bd9Sstevel@tonic-gate * if the idle time is zero, it prints 4 blanks. 8267c478bd9Sstevel@tonic-gate */ 8277c478bd9Sstevel@tonic-gate void 8287c478bd9Sstevel@tonic-gate stimeprint(time_t *dt) 8297c478bd9Sstevel@tonic-gate { 8307c478bd9Sstevel@tonic-gate struct tm *delta; 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate delta = gmtime(dt); 8337c478bd9Sstevel@tonic-gate if (delta->tm_yday == 0) 8347c478bd9Sstevel@tonic-gate if (delta->tm_hour == 0) 8357c478bd9Sstevel@tonic-gate if (delta->tm_min == 0) 8367c478bd9Sstevel@tonic-gate (void) printf(" "); 8377c478bd9Sstevel@tonic-gate else 8387c478bd9Sstevel@tonic-gate (void) printf(" %2d", delta->tm_min); 8397c478bd9Sstevel@tonic-gate else 8407c478bd9Sstevel@tonic-gate if (delta->tm_hour >= 10) 8417c478bd9Sstevel@tonic-gate (void) printf("%3d:", delta->tm_hour); 8427c478bd9Sstevel@tonic-gate else 8437c478bd9Sstevel@tonic-gate (void) printf("%1d:%02d", 8447c478bd9Sstevel@tonic-gate delta->tm_hour, delta->tm_min); 8457c478bd9Sstevel@tonic-gate else 8467c478bd9Sstevel@tonic-gate (void) printf("%3dd", delta->tm_yday); 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate /* 8507c478bd9Sstevel@tonic-gate * print idle time in long format with care being taken not to pluralize 8517c478bd9Sstevel@tonic-gate * 1 minutes or 1 hours or 1 days. 8527c478bd9Sstevel@tonic-gate * print "prefix" first. 8537c478bd9Sstevel@tonic-gate */ 8547c478bd9Sstevel@tonic-gate void 8557c478bd9Sstevel@tonic-gate ltimeprint(char *before, time_t *dt, char *after) 8567c478bd9Sstevel@tonic-gate { 8577c478bd9Sstevel@tonic-gate struct tm *delta; 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate delta = gmtime(dt); 8607c478bd9Sstevel@tonic-gate if (delta->tm_yday == 0 && delta->tm_hour == 0 && delta->tm_min == 0 && 8617c478bd9Sstevel@tonic-gate delta->tm_sec <= 10) 8627c478bd9Sstevel@tonic-gate return; 8637c478bd9Sstevel@tonic-gate (void) printf("%s", before); 8647c478bd9Sstevel@tonic-gate if (delta->tm_yday >= 10) 8657c478bd9Sstevel@tonic-gate (void) printf("%d days", delta->tm_yday); 8667c478bd9Sstevel@tonic-gate else if (delta->tm_yday > 0) 8677c478bd9Sstevel@tonic-gate (void) printf("%d day%s %d hour%s", 8687c478bd9Sstevel@tonic-gate delta->tm_yday, delta->tm_yday == 1 ? "" : "s", 8697c478bd9Sstevel@tonic-gate delta->tm_hour, delta->tm_hour == 1 ? "" : "s"); 8707c478bd9Sstevel@tonic-gate else 8717c478bd9Sstevel@tonic-gate if (delta->tm_hour >= 10) 8727c478bd9Sstevel@tonic-gate (void) printf("%d hours", delta->tm_hour); 8737c478bd9Sstevel@tonic-gate else if (delta->tm_hour > 0) 8747c478bd9Sstevel@tonic-gate (void) printf("%d hour%s %d minute%s", 8757c478bd9Sstevel@tonic-gate delta->tm_hour, delta->tm_hour == 1 ? "" : "s", 8767c478bd9Sstevel@tonic-gate delta->tm_min, delta->tm_min == 1 ? "" : "s"); 8777c478bd9Sstevel@tonic-gate else 8787c478bd9Sstevel@tonic-gate if (delta->tm_min >= 10) 8797c478bd9Sstevel@tonic-gate (void) printf("%2d minutes", delta->tm_min); 8807c478bd9Sstevel@tonic-gate else if (delta->tm_min == 0) 8817c478bd9Sstevel@tonic-gate (void) printf("%2d seconds", delta->tm_sec); 8827c478bd9Sstevel@tonic-gate else 8837c478bd9Sstevel@tonic-gate (void) printf("%d minute%s %d second%s", 8847c478bd9Sstevel@tonic-gate delta->tm_min, 8857c478bd9Sstevel@tonic-gate delta->tm_min == 1 ? "" : "s", 8867c478bd9Sstevel@tonic-gate delta->tm_sec, 8877c478bd9Sstevel@tonic-gate delta->tm_sec == 1 ? "" : "s"); 8887c478bd9Sstevel@tonic-gate (void) printf("%s", after); 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate /* 8927c478bd9Sstevel@tonic-gate * The grammar of the pw_gecos field is sufficiently complex that the 8937c478bd9Sstevel@tonic-gate * best way to parse it is by using an explicit finite-state machine, 8947c478bd9Sstevel@tonic-gate * in which a table defines the rules of interpretation. 8957c478bd9Sstevel@tonic-gate * 8967c478bd9Sstevel@tonic-gate * Some special rules are necessary to handle the fact that names 8977c478bd9Sstevel@tonic-gate * may contain certain punctuation characters. At this writing, 8987c478bd9Sstevel@tonic-gate * the possible punctuation characters are '.', '-', and '_'. 8997c478bd9Sstevel@tonic-gate * 9007c478bd9Sstevel@tonic-gate * Other rules are needed to account for characters that require special 9017c478bd9Sstevel@tonic-gate * processing when they appear in the pw_gecos field. At present, there 9027c478bd9Sstevel@tonic-gate * are three such characters, with these default values and effects: 9037c478bd9Sstevel@tonic-gate * 9047c478bd9Sstevel@tonic-gate * gecos_ignore_c '*' This character is ignored. 9057c478bd9Sstevel@tonic-gate * gecos_sep_c ',' Delimits displayed and nondisplayed contents. 9067c478bd9Sstevel@tonic-gate * gecos_samename '&' Copies the login name into the output. 9077c478bd9Sstevel@tonic-gate * 9087c478bd9Sstevel@tonic-gate * As the program examines each successive character in the returned 9097c478bd9Sstevel@tonic-gate * pw_gecos value, it fetches (from the table) the FSM rule applicable 9107c478bd9Sstevel@tonic-gate * for that character in the current machine state, and thus determines 9117c478bd9Sstevel@tonic-gate * the next state. 9127c478bd9Sstevel@tonic-gate * 9137c478bd9Sstevel@tonic-gate * The possible states are: 9147c478bd9Sstevel@tonic-gate * S0 start 9157c478bd9Sstevel@tonic-gate * S1 in a word 9167c478bd9Sstevel@tonic-gate * S2 not in a word 9177c478bd9Sstevel@tonic-gate * S3 copy login name into output 9187c478bd9Sstevel@tonic-gate * S4 end of GECOS field 9197c478bd9Sstevel@tonic-gate * 9207c478bd9Sstevel@tonic-gate * Here follows a depiction of the state transitions. 9217c478bd9Sstevel@tonic-gate * 9227c478bd9Sstevel@tonic-gate * 9237c478bd9Sstevel@tonic-gate * gecos_ignore_c OR isspace OR any other character 9247c478bd9Sstevel@tonic-gate * +--+ 9257c478bd9Sstevel@tonic-gate * | | 9267c478bd9Sstevel@tonic-gate * | V 9277c478bd9Sstevel@tonic-gate * +-----+ 9287c478bd9Sstevel@tonic-gate * NULL OR | S0 | isalpha OR isdigit 9297c478bd9Sstevel@tonic-gate * +---------------|start|------------------------+ 9307c478bd9Sstevel@tonic-gate * | gecos_sep_c +-----+ | isalpha OR isdigit 9317c478bd9Sstevel@tonic-gate * | | | | +---------------------+ 9327c478bd9Sstevel@tonic-gate * | | | | | OR '.' '-' '_' | 9337c478bd9Sstevel@tonic-gate * | | |isspace | | | 9347c478bd9Sstevel@tonic-gate * | | +-------+ V V | 9357c478bd9Sstevel@tonic-gate * | | | +-----------+ | 9367c478bd9Sstevel@tonic-gate * | | | | S1 |<--+ | 9377c478bd9Sstevel@tonic-gate * | | | | in a word | | isalpha OR | 9387c478bd9Sstevel@tonic-gate * | | | +-----------+ | isdigit OR | 9397c478bd9Sstevel@tonic-gate * | | | | | | | | '.' '-' '_' | 9407c478bd9Sstevel@tonic-gate * | | +----- ---------------+ | | +-----+ | 9417c478bd9Sstevel@tonic-gate * | | | | | | | 9427c478bd9Sstevel@tonic-gate * | | | | gecos_ignore_c | | | 9437c478bd9Sstevel@tonic-gate * | | | | isspace | | | 9447c478bd9Sstevel@tonic-gate * | | | | ispunct/other | | | 9457c478bd9Sstevel@tonic-gate * | | | | any other char | | | 9467c478bd9Sstevel@tonic-gate * | | | | +---------------+ | | 9477c478bd9Sstevel@tonic-gate * | | | | | |NULL OR gecos_sep_c | 9487c478bd9Sstevel@tonic-gate * | | | | | +------------------+ | 9497c478bd9Sstevel@tonic-gate * | gecos_samename| | V V | | 9507c478bd9Sstevel@tonic-gate * | +-------------+ | +---------------+ | | 9517c478bd9Sstevel@tonic-gate * | | | | S2 | isspace OR '.' '-' '_' | | 9527c478bd9Sstevel@tonic-gate * | | gecos_samename | | not in a word |<---------------------+ | | 9537c478bd9Sstevel@tonic-gate * | | +---------------+ +---------------+ OR gecos_ignore_c | | | 9547c478bd9Sstevel@tonic-gate * | | | | ^ | | OR ispunct OR other | | | 9557c478bd9Sstevel@tonic-gate * | | | | | | | | | | 9567c478bd9Sstevel@tonic-gate * | | | gecos_samename | | | +-----------------------+ | | 9577c478bd9Sstevel@tonic-gate * | | | +---------------------+ | | | | 9587c478bd9Sstevel@tonic-gate * | | | | | | | | 9597c478bd9Sstevel@tonic-gate * | | | | gecos_ignore_c| | NULL OR gecos_sep_c | | 9607c478bd9Sstevel@tonic-gate * | | | | gecos_samename| +-----------------------+ | | 9617c478bd9Sstevel@tonic-gate * | | | | ispunct/other | | | | 9627c478bd9Sstevel@tonic-gate * | V V V isspace | | | | 9637c478bd9Sstevel@tonic-gate * | +-----------------+ any other char| | | | 9647c478bd9Sstevel@tonic-gate * | | S3 |---------------+ isalpha OR isdigit OR | | | 9657c478bd9Sstevel@tonic-gate * | |insert login name|------------------------------------------ ----- ---+ 9667c478bd9Sstevel@tonic-gate * | +-----------------+ '.' '-' '_' | | 9677c478bd9Sstevel@tonic-gate * | | NULL OR gecos_sep_c | | 9687c478bd9Sstevel@tonic-gate * | +------------------------------------------+ | | 9697c478bd9Sstevel@tonic-gate * | | | | 9707c478bd9Sstevel@tonic-gate * | V V V 9717c478bd9Sstevel@tonic-gate * | +------------+ 9727c478bd9Sstevel@tonic-gate * | NULL OR gecos_sep_c | S4 | 9737c478bd9Sstevel@tonic-gate * +-------------------------------------------------------->|end of gecos|<--+ 9747c478bd9Sstevel@tonic-gate * +------------+ | 9757c478bd9Sstevel@tonic-gate * | all | 9767c478bd9Sstevel@tonic-gate * +-----+ 9777c478bd9Sstevel@tonic-gate * 9787c478bd9Sstevel@tonic-gate * 9797c478bd9Sstevel@tonic-gate * The transitions from the above diagram are summarized in 9807c478bd9Sstevel@tonic-gate * the following table of target states, which is implemented 9817c478bd9Sstevel@tonic-gate * in code as the gecos_fsm array. 9827c478bd9Sstevel@tonic-gate * 9837c478bd9Sstevel@tonic-gate * Input: 9847c478bd9Sstevel@tonic-gate * +--gecos_ignore_c 9857c478bd9Sstevel@tonic-gate * | +--gecos_sep_c 9867c478bd9Sstevel@tonic-gate * | | +--gecos_samename 9877c478bd9Sstevel@tonic-gate * | | | +--isalpha 9887c478bd9Sstevel@tonic-gate * | | | | +--isdigit 9897c478bd9Sstevel@tonic-gate * | | | | | +--isspace 9907c478bd9Sstevel@tonic-gate * | | | | | | +--punctuation possible in name 9917c478bd9Sstevel@tonic-gate * | | | | | | | +--other punctuation 9927c478bd9Sstevel@tonic-gate * | | | | | | | | +--NULL character 9937c478bd9Sstevel@tonic-gate * | | | | | | | | | +--any other character 9947c478bd9Sstevel@tonic-gate * | | | | | | | | | | 9957c478bd9Sstevel@tonic-gate * V V V V V V V V V V 9967c478bd9Sstevel@tonic-gate * From: --------------------------------------------------- 9977c478bd9Sstevel@tonic-gate * S0 | S0 | S4 | S3 | S1 | S1 | S0 | S1 | S2 | S4 | S0 | 9987c478bd9Sstevel@tonic-gate * S1 | S2 | S4 | S3 | S1 | S1 | S2 | S1 | S2 | S4 | S2 | 9997c478bd9Sstevel@tonic-gate * S2 | S2 | S4 | S3 | S1 | S1 | S2 | S2 | S2 | S4 | S2 | 10007c478bd9Sstevel@tonic-gate * S3 | S2 | S4 | S2 | S1 | S1 | S2 | S1 | S2 | S4 | S2 | 10017c478bd9Sstevel@tonic-gate * S4 | S4 | S4 | S4 | S4 | S4 | S4 | S4 | S4 | S4 | S4 | 10027c478bd9Sstevel@tonic-gate * 10037c478bd9Sstevel@tonic-gate */ 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate /* 10067c478bd9Sstevel@tonic-gate * Data types and structures for scanning the pw_gecos field. 10077c478bd9Sstevel@tonic-gate */ 10087c478bd9Sstevel@tonic-gate typedef enum gecos_state { 10097c478bd9Sstevel@tonic-gate S0, /* start */ 10107c478bd9Sstevel@tonic-gate S1, /* in a word */ 10117c478bd9Sstevel@tonic-gate S2, /* not in a word */ 10127c478bd9Sstevel@tonic-gate S3, /* copy login */ 10137c478bd9Sstevel@tonic-gate S4 /* end of gecos */ 10147c478bd9Sstevel@tonic-gate } gecos_state_t; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate #define GFSM_ROWS 5 10177c478bd9Sstevel@tonic-gate #define GFSM_COLS 10 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate gecos_state_t gecos_fsm[GFSM_ROWS][GFSM_COLS] = { 10207c478bd9Sstevel@tonic-gate {S0, S4, S3, S1, S1, S0, S1, S2, S4, S0}, /* S0 */ 10217c478bd9Sstevel@tonic-gate {S2, S4, S3, S1, S1, S2, S1, S2, S4, S2}, /* S1 */ 10227c478bd9Sstevel@tonic-gate {S2, S4, S3, S1, S1, S2, S2, S2, S4, S2}, /* S2 */ 10237c478bd9Sstevel@tonic-gate {S2, S4, S2, S1, S1, S2, S1, S2, S4, S2}, /* S3 */ 10247c478bd9Sstevel@tonic-gate {S4, S4, S4, S4, S4, S4, S4, S4, S4, S4} /* S4 */ 10257c478bd9Sstevel@tonic-gate }; 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate /* 10287c478bd9Sstevel@tonic-gate * Scan the pw_gecos field according to defined state table; 10297c478bd9Sstevel@tonic-gate * return the next state according the the rules. 10307c478bd9Sstevel@tonic-gate */ 10317c478bd9Sstevel@tonic-gate gecos_state_t 10327c478bd9Sstevel@tonic-gate gecos_scan_state(gecos_state_t instate, char ch) 10337c478bd9Sstevel@tonic-gate { 10347c478bd9Sstevel@tonic-gate if (ch == gecos_ignore_c) { 10357c478bd9Sstevel@tonic-gate return (gecos_fsm[instate][0]); 10367c478bd9Sstevel@tonic-gate } else if (ch == gecos_sep_c) { 10377c478bd9Sstevel@tonic-gate return (gecos_fsm[instate][1]); 10387c478bd9Sstevel@tonic-gate } else if (ch == gecos_samename) { 10397c478bd9Sstevel@tonic-gate return (gecos_fsm[instate][2]); 10407c478bd9Sstevel@tonic-gate } else if (isalpha(ch)) { 10417c478bd9Sstevel@tonic-gate return (gecos_fsm[instate][3]); 10427c478bd9Sstevel@tonic-gate } else if (isdigit(ch)) { 10437c478bd9Sstevel@tonic-gate return (gecos_fsm[instate][4]); 10447c478bd9Sstevel@tonic-gate } else if (isspace(ch)) { 10457c478bd9Sstevel@tonic-gate return (gecos_fsm[instate][5]); 10467c478bd9Sstevel@tonic-gate } else if (ch == '.' || ch == '-' || ch == '_') { 10477c478bd9Sstevel@tonic-gate return (gecos_fsm[instate][6]); 10487c478bd9Sstevel@tonic-gate } else if (ispunct(ch)) { 10497c478bd9Sstevel@tonic-gate return (gecos_fsm[instate][7]); 10507c478bd9Sstevel@tonic-gate } else if (ch == '\0') { 10517c478bd9Sstevel@tonic-gate return (gecos_fsm[instate][8]); 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate return (gecos_fsm[instate][9]); 10547c478bd9Sstevel@tonic-gate } 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate /* 10587c478bd9Sstevel@tonic-gate * Compare the given argument, which is taken to be a username, with 10597c478bd9Sstevel@tonic-gate * the login name and with strings in the the pw_gecos field. 10607c478bd9Sstevel@tonic-gate */ 10617c478bd9Sstevel@tonic-gate int 10627c478bd9Sstevel@tonic-gate matchcmp(char *gname, char *login, char *given) 10637c478bd9Sstevel@tonic-gate { 10647c478bd9Sstevel@tonic-gate char buffer[100]; 10657c478bd9Sstevel@tonic-gate char *bp, *lp, *gp; 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate gecos_state_t kstate = S0; 10687c478bd9Sstevel@tonic-gate gecos_state_t kstate_next = S0; 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate if (*gname == '\0' && *given == '\0') 10717c478bd9Sstevel@tonic-gate return (1); 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate bp = buffer; 10747c478bd9Sstevel@tonic-gate gp = gname; 10757c478bd9Sstevel@tonic-gate 10767c478bd9Sstevel@tonic-gate do { 10777c478bd9Sstevel@tonic-gate kstate_next = gecos_scan_state(kstate, *gp); 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate switch (kstate_next) { 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate case S0: 10827c478bd9Sstevel@tonic-gate gp++; 10837c478bd9Sstevel@tonic-gate break; 10847c478bd9Sstevel@tonic-gate case S1: 10857c478bd9Sstevel@tonic-gate if (bp < buffer + sizeof (buffer)) { 10867c478bd9Sstevel@tonic-gate *bp++ = *gp++; 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate break; 10897c478bd9Sstevel@tonic-gate case S2: 10907c478bd9Sstevel@tonic-gate if (kstate == S1 || kstate == S3) { 10917c478bd9Sstevel@tonic-gate *bp++ = ' '; 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate gp++; 10947c478bd9Sstevel@tonic-gate break; 10957c478bd9Sstevel@tonic-gate case S3: 10967c478bd9Sstevel@tonic-gate lp = login; 10977c478bd9Sstevel@tonic-gate do { 10987c478bd9Sstevel@tonic-gate *bp++ = *lp++; 10997c478bd9Sstevel@tonic-gate } while (*bp != '\0' && bp < buffer + sizeof (buffer)); 11007c478bd9Sstevel@tonic-gate bp--; 11017c478bd9Sstevel@tonic-gate break; 11027c478bd9Sstevel@tonic-gate case S4: 11037c478bd9Sstevel@tonic-gate *bp++ = '\0'; 11047c478bd9Sstevel@tonic-gate break; 11057c478bd9Sstevel@tonic-gate default: 11067c478bd9Sstevel@tonic-gate *bp++ = '\0'; 11077c478bd9Sstevel@tonic-gate break; 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate kstate = kstate_next; 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate } while ((bp < buffer + sizeof (buffer)) && kstate != S4); 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate gp = strtok(buffer, " "); 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate while (gp != NULL) { 11167c478bd9Sstevel@tonic-gate if (namecmp(gp, given) > 0) { 11177c478bd9Sstevel@tonic-gate return (1); 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate gp = strtok(NULL, " "); 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate return (0); 11227c478bd9Sstevel@tonic-gate } 11237c478bd9Sstevel@tonic-gate 11247c478bd9Sstevel@tonic-gate /* 11257c478bd9Sstevel@tonic-gate * Perform the character-by-character comparison. 11267c478bd9Sstevel@tonic-gate * It is intended that "finger foo" should match "foo2", but an argument 11277c478bd9Sstevel@tonic-gate * consisting entirely of digits should not be matched too broadly. 11287c478bd9Sstevel@tonic-gate * Also, we do not want "finger foo123" to match "Mr. Foo" in the gecos. 11297c478bd9Sstevel@tonic-gate */ 11307c478bd9Sstevel@tonic-gate int 11317c478bd9Sstevel@tonic-gate namecmp(char *name1, char *name2) 11327c478bd9Sstevel@tonic-gate { 11337c478bd9Sstevel@tonic-gate char c1, c2; 11347c478bd9Sstevel@tonic-gate boolean_t alphaseen = B_FALSE; 11357c478bd9Sstevel@tonic-gate boolean_t digitseen = B_FALSE; 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate for (;;) { 11387c478bd9Sstevel@tonic-gate c1 = *name1++; 11397c478bd9Sstevel@tonic-gate if (isalpha(c1)) 11407c478bd9Sstevel@tonic-gate alphaseen = B_TRUE; 11417c478bd9Sstevel@tonic-gate if (isdigit(c1)) 11427c478bd9Sstevel@tonic-gate digitseen = B_TRUE; 11437c478bd9Sstevel@tonic-gate if (isupper(c1)) 11447c478bd9Sstevel@tonic-gate c1 = tolower(c1); 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate c2 = *name2++; 11477c478bd9Sstevel@tonic-gate if (isupper(c2)) 11487c478bd9Sstevel@tonic-gate c2 = tolower(c2); 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate if (c1 != c2) 11517c478bd9Sstevel@tonic-gate break; 11527c478bd9Sstevel@tonic-gate if (c1 == '\0') 11537c478bd9Sstevel@tonic-gate return (1); 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate if (!c1) { 11567c478bd9Sstevel@tonic-gate for (name2--; isdigit(*name2); name2++) 11577c478bd9Sstevel@tonic-gate ; 11587c478bd9Sstevel@tonic-gate if (*name2 == '\0' && digitseen) { 11597c478bd9Sstevel@tonic-gate return (1); 11607c478bd9Sstevel@tonic-gate } 11617c478bd9Sstevel@tonic-gate } else if (!c2) { 11627c478bd9Sstevel@tonic-gate for (name1--; isdigit(*name1); name1++) 11637c478bd9Sstevel@tonic-gate ; 11647c478bd9Sstevel@tonic-gate if (*name1 == '\0' && alphaseen) { 11657c478bd9Sstevel@tonic-gate return (1); 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate } 11687c478bd9Sstevel@tonic-gate return (0); 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate int 11737c478bd9Sstevel@tonic-gate netfinger(char *name) 11747c478bd9Sstevel@tonic-gate { 11757c478bd9Sstevel@tonic-gate char *host; 11767c478bd9Sstevel@tonic-gate struct hostent *hp; 11777c478bd9Sstevel@tonic-gate struct sockaddr_in6 sin6; 11787c478bd9Sstevel@tonic-gate struct in6_addr ipv6addr; 11797c478bd9Sstevel@tonic-gate struct in_addr ipv4addr; 11807c478bd9Sstevel@tonic-gate int s; 11817c478bd9Sstevel@tonic-gate FILE *f; 11827c478bd9Sstevel@tonic-gate int c; 11837c478bd9Sstevel@tonic-gate int lastc; 11847c478bd9Sstevel@tonic-gate char abuf[INET6_ADDRSTRLEN]; 11857c478bd9Sstevel@tonic-gate int error_num; 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate if (name == NULL) 11887c478bd9Sstevel@tonic-gate return (0); 11897c478bd9Sstevel@tonic-gate host = strrchr(name, '@'); 11907c478bd9Sstevel@tonic-gate if (host == NULL) 11917c478bd9Sstevel@tonic-gate return (0); 11927c478bd9Sstevel@tonic-gate *host++ = 0; 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate if ((hp = getipnodebyname(host, AF_INET6, AI_ALL | AI_ADDRCONFIG | 11957c478bd9Sstevel@tonic-gate AI_V4MAPPED, &error_num)) == NULL) { 11967c478bd9Sstevel@tonic-gate if (error_num == TRY_AGAIN) { 11977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11987c478bd9Sstevel@tonic-gate "unknown host: %s (try again later)\n", host); 11997c478bd9Sstevel@tonic-gate } else { 12007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "unknown host: %s\n", host); 12017c478bd9Sstevel@tonic-gate } 12027c478bd9Sstevel@tonic-gate return (1); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate /* 12067c478bd9Sstevel@tonic-gate * If hp->h_name is a IPv4-mapped IPv6 literal, we'll convert it to 12077c478bd9Sstevel@tonic-gate * IPv4 literal address. 12087c478bd9Sstevel@tonic-gate */ 12097c478bd9Sstevel@tonic-gate if ((inet_pton(AF_INET6, hp->h_name, &ipv6addr) > 0) && 12107c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&ipv6addr)) { 12117c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_INADDR(&ipv6addr, &ipv4addr); 12127c478bd9Sstevel@tonic-gate (void) printf("[%s] ", inet_ntop(AF_INET, &ipv4addr, abuf, 12137c478bd9Sstevel@tonic-gate sizeof (abuf))); 12147c478bd9Sstevel@tonic-gate } else { 12157c478bd9Sstevel@tonic-gate (void) printf("[%s] ", hp->h_name); 12167c478bd9Sstevel@tonic-gate } 12177c478bd9Sstevel@tonic-gate bzero(&sin6, sizeof (sin6)); 12187c478bd9Sstevel@tonic-gate sin6.sin6_family = hp->h_addrtype; 12197c478bd9Sstevel@tonic-gate bcopy(hp->h_addr_list[0], (char *)&sin6.sin6_addr, hp->h_length); 12207c478bd9Sstevel@tonic-gate sin6.sin6_port = htons(IPPORT_FINGER); 12217c478bd9Sstevel@tonic-gate s = socket(sin6.sin6_family, SOCK_STREAM, 0); 12227c478bd9Sstevel@tonic-gate if (s < 0) { 12237c478bd9Sstevel@tonic-gate (void) fflush(stdout); 12247c478bd9Sstevel@tonic-gate perror("socket"); 12257c478bd9Sstevel@tonic-gate freehostent(hp); 12267c478bd9Sstevel@tonic-gate return (1); 12277c478bd9Sstevel@tonic-gate } 12287c478bd9Sstevel@tonic-gate while (connect(s, (struct sockaddr *)&sin6, sizeof (sin6)) < 0) { 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate if (hp && hp->h_addr_list[1]) { 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate hp->h_addr_list++; 12337c478bd9Sstevel@tonic-gate bcopy(hp->h_addr_list[0], 12347c478bd9Sstevel@tonic-gate (caddr_t)&sin6.sin6_addr, hp->h_length); 12357c478bd9Sstevel@tonic-gate (void) close(s); 12367c478bd9Sstevel@tonic-gate s = socket(sin6.sin6_family, SOCK_STREAM, 0); 12377c478bd9Sstevel@tonic-gate if (s < 0) { 12387c478bd9Sstevel@tonic-gate (void) fflush(stdout); 12397c478bd9Sstevel@tonic-gate perror("socket"); 12407c478bd9Sstevel@tonic-gate freehostent(hp); 12417c478bd9Sstevel@tonic-gate return (0); 12427c478bd9Sstevel@tonic-gate } 12437c478bd9Sstevel@tonic-gate continue; 12447c478bd9Sstevel@tonic-gate } 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate (void) fflush(stdout); 12477c478bd9Sstevel@tonic-gate perror("connect"); 12487c478bd9Sstevel@tonic-gate (void) close(s); 12497c478bd9Sstevel@tonic-gate freehostent(hp); 12507c478bd9Sstevel@tonic-gate return (1); 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate freehostent(hp); 12537c478bd9Sstevel@tonic-gate hp = NULL; 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate (void) printf("\n"); 12567c478bd9Sstevel@tonic-gate if (large) 12577c478bd9Sstevel@tonic-gate (void) write(s, "/W ", 3); 12587c478bd9Sstevel@tonic-gate (void) write(s, name, strlen(name)); 12597c478bd9Sstevel@tonic-gate (void) write(s, "\r\n", 2); 12607c478bd9Sstevel@tonic-gate f = fdopen(s, "r"); 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate lastc = '\n'; 12637c478bd9Sstevel@tonic-gate while ((c = getc(f)) != EOF) { 12647c478bd9Sstevel@tonic-gate /* map CRLF -> newline */ 12657c478bd9Sstevel@tonic-gate if ((lastc == '\r') && (c != '\n')) 12667c478bd9Sstevel@tonic-gate /* print out saved CR */ 12677c478bd9Sstevel@tonic-gate (void) putchar('\r'); 12687c478bd9Sstevel@tonic-gate lastc = c; 12697c478bd9Sstevel@tonic-gate if (c == '\r') 12707c478bd9Sstevel@tonic-gate continue; 12717c478bd9Sstevel@tonic-gate (void) putchar(c); 12727c478bd9Sstevel@tonic-gate } 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate if (lastc != '\n') 12757c478bd9Sstevel@tonic-gate (void) putchar('\n'); 12767c478bd9Sstevel@tonic-gate (void) fclose(f); 12777c478bd9Sstevel@tonic-gate return (1); 12787c478bd9Sstevel@tonic-gate } 12797c478bd9Sstevel@tonic-gate 12807c478bd9Sstevel@tonic-gate /* 12817c478bd9Sstevel@tonic-gate * AnyMail - takes a username (string pointer thereto), and 12827c478bd9Sstevel@tonic-gate * prints on standard output whether there is any unread mail, 12837c478bd9Sstevel@tonic-gate * and if so, how old it is. (JCM@Shasta 15 March 80) 12847c478bd9Sstevel@tonic-gate */ 12857c478bd9Sstevel@tonic-gate void 12867c478bd9Sstevel@tonic-gate AnyMail(char *name) 12877c478bd9Sstevel@tonic-gate { 12887c478bd9Sstevel@tonic-gate struct stat buf; /* space for file status buffer */ 12897c478bd9Sstevel@tonic-gate char *mbxdir = MAILDIR; /* string with path preamble */ 12907c478bd9Sstevel@tonic-gate char *mbxpath; /* space for entire pathname */ 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate char *timestr; 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate mbxpath = malloc(strlen(name) + strlen(MAILDIR) + 1); 12957c478bd9Sstevel@tonic-gate if (mbxpath == (char *)NULL) 12967c478bd9Sstevel@tonic-gate return; 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate (void) strcpy(mbxpath, mbxdir); /* copy preamble into path name */ 12997c478bd9Sstevel@tonic-gate (void) strcat(mbxpath, name); /* concatenate user name to path */ 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate if (stat(mbxpath, &buf) == -1 || buf.st_size == 0) { 13027c478bd9Sstevel@tonic-gate /* Mailbox is empty or nonexistent */ 13037c478bd9Sstevel@tonic-gate (void) printf("No unread mail\n"); 13047c478bd9Sstevel@tonic-gate } else { 13057c478bd9Sstevel@tonic-gate if (buf.st_mtime < buf.st_atime) { 13067c478bd9Sstevel@tonic-gate /* 13077c478bd9Sstevel@tonic-gate * No new mail since the last time the user read it. 13087c478bd9Sstevel@tonic-gate */ 13097c478bd9Sstevel@tonic-gate (void) printf("Mail last read "); 13107c478bd9Sstevel@tonic-gate (void) printf("%s", ctime(&buf.st_atime)); 13117c478bd9Sstevel@tonic-gate } else if (buf.st_mtime > buf.st_atime) { 13127c478bd9Sstevel@tonic-gate /* 13137c478bd9Sstevel@tonic-gate * New mail has definitely arrived since the last time 13147c478bd9Sstevel@tonic-gate * mail was read. mtime is the time the most recent 13157c478bd9Sstevel@tonic-gate * message arrived; atime is either the time the oldest 13167c478bd9Sstevel@tonic-gate * unread message arrived, or the last time the mail 13177c478bd9Sstevel@tonic-gate * was read. 13187c478bd9Sstevel@tonic-gate */ 13197c478bd9Sstevel@tonic-gate (void) printf("New mail received "); 13207c478bd9Sstevel@tonic-gate timestr = ctime(&buf.st_mtime); /* time last modified */ 13217c478bd9Sstevel@tonic-gate timestr[24] = '\0'; /* suppress newline (ugh) */ 13227c478bd9Sstevel@tonic-gate (void) printf("%s", timestr); 13237c478bd9Sstevel@tonic-gate (void) printf(";\n unread since "); 13247c478bd9Sstevel@tonic-gate (void) printf("%s", ctime(&buf.st_atime)); 13257c478bd9Sstevel@tonic-gate } else { 13267c478bd9Sstevel@tonic-gate /* 13277c478bd9Sstevel@tonic-gate * There is something in mailbox, but we can't really 13287c478bd9Sstevel@tonic-gate * be sure whether it is mail held there by the user 13297c478bd9Sstevel@tonic-gate * or a (single) new message that was placed in a newly 13307c478bd9Sstevel@tonic-gate * recreated mailbox, so punt and call it "unread mail." 13317c478bd9Sstevel@tonic-gate */ 13327c478bd9Sstevel@tonic-gate (void) printf("Unread mail since "); 13337c478bd9Sstevel@tonic-gate (void) printf("%s", ctime(&buf.st_mtime)); 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate } 13367c478bd9Sstevel@tonic-gate free(mbxpath); 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate /* 13407c478bd9Sstevel@tonic-gate * return true iff we've already printed project/plan for this uid; 13417c478bd9Sstevel@tonic-gate * if not, enter this uid into table (so this function has a side-effect.) 13427c478bd9Sstevel@tonic-gate */ 13437c478bd9Sstevel@tonic-gate #define PPMAX 4096 /* assume no more than 4096 logged-in users */ 13447c478bd9Sstevel@tonic-gate uid_t PlanPrinted[PPMAX+1]; 13457c478bd9Sstevel@tonic-gate int PPIndex = 0; /* index of next unused table entry */ 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate int 13487c478bd9Sstevel@tonic-gate AlreadyPrinted(uid_t uid) 13497c478bd9Sstevel@tonic-gate { 13507c478bd9Sstevel@tonic-gate int i = 0; 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate while (i++ < PPIndex) { 13537c478bd9Sstevel@tonic-gate if (PlanPrinted[i] == uid) 13547c478bd9Sstevel@tonic-gate return (1); 13557c478bd9Sstevel@tonic-gate } 13567c478bd9Sstevel@tonic-gate if (i < PPMAX) { 13577c478bd9Sstevel@tonic-gate PlanPrinted[i] = uid; 13587c478bd9Sstevel@tonic-gate PPIndex++; 13597c478bd9Sstevel@tonic-gate } 13607c478bd9Sstevel@tonic-gate return (0); 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate #define FIFOREADTIMEOUT (60) /* read timeout on select */ 13647c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */ 13657c478bd9Sstevel@tonic-gate #define PRINT_CHAR(c) \ 13667c478bd9Sstevel@tonic-gate ( \ 13677c478bd9Sstevel@tonic-gate ((termpass & TS_HIGH) && ((int)c) > 126) \ 13687c478bd9Sstevel@tonic-gate || \ 13697c478bd9Sstevel@tonic-gate (isascii((int)c) && \ 13707c478bd9Sstevel@tonic-gate (isprint((int)c) || isspace((int)c)) \ 13717c478bd9Sstevel@tonic-gate ) \ 13727c478bd9Sstevel@tonic-gate || \ 13737c478bd9Sstevel@tonic-gate ((termpass & TS_LOW) && ((int)c) < 32) \ 13747c478bd9Sstevel@tonic-gate ) 13757c478bd9Sstevel@tonic-gate /* END CSTYLED */ 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate void 13797c478bd9Sstevel@tonic-gate catfile(char *s, mode_t mode, int trunc_at_nl) 13807c478bd9Sstevel@tonic-gate { 13817c478bd9Sstevel@tonic-gate if (S_ISFIFO(mode)) { 13827c478bd9Sstevel@tonic-gate int fd; 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate fd = open(s, O_RDONLY | O_NONBLOCK); 13857c478bd9Sstevel@tonic-gate if (fd != -1) { 13867c478bd9Sstevel@tonic-gate fd_set readfds, exceptfds; 13877c478bd9Sstevel@tonic-gate struct timeval tv; 13887c478bd9Sstevel@tonic-gate 13897c478bd9Sstevel@tonic-gate FD_ZERO(&readfds); 13907c478bd9Sstevel@tonic-gate FD_ZERO(&exceptfds); 13917c478bd9Sstevel@tonic-gate FD_SET(fd, &readfds); 13927c478bd9Sstevel@tonic-gate FD_SET(fd, &exceptfds); 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate timerclear(&tv); 13957c478bd9Sstevel@tonic-gate tv.tv_sec = FIFOREADTIMEOUT; 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate (void) fflush(stdout); 13987c478bd9Sstevel@tonic-gate while (select(fd + 1, &readfds, (fd_set *) 0, 13997c478bd9Sstevel@tonic-gate &exceptfds, &tv) != -1) { 14007c478bd9Sstevel@tonic-gate unsigned char buf[BUFSIZ]; 14017c478bd9Sstevel@tonic-gate int nread; 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate nread = read(fd, buf, sizeof (buf)); 14047c478bd9Sstevel@tonic-gate if (nread > 0) { 14057c478bd9Sstevel@tonic-gate unsigned char *p; 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate FD_SET(fd, &readfds); 14087c478bd9Sstevel@tonic-gate FD_SET(fd, &exceptfds); 14097c478bd9Sstevel@tonic-gate for (p = buf; p < buf + nread; p++) { 14107c478bd9Sstevel@tonic-gate if (trunc_at_nl && *p == '\n') 14117c478bd9Sstevel@tonic-gate goto out; 14127c478bd9Sstevel@tonic-gate if (PRINT_CHAR(*p)) 14137c478bd9Sstevel@tonic-gate (void) putchar((int)*p); 14147c478bd9Sstevel@tonic-gate else if (isascii(*p)) 14157c478bd9Sstevel@tonic-gate (void) fputs(unctrl(*p), 14167c478bd9Sstevel@tonic-gate stdout); 14177c478bd9Sstevel@tonic-gate } 14187c478bd9Sstevel@tonic-gate } else 14197c478bd9Sstevel@tonic-gate break; 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate out: 14227c478bd9Sstevel@tonic-gate (void) close(fd); 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate } else { 14257c478bd9Sstevel@tonic-gate int c; 14267c478bd9Sstevel@tonic-gate FILE *fp; 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate fp = fopen(s, "r"); 14297c478bd9Sstevel@tonic-gate if (fp) { 14307c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) { 14317c478bd9Sstevel@tonic-gate if (trunc_at_nl && c == '\n') 14327c478bd9Sstevel@tonic-gate break; 14337c478bd9Sstevel@tonic-gate if (PRINT_CHAR(c)) 14347c478bd9Sstevel@tonic-gate (void) putchar((int)c); 14357c478bd9Sstevel@tonic-gate else 14367c478bd9Sstevel@tonic-gate if (isascii(c)) 14377c478bd9Sstevel@tonic-gate (void) fputs(unctrl(c), stdout); 14387c478bd9Sstevel@tonic-gate } 14397c478bd9Sstevel@tonic-gate (void) fclose(fp); 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate } 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate void 14467c478bd9Sstevel@tonic-gate initscreening(void) 14477c478bd9Sstevel@tonic-gate { 14487c478bd9Sstevel@tonic-gate char *options, *value; 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate if (defopen(defaultfile) == 0) { 14517c478bd9Sstevel@tonic-gate char *cp; 14527c478bd9Sstevel@tonic-gate int flags; 14537c478bd9Sstevel@tonic-gate 14547c478bd9Sstevel@tonic-gate /* 14557c478bd9Sstevel@tonic-gate * ignore case 14567c478bd9Sstevel@tonic-gate */ 14577c478bd9Sstevel@tonic-gate flags = defcntl(DC_GETFLAGS, 0); 14587c478bd9Sstevel@tonic-gate TURNOFF(flags, DC_CASE); 1459*06e1a714Sraf (void) defcntl(DC_SETFLAGS, flags); 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate if (cp = defread(passvar)) { 14627c478bd9Sstevel@tonic-gate options = cp; 14637c478bd9Sstevel@tonic-gate while (*options != '\0') 14647c478bd9Sstevel@tonic-gate switch (getsubopt(&options, termopts, &value)) { 14657c478bd9Sstevel@tonic-gate case TERM_LOW: 14667c478bd9Sstevel@tonic-gate termpass |= TS_LOW; 14677c478bd9Sstevel@tonic-gate break; 14687c478bd9Sstevel@tonic-gate case TERM_HIGH: 14697c478bd9Sstevel@tonic-gate termpass |= TS_HIGH; 14707c478bd9Sstevel@tonic-gate break; 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate } 14737c478bd9Sstevel@tonic-gate (void) defopen(NULL); /* close default file */ 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate } 1476