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

📄 last.c

📁 操作系统源代码
💻 C
字号:
/* last - display login history			Author: Terrence W. Holm *//* last-	Display the user log-in history. *		Last(1) searches backwards through the file of log-in *		records (/usr/adm/wtmp), displaying the length of *		log-in sessions as requested by the options: * * Usage:	last [-r] [-count] [-f file] [name] [tty] ... * *		-r	Search backwards only until the last reboot *			record. * *		-count	Only print out <count> records. Last(1) stops *			when either -r or -count is satisfied, or at *			the end of the file if neither is given. * *		-f file	Use "file" instead of "/usr/adm/wtmp". * *		name	Print records for the user "name". * *		tty	Print records for the terminal "tty". Actually, *			a list of names may be given and all records *			that match either the user or tty name are *			printed. If no names are given then all records *			are displayed. * *		A sigquit (^\) causes last(1) to display how far it *		has gone back in the log-in record file, it then *		continues. This is used to check on the progress of *		long running searches. A sigint will stop last(1). * * Author:	Terrence W. Holm	May 1988 * * Revision: *		Fred van Kempen, October 1989 *		 -Adapted to MSS. *		 -Adapted to new utmp database. * *		Fred van Kempen, December 1989 *		 -Adapted to POSIX (MINIX 1.5) * *		Fred van Kempen, January 1990 *		 -Final edit for 1.5 */#include <sys/types.h>#include <signal.h>#include <string.h>#include <utmp.h>#include <time.h>#include <stdlib.h>#include <stdio.h>#define  FALSE	0#define  TRUE	1#define  BUFFER_SIZE     4096	/* Room for wtmp records */#define  MAX_WTMP_COUNT  ( BUFFER_SIZE / sizeof(struct utmp) )#define  min( a, b )     ( (a < b) ? a : b )#define  max( a, b )	 ( (a > b) ? a : b )typedef struct logout {		/* A logout time record */  char line[12];		/* The terminal name */  long time;			/* The logout time */  struct logout *next;		/* Next in linked list */} logout;static char *Version = "@(#) LAST 1.7 (10/24/92)";/* command-line option flags */char boot_limit = FALSE;	/* stop on latest reboot */char count_limit = FALSE;	/* stop after print_count */int print_count;int arg_count;			/* used to select specific */char **args;			/* users and ttys *//* global variables */long boot_time = 0;		/* Zero means no reboot yet */char *boot_down;		/* "crash" or "down " flag */logout *first_link = NULL;	/* List of logout times */int interrupt = FALSE;		/* If sigint or sigquit occurs */_PROTOTYPE(int main, (int argc, char **argv));_PROTOTYPE(void Sigint, (int sig));_PROTOTYPE(void Sigquit, (int sig));_PROTOTYPE(void usage, (void));_PROTOTYPE(void Process, (struct utmp *wtmp));_PROTOTYPE(int Print_Record, (struct utmp *wtmp));_PROTOTYPE(void Print_Duration, (long from, long to));_PROTOTYPE(void Record_Logout_Time, (struct utmp *wtmp));/* Sigint() and Sigquit() Flag occurrence of an interrupt. */void Sigint(sig)int sig;{  interrupt = SIGINT;}void Sigquit(sig)int sig;{  interrupt = SIGQUIT;}void usage(){  fprintf(stderr, "Usage: last [-r] [-count] [-f file] [name] [tty] ...\n");  exit(-1);}/* A log-in record format file contains four types of records. * *  [1] generated on a system reboot: * *	line="~", name="reboot", host="", time=date() * * *  [2] generated after a shutdown: * *	line="~", name="shutdown", host="", time=date() * * *  [3] generated on a successful login(1) * *	line=ttyname(), name=cuserid(), host=, time=date() * * *  [4] generated by init(8) on a logout * *	line=ttyname(), name="", host="", time=date() * * * Note: This version of last(1) does not recognize the '|' and '}' time *	 change records. Last(1) pairs up line login's and logout's to *	 generate four types of output lines: * *	  [1] a system reboot or shutdown * *	   reboot    ~       Mon May 16 14:16 *	   shutdown  ~       Mon May 16 14:15 * *	  [2] a login with a matching logout * *	   edwin     tty1    Thu May 26 20:05 - 20:32  (00:27) * *	  [3] a login followed by a reboot or shutdown * *	   root      tty0    Mon May 16 13:57 - crash  (00:19) *	   root      tty1    Mon May 16 13:45 - down   (00:30) * *	  [4] a login not followed by a logout or reboot * *	   terry     tty0    Thu May 26 21:19   still logged in */void Process(wtmp)struct utmp *wtmp;{  logout *link;  logout *next_link;  /* suppress the job number on an "ftp" line */  if (!strncmp(wtmp->ut_line, "ftp", (size_t)3)) strncpy(wtmp->ut_line, "ftp", (size_t)8);  if (!strcmp(wtmp->ut_line, "~")) {	/* A reboot or shutdown record  */	if (boot_limit) exit(0);	if (Print_Record(wtmp)) putchar('\n');	boot_time = wtmp->ut_time;	if (!strcmp(wtmp->ut_name, "reboot"))		boot_down = "crash";	else		boot_down = "down ";	/* remove any logout records */	for (link = first_link; link != NULL; link = next_link) {		next_link = link->next;		free(link);	}	first_link = NULL;  } else if (wtmp->ut_name[0] == '\0') {	/* A logout record */	Record_Logout_Time(wtmp);  } else {	/* A login record */	for (link = first_link; link != NULL; link = link->next)		if (!strncmp(link->line, wtmp->ut_line, (size_t)8)) {			/* found corresponding logout record */			if (Print_Record(wtmp)) {				printf("- %.5s ", ctime(&link->time) + 11);				Print_Duration(wtmp->ut_time, link->time);			}			/* record login time */			link->time = wtmp->ut_time;			return;		}	/* could not find a logout record for this login tty */	if (Print_Record(wtmp))		if (boot_time == 0)	/* still on */			printf("  still logged in\n");		else {		/* system crashed while on */			printf("- %s ", boot_down);			Print_Duration(wtmp->ut_time, boot_time);		}	Record_Logout_Time(wtmp);	/* Needed in case of 2					 * consecutive logins  */  }}/* Print_Record(wtmp) If the record was requested, then print out * the user name, terminal, host and time. */int Print_Record(wtmp)struct utmp *wtmp;{  int i;  char print_flag = FALSE;  /* check if we have already printed the requested number of records */  if (count_limit && print_count == 0) exit(0);  for (i = 0; i < arg_count; ++i)	if (!strncmp(args[i], wtmp->ut_name, sizeof(wtmp->ut_name)) ||	    !strncmp(args[i], wtmp->ut_line, sizeof(wtmp->ut_line)))		print_flag = TRUE;  if (arg_count == 0 || print_flag) {#ifdef RLOGIN	printf("%-8.8s  %-8.8s %-16.16s %.16s ",	       wtmp->ut_name, wtmp->ut_line, wtmp->ut_host,	       ctime(&wtmp->ut_time));#else	printf("%-8.8s  %-8.8s  %.16s ",	       wtmp->ut_name, wtmp->ut_line, ctime(&wtmp->ut_time));#endif	--print_count;	return(TRUE);  }  return(FALSE);}/* Print_Duration(from, to) Calculate and print the days and hh:mm between * the log-in and the log-out. */void Print_Duration(from, to)long from;long to;{  long delta, days, hours, minutes;  delta = max(to - from, 0);  days = delta / (24L * 60L * 60L);  delta = delta % (24L * 60L * 60L);  hours = delta / (60L * 60L);  delta = delta % (60L * 60L);  minutes = delta / 60L;  if (days > 0)	printf("(%ld+", days);  else	printf(" (");  printf("%02ld:%02ld)\n", hours, minutes);}/* Record_Logout_Time(wtmp) A linked list of "last logout time" is kept. * Each element of the list is for one terminal. */void Record_Logout_Time(wtmp)struct utmp *wtmp;{  logout *link;  /* see if the terminal is already in the list */  for (link = first_link; link != NULL; link = link->next)	if (!strncmp(link->line, wtmp->ut_line, (size_t)8)) {		link->time = wtmp->ut_time;		return;	}  /* allocate a new logout record, for a tty not previously encountered */  link = (logout *) malloc(sizeof(logout));  if (link == NULL) {	fprintf(stderr, "last: malloc failure\n");	exit(1);  }  strncpy(link->line, wtmp->ut_line, (size_t)8);  link->time = wtmp->ut_time;  link->next = first_link;  first_link = link;}int main(argc, argv)int argc;char *argv[];{  char *wtmp_file = WTMP;  FILE *f;  long size;			/* Number of wtmp records in the file	 */  long now;			/* time */  int wtmp_count;		/* How many to read into wtmp_buffer	 */  struct utmp wtmp_buffer[MAX_WTMP_COUNT];  --argc;  ++argv;  while (argc > 0 && *argv[0] == '-') {	if (!strcmp(argv[0], "-r"))		boot_limit = TRUE;	else if (argc > 1 && !strcmp(argv[0], "-f")) {		wtmp_file = argv[1];		--argc;		++argv;	} else if ((print_count = atoi(argv[0] + 1)) > 0)		count_limit = TRUE;	else		usage();	--argc;	++argv;  }  arg_count = argc;  args = argv;  if ((f = fopen(wtmp_file, "r")) == NULL) {	perror(wtmp_file);	exit(1);  }  if (fseek(f, 0L, 2) != 0 || (size = ftell(f)) % sizeof(struct utmp) != 0) {	fprintf(stderr, "last: invalid wtmp file\n");	exit(1);  }  if (signal(SIGINT, SIG_IGN) != SIG_IGN) {	signal(SIGINT, Sigint);	signal(SIGQUIT, Sigquit);  }  size /= sizeof(struct utmp);	/* Number of records in wtmp	 */  if (size == 0) {	now = time((time_t *)0);	printf("\nwtmp begins %.16s \n", ctime(&now));	exit(0);  }  while (size > 0) {	wtmp_count = (int) min(size, MAX_WTMP_COUNT);	size -= (long) wtmp_count;	fseek(f, size * sizeof(struct utmp), 0);	if (fread(&wtmp_buffer[0], sizeof(struct utmp), (size_t)wtmp_count, f)	    != wtmp_count) {		fprintf(stderr, "last: read error on wtmp file\n");		exit(1);	}	while (--wtmp_count >= 0) {		Process(&wtmp_buffer[wtmp_count]);		if (interrupt) {			printf("\ninterrupted %.16s \n",			   ctime(&wtmp_buffer[wtmp_count].ut_time));			if (interrupt == SIGINT) exit(2);			interrupt = FALSE;			signal(SIGQUIT, Sigquit);		}	}  }				/* end while(size > 0) */  printf("\nwtmp begins %.16s \n", ctime(&wtmp_buffer[0].ut_time));  return(0);}

⌨️ 快捷键说明

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