Continuing with the privacy on a public unix system theme, one other binary that easily allows users to gain information about another user is last. Not only does last show the host or ip of a user as in the case with w and who, but last also shows when a user has logged on, allowing someone to learn information about usage patterns that most people would prefer to keep to themself.

The easiest way to avoid people seeing what they should not with last would be to stop people from using it by simply changing the permissions, however, some people like to see when they last logged on, and to make sure their account was only used by themselves. For these reasons, and several others, last is important. To that end, I decided to modify the last binary to make it so that a user can use it as normal, except that it will only give information about that user unless they are in group 0 (wheel), which on a freebsd machine is the users who are allowed to su to root.

To implement this, modifications of the want function were required to take into account both whether a user is in group wheel, and if not, what their login is, to ensure they see only that information.

int
want(bp)
    struct utmp *bp;
{
      
    struct passwd *pw;
    int id;
    gid_t gidset[5];
    int i;
    int groups;
    int access=0;
    ARG *step;

    id = getuid();
    pw = getpwuid(id);
    groups = getgroups(5, gidset);
    for (i=0; i<=groups-1; i++)
        if (gidset[i]==0) access=1;
    if (getgid()==0) access=1;

    if (!strcmp(bp->ut_name,pw->pw_name) || access==1) {
        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);
}