restore creation of y.tab.c
[unix-history] / usr / src / usr.bin / lastcomm / lastcomm.c
static char *sccsid = "@(#)lastcomm.c 4.4 (Berkeley) 82/07/17";
/*
* last command
*/
# include <stdio.h>
# include <sys/param.h>
# include <sys/acct.h>
# include <sys/dir.h>
# include <signal.h>
# include <pwd.h>
# include <stat.h>
# include <utmp.h>
# include <struct.h>
# define N_USER 4000 /* highest alloc user # */
# define N_DEVS 43 /* hash value for device names */
# define NDEVS 500 /* max number of file names in /dev */
struct acct acct_buff [BUFSIZ / sizeof (struct acct)];
char user_list [N_USER][fldsiz(utmp, ut_name) + 1];
struct devhash {
dev_t dev_dev;
char dev_name [fldsiz(utmp, ut_line) + 1];
struct devhash * dev_nxt;
}
* dev_hash [ N_DEVS ],
* dev_chain ;
# define HASH(d) (((int) d) % N_DEVS)
time_t expand ();
char * flagbits();
char * tername();
struct passwd
*passwd,
*getpwent ();
struct stat stat_buff;
# define equal(a, b) (strcmp(a, b) == 0)
main (argc, argv)
char **argv;
{
char acct_desc,
*p;
long i,
j,
i_block,
n_blocks,
n_byte,
n_entry;
float x;
/*
* set up user names
*/
while (passwd = getpwent ())
{
if (user_list[passwd->pw_uid][0]==0)
move (passwd->pw_name, user_list [passwd->pw_uid]);
}
/*
* find dev numbers corresponding to names in /dev
*/
setupdevs();
acct_desc = open ("/usr/adm/acct", 0);
if (acct_desc < 0)
{
perror ("/usr/adm/acct");
return;
}
fstat (acct_desc, &stat_buff);
n_blocks = (stat_buff.st_size + BUFSIZ - 1) / BUFSIZ;
/*
* read one block's worth
*/
for (i_block = n_blocks - 1; i_block >= 0; i_block--)
{
lseek (acct_desc, i_block * BUFSIZ, 0);
n_byte = read (acct_desc, acct_buff, BUFSIZ);
n_entry = n_byte / sizeof acct_buff [0];
for (i = n_entry - 1; i >= 0; i--)
{
if (!*user_list [acct_buff [i].ac_uid])
continue;
/*
* get the times
*/
x = expand (acct_buff [i].ac_utime)
+
expand (acct_buff [i].ac_stime);
/*
* null terminate the command name
*/
acct_buff [i].ac_comm [10] = 0;
/*
* replace missing command names with question marks
*/
if (!*acct_buff [i].ac_comm)
{
move ("?", acct_buff [i].ac_comm);
}
/*
* replace control characters with question marks
*/
for (p = acct_buff [i].ac_comm; *p; p++)
{
if (*p < '!' || '~' < *p)
*p = '?';
}
for (j = 1; j < argc; j++)
{
if
(
equal (acct_buff [i].ac_comm, argv [j])
||
equal
(
user_list[acct_buff[i].ac_uid],
argv [j]
)
||
equal
(
tername(acct_buff[i].ac_tty),
argv[j]
)
)
{
break;
}
}
if (argc == 1 || j != argc)
{
printf
(
"%-*s %s %-*s %-*s %6.2f %.16s\n"
, fldsiz(acct, ac_comm)
, acct_buff [i].ac_comm
, flagbits(acct_buff [i].ac_flag)
, fldsiz(utmp, ut_name)
, user_list [acct_buff [i].ac_uid]
, fldsiz(utmp, ut_line)
, tername(acct_buff [i].ac_tty)
, x / 60.0
, ctime (&acct_buff [i].ac_btime)
);
}
}
}
}
time_t
expand (t)
unsigned t;
{
register time_t nt;
nt = t & 017777;
t >>= 13;
while (t)
{
t--;
nt <<= 3;
}
return (nt);
}
move (a, b)
char *a, *b;
{
while (*b++ = *a++)
;
}
char *
flagbits(f)
register int f;
{
register int i = 0;
static char flags[20];
# define BIT(flag, ch) flags[i++] = ( f & flag ) ? ch : ' '
BIT( ASU, 'S');
BIT( AFORK, 'F');
BIT( ACOMPAT, 'C');
BIT( ACORE, 'D');
BIT( AXSIG, 'X');
flags[i] = '\0';
return(flags);
}
setupdevs()
{
register DIR * fd;
register struct devhash * hashtab;
register ndevs = NDEVS;
struct direct * dp;
if ((fd = opendir("/dev")) == NULL) {
perror("/dev");
return;
}
if ((hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash)))
== (struct devhash *) 0) {
fprintf(stderr, "No mem for dev table\n");
return;
}
while (dp = readdir(fd)) {
if (dp->d_ino == 0)
continue;
#ifdef MELB
if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console"))
continue;
#endif
strncpy(hashtab->dev_name, dp->d_name, fldsiz(utmp, ut_line));
hashtab->dev_name[fldsiz(utmp, ut_line)] = 0;
hashtab->dev_nxt = dev_chain;
dev_chain = hashtab;
hashtab++;
if (--ndevs <= 0)
break;
}
closedir(fd);
}
char *
tername(dev)
dev_t dev;
{
register struct devhash *hp, *nhp;
struct stat statb;
char name [fldsiz(devhash, dev_name) + 6];
static dev_t lastdev = (dev_t) -1;
static char *lastname;
if (dev == NODEV)
return("__");
if (dev == lastdev)
return(lastname);
for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt)
if (hp->dev_dev == dev) {
lastdev = dev;
return(lastname = hp->dev_name);
}
for (hp = dev_chain; hp; hp = nhp) {
nhp = hp->dev_nxt;
strcpy(name, "/dev/");
strcat(name, hp->dev_name);
if (stat(name, &statb) < 0) /* name truncated usually */
continue;
if ((statb.st_mode & S_IFMT) != S_IFCHR)
continue;
hp->dev_dev = statb.st_rdev;
hp->dev_nxt = dev_hash[HASH(hp->dev_dev)];
dev_hash[HASH(hp->dev_dev)] = hp;
if (hp->dev_dev == dev) {
dev_chain = nhp;
lastdev = dev;
return(lastname = hp->dev_name);
}
}
dev_chain = (struct devhash *) 0;
return("??");
}