Yawho (Yet Another Who) is a fast and simple program similar to 'w' that shows shows standard information (name, tty, processes.), plus whether telnet or ssh was used to access your machine. 4k.
49fb9ac61e4ac25b554ddce9c58a0369ecb6a1f6b7adddb10e76f1483cf721cd
/*
yawho 1.0 (Yet Another Who)
Simple program similar to 'w'. I wrote this because sometimes it is
good to know which users uses ssh and which uses telnet.
It shows you:
DAEMON - name of the daemon which was used to connect to your machine
USER
TTY
SHP (SHELL PID)
- pid of the login shell (just in case you're an admin and want
to kill someone's session ;-)
FROM
WHAT
You have to have read access to utmp and proc/.
compile: gcc yawho.c -o yawho
author: Michal Suszycki, mike@wizard.ae.krakow.pl
http://wizard.ae.krakow.pl/~mike
*/
#include <utmp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/ioctl.h>
#ifndef UTMP_FILE
#define UTMP_FILE "/var/run/utmp"
#endif
// Find parent pid (in /proc/pid/stat)
int get_ppid(int pid)
{
static int ppid;
char buff[256];
FILE *f;
sprintf(buff,"/proc/%d/stat",pid);
if (!(f = fopen(buff,"rt")))
return (-1);
fscanf(f,"%*d %*s %*c %d",&ppid);
fclose(f);
return ppid;
}
// For given pid find appropriate name (in /proc/pid/stat)
char *get_name(int pid)
{
static char buf[256];
FILE *f;
sprintf(buf,"/proc/%d/stat",pid);
if (!(f = fopen(buf,"rt")))
return "can't read";
fscanf(f,"%*d %s",buf);
fclose(f);
return buf;
}
char *get_cmdline(int pid)
{
static char buff[512];
FILE *f;
int i = 0;
sprintf(buff,"/proc/%d/cmdline",pid);
if (!(f = fopen(buff,"rt")))
return "-";
while (fread(buff+i,1,1,f) == 1){
if (buff[i] == '\0') buff[i] = ' ';
if (i == 512 - 2) break;
i++;
}
buff[i] = '\0';
fclose(f);
return buff;
}
/* get process group ID of the process which currently owns the tty
and return it's command line.
*/
char *get_command(int pid)
{
static char buf[256];
FILE *f;
static int tpgid;
sprintf(buf,"/proc/%d/stat",pid);
if (!(f = fopen(buf,"r"))) return "-";
fscanf(f,"%*d %*s %*c %*d %*d %*d %*d %d",&tpgid);
fclose(f);
return get_cmdline(tpgid);
}
struct utmp ent;
void main(int argc, char **argv)
{
int all = 0 ,ssh_users , telnet_users, local_users;
int fd, pid, ppid, i, longopt = 0;
char login[UT_NAMESIZE + 1], *parent;
struct winsize win;
void *tab[] = {
"(sshd)", &ssh_users,
"(sshd1)", &ssh_users,
"(in.telnetd)", &telnet_users,
"(init)", &local_users
};
if (argc == 2 && !strcmp(argv[1],"-l"))
longopt = 1;
else if (argc >= 2){
fprintf(stderr,"Unknown option.\nUsage: yawho [-l]\n"
"-l\tLong display (don't cut processes' names)\n");
exit (0);
}
if (ioctl(1,TIOCGWINSZ,&win) != -1 && win.ws_col < 80){
fprintf(stderr,"\t####### WARNING #######\n");
fprintf(stderr,"Not enough columns. Output could be unreadable.\n");
}
for (i = 0 ; i < 8 ; i += 2)
*(int *)tab[i+1] = 0;
if ((fd = open(UTMP_FILE ,O_RDONLY)) == -1) {
perror("open");
exit (0);
}
printf ("DAEMON USER TTY SHP FROM WHAT\n");
while (read(fd,&ent,sizeof(ent))){
strncpy(login,ent.ut_user,UT_NAMESIZE);
login[UT_NAMESIZE] = '\0';
pid = ent.ut_pid;
if (ent.ut_type == 7){
ppid = get_ppid(pid);
parent = get_name(ppid);
for (i = 0; i < 8 ; i += 2)
if (!strcmp((char *) tab[i], parent))
( *(int *)tab[i+1] )++;
printf("%-13.13s %-9.9s %-6.6s %-6d %-16.16s ",
parent,login,ent.ut_line,pid,ent.ut_host);
if (longopt)
printf("%-25s\n",get_command(pid));
else
printf("%-25.25s\n",get_command(pid));
all++;
}
}
close(fd);
printf("\n%d user",all);
all?printf("s "):printf(" ");
printf ("(%d local, %d telnet, %d ssh, %d other)\n",
local_users,telnet_users ,ssh_users, all-telnet_users-ssh_users-local_users);
}