#include <errno.h>
#include <fcntl.h>
#include <libutil.h>
+#include <utmpx.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
typedef struct init_session {
int se_index; /* index of entry in ttys file */
pid_t se_process; /* controlling process */
- time_t se_started; /* used to avoid thrashing */
+ struct timeval se_started; /* used to avoid thrashing */
int se_flags; /* status of session */
#define SE_SHUTDOWN 0x1 /* session won't be restarted */
#define SE_PRESENT 0x2 /* session is in /etc/ttys */
static int runshutdown(void);
static char *strk(char *);
+#define DEATH 'd'
+#define SINGLE_USER 's'
+#define RUNCOM 'r'
+#define READ_TTYS 't'
+#define MULTI_USER 'm'
+#define CLEAN_TTYS 'T'
+#define CATATONIA 'c'
+
static state_func_t single_user(void);
static state_func_t runcom(void);
static state_func_t read_ttys(void);
static void del_session(session_t *);
static session_t *find_session(pid_t);
+#ifdef SUPPORT_UTMPX
+static struct timeval boot_time;
+state_t current_state = death;
+static void session_utmpx(const session_t *, int);
+static void make_utmpx(const char *, const char *, int, pid_t,
+ const struct timeval *, int);
+static char get_runlevel(const state_t);
+static void utmpx_set_runlevel(char, char);
+#endif
+
static int Reboot = FALSE;
static int howto = RB_AUTOBOOT;
static session_t *sessions;
state_t requested_transition = runcom;
+
/*
* The mother of all processes.
*/
sigset_t mask;
struct stat sts;
+#ifdef SUPPORT_UTMPX
+ (void)gettimeofday(&boot_time, NULL);
+#endif /* SUPPORT_UTMPX */
/* Dispose of random users. */
if (getuid() != 0)
static void
transition(state_t s)
{
- for (;;)
+ for (;;) {
+#ifdef SUPPORT_UTMPX
+ utmpx_set_runlevel(get_runlevel(current_state),
+ get_runlevel(s));
+ current_state = s;
+#endif
s = (state_t) (*s)();
+ }
}
/*
{
char *line = sp->se_device + sizeof(_PATH_DEV) - 1;
+#ifdef SUPPORT_UTMPX
+ if (logoutx(line, 0, DEAD_PROCESS))
+ logwtmpx(line, "", "", 0, DEAD_PROCESS);
+#endif
if (logout(line))
logwtmp(line, "", "");
}
runcom_mode = AUTOBOOT; /* the default */
/* NB: should send a message to the session logger to avoid blocking. */
+#ifdef SUPPORT_UTMPX
+ logwtmpx("~", "reboot", "", 0, INIT_PROCESS);
+#endif
logwtmp("~", "reboot", "");
return (state_func_t) read_ttys;
}
if ((*session_db->put)(session_db, &key, &data, 0))
emergency("insert %d: %s", sp->se_process, strerror(errno));
+#ifdef SUPPORT_UTMPX
+ session_utmpx(sp, 1);
+#endif
}
/*
if ((*session_db->del)(session_db, &key, 0))
emergency("delete %d: %s", sp->se_process, strerror(errno));
+#ifdef SUPPORT_UTMPX
+ session_utmpx(sp, 0);
+#endif
}
/*
session_t *sp, *snext;
struct ttyent *typ;
+#ifdef SUPPORT_UTMPX
+ if (sessions == NULL) {
+ struct stat st;
+
+ make_utmpx("", BOOT_MSG, BOOT_TIME, 0, &boot_time, 0);
+
+ /*
+ * If wtmpx is not empty, pick the down time from there
+ */
+ if (stat(_PATH_WTMPX, &st) != -1 && st.st_size != 0) {
+ struct timeval down_time;
+
+ TIMESPEC_TO_TIMEVAL(&down_time,
+ st.st_atime > st.st_mtime ?
+ &st.st_atimespec : &st.st_mtimespec);
+ make_utmpx("", DOWN_MSG, DOWN_TIME, 0, &down_time, 0);
+ }
+ }
+#endif
/*
* Destroy any previous session state.
* There shouldn't be any, but just in case...
int too_quick = 0;
char term[64], *env[2];
- if (current_time >= sp->se_started &&
- current_time - sp->se_started < GETTY_SPACING) {
+ if (current_time >= sp->se_started.tv_sec &&
+ current_time - sp->se_started.tv_sec < GETTY_SPACING) {
if (++sp->se_nspace > GETTY_NSPACE) {
sp->se_nspace = 0;
too_quick = 1;
}
sp->se_process = pid;
- sp->se_started = time(NULL);
+ gettimeofday(&sp->se_started, NULL);
add_session(sp);
}
break;
}
sp->se_process = pid;
- sp->se_started = time(NULL);
+ gettimeofday(&sp->se_started, NULL);
add_session(sp);
}
) {
/* Don't set SE_SHUTDOWN here */
sp->se_nspace = 0;
- sp->se_started = 0;
+ sp->se_started.tv_sec = sp->se_started.tv_usec = 0;
kill(sp->se_process, SIGHUP);
}
if (old_getty)
static const int death_sigs[2] = { SIGTERM, SIGKILL };
/* NB: should send a message to the session logger to avoid blocking. */
+#ifdef SUPPORT_UTMPX
+ logwtmpx("~", "shutdown", "", 0, INIT_PROCESS);
+#endif
logwtmp("~", "shutdown", "");
for (sp = sessions; sp; sp = sp->se_next) {
}
}
#endif
+
+#ifdef SUPPORT_UTMPX
+static void
+session_utmpx(const session_t *sp, int add)
+{
+ const char *name = sp->se_getty ? sp->se_getty :
+ (sp->se_window ? sp->se_window : "");
+ const char *line = sp->se_device + sizeof(_PATH_DEV) - 1;
+
+ make_utmpx(name, line, add ? LOGIN_PROCESS : DEAD_PROCESS,
+ sp->se_process, &sp->se_started, sp->se_index);
+}
+
+static void
+make_utmpx(const char *name, const char *line, int type, pid_t pid,
+ const struct timeval *tv, int session)
+{
+ struct utmpx ut;
+ const char *eline;
+
+ (void)memset(&ut, 0, sizeof(ut));
+ (void)strlcpy(ut.ut_name, name, sizeof(ut.ut_name));
+ ut.ut_type = type;
+ (void)strlcpy(ut.ut_line, line, sizeof(ut.ut_line));
+ ut.ut_pid = pid;
+ if (tv)
+ ut.ut_tv = *tv;
+ else
+ (void)gettimeofday(&ut.ut_tv, NULL);
+ ut.ut_session = session;
+
+ eline = line + strlen(line);
+ if ((size_t)(eline - line) >= sizeof(ut.ut_id))
+ line = eline - sizeof(ut.ut_id);
+ (void)strncpy(ut.ut_id, line, sizeof(ut.ut_id));
+
+ if (pututxline(&ut) == NULL)
+ warning("can't add utmpx record for `%s': %m", ut.ut_line);
+ endutxent();
+}
+
+static char
+get_runlevel(const state_t s)
+{
+ if (s == (state_t)single_user)
+ return SINGLE_USER;
+ if (s == (state_t)runcom)
+ return RUNCOM;
+ if (s == (state_t)read_ttys)
+ return READ_TTYS;
+ if (s == (state_t)multi_user)
+ return MULTI_USER;
+ if (s == (state_t)clean_ttys)
+ return CLEAN_TTYS;
+ if (s == (state_t)catatonia)
+ return CATATONIA;
+ return DEATH;
+}
+
+static void
+utmpx_set_runlevel(char old, char new)
+{
+ struct utmpx ut;
+
+ /*
+ * Don't record any transitions until we did the first transition
+ * to read ttys, which is when we are guaranteed to have a read-write
+ * /var. Perhaps use a different variable for this?
+ */
+ if (sessions == NULL)
+ return;
+
+ (void)memset(&ut, 0, sizeof(ut));
+ (void)snprintf(ut.ut_line, sizeof(ut.ut_line), RUNLVL_MSG, new);
+ ut.ut_type = RUN_LVL;
+ (void)gettimeofday(&ut.ut_tv, NULL);
+ ut.ut_exit.e_exit = old;
+ ut.ut_exit.e_termination = new;
+ if (pututxline(&ut) == NULL)
+ warning("can't add utmpx record for `runlevel': %m");
+ endutxent();
+}
+#endif
+/* $NetBSD: last.c,v 1.15 2000/06/30 06:19:58 simonb Exp $ */
+
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.bin/last/last.c,v 1.10.6.11 2002/11/02 23:00:26 mux Exp $
- * $DragonFly: src/usr.bin/last/last.c,v 1.5 2004/09/14 00:13:36 drhodus Exp $
- *
- * @(#) Copyright (c) 1987, 1993, 1994 The Regents of the University of California. All rights reserved.
- * @(#)last.c 8.2 (Berkeley) 4/2/94
*/
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)last.c 8.2 (Berkeley) 4/2/94";
+#endif
+__RCSID("$NetBSD: last.c,v 1.15 2000/06/30 06:19:58 simonb Exp $");
+#endif /* not lint */
+
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <fcntl.h>
-#include <langinfo.h>
-#include <locale.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <tzfile.h>
#include <unistd.h>
+#ifdef SUPPORT_UTMPX
+#include <utmpx.h>
+#endif
+#ifdef SUPPORT_UTMP
#include <utmp.h>
-#include <sys/queue.h>
+#endif
+
+#ifndef UT_NAMESIZE
+#define UT_NAMESIZE 8
+#define UT_LINESIZE 8
+#define UT_HOSTSIZE 16
+#endif
+#ifndef SIGNATURE
+#define SIGNATURE -1
+#endif
+
+
+
+#define NO 0 /* false/no */
+#define YES 1 /* true/yes */
+
+#define TBUFLEN 30 /* length of time string buffer */
+#define TFMT "%a %b %d %R" /* strftime format string */
+#define LTFMT "%a %b %d %Y %T" /* strftime long format string */
+#define TFMTS "%R" /* strftime format string - time only */
+#define LTFMTS "%T" /* strftime long format string - " */
-#define NO 0 /* false/no */
-#define YES 1 /* true/yes */
-#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
+/* fmttime() flags */
+#define FULLTIME 0x1 /* show year, seconds */
+#define TIMEONLY 0x2 /* show time only, not date */
+#define GMT 0x4 /* show time at GMT, for offsets only */
-static struct utmp buf[1024]; /* utmp read buffer */
+#define MAXUTMP 1024;
typedef struct arg {
- char *name; /* argument */
+ char *name; /* argument */
#define HOST_TYPE -2
#define TTY_TYPE -3
#define USER_TYPE -4
- int type; /* type of arg */
- struct arg *next; /* linked list pointer */
+ int type; /* type of arg */
+ struct arg *next; /* linked list pointer */
} ARG;
-ARG *arglist; /* head of linked list */
-
-LIST_HEAD(ttylisthead, ttytab) ttylist;
-
-struct ttytab {
- time_t logout; /* log out time */
- char tty[UT_LINESIZE + 1]; /* terminal name */
- LIST_ENTRY(ttytab) list;
-};
-
-static const char *crmsg; /* cause of last reboot */
-static long currentout, /* current logout value */
- maxrec; /* records to display */
-static const char *file = _PATH_WTMP; /* wtmp file */
-static int sflag = 0; /* show delta in seconds */
-static int width = 5; /* show seconds in delta */
-static int yflag; /* show year */
-static int d_first;
-static int snapfound = 0; /* found snapshot entry? */
-static time_t snaptime; /* if != 0, we will only
- * report users logged in
- * at this snapshot time
- */
+static ARG *arglist; /* head of linked list */
+
+typedef struct ttytab {
+ time_t logout; /* log out time */
+ char tty[128]; /* terminal name */
+ struct ttytab *next; /* linked list pointer */
+} TTY;
+static TTY *ttylist; /* head of linked list */
+
+static time_t currentout; /* current logout value */
+static long maxrec; /* records to display */
+static int fulltime = 0; /* Display seconds? */
int main(int, char *[]);
-void addarg(int, char *);
-time_t dateconv(char *);
-void doentry(struct utmp *);
-void hostconv(char *);
-void onintr(int);
-void printentry(struct utmp *, struct ttytab *);
-char *ttyconv(char *);
-char *ttyconv(char *);
-int want(struct utmp *);
-void usage(void);
-void wtmp(void);
-
-void
-usage(void)
+
+static void addarg(int, char *);
+static TTY *addtty(const char *);
+static void hostconv(char *);
+static char *ttyconv(char *);
+#ifdef SUPPORT_UTMPX
+static void wtmpx(const char *, int, int, int);
+#endif
+#ifdef SUPPORT_UTMP
+static void wtmp(const char *, int, int, int);
+#endif
+static char *fmttime(time_t, int);
+static void usage(void);
+
+static
+void usage(void)
{
- (void)fprintf(stderr,
-"usage: last [-#] [-y] [-d [[CC]YY][MMDD]hhmm[.SS]] [-f file] [-h host]\n"
-"\t[-t tty] [-s|w] [user ...]\n");
+ (void)fprintf(stderr, "Usage: %s [-#%s] [-f file] [-t tty]"
+ " [-h hostname] [-T] [user ...]\n", getprogname(),
+#ifdef SUPPORT_UTMPX
+ "w"
+#else
+ ""
+#endif
+ );
exit(1);
}
int
-main(int argc, char **argv)
+main(int argc, char *argv[])
{
int ch;
char *p;
-
- (void) setlocale(LC_TIME, "");
- d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+ char *file = NULL;
+ int namesize = UT_NAMESIZE;
+ int linesize = UT_LINESIZE;
+ int hostsize = UT_HOSTSIZE;
maxrec = -1;
- snaptime = 0;
- while ((ch = getopt(argc, argv, "0123456789d:f:h:st:wy")) != -1)
+
+ while ((ch = getopt(argc, argv, "0123456789f:h:H:L:N:t:T")) != -1)
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
* a number after a dash.
*/
if (maxrec == -1) {
- p = strchr(argv[optind - 1], ch);
- if (p == NULL)
- p = strchr(argv[optind], ch);
- maxrec = atol(p);
+ p = argv[optind - 1];
+ if (p[0] == '-' && p[1] == ch && !p[2])
+ maxrec = atol(++p);
+ else
+ maxrec = atol(argv[optind] + 1);
if (!maxrec)
exit(0);
}
break;
- case 'd':
- snaptime = dateconv(optarg);
- break;
case 'f':
file = optarg;
break;
hostconv(optarg);
addarg(HOST_TYPE, optarg);
break;
- case 's':
- sflag++; /* Show delta as seconds */
- break;
case 't':
addarg(TTY_TYPE, ttyconv(optarg));
break;
- case 'w':
- width = 8;
+ case 'U':
+ namesize = atoi(optarg);
+ break;
+ case 'L':
+ linesize = atoi(optarg);
+ break;
+ case 'H':
+ hostsize = atoi(optarg);
break;
- case 'y':
- yflag++;
+ case 'T':
+ fulltime = 1;
break;
case '?':
default:
usage();
}
- if (sflag && width == 8) usage();
-
if (argc) {
setlinebuf(stdout);
for (argv += optind; *argv; ++argv) {
addarg(USER_TYPE, *argv);
}
}
- wtmp();
- exit(0);
-}
-
-/*
- * wtmp --
- * read through the wtmp file
- */
-void
-wtmp(void)
-{
- struct utmp *bp; /* current structure */
- struct stat stb; /* stat of file for size */
- long bl;
- int bytes, wfd;
- char ct[80];
- struct tm *tm;
-
- LIST_INIT(&ttylist);
-
- if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1)
- err(1, "%s", file);
- bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
-
- (void)time(&buf[0].ut_time);
- (void)signal(SIGINT, onintr);
- (void)signal(SIGQUIT, onintr);
-
- while (--bl >= 0) {
- if (lseek(wfd, (off_t)(bl * sizeof(buf)), L_SET) == -1 ||
- (bytes = read(wfd, buf, sizeof(buf))) == -1)
- err(1, "%s", file);
- for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp)
- doentry(bp);
- }
- tm = localtime(&buf[0].ut_time);
- (void) strftime(ct, sizeof(ct), "\nwtmp begins %+\n", tm);
- printf("%s", ct);
-}
-
-/*
- * doentry --
- * process a single wtmp entry
- */
-void
-doentry(struct utmp *bp)
-{
- struct ttytab *tt, *ttx; /* ttylist entry */
-
- /*
- * if the terminal line is '~', the machine stopped.
- * see utmp(5) for more info.
- */
- if (bp->ut_line[0] == '~' && !bp->ut_line[1]) {
- /* everybody just logged out */
- for (tt = LIST_FIRST(&ttylist); tt;) {
- LIST_REMOVE(tt, list);
- ttx = tt;
- tt = LIST_NEXT(tt, list);
- free(ttx);
- }
- currentout = -bp->ut_time;
- crmsg = strncmp(bp->ut_name, "shutdown", UT_NAMESIZE) ?
- "crash" : "shutdown";
- /*
- * if we're in snapshot mode, we want to exit if this
- * shutdown/reboot appears while we we are tracking the
- * active range
- */
- if (snaptime && snapfound)
- exit(0);
- /*
- * don't print shutdown/reboot entries unless flagged for
- */
- if (!snaptime && want(bp))
- printentry(bp, NULL);
- return;
- }
- /*
- * if the line is '{' or '|', date got set; see
- * utmp(5) for more info.
- */
- if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|') &&
- !bp->ut_line[1]) {
- if (want(bp) && !snaptime)
- printentry(bp, NULL);
- return;
- }
- /* find associated tty */
- LIST_FOREACH(tt, &ttylist, list)
- if (!strncmp(tt->tty, bp->ut_line, UT_LINESIZE))
- break;
-
- if (tt == NULL) {
- /* add new one */
- tt = malloc(sizeof(struct ttytab));
- if (tt == NULL)
- err(1, "malloc failure");
- tt->logout = currentout;
- strncpy(tt->tty, bp->ut_line, UT_LINESIZE);
- LIST_INSERT_HEAD(&ttylist, tt, list);
- }
-
- /*
- * print record if not in snapshot mode and wanted
- * or in snapshot mode and in snapshot range
- */
- if (bp->ut_name[0] && (want(bp) || (bp->ut_time < snaptime &&
- (tt->logout > snaptime || tt->logout < 1)))) {
- snapfound = 1;
- /*
- * when uucp and ftp log in over a network, the entry in
- * the utmp file is the name plus their process id. See
- * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
- */
- if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
- bp->ut_line[3] = '\0';
- else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
- bp->ut_line[4] = '\0';
- printentry(bp, tt);
- }
- tt->logout = bp->ut_time;
-}
-
-/*
- * printentry --
- * output an entry
- *
- * If `tt' is non-NULL, use it and `crmsg' to print the logout time or
- * logout type (crash/shutdown) as appropriate.
- */
-void
-printentry(struct utmp *bp, struct ttytab *tt)
-{
- char ct[80];
- struct tm *tm;
- time_t delta; /* time difference */
-
- if (maxrec != -1 && !maxrec--)
- exit(0);
- tm = localtime(&bp->ut_time);
- (void) strftime(ct, sizeof(ct), d_first ?
- (yflag ? "%a %e %b %Y %R" : "%a %e %b %R") :
- (yflag ? "%a %b %e %Y %R" : "%a %b %e %R"), tm);
- printf("%-*.*s %-*.*s %-*.*s %s%c",
- UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
- UT_LINESIZE, UT_LINESIZE, bp->ut_line,
- UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
- ct, tt == NULL ? '\n' : ' ');
- if (tt == NULL)
- return;
- if (!tt->logout) {
- puts(" still logged in");
- return;
- }
- if (tt->logout < 0) {
- tt->logout = -tt->logout;
- printf("- %s", crmsg);
- } else {
- tm = localtime(&tt->logout);
- (void) strftime(ct, sizeof(ct), "%R", tm);
- printf("- %s", ct);
- }
- delta = tt->logout - bp->ut_time;
- if (sflag) {
- printf(" (%8ld)\n", (long)delta);
- } else {
- tm = gmtime(&delta);
- (void) strftime(ct, sizeof(ct), width >= 8 ? "%T" : "%R", tm);
- if (delta < 86400)
- printf(" (%s)\n", ct);
+ if (file == NULL) {
+ /* XXX: for now, default to utmp */
+#ifdef SUPPORT_UTMP
+ if (access(_PATH_WTMP, R_OK) == 0)
+ file = _PATH_WTMP;
else
- printf(" (%ld+%s)\n", (long)delta / 86400, ct);
+#endif
+#ifdef SUPPORT_UTMPX
+ if (access(_PATH_WTMPX, R_OK) == 0)
+ file = _PATH_WTMPX;
+#endif
+ if (file == NULL)
+#if defined(SUPPORT_UTMPX) && defined(SUPPORT_UTMP)
+ errx(1, "Cannot access `%s' or `%s'", _PATH_WTMPX,
+ _PATH_WTMP);
+#elif defined(SUPPORT_UTMPX)
+ errx(1, "Cannot access `%s'", _PATH_WTMPX);
+#elif defined(SUPPORT_UTMP)
+ errx(1, "Cannot access `%s'", _PATH_WTMP);
+#else
+ errx(1, "No utmp or utmpx support compiled in.");
+#endif
}
+#if defined(SUPPORT_UTMPX) && defined(SUPPORT_UTMP)
+ if (file[strlen(file) - 1] == 'x')
+ wtmpx(file, namesize, linesize, hostsize);
+ else
+ wtmp(file, namesize, linesize, hostsize);
+#elif defined(SUPPORT_UTMPX)
+ wtmpx(file, namesize, linesize, hostsize);
+#elif defined(SUPPORT_UTMP)
+ wtmp(file, namesize, linesize, hostsize);
+#else
+ errx(1, "Nu utmp or utmpx support compiled in.");
+#endif
+ exit(0);
}
-/*
- * want --
- * see if want this entry
- */
-int
-want(struct utmp *bp)
-{
- ARG *step;
-
- if (snaptime)
- return (NO);
-
- if (!arglist)
- return (YES);
-
- for (step = arglist; step; step = step->next)
- switch(step->type) {
- case HOST_TYPE:
- if (!strncasecmp(step->name, bp->ut_host, UT_HOSTSIZE))
- return (YES);
- break;
- case TTY_TYPE:
- if (!strncmp(step->name, bp->ut_line, UT_LINESIZE))
- return (YES);
- break;
- case USER_TYPE:
- if (!strncmp(step->name, bp->ut_name, UT_NAMESIZE))
- return (YES);
- break;
- }
- return (NO);
-}
/*
* addarg --
* add an entry to a linked list of arguments
*/
-void
+static void
addarg(int type, char *arg)
{
ARG *cur;
}
/*
+ * addtty --
+ * add an entry to a linked list of ttys
+ */
+static TTY *
+addtty(const char *ttyname)
+{
+ TTY *cur;
+
+ if (!(cur = (TTY *)malloc((u_int)sizeof(TTY))))
+ err(1, "malloc failure");
+ cur->next = ttylist;
+ cur->logout = currentout;
+ memmove(cur->tty, ttyname, sizeof(cur->tty));
+ return (ttylist = cur);
+}
+
+/*
* hostconv --
* convert the hostname to search pattern; if the supplied host name
* has a domain attached that is the same as the current domain, rip
* off the domain suffix since that's what login(1) does.
*/
-void
+static void
hostconv(char *arg)
{
static int first = 1;
- static char *hostdot, name[MAXHOSTNAMELEN];
+ static char *hostdot, name[MAXHOSTNAMELEN + 1];
char *argdot;
if (!(argdot = strchr(arg, '.')))
first = 0;
if (gethostname(name, sizeof(name)))
err(1, "gethostname");
+ name[sizeof(name) - 1] = '\0';
hostdot = strchr(name, '.');
}
if (hostdot && !strcasecmp(hostdot, argdot))
* ttyconv --
* convert tty to correct name.
*/
-char *
+static char *
ttyconv(char *arg)
{
char *mval;
}
/*
- * dateconv --
- * Convert the snapshot time in command line given in the format
- * [[CC]YY]MMDDhhmm[.SS]] to a time_t.
- * Derived from atime_arg1() in usr.bin/touch/touch.c
+ * fmttime --
+ * return pointer to (static) formatted time string.
*/
-time_t
-dateconv(char *arg)
+static char *
+fmttime(time_t t, int flags)
{
- time_t timet;
- struct tm *t;
- int yearset;
- char *p;
-
- /* Start with the current time. */
- if (time(&timet) < 0)
- err(1, "time");
- if ((t = localtime(&timet)) == NULL)
- err(1, "localtime");
-
- /* [[CC]YY]MMDDhhmm[.SS] */
- if ((p = strchr(arg, '.')) == NULL)
- t->tm_sec = 0; /* Seconds defaults to 0. */
- else {
- if (strlen(p + 1) != 2)
- goto terr;
- *p++ = '\0';
- t->tm_sec = ATOI2(p);
- }
-
- yearset = 0;
- switch (strlen(arg)) {
- case 12: /* CCYYMMDDhhmm */
- t->tm_year = ATOI2(arg);
- t->tm_year *= 100;
- yearset = 1;
- /* FALLTHROUGH */
- case 10: /* YYMMDDhhmm */
- if (yearset) {
- yearset = ATOI2(arg);
- t->tm_year += yearset;
- } else {
- yearset = ATOI2(arg);
- if (yearset < 69)
- t->tm_year = yearset + 2000;
- else
- t->tm_year = yearset + 1900;
- }
- t->tm_year -= 1900; /* Convert to UNIX time. */
- /* FALLTHROUGH */
- case 8: /* MMDDhhmm */
- t->tm_mon = ATOI2(arg);
- --t->tm_mon; /* Convert from 01-12 to 00-11 */
- t->tm_mday = ATOI2(arg);
- t->tm_hour = ATOI2(arg);
- t->tm_min = ATOI2(arg);
- break;
- case 4: /* hhmm */
- t->tm_hour = ATOI2(arg);
- t->tm_min = ATOI2(arg);
- break;
- default:
- goto terr;
- }
- t->tm_isdst = -1; /* Figure out DST. */
- timet = mktime(t);
- if (timet == -1)
-terr: errx(1,
- "out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]");
- return timet;
+ struct tm *tm;
+ static char tbuf[TBUFLEN];
+
+ tm = (flags & GMT) ? gmtime(&t) : localtime(&t);
+ strftime(tbuf, sizeof(tbuf),
+ (flags & TIMEONLY)
+ ? (flags & FULLTIME ? LTFMTS : TFMTS)
+ : (flags & FULLTIME ? LTFMT : TFMT),
+ tm);
+ return (tbuf);
}
+#ifdef SUPPORT_UTMP
+#define TYPE(a) 0
+#define NAMESIZE UT_NAMESIZE
+#define LINESIZE UT_LINESIZE
+#define HOSTSIZE UT_HOSTSIZE
+#define ut_timefld ut_time
+#define FIRSTVALID 0
+#include "want.c"
+#undef TYPE
+#undef NAMESIZE
+#undef LINESIZE
+#undef HOSTSIZE
+#undef ut_timefld
+#undef FIRSTVALID
+#endif
-/*
- * onintr --
- * on interrupt, we inform the user how far we've gotten
- */
-void
-onintr(int signo)
-{
- char ct[80];
- struct tm *tm;
-
- tm = localtime(&buf[0].ut_time);
- (void) strftime(ct, sizeof(ct),
- d_first ? "%a %e %b %R" : "%a %b %e %R",
- tm);
- printf("\ninterrupted %s\n", ct);
- if (signo == SIGINT)
- exit(1);
- (void)fflush(stdout); /* fix required for rsh */
-}
+#ifdef SUPPORT_UTMPX
+#define utmp utmpx
+#define want wantx
+#define wtmp wtmpx
+#define buf bufx
+#define onintr onintrx
+#define TYPE(a) (a)->ut_type
+#define NAMESIZE UTX_USERSIZE
+#define LINESIZE UTX_LINESIZE
+#define HOSTSIZE UTX_HOSTSIZE
+#define ut_timefld ut_xtime
+#define FIRSTVALID 1
+#include "want.c"
+#endif