⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 finger.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1980 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#ifndef lintstatic char sccsid[] = "@(#)finger.c 1.1 87/12/21 SMI"; /* from 5.8 3/13/86 */#endif /* not lint *//* * This is a finger program.  It prints out useful information about users * by digging it up from various system files. * * There are three output formats, all of which give login name, teletype * line number, and login time.  The short output format is reminiscent * of finger on ITS, and gives one line of information per user containing * in addition to the minimum basic requirements (MBR), the full name of * the user, his idle time and location.  The * quick style output is UNIX who-like, giving only name, teletype and * login time.  Finally, the long style output give the same information * as the short (in more legible format), the home directory and shell * of the user, and, if it exits, a copy of the file .plan in the users * home directory.  Finger may be called with or without a list of people * to finger -- if no list is given, all the people currently logged in * are fingered. * * The program is validly called by one of the following: * *	finger			{short form list of users} *	finger -l		{long form list of users} *	finger -b		{briefer long form list of users} *	finger -q		{quick list of users} *	finger -i		{quick list of users with idle times} *	finger namelist		{long format list of specified users} *	finger -s namelist	{short format list of specified users} *	finger -w namelist	{narrow short format list of specified users} * * where 'namelist' is a list of users login names. * The other options can all be given after one '-', or each can have its * own '-'.  The -f option disables the printing of headers for short and * quick outputs.  The -b option briefens long format outputs.  The -p * option turns off plans for long format outputs. */#include <sys/types.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <pwd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <utmp.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <net/gen/in.h>#include <net/gen/inet.h>#include <net/gen/netdb.h>#include <net/gen/socket.h>#include <net/gen/tcp.h>#include <net/gen/tcp_hdr.h>#include <net/gen/tcp_io.h>#include <net/hton.h>#include <net/netlib.h>#define NONOTHING	1		/* don't say "No plan", or "No mail" */#define NONET	0#define ASTERISK	'*'		/* ignore this in real name */#define COMMA		','		/* separator in pw_gecos field */#define COMMAND		'-'		/* command line flag char */#define SAMENAME	'&'		/* repeat login name in real name */#define TALKABLE	0220		/* tty is writable if this mode */struct utmp user;#define NMAX sizeof(user.ut_name)#define LMAX sizeof(user.ut_line)#define HMAX sizeof(user.ut_host)struct person {			/* one for each person fingered */	char *name;			/* name */	char tty[LMAX+1];		/* null terminated tty line */	char host[HMAX+1];		/* null terminated remote host name */	long loginat;			/* time of (last) login */	long idletime;			/* how long idle (if logged in) */	char *realname;			/* pointer to full name */	struct passwd *pwd;		/* structure of /etc/passwd stuff */	char loggedin;			/* person is logged in */	char writable;			/* tty is writable */	char original;			/* this is not a duplicate entry */	struct person *link;		/* link to next person */	char *where;			/* terminal location */	char hostt[HMAX+1];		/* login host */};char LASTLOG[] = "/usr/adm/lastlog";	/* last login info */char USERLOG[] = "/etc/utmp";		/* who is logged in */char PLAN[] = "/.plan";			/* what plan file is */char PROJ[] = "/.project";		/* what project file */	int unbrief = 1;			/* -b option default */int header = 1;				/* -f option default */int hack = 1;				/* -h option default */int idle = 0;				/* -i option default */int large = 0;				/* -l option default */int match = 1;				/* -m option default */int plan = 1;				/* -p option default */int unquick = 1;			/* -q option default */int small = 0;				/* -s option default */int wide = 1;				/* -w option default */int unshort;int lf;					/* LASTLOG file descriptor */struct person *person1;			/* list of people */long tloc;				/* current time */#if !_MINIXchar *strcpy();char *ctime();#endifchar *prog_name;int main (int argc, char *argv[]);static void doall(void);static void donames(char **args);static void print(void);static void fwopen(void);static void decode(struct person *pers);static void fwclose(void);static int netfinger (char *name);static int matchcmp (char *gname, char *login, char *given);static void quickprint (struct person *pers);static void shortprint (struct person *pers);static void personprint (struct person *pers);static int AlreadyPrinted(int uid);static int AnyMail (char *name);static struct passwd *pwdcopy(struct passwd *pfrom);static void findidle (struct person *pers);static int ltimeprint (char *dt, long *before, char *after);static void stimeprint (long *dt);static void findwhen (struct person *pers);static int namecmp (char *name1, char *name2);main(argc, argv)	int argc;	register char **argv;{	FILE *fp;	register char *s;	prog_name= argv[0];	/* parse command line for (optional) arguments */	while (*++argv && **argv == COMMAND)		for (s = *argv + 1; *s; s++)			switch (*s) {			case 'b':				unbrief = 0;				break;			case 'f':				header = 0;				break;			case 'h':				hack = 0;				break;			case 'i':				idle = 1;				unquick = 0;				break;			case 'l':				large = 1;				break;			case 'm':				match = 0;				break;			case 'p':				plan = 0;				break;			case 'q':				unquick = 0;				break;			case 's':				small = 1;				break;			case 'w':				wide = 0;				break;			default:				fprintf(stderr, "Usage: finger [-bfhilmpqsw] [login1 [login2 ...] ]\n");				exit(1);			}	if (unquick || idle)		time(&tloc);	/*	 * *argv == 0 means no names given	 */	if (*argv == 0)		doall();	else		donames(argv);	if (person1)		print();	exit(0);}static void doall(){	register struct person *p;	register struct passwd *pw;	int uf;	char name[NMAX + 1];	unshort = large;	if ((uf = open(USERLOG, 0)) < 0) {		fprintf(stderr, "finger: error opening %s\n", USERLOG);		exit(2);	}	if (unquick) {		setpwent();		fwopen();	}	while (read(uf, (char *)&user, sizeof user) == sizeof user) {		if (user.ut_name[0] == 0)			continue;		if (person1 == 0)			p = person1 = (struct person *) malloc(sizeof *p);		else {			p->link = (struct person *) malloc(sizeof *p);			p = p->link;		}		bcopy(user.ut_name, name, NMAX);		name[NMAX] = 0;		bcopy(user.ut_line, p->tty, LMAX);		p->tty[LMAX] = 0;		bcopy(user.ut_host, p->host, HMAX);		p->host[HMAX] = 0;		p->loginat = user.ut_time;		p->pwd = 0;		p->loggedin = 1;		p->where = NULL;		if (unquick && (pw = getpwnam(name))) {			p->pwd = pwdcopy(pw);			decode(p);			p->name = p->pwd->pw_name;		} else			p->name = strcpy(malloc(strlen(name) + 1), name);	}	if (unquick) {		fwclose();		endpwent();	}	close(uf);	if (person1 == 0) {		printf("No one logged on\n");		return;	}	p->link = 0;}static void donames(argv)	char **argv;{	register struct person *p;	register struct passwd *pw;	int uf;	/*	 * get names from command line and check to see if they're	 * logged in	 */	unshort = !small;	for (; *argv != 0; argv++) {		if (netfinger(*argv))			continue;		if (person1 == 0)			p = person1 = (struct person *) malloc(sizeof *p);		else {			p->link = (struct person *) malloc(sizeof *p);			p = p->link;		}		p->name = *argv;		p->loggedin = 0;		p->original = 1;		p->pwd = 0;	}	if (person1 == 0)		return;	p->link = 0;	/*	 * if we are doing it, read /etc/passwd for the useful info	 */	if (unquick) {		setpwent();		if (!match) {			for (p = person1; p != 0; p = p->link)				if (pw = getpwnam(p->name))					p->pwd = pwdcopy(pw);		} else while ((pw = getpwent()) != 0) {			for (p = person1; p != 0; p = p->link) {				if (!p->original)					continue;				if (strcmp(p->name, pw->pw_name) != 0 &&				    !matchcmp(pw->pw_gecos, pw->pw_name, p->name))					continue;				if (p->pwd == 0)					p->pwd = pwdcopy(pw);				else {					struct person *new;					/*					 * handle multiple login names, insert					 * new "duplicate" entry behind					 */					new = (struct person *)						malloc(sizeof *new);					new->pwd = pwdcopy(pw);					new->name = p->name;					new->original = 1;					new->loggedin = 0;					new->link = p->link;					p->original = 0;					p->link = new;					p = new;				}			}		}		endpwent();	}	/* Now get login information */	if ((uf = open(USERLOG, 0)) < 0) {		fprintf(stderr, "finger: error opening %s\n", USERLOG);		exit(2);	}	while (read(uf, (char *)&user, sizeof user) == sizeof user) {		if (*user.ut_name == 0)			continue;		for (p = person1; p != 0; p = p->link) {			if (p->loggedin == 2)				continue;			if (strncmp(p->pwd ? p->pwd->pw_name : p->name,				    user.ut_name, NMAX) != 0)				continue;			if (p->loggedin == 0) {				bcopy(user.ut_line, p->tty, LMAX);				p->tty[LMAX] = 0;				bcopy(user.ut_host, p->host, HMAX);				p->host[HMAX] = 0;				p->loginat = user.ut_time;				p->loggedin = 1;			} else {	/* p->loggedin == 1 */				struct person *new;				new = (struct person *) malloc(sizeof *new);				new->name = p->name;				bcopy(user.ut_line, new->tty, LMAX);				new->tty[LMAX] = 0;				bcopy(user.ut_host, new->host, HMAX);				new->host[HMAX] = 0;				new->loginat = user.ut_time;				new->pwd = p->pwd;				new->loggedin = 1;				new->original = 0;				new->link = p->link;				p->loggedin = 2;				p->link = new;				p = new;			}		}	}	close(uf);	if (unquick) {		fwopen();		for (p = person1; p != 0; p = p->link)			decode(p);		fwclose();	}}static void print(){	register FILE *fp;	register struct person *p;	register char *s;	register c;	/*	 * print out what we got	 */	if (header) {		if (unquick) {			if (!unshort)				if (wide)					printf("Login       Name              TTY Idle    When            Where\n");				else					printf("Login    TTY Idle    When            Where\n");		} else {			printf("Login      TTY            When");			if (idle)				printf("             Idle");			putchar('\n');		}	}	for (p = person1; p != 0; p = p->link) {		if (!unquick) {			quickprint(p);			continue;		}		if (!unshort) {			shortprint(p);			continue;		}		personprint(p);		if (p->pwd != 0 && !AlreadyPrinted(p->pwd->pw_uid)) {			AnyMail(p->pwd->pw_name);			if (hack) {				s = malloc(strlen(p->pwd->pw_dir) +					sizeof PROJ);				strcpy(s, p->pwd->pw_dir);				strcat(s, PROJ);				if ((fp = fopen(s, "r")) != 0) {					printf("Project: ");					while ((c = getc(fp)) != EOF) {						if (c == '\n')							break;						if (isprint(c) || isspace(c))							putchar(c);						else							putchar(c ^ 100);					}					fclose(fp);					putchar('\n');				}				free(s);			}			if (plan) {				s = malloc(strlen(p->pwd->pw_dir) +					sizeof PLAN);				strcpy(s, p->pwd->pw_dir);				strcat(s, PLAN);				if ((fp = fopen(s, "r")) == 0) {					if (!NONOTHING) printf("No Plan.\n");				} else {					printf("Plan:\n");					while ((c = getc(fp)) != EOF)						if (isprint(c) || isspace(c))							putchar(c);						else							putchar(c ^ 100);					fclose(fp);				}				free(s);			}		}		if (p->link != 0)			putchar('\n');	}}/* * Duplicate a pwd entry. * Note: Only the useful things (what the program currently uses) are copied. */static struct passwd *pwdcopy(pfrom)	register struct passwd *pfrom;{	register struct passwd *pto;	pto = (struct passwd *) malloc(sizeof *pto);#define savestr(s) strcpy(malloc(strlen(s) + 1), s)	pto->pw_name = savestr(pfrom->pw_name);	pto->pw_uid = pfrom->pw_uid;	pto->pw_gecos = savestr(pfrom->pw_gecos);	pto->pw_dir = savestr(pfrom->pw_dir);	pto->pw_shell = savestr(pfrom->pw_shell);#undef savestr	return pto;}/* * print out information on quick format giving just name, tty, login time * and idle time if idle is set. */static void quickprint(pers)	register struct person *pers;{	printf("%-*.*s  ", NMAX, NMAX, pers->name);	if (pers->loggedin) {		if (idle) {			findidle(pers);			printf("%c%-*s %-16.16s", pers->writable ? ' ' : '*',				LMAX, pers->tty, ctime(&pers->loginat));			ltimeprint("   ", &pers->idletime, "");		} else			printf(" %-*s %-16.16s", LMAX,				pers->tty, ctime(&pers->loginat));		putchar('\n');	} else		printf("          Not Logged In\n");}/* * print out information in short format, giving login name, full name, * tty, idle time, login time, and host. */static void shortprint(pers)	register struct person *pers;{	char *p;	char dialup;	if (pers->pwd == 0) {		printf("%-15s       ???\n", pers->name);		return;	}	printf("%-*s", NMAX, pers->pwd->pw_name);	dialup = 0;	if (wide) {		if (pers->realname)			printf(" %-20.20s", pers->realname);		else			printf("        ???          ");	}	putchar(' ');	if (pers->loggedin && !pers->writable)		putchar('*');	else		putchar(' ');	if (*pers->tty) {		if (pers->tty[0] == 't' && pers->tty[1] == 't' &&		    pers->tty[2] == 'y') {			if (pers->tty[3] == 'd' && pers->loggedin)				dialup = 1;			printf("%-2.2s ", pers->tty + 3);		} else			printf("%-2.2s ", pers->tty);	} else		printf("   ");	p = ctime(&pers->loginat);	if (pers->loggedin) {		stimeprint(&pers->idletime);		printf(" %3.3s %-5.5s ", p, p + 11);	} else if (pers->loginat == 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -