How Do You Detect A User's Name With "fopen" in C.....? :<

B

blackneos940

Guest
I ask because I'm testing a VM with Windows 10 (I know, I know.... It's just for testing purposes:D)..... :) Anywho, I was wondering how to detect a Username..... :) You see, I already know how to write to a specific Directory (which is fun, when you know where the Start Menu Folder is in Windows..... >:)) Anywho, eventually, when I start making serious Applications, I'll need to detect the User's name, whether in *Nix, Windows, or OSX, or other Unices..... Like, for instance, in Linux, it's /home/nyancat/folders_that_come_next.... And in Windows, it's C:\Users\Doge\folders_that_come_next.... :3 I know it's possible, but, I know not HOW, or whether I'm even using the right LANGUAGE..... :\ Oh, someone's mowin' the Lawn outside..... :3 Anywho, if it's doable in C, can someone tell me how.....? I keep looking it up Online, but the *real* trick is knowing HOW to ask the Search Engine in question..... I DID learn how to find the Windows User's name, but all I can do is printf that Data..... :\

This is how I did that:

Code:
#include  <stdio.h>

int main(void)

{
    printf("%s\n", getenv("USERPROFILE"));  // Print user's home directory.
    return 0;

}

Anywho, that's pretty COOL..... :3 Nevertheless, it's not quite enough right now..... :\

Thanks for any help, guys!!..... ^^
~Namaste!....... :3
 


whoami(1) is a standard Unix utility and has different implementations.
This one is from GNU Coreutils:
Code:
/* whoami -- print effective userid

   Copyright (C) 1989-2016 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* Equivalent to 'id -un'. */
/* Written by Richard Mlynarik. */

#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#include <getopt.h>

#include "system.h"
#include "error.h"
#include "long-options.h"
#include "quote.h"

/* The official name of this program (e.g., no 'g' prefix).  */
#define PROGRAM_NAME "whoami"

#define AUTHORS proper_name ("Richard Mlynarik")

void
usage (int status)
{
  if (status != EXIT_SUCCESS)
    emit_try_help ();
  else
    {
      printf (_("Usage: %s [OPTION]...\n"), program_name);
      fputs (_("\
Print the user name associated with the current effective user ID.\n\
Same as id -un.\n\
\n\
"), stdout);
      fputs (HELP_OPTION_DESCRIPTION, stdout);
      fputs (VERSION_OPTION_DESCRIPTION, stdout);
      emit_ancillary_info (PROGRAM_NAME);
    }
  exit (status);
}

int
main (int argc, char **argv)
{
  struct passwd *pw;
  uid_t uid;
  uid_t NO_UID = -1;

  initialize_main (&argc, &argv);
  set_program_name (argv[0]);
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  atexit (close_stdout);

  parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                      usage, AUTHORS, (char const *) NULL);
  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
    usage (EXIT_FAILURE);

  if (optind != argc)
    {
      error (0, 0, _("extra operand %s"), quote (argv[optind]));
      usage (EXIT_FAILURE);
    }

  errno = 0;
  uid = geteuid ();
  pw = (uid == NO_UID && errno ? NULL : getpwuid (uid));
  if (!pw)
    error (EXIT_FAILURE, errno, _("cannot find name for user ID %lu"),
           (unsigned long int) uid);
  puts (pw->pw_name);
  return EXIT_SUCCESS;
}

This is from Busybox:
Code:
/* vi: set sw=4 ts=4: */
/*
* Mini whoami implementation for busybox
*
* Copyright (C) 2000 Edward Betts <[email protected]>.
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/

/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */

//usage:#define whoami_trivial_usage
//usage: ""
//usage:#define whoami_full_usage "\n\n"
//usage: "Print the user name associated with the current effective user id"

#include "libbb.h"

/* This is a NOFORK applet. Be very careful! */

int whoami_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int whoami_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
{
if (argv[1])
bb_show_usage();

/* Will complain and die if username not found */
puts(xuid2uname(geteuid()));

return fflush_all();
}

OS X uses slightly modified NetBSD version of who:
Code:
/* $NetBSD: who.c,v 1.23 2008/07/24 15:35:41 christos Exp $ */

/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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.
*/

#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1989, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */

#ifndef lint
#if 0
static char sccsid[] = "@(#)who.c 8.1 (Berkeley) 6/6/93";
#endif
__RCSID("$NetBSD: who.c,v 1.23 2008/07/24 15:35:41 christos Exp $");
#endif /* not lint */

#include <sys/types.h>
#include <sys/stat.h>

#include <err.h>
#include <locale.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef SUPPORT_UTMP
#include <utmp.h>
#endif
#ifdef SUPPORT_UTMPX
#include <utmpx.h>
#endif
#ifdef __APPLE__
#include <limits.h>
#include <paths.h>
#include <stdint.h>
#endif /* __APPLE__ */

#include "utmpentry.h"

#ifdef __APPLE__
#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
#endif /* __APPLE__ */

static void output_labels(void);
static void who_am_i(const char *, int);
static void usage(void) __dead;
static void process(const char *, int);
static void eprint(const struct utmpentry *);
static void print(const char *, const char *, time_t, const char *, pid_t pid,
uint16_t term, uint16_t xit, uint16_t sess, uint16_t type);
static void quick(const char *);

static int show_term; /* show term state */
static int show_idle; /* show idle time */
#ifndef __APPLE__
static int show_details; /* show exit status etc. */
#endif /* !__APPLE__ */

struct ut_type_names {
int type;
const char *name;
} ut_type_names[] = {
#ifdef SUPPORT_UTMPX
{ EMPTY, "empty" },
{ RUN_LVL, "run level" },
{ BOOT_TIME, "boot time" },
{ OLD_TIME, "old time" },
{ NEW_TIME, "new time" },
{ INIT_PROCESS, "init process" },
{ LOGIN_PROCESS, "login process" },
{ USER_PROCESS, "user process" },
{ DEAD_PROCESS, "dead process" },
#if defined(_NETBSD_SOURCE)
{ ACCOUNTING, "accounting" },
{ SIGNATURE, "signature" },
{ DOWN_TIME, "down time" },
#endif /* _NETBSD_SOURCE */
#endif /* SUPPORT_UTMPX */
{ -1, "unknown" }
};

int
main(int argc, char *argv[])
{
int c, only_current_term, show_labels, quick_mode, default_mode;
int et = 0;

setlocale(LC_ALL, "");

only_current_term = show_term = show_idle = show_labels = 0;
quick_mode = default_mode = 0;

while ((c = getopt(argc, argv, "abdHlmpqrsTtuv")) != -1) {
switch (c) {
case 'a':
et = -1;
#ifdef __APPLE__
show_idle = 1;
#else /* !__APPLE__ */
show_idle = show_details = 1;
#endif /* __APPLE__ */
break;
case 'b':
et |= (1 << BOOT_TIME);
break;
case 'd':
et |= (1 << DEAD_PROCESS);
break;
case 'H':
show_labels = 1;
break;
case 'l':
et |= (1 << LOGIN_PROCESS);
break;
case 'm':
only_current_term = 1;
break;
case 'p':
et |= (1 << INIT_PROCESS);
break;
case 'q':
quick_mode = 1;
break;
case 'r':
et |= (1 << RUN_LVL);
break;
case 's':
default_mode = 1;
break;
case 'T':
show_term = 1;
break;
case 't':
et |= (1 << NEW_TIME);
break;
case 'u':
show_idle = 1;
break;
#ifndef __APPLE__
case 'v':
show_details = 1;
break;
#endif /* !__APPLE__ */
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;

if (et != 0)
etype = et;

#ifndef __APPLE__
if (chdir("/dev")) {
err(EXIT_FAILURE, "cannot change directory to /dev");
/* NOTREACHED */
}
#endif /* !__APPLE__ */

if (default_mode)
only_current_term = show_term = show_idle = 0;

switch (argc) {
case 0: /* who */
if (quick_mode) {
quick(NULL);
} else if (only_current_term) {
who_am_i(NULL, show_labels);
} else {
process(NULL, show_labels);
}
break;
case 1: /* who utmp_file */
if (quick_mode) {
quick(*argv);
} else if (only_current_term) {
who_am_i(*argv, show_labels);
} else {
process(*argv, show_labels);
}
break;
case 2: /* who am i */
who_am_i(NULL, show_labels);
break;
default:
usage();
/* NOTREACHED */
}

return 0;
}

static char *
strrstr(const char *str, const char *pat)
{
const char *estr;
size_t len;
if (*pat == '\0')
return __UNCONST(str);

len = strlen(pat);

for (estr = str + strlen(str); str < estr; estr--)
if (strncmp(estr, pat, len) == 0)
return __UNCONST(estr);
return NULL;
}

static void
who_am_i(const char *fname, int show_labels)
{
struct passwd *pw;
const char *p;
char *t;
time_t now;
struct utmpentry *ehead, *ep;

/* search through the utmp and find an entry for this tty */
if ((p = ttyname(STDIN_FILENO)) != NULL) {

/* strip directory prefixes for ttys */
if ((t = strrstr(p, "/pts/")) != NULL ||
(t = strrchr(p, '/')) != NULL)
p = t + 1;

(void)getutentries(fname, &ehead);
for (ep = ehead; ep; ep = ep->next)
if (strcmp(ep->line, p) == 0) {
if (show_labels)
output_labels();
eprint(ep);
return;
}
} else
p = "tty??";

(void)time(&now);
pw = getpwuid(getuid());
if (show_labels)
output_labels();
print(pw ? pw->pw_name : "?", p, now, "", getpid(), 0, 0, 0, 0);
}

static void
process(const char *fname, int show_labels)
{
struct utmpentry *ehead, *ep;
(void)getutentries(fname, &ehead);
if (show_labels)
output_labels();
for (ep = ehead; ep != NULL; ep = ep->next)
eprint(ep);
#ifdef __APPLE__
if ((etype & (1 << RUN_LVL)) != 0) {
printf(" . run-level 3\n");
}
#endif /* __APPLE__ */
}

static void
eprint(const struct utmpentry *ep)
{
print(ep->name, ep->line, (time_t)ep->tv.tv_sec, ep->host, ep->pid,
#ifdef __APPLE__
0, 0, 0, ep->type);
#else /* !__APPLE__ */
ep->term, ep->exit, ep->sess, ep->type);
#endif /* __APPLE__ */
}

static void
print(const char *name, const char *line, time_t t, const char *host,
pid_t pid, uint16_t term, uint16_t xit, uint16_t sess, uint16_t type)
{
struct stat sb;
char state;
static time_t now = 0;
time_t idle;
const char *types = NULL;
size_t i;

state = '?';
idle = 0;

for (i = 0; ut_type_names[i].type >= 0; i++) {
types = ut_type_names[i].name;
if (ut_type_names[i].type == type)
break;
}

if (show_term || show_idle) {
if (now == 0)
time(&now);

#ifdef __APPLE__
char tty[PATH_MAX + 1];
snprintf(tty, sizeof(tty), "%s%s", _PATH_DEV, line);
if (stat(tty, &sb) == 0) {
#else /* !__APPLE__ */
if (stat(line, &sb) == 0) {
#endif /* __APPLE__ */
state = (sb.st_mode & 020) ? '+' : '-';
idle = now - sb.st_atime;
}

}

#ifdef __APPLE__
switch (type) {
case LOGIN_PROCESS:
(void)printf("%-*.*s ", maxname, maxname, "LOGIN");
break;
case BOOT_TIME:
(void)printf("%-*.*s ", maxname, maxname, "reboot");
break;
default:
(void)printf("%-*.*s ", maxname, maxname, name);
break;
}
#else /* !__APPLE__ */
(void)printf("%-*.*s ", maxname, maxname, name);
#endif /* __APPLE__ */

if (show_term)
(void)printf("%c ", state);

#ifdef __APPLE__
(void)printf("%-*.*s ", maxline, maxline, type == BOOT_TIME ? "~" : line);
#else /* !__APPLE__ */
(void)printf("%-*.*s ", maxline, maxline, line);
#endif /* __APPLE__ */
(void)printf("%.12s ", ctime(&t) + 4);

if (show_idle) {
if (idle < 60)
(void)printf(" . ");
else if (idle < (24 * 60 * 60))
(void)printf("%02ld:%02ld ",
(long)(idle / (60 * 60)),
(long)(idle % (60 * 60)) / 60);
else
(void)printf(" old ");

(void)printf("\t%6d", pid);

#ifndef __APPLE__
if (show_details) {
if (type == RUN_LVL)
(void)printf("\tnew=%c old=%c", term, xit);
else
(void)printf("\tterm=%d exit=%d", term, xit);
(void)printf(" sess=%d", sess);
(void)printf(" type=%s ", types);
}
#endif /* !__APPLE__ */
}

#ifdef __APPLE__
/* 6179576 */
if (type == DEAD_PROCESS)
(void)printf("\tterm=%d exit=%d", 0, 0);
#endif /* __APPLE__ */

if (*host)
(void)printf("\t(%.*s)", maxhost, host);
(void)putchar('\n');
}

static void
output_labels(void)
{
(void)printf("%-*.*s ", maxname, maxname, "USER");

if (show_term)
(void)printf("S ");

(void)printf("%-*.*s ", maxline, maxline, "LINE");
(void)printf("WHEN ");

if (show_idle) {
(void)printf("IDLE ");
(void)printf("\t PID");

(void)printf("\tCOMMENT");
}

(void)putchar('\n');
}

static void
quick(const char *fname)
{
struct utmpentry *ehead, *ep;
int num = 0;

(void)getutentries(fname, &ehead);
for (ep = ehead; ep != NULL; ep = ep->next) {
(void)printf("%-*s ", maxname, ep->name);
if ((++num % 8) == 0)
(void)putchar('\n');
}
if (num % 8)
(void)putchar('\n');

(void)printf("# users = %d\n", num);
}

static void
usage(void)
{
#ifdef __APPLE__
(void)fprintf(stderr, "Usage: %s [-abdHlmpqrsTtu] [file]\n\t%s am i\n",
#else /* !__APPLE__ */
(void)fprintf(stderr, "Usage: %s [-abdHlmqrsTtuv] [file]\n\t%s am i\n",
#endif /* __APPLE__ */
getprogname(), getprogname());
exit(EXIT_FAILURE);
}

So, here's NetBSD's one:
Code:
/* $NetBSD: who.c,v 1.25 2015/11/21 15:01:43 christos Exp $ */

/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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.
*/

#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1989, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */

#ifndef lint
#if 0
static char sccsid[] = "@(#)who.c 8.1 (Berkeley) 6/6/93";
#endif
__RCSID("$NetBSD: who.c,v 1.25 2015/11/21 15:01:43 christos Exp $");
#endif /* not lint */

#include <sys/types.h>
#include <sys/stat.h>

#include <err.h>
#include <locale.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef SUPPORT_UTMP
#include <utmp.h>
#endif
#ifdef SUPPORT_UTMPX
#include <utmpx.h>
#endif

#include "utmpentry.h"

static void output_labels(void);
static void who_am_i(const char *, int);
static void usage(void) __dead;
static void process(const char *, int);
static void eprint(const struct utmpentry *);
static void print(const char *, const char *, time_t, const char *, pid_t pid,
uint16_t term, uint16_t xit, uint16_t sess, uint16_t type);
static void quick(const char *);

static int show_term; /* show term state */
static int show_idle; /* show idle time */
static int show_details; /* show exit status etc. */

struct ut_type_names {
int type;
const char *name;
} ut_type_names[] = {
#ifdef SUPPORT_UTMPX
{ EMPTY, "empty" },
{ RUN_LVL, "run level" },
{ BOOT_TIME, "boot time" },
{ OLD_TIME, "old time" },
{ NEW_TIME, "new time" },
{ INIT_PROCESS, "init process" },
{ LOGIN_PROCESS, "login process" },
{ USER_PROCESS, "user process" },
{ DEAD_PROCESS, "dead process" },
#if defined(_NETBSD_SOURCE)
{ ACCOUNTING, "accounting" },
{ SIGNATURE, "signature" },
{ DOWN_TIME, "down time" },
#endif /* _NETBSD_SOURCE */
#endif /* SUPPORT_UTMPX */
{ -1, "unknown" }
};

int
main(int argc, char *argv[])
{
int c, only_current_term, show_labels, quick_mode, default_mode;
int et = 0;

setlocale(LC_ALL, "");

only_current_term = show_term = show_idle = show_labels = 0;
quick_mode = default_mode = 0;

while ((c = getopt(argc, argv, "abdHlmpqrsTtuv")) != -1) {
switch (c) {
case 'a':
et = -1;
show_idle = show_details = 1;
break;
case 'b':
et |= (1 << BOOT_TIME);
break;
case 'd':
et |= (1 << DEAD_PROCESS);
break;
case 'H':
show_labels = 1;
break;
case 'l':
et |= (1 << LOGIN_PROCESS);
break;
case 'm':
only_current_term = 1;
break;
case 'p':
et |= (1 << INIT_PROCESS);
break;
case 'q':
quick_mode = 1;
break;
case 'r':
et |= (1 << RUN_LVL);
break;
case 's':
default_mode = 1;
break;
case 'T':
show_term = 1;
break;
case 't':
et |= (1 << NEW_TIME);
break;
case 'u':
show_idle = 1;
break;
case 'v':
show_details = 1;
break;
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;

if (et != 0)
etype = et;

if (chdir("/dev")) {
err(EXIT_FAILURE, "cannot change directory to /dev");
/* NOTREACHED */
}

if (default_mode)
only_current_term = show_term = show_idle = 0;

switch (argc) {
case 0: /* who */
if (quick_mode) {
quick(NULL);
} else if (only_current_term) {
who_am_i(NULL, show_labels);
} else {
process(NULL, show_labels);
}
break;
case 1: /* who utmp_file */
if (quick_mode) {
quick(*argv);
} else if (only_current_term) {
who_am_i(*argv, show_labels);
} else {
process(*argv, show_labels);
}
break;
case 2: /* who am i */
who_am_i(NULL, show_labels);
break;
default:
usage();
/* NOTREACHED */
}

return 0;
}

static char *
strrstr(const char *str, const char *pat)
{
const char *estr;
size_t len;
if (*pat == '\0')
return __UNCONST(str);

len = strlen(pat);

for (estr = str + strlen(str); str < estr; estr--)
if (strncmp(estr, pat, len) == 0)
return __UNCONST(estr);
return NULL;
}

static void
who_am_i(const char *fname, int show_labels)
{
struct passwd *pw;
const char *p;
char *t;
time_t now;
struct utmpentry *ehead, *ep;

/* search through the utmp and find an entry for this tty */
if ((p = ttyname(STDIN_FILENO)) != NULL) {

/* strip directory prefixes for ttys */
if ((t = strrstr(p, "/pts/")) != NULL ||
(t = strrchr(p, '/')) != NULL)
p = t + 1;

(void)getutentries(fname, &ehead);
for (ep = ehead; ep; ep = ep->next)
if (strcmp(ep->line, p) == 0) {
if (show_labels)
output_labels();
eprint(ep);
return;
}
} else
p = "tty??";

(void)time(&now);
pw = getpwuid(getuid());
if (show_labels)
output_labels();
print(pw ? pw->pw_name : "?", p, now, "", getpid(), 0, 0, 0, 0);
}

static void
process(const char *fname, int show_labels)
{
struct utmpentry *ehead, *ep;
(void)getutentries(fname, &ehead);
if (show_labels)
output_labels();
for (ep = ehead; ep != NULL; ep = ep->next)
eprint(ep);
}

static void
eprint(const struct utmpentry *ep)
{
print(ep->name, ep->line, (time_t)ep->tv.tv_sec, ep->host, ep->pid,
ep->term, ep->exit, ep->sess, ep->type);
}

static void
print(const char *name, const char *line, time_t t, const char *host,
pid_t pid, uint16_t term, uint16_t xit, uint16_t sess, uint16_t type)
{
struct stat sb;
char state;
static time_t now = 0;
time_t idle;
const char *types = NULL;
size_t i;
char *tstr;

state = '?';
idle = 0;

for (i = 0; ut_type_names[i].type >= 0; i++) {
types = ut_type_names[i].name;
if (ut_type_names[i].type == type)
break;
}

if (show_term || show_idle) {
if (now == 0)
time(&now);

if (stat(line, &sb) == 0) {
state = (sb.st_mode & 020) ? '+' : '-';
idle = now - sb.st_atime;
}

}

(void)printf("%-*.*s ", (int)maxname, (int)maxname, name);

if (show_term)
(void)printf("%c ", state);

(void)printf("%-*.*s ", (int)maxline, (int)maxline, line);
tstr = ctime(&t);
(void)printf("%.12s ", tstr ? tstr + 4 : "?");

if (show_idle) {
if (idle < 60)
(void)printf(" . ");
else if (idle < (24 * 60 * 60))
(void)printf("%02ld:%02ld ",
(long)(idle / (60 * 60)),
(long)(idle % (60 * 60)) / 60);
else
(void)printf(" old ");

(void)printf("\t%6d", pid);

if (show_details) {
if (type == RUN_LVL)
(void)printf("\tnew=%c old=%c", term, xit);
else
(void)printf("\tterm=%d exit=%d", term, xit);
(void)printf(" sess=%d", sess);
(void)printf(" type=%s ", types);
}
}

if (*host)
(void)printf("\t(%.*s)", (int)maxhost, host);
(void)putchar('\n');
}

static void
output_labels(void)
{
(void)printf("%-*.*s ", (int)maxname, (int)maxname, "USER");

if (show_term)
(void)printf("S ");

(void)printf("%-*.*s ", (int)maxline, (int)maxline, "LINE");
(void)printf("WHEN ");

if (show_idle) {
(void)printf("IDLE ");
(void)printf("\t PID");

(void)printf("\tCOMMENT");
}

(void)putchar('\n');
}

static void
quick(const char *fname)
{
struct utmpentry *ehead, *ep;
int num = 0;

(void)getutentries(fname, &ehead);
for (ep = ehead; ep != NULL; ep = ep->next) {
(void)printf("%-*s ", (int)maxname, ep->name);
if ((++num % 8) == 0)
(void)putchar('\n');
}
if (num % 8)
(void)putchar('\n');

(void)printf("# users = %d\n", num);
}

static void
usage(void)
{
(void)fprintf(stderr, "Usage: %s [-abdHlmqrsTtuv] [file]\n\t%s am i\n",
getprogname(), getprogname());
exit(EXIT_FAILURE);
}

And from suckless:
Code:
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>

#include "util.h"

static void
usage(void)
{
eprintf("usage: %s\n", argv0);
}

int
main(int argc, char *argv[])
{
uid_t uid;
struct passwd *pw;

argv0 = argv[0], argc--, argv++;

if (argc)
usage();

uid = geteuid();
errno = 0;
if (!(pw = getpwuid(uid))) {
if (errno)
eprintf("getpwuid %d:", uid);
else
eprintf("getpwuid %d: no such user\n", uid);
}
puts(pw->pw_name);

return fshut(stdout, "<stdout>");
}

If we cut down suckless' version of it (removing errno and their util.h library), we will have:
Code:
#include <stdio.h>
#include <pwd.h>
#include <unistd.h>

int
main (void) {
uid_t uid;
struct passwd *pw;
uid = getuid();
if (!(pw = getpwuid(uid))) {
printf("getpwuid %d:", uid);
}
puts (pw->pw_name);
}
 
whoami(1) is a standard Unix utility and has different implementations.
This one is from GNU Coreutils:
Code:
/* whoami -- print effective userid

   Copyright (C) 1989-2016 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* Equivalent to 'id -un'. */
/* Written by Richard Mlynarik. */

#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#include <getopt.h>

#include "system.h"
#include "error.h"
#include "long-options.h"
#include "quote.h"

/* The official name of this program (e.g., no 'g' prefix).  */
#define PROGRAM_NAME "whoami"

#define AUTHORS proper_name ("Richard Mlynarik")

void
usage (int status)
{
  if (status != EXIT_SUCCESS)
    emit_try_help ();
  else
    {
      printf (_("Usage: %s [OPTION]...\n"), program_name);
      fputs (_("\
Print the user name associated with the current effective user ID.\n\
Same as id -un.\n\
\n\
"), stdout);
      fputs (HELP_OPTION_DESCRIPTION, stdout);
      fputs (VERSION_OPTION_DESCRIPTION, stdout);
      emit_ancillary_info (PROGRAM_NAME);
    }
  exit (status);
}

int
main (int argc, char **argv)
{
  struct passwd *pw;
  uid_t uid;
  uid_t NO_UID = -1;

  initialize_main (&argc, &argv);
  set_program_name (argv[0]);
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  atexit (close_stdout);

  parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                      usage, AUTHORS, (char const *) NULL);
  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
    usage (EXIT_FAILURE);

  if (optind != argc)
    {
      error (0, 0, _("extra operand %s"), quote (argv[optind]));
      usage (EXIT_FAILURE);
    }

  errno = 0;
  uid = geteuid ();
  pw = (uid == NO_UID && errno ? NULL : getpwuid (uid));
  if (!pw)
    error (EXIT_FAILURE, errno, _("cannot find name for user ID %lu"),
           (unsigned long int) uid);
  puts (pw->pw_name);
  return EXIT_SUCCESS;
}

This is from Busybox:
Code:
/* vi: set sw=4 ts=4: */
/*
* Mini whoami implementation for busybox
*
* Copyright (C) 2000 Edward Betts <[email protected]>.
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/

/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */

//usage:#define whoami_trivial_usage
//usage: ""
//usage:#define whoami_full_usage "\n\n"
//usage: "Print the user name associated with the current effective user id"

#include "libbb.h"

/* This is a NOFORK applet. Be very careful! */

int whoami_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int whoami_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
{
if (argv[1])
bb_show_usage();

/* Will complain and die if username not found */
puts(xuid2uname(geteuid()));

return fflush_all();
}

OS X uses slightly modified NetBSD version of who:
Code:
/* $NetBSD: who.c,v 1.23 2008/07/24 15:35:41 christos Exp $ */

/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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.
*/

#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1989, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */

#ifndef lint
#if 0
static char sccsid[] = "@(#)who.c 8.1 (Berkeley) 6/6/93";
#endif
__RCSID("$NetBSD: who.c,v 1.23 2008/07/24 15:35:41 christos Exp $");
#endif /* not lint */

#include <sys/types.h>
#include <sys/stat.h>

#include <err.h>
#include <locale.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef SUPPORT_UTMP
#include <utmp.h>
#endif
#ifdef SUPPORT_UTMPX
#include <utmpx.h>
#endif
#ifdef __APPLE__
#include <limits.h>
#include <paths.h>
#include <stdint.h>
#endif /* __APPLE__ */

#include "utmpentry.h"

#ifdef __APPLE__
#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
#endif /* __APPLE__ */

static void output_labels(void);
static void who_am_i(const char *, int);
static void usage(void) __dead;
static void process(const char *, int);
static void eprint(const struct utmpentry *);
static void print(const char *, const char *, time_t, const char *, pid_t pid,
uint16_t term, uint16_t xit, uint16_t sess, uint16_t type);
static void quick(const char *);

static int show_term; /* show term state */
static int show_idle; /* show idle time */
#ifndef __APPLE__
static int show_details; /* show exit status etc. */
#endif /* !__APPLE__ */

struct ut_type_names {
int type;
const char *name;
} ut_type_names[] = {
#ifdef SUPPORT_UTMPX
{ EMPTY, "empty" },
{ RUN_LVL, "run level" },
{ BOOT_TIME, "boot time" },
{ OLD_TIME, "old time" },
{ NEW_TIME, "new time" },
{ INIT_PROCESS, "init process" },
{ LOGIN_PROCESS, "login process" },
{ USER_PROCESS, "user process" },
{ DEAD_PROCESS, "dead process" },
#if defined(_NETBSD_SOURCE)
{ ACCOUNTING, "accounting" },
{ SIGNATURE, "signature" },
{ DOWN_TIME, "down time" },
#endif /* _NETBSD_SOURCE */
#endif /* SUPPORT_UTMPX */
{ -1, "unknown" }
};

int
main(int argc, char *argv[])
{
int c, only_current_term, show_labels, quick_mode, default_mode;
int et = 0;

setlocale(LC_ALL, "");

only_current_term = show_term = show_idle = show_labels = 0;
quick_mode = default_mode = 0;

while ((c = getopt(argc, argv, "abdHlmpqrsTtuv")) != -1) {
switch (c) {
case 'a':
et = -1;
#ifdef __APPLE__
show_idle = 1;
#else /* !__APPLE__ */
show_idle = show_details = 1;
#endif /* __APPLE__ */
break;
case 'b':
et |= (1 << BOOT_TIME);
break;
case 'd':
et |= (1 << DEAD_PROCESS);
break;
case 'H':
show_labels = 1;
break;
case 'l':
et |= (1 << LOGIN_PROCESS);
break;
case 'm':
only_current_term = 1;
break;
case 'p':
et |= (1 << INIT_PROCESS);
break;
case 'q':
quick_mode = 1;
break;
case 'r':
et |= (1 << RUN_LVL);
break;
case 's':
default_mode = 1;
break;
case 'T':
show_term = 1;
break;
case 't':
et |= (1 << NEW_TIME);
break;
case 'u':
show_idle = 1;
break;
#ifndef __APPLE__
case 'v':
show_details = 1;
break;
#endif /* !__APPLE__ */
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;

if (et != 0)
etype = et;

#ifndef __APPLE__
if (chdir("/dev")) {
err(EXIT_FAILURE, "cannot change directory to /dev");
/* NOTREACHED */
}
#endif /* !__APPLE__ */

if (default_mode)
only_current_term = show_term = show_idle = 0;

switch (argc) {
case 0: /* who */
if (quick_mode) {
quick(NULL);
} else if (only_current_term) {
who_am_i(NULL, show_labels);
} else {
process(NULL, show_labels);
}
break;
case 1: /* who utmp_file */
if (quick_mode) {
quick(*argv);
} else if (only_current_term) {
who_am_i(*argv, show_labels);
} else {
process(*argv, show_labels);
}
break;
case 2: /* who am i */
who_am_i(NULL, show_labels);
break;
default:
usage();
/* NOTREACHED */
}

return 0;
}

static char *
strrstr(const char *str, const char *pat)
{
const char *estr;
size_t len;
if (*pat == '\0')
return __UNCONST(str);

len = strlen(pat);

for (estr = str + strlen(str); str < estr; estr--)
if (strncmp(estr, pat, len) == 0)
return __UNCONST(estr);
return NULL;
}

static void
who_am_i(const char *fname, int show_labels)
{
struct passwd *pw;
const char *p;
char *t;
time_t now;
struct utmpentry *ehead, *ep;

/* search through the utmp and find an entry for this tty */
if ((p = ttyname(STDIN_FILENO)) != NULL) {

/* strip directory prefixes for ttys */
if ((t = strrstr(p, "/pts/")) != NULL ||
(t = strrchr(p, '/')) != NULL)
p = t + 1;

(void)getutentries(fname, &ehead);
for (ep = ehead; ep; ep = ep->next)
if (strcmp(ep->line, p) == 0) {
if (show_labels)
output_labels();
eprint(ep);
return;
}
} else
p = "tty??";

(void)time(&now);
pw = getpwuid(getuid());
if (show_labels)
output_labels();
print(pw ? pw->pw_name : "?", p, now, "", getpid(), 0, 0, 0, 0);
}

static void
process(const char *fname, int show_labels)
{
struct utmpentry *ehead, *ep;
(void)getutentries(fname, &ehead);
if (show_labels)
output_labels();
for (ep = ehead; ep != NULL; ep = ep->next)
eprint(ep);
#ifdef __APPLE__
if ((etype & (1 << RUN_LVL)) != 0) {
printf(" . run-level 3\n");
}
#endif /* __APPLE__ */
}

static void
eprint(const struct utmpentry *ep)
{
print(ep->name, ep->line, (time_t)ep->tv.tv_sec, ep->host, ep->pid,
#ifdef __APPLE__
0, 0, 0, ep->type);
#else /* !__APPLE__ */
ep->term, ep->exit, ep->sess, ep->type);
#endif /* __APPLE__ */
}

static void
print(const char *name, const char *line, time_t t, const char *host,
pid_t pid, uint16_t term, uint16_t xit, uint16_t sess, uint16_t type)
{
struct stat sb;
char state;
static time_t now = 0;
time_t idle;
const char *types = NULL;
size_t i;

state = '?';
idle = 0;

for (i = 0; ut_type_names[i].type >= 0; i++) {
types = ut_type_names[i].name;
if (ut_type_names[i].type == type)
break;
}

if (show_term || show_idle) {
if (now == 0)
time(&now);

#ifdef __APPLE__
char tty[PATH_MAX + 1];
snprintf(tty, sizeof(tty), "%s%s", _PATH_DEV, line);
if (stat(tty, &sb) == 0) {
#else /* !__APPLE__ */
if (stat(line, &sb) == 0) {
#endif /* __APPLE__ */
state = (sb.st_mode & 020) ? '+' : '-';
idle = now - sb.st_atime;
}

}

#ifdef __APPLE__
switch (type) {
case LOGIN_PROCESS:
(void)printf("%-*.*s ", maxname, maxname, "LOGIN");
break;
case BOOT_TIME:
(void)printf("%-*.*s ", maxname, maxname, "reboot");
break;
default:
(void)printf("%-*.*s ", maxname, maxname, name);
break;
}
#else /* !__APPLE__ */
(void)printf("%-*.*s ", maxname, maxname, name);
#endif /* __APPLE__ */

if (show_term)
(void)printf("%c ", state);

#ifdef __APPLE__
(void)printf("%-*.*s ", maxline, maxline, type == BOOT_TIME ? "~" : line);
#else /* !__APPLE__ */
(void)printf("%-*.*s ", maxline, maxline, line);
#endif /* __APPLE__ */
(void)printf("%.12s ", ctime(&t) + 4);

if (show_idle) {
if (idle < 60)
(void)printf(" . ");
else if (idle < (24 * 60 * 60))
(void)printf("%02ld:%02ld ",
(long)(idle / (60 * 60)),
(long)(idle % (60 * 60)) / 60);
else
(void)printf(" old ");

(void)printf("\t%6d", pid);

#ifndef __APPLE__
if (show_details) {
if (type == RUN_LVL)
(void)printf("\tnew=%c old=%c", term, xit);
else
(void)printf("\tterm=%d exit=%d", term, xit);
(void)printf(" sess=%d", sess);
(void)printf(" type=%s ", types);
}
#endif /* !__APPLE__ */
}

#ifdef __APPLE__
/* 6179576 */
if (type == DEAD_PROCESS)
(void)printf("\tterm=%d exit=%d", 0, 0);
#endif /* __APPLE__ */

if (*host)
(void)printf("\t(%.*s)", maxhost, host);
(void)putchar('\n');
}

static void
output_labels(void)
{
(void)printf("%-*.*s ", maxname, maxname, "USER");

if (show_term)
(void)printf("S ");

(void)printf("%-*.*s ", maxline, maxline, "LINE");
(void)printf("WHEN ");

if (show_idle) {
(void)printf("IDLE ");
(void)printf("\t PID");

(void)printf("\tCOMMENT");
}

(void)putchar('\n');
}

static void
quick(const char *fname)
{
struct utmpentry *ehead, *ep;
int num = 0;

(void)getutentries(fname, &ehead);
for (ep = ehead; ep != NULL; ep = ep->next) {
(void)printf("%-*s ", maxname, ep->name);
if ((++num % 8) == 0)
(void)putchar('\n');
}
if (num % 8)
(void)putchar('\n');

(void)printf("# users = %d\n", num);
}

static void
usage(void)
{
#ifdef __APPLE__
(void)fprintf(stderr, "Usage: %s [-abdHlmpqrsTtu] [file]\n\t%s am i\n",
#else /* !__APPLE__ */
(void)fprintf(stderr, "Usage: %s [-abdHlmqrsTtuv] [file]\n\t%s am i\n",
#endif /* __APPLE__ */
getprogname(), getprogname());
exit(EXIT_FAILURE);
}

So, here's NetBSD's one:
Code:
/* $NetBSD: who.c,v 1.25 2015/11/21 15:01:43 christos Exp $ */

/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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.
*/

#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1989, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */

#ifndef lint
#if 0
static char sccsid[] = "@(#)who.c 8.1 (Berkeley) 6/6/93";
#endif
__RCSID("$NetBSD: who.c,v 1.25 2015/11/21 15:01:43 christos Exp $");
#endif /* not lint */

#include <sys/types.h>
#include <sys/stat.h>

#include <err.h>
#include <locale.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef SUPPORT_UTMP
#include <utmp.h>
#endif
#ifdef SUPPORT_UTMPX
#include <utmpx.h>
#endif

#include "utmpentry.h"

static void output_labels(void);
static void who_am_i(const char *, int);
static void usage(void) __dead;
static void process(const char *, int);
static void eprint(const struct utmpentry *);
static void print(const char *, const char *, time_t, const char *, pid_t pid,
uint16_t term, uint16_t xit, uint16_t sess, uint16_t type);
static void quick(const char *);

static int show_term; /* show term state */
static int show_idle; /* show idle time */
static int show_details; /* show exit status etc. */

struct ut_type_names {
int type;
const char *name;
} ut_type_names[] = {
#ifdef SUPPORT_UTMPX
{ EMPTY, "empty" },
{ RUN_LVL, "run level" },
{ BOOT_TIME, "boot time" },
{ OLD_TIME, "old time" },
{ NEW_TIME, "new time" },
{ INIT_PROCESS, "init process" },
{ LOGIN_PROCESS, "login process" },
{ USER_PROCESS, "user process" },
{ DEAD_PROCESS, "dead process" },
#if defined(_NETBSD_SOURCE)
{ ACCOUNTING, "accounting" },
{ SIGNATURE, "signature" },
{ DOWN_TIME, "down time" },
#endif /* _NETBSD_SOURCE */
#endif /* SUPPORT_UTMPX */
{ -1, "unknown" }
};

int
main(int argc, char *argv[])
{
int c, only_current_term, show_labels, quick_mode, default_mode;
int et = 0;

setlocale(LC_ALL, "");

only_current_term = show_term = show_idle = show_labels = 0;
quick_mode = default_mode = 0;

while ((c = getopt(argc, argv, "abdHlmpqrsTtuv")) != -1) {
switch (c) {
case 'a':
et = -1;
show_idle = show_details = 1;
break;
case 'b':
et |= (1 << BOOT_TIME);
break;
case 'd':
et |= (1 << DEAD_PROCESS);
break;
case 'H':
show_labels = 1;
break;
case 'l':
et |= (1 << LOGIN_PROCESS);
break;
case 'm':
only_current_term = 1;
break;
case 'p':
et |= (1 << INIT_PROCESS);
break;
case 'q':
quick_mode = 1;
break;
case 'r':
et |= (1 << RUN_LVL);
break;
case 's':
default_mode = 1;
break;
case 'T':
show_term = 1;
break;
case 't':
et |= (1 << NEW_TIME);
break;
case 'u':
show_idle = 1;
break;
case 'v':
show_details = 1;
break;
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;

if (et != 0)
etype = et;

if (chdir("/dev")) {
err(EXIT_FAILURE, "cannot change directory to /dev");
/* NOTREACHED */
}

if (default_mode)
only_current_term = show_term = show_idle = 0;

switch (argc) {
case 0: /* who */
if (quick_mode) {
quick(NULL);
} else if (only_current_term) {
who_am_i(NULL, show_labels);
} else {
process(NULL, show_labels);
}
break;
case 1: /* who utmp_file */
if (quick_mode) {
quick(*argv);
} else if (only_current_term) {
who_am_i(*argv, show_labels);
} else {
process(*argv, show_labels);
}
break;
case 2: /* who am i */
who_am_i(NULL, show_labels);
break;
default:
usage();
/* NOTREACHED */
}

return 0;
}

static char *
strrstr(const char *str, const char *pat)
{
const char *estr;
size_t len;
if (*pat == '\0')
return __UNCONST(str);

len = strlen(pat);

for (estr = str + strlen(str); str < estr; estr--)
if (strncmp(estr, pat, len) == 0)
return __UNCONST(estr);
return NULL;
}

static void
who_am_i(const char *fname, int show_labels)
{
struct passwd *pw;
const char *p;
char *t;
time_t now;
struct utmpentry *ehead, *ep;

/* search through the utmp and find an entry for this tty */
if ((p = ttyname(STDIN_FILENO)) != NULL) {

/* strip directory prefixes for ttys */
if ((t = strrstr(p, "/pts/")) != NULL ||
(t = strrchr(p, '/')) != NULL)
p = t + 1;

(void)getutentries(fname, &ehead);
for (ep = ehead; ep; ep = ep->next)
if (strcmp(ep->line, p) == 0) {
if (show_labels)
output_labels();
eprint(ep);
return;
}
} else
p = "tty??";

(void)time(&now);
pw = getpwuid(getuid());
if (show_labels)
output_labels();
print(pw ? pw->pw_name : "?", p, now, "", getpid(), 0, 0, 0, 0);
}

static void
process(const char *fname, int show_labels)
{
struct utmpentry *ehead, *ep;
(void)getutentries(fname, &ehead);
if (show_labels)
output_labels();
for (ep = ehead; ep != NULL; ep = ep->next)
eprint(ep);
}

static void
eprint(const struct utmpentry *ep)
{
print(ep->name, ep->line, (time_t)ep->tv.tv_sec, ep->host, ep->pid,
ep->term, ep->exit, ep->sess, ep->type);
}

static void
print(const char *name, const char *line, time_t t, const char *host,
pid_t pid, uint16_t term, uint16_t xit, uint16_t sess, uint16_t type)
{
struct stat sb;
char state;
static time_t now = 0;
time_t idle;
const char *types = NULL;
size_t i;
char *tstr;

state = '?';
idle = 0;

for (i = 0; ut_type_names[i].type >= 0; i++) {
types = ut_type_names[i].name;
if (ut_type_names[i].type == type)
break;
}

if (show_term || show_idle) {
if (now == 0)
time(&now);

if (stat(line, &sb) == 0) {
state = (sb.st_mode & 020) ? '+' : '-';
idle = now - sb.st_atime;
}

}

(void)printf("%-*.*s ", (int)maxname, (int)maxname, name);

if (show_term)
(void)printf("%c ", state);

(void)printf("%-*.*s ", (int)maxline, (int)maxline, line);
tstr = ctime(&t);
(void)printf("%.12s ", tstr ? tstr + 4 : "?");

if (show_idle) {
if (idle < 60)
(void)printf(" . ");
else if (idle < (24 * 60 * 60))
(void)printf("%02ld:%02ld ",
(long)(idle / (60 * 60)),
(long)(idle % (60 * 60)) / 60);
else
(void)printf(" old ");

(void)printf("\t%6d", pid);

if (show_details) {
if (type == RUN_LVL)
(void)printf("\tnew=%c old=%c", term, xit);
else
(void)printf("\tterm=%d exit=%d", term, xit);
(void)printf(" sess=%d", sess);
(void)printf(" type=%s ", types);
}
}

if (*host)
(void)printf("\t(%.*s)", (int)maxhost, host);
(void)putchar('\n');
}

static void
output_labels(void)
{
(void)printf("%-*.*s ", (int)maxname, (int)maxname, "USER");

if (show_term)
(void)printf("S ");

(void)printf("%-*.*s ", (int)maxline, (int)maxline, "LINE");
(void)printf("WHEN ");

if (show_idle) {
(void)printf("IDLE ");
(void)printf("\t PID");

(void)printf("\tCOMMENT");
}

(void)putchar('\n');
}

static void
quick(const char *fname)
{
struct utmpentry *ehead, *ep;
int num = 0;

(void)getutentries(fname, &ehead);
for (ep = ehead; ep != NULL; ep = ep->next) {
(void)printf("%-*s ", (int)maxname, ep->name);
if ((++num % 8) == 0)
(void)putchar('\n');
}
if (num % 8)
(void)putchar('\n');

(void)printf("# users = %d\n", num);
}

static void
usage(void)
{
(void)fprintf(stderr, "Usage: %s [-abdHlmqrsTtuv] [file]\n\t%s am i\n",
getprogname(), getprogname());
exit(EXIT_FAILURE);
}

And from suckless:
Code:
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>

#include "util.h"

static void
usage(void)
{
eprintf("usage: %s\n", argv0);
}

int
main(int argc, char *argv[])
{
uid_t uid;
struct passwd *pw;

argv0 = argv[0], argc--, argv++;

if (argc)
usage();

uid = geteuid();
errno = 0;
if (!(pw = getpwuid(uid))) {
if (errno)
eprintf("getpwuid %d:", uid);
else
eprintf("getpwuid %d: no such user\n", uid);
}
puts(pw->pw_name);

return fshut(stdout, "<stdout>");
}

If we cut down suckless' version of it (removing errno and their util.h library), we will have:
Code:
#include <stdio.h>
#include <pwd.h>
#include <unistd.h>

int
main (void) {
uid_t uid;
struct passwd *pw;
uid = getuid();
if (!(pw = getpwuid(uid))) {
printf("getpwuid %d:", uid);
}
puts (pw->pw_name);
}

Wooo!..... ^^ Mitt Green to the rescue again!!..... ^^ Seriously, thank you, buddy..... :3 I'll compile some of these and let you know how it goes, ok.....? Also, just to be certain: I can use fopen with these.....? I'm assuming so, since you knowingly answered, knowing about me speaking on fopen..... :) Have a good day, ok buddy.....? :3
 
Wooo!..... ^^ Mitt Green to the rescue again!!..... ^^ Seriously, thank you, buddy..... :3 I'll compile some of these and let you know how it goes, ok.....? Also, just to be certain: I can use fopen with these.....?
What do you mean? fopen() has only these modes:
  • "r" for reading and the file must exist;
  • "w" for writing;
  • "a" for appending;
  • "r+" for reading and writing and the file must exist;
  • "w+" for reading and writing;
  • "a+" for appending and writing.
You apparently can read/write/append those C source files with fopen(), but if you mean, whether you can retrieve a file with it to print current user name, then you can't. whoami(1) prints the user name, associated with the current effective user ID. /etc/passwd maps user names, but in the kernel only UIDs are used; they are stored in the inodes of the filesystem.
I'm assuming so, since you knowingly answered, knowing about me speaking on fopen..... :) Have a good day, ok buddy.....? :3
Cheers :D
 
What do you mean? fopen() has only these modes:
  • "r" for reading and the file must exist;
  • "w" for writing;
  • "a" for appending;
  • "r+" for reading and writing and the file must exist;
  • "w+" for reading and writing;
  • "a+" for appending and writing.
You apparently can read/write/append those C source files with fopen(), but if you mean, whether you can retrieve a file with it to print current user name, then you can't. whoami(1) prints the user name, associated with the current effective user ID. /etc/passwd maps user names, but in the kernel only UIDs are used; they are stored in the inodes of the filesystem.

Cheers :D

Yeah, I know about those Modes..... :) What I meant was.... You know how, when you run an Install Program, whether on Linux or Windows, or OS X or *BSD, etc....? Somehow, it knows where to install the Files, even if it's run on MANY different PCs..... :\ What I'm wondering, is how it gets the User's Folder Name, which IS that User's chosen name, as THAT'S what keeps me from porting Programs to other Computers...... :) I.E., I would have to change

Code:
#include <stdio.h>

int main(void)

{
  FILE *ptr;

  ptr = fopen ("/home/blackneos940/.config/somefile.txt", "w");

  /*Rest of Code goes here*/

  return 0;

}

To:

Code:
#include <stdio.h>

int main(void)

{
  FILE *ptr;

  ptr = fopen ("/home/Mitt_Green/.config/somefile.txt", "w")

  /*Rest of Code goes here*/

  return 0;

}

And the Username in fopen would change automatically for each User, so I wouldn't have to change it manually..... :) Basically, I was wondering how a Program, in C, would be able to do that, but I guess it can't then..... :( Hmm.... :\

Cheers to MANY Years, good sir!..... ^^
 
From the Linux man files:
http://linux.die.net/man/3/getlogin_r

I had to look this one up honestly. I don't exactly run C on Windows very often.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx

Hello, good sir..... :3 I think that first one is interesting, because it uses the "unistd.h" Header File that Mitt talked about!..... ^^ Also, the other one is C++, but that's just as well..... I need to practice more C++, also..... ^^ Thanks for your help, and have a good day, ok, Mr. Vade.....? :3
 
Yeah, I know about those Modes..... :) What I meant was.... You know how, when you run an Install Program, whether on Linux or Windows, or OS X or *BSD, etc....? Somehow, it knows where to install the Files, even if it's run on MANY different PCs..... :\ What I'm wondering, is how it gets the User's Folder Name, which IS that User's chosen name, as THAT'S what keeps me from porting Programs to other Computers......
And the Username in fopen would change automatically for each User, so I wouldn't have to change it manually..... :) Basically, I was wondering how a Program, in C, would be able to do that, but I guess it can't then..... :( Hmm.... :\
Cheers to MANY Years, good sir!..... ^^
What you are talking about is done by make. If a programme is made with GNU Autotools (a.k.a. Autohell), then configure script prepares environment, checking for necessary libraries and, if run with --prefix option, exports it to Makefile; by default prefix is /usr/local. Autotools is a very complicated system, a much simpler approach exists, when you create a short configuration file for Makefile, where you declare install directory, compiling options etc.

fopen() doesn't handle environment variables. getenv() from stdlib.h does, e.g.:
Code:
#include <stdio.h>
#include <stdlib.h>

int main () {
printf("%s\n", getenv("HOME"));
return(0);
}
It will print your home environment, e.g.:
Code:
/home/blackneos940
 
Last edited:
What you are talking about is done by make. If a programme is made with GNU Autotools (a.k.a. Autohell), then configure script prepares environment, checking for necessary libraries and, if run with --prefix option, exports it to Makefile; by default prefix is /usr/local. Autotools is a very complicated system, a much simpler approach exists, when you create a short configuration file for Makefile, where you declare install directory, compiling options etc.

fopen() doesn't handle environment variables. getenv() from stdlib.h does, e.g.:
Code:
#include <stdio.h>
#include <stdlib.h>

int main () {
printf("%s\n", getenv("HOME"));
return(0);
}
It will print your home environment, e.g.:
Code:
/home/blackneos940
AH.....! :D "I see!", said the blind man!..... ^^ So, that's what those "Make" Files are all about..... :3 Autotools, huh.....? If it's complicated, I can learn it..... :3 But right now, Imma build a Castle in Minecraft..... :3 So, I think I know why fopen didn't work for this sort of thing....... :\ Anywho, I appreciate the help, good sir..... :3 Ciao!!..... ^^
 
What I meant was.... You know how, when you run an Install Program, whether on Linux or Windows, or OS X or *BSD, etc....? Somehow, it knows where to install the Files, even if it's run on MANY different PCs..... :\ What I'm wondering, is how it gets the User's Folder Name, which IS that User's chosen name​

Hello, from what you wrote it seems to me that you need the home directory of the current user.
It is typically in the environment variable HOME that you can read with getenv("HOME").
If this is not enough (some systems may not have it), you can get it by using one of the examples from Mitt (like the "cut down suckless") but use pw_dir instead of pw_name of struct passwd.
 
What I meant was.... You know how, when you run an Install Program, whether on Linux or Windows, or OS X or *BSD, etc....? Somehow, it knows where to install the Files, even if it's run on MANY different PCs..... :\ What I'm wondering, is how it gets the User's Folder Name, which IS that User's chosen name​

Hello, from what you wrote it seems to me that you need the home directory of the current user.
It is typically in the environment variable HOME that you can read with getenv("HOME").
If this is not enough (some systems may not have it), you can get it by using one of the examples from Mitt (like the "cut down suckless") but use pw_dir instead of pw_name of struct passwd.
Ah, ok!..... ^^ I didn't know it worked using "HOME" on *nix Systems..... :) I appreciate the help, good sir..... :3 Also, I was curious, as to how Setup Programs know how to write Files to a user's Directory, even though each user has a different name.... :) Also, I like your name..... :)
 
I am glad to be at your service. :)
Some additional notes:

If your program is named "foo", save user-specific configuration in $HOME/.foo (starting with a dot which hides it from normal directory listings). To see such files, type
ls -a​
in the shell or show hidden files in the file manager menu.

Typical Linux systems do not use installers but package management systems (search for linux package management) like rpm or dpkg.

You may distribute your software in source or binary tgz format as well and install them in "/opt/foo", put executables in "/usr/local/bin". Without root access, install executables to $HOME/bin which is usually in the search PATH.

You may also look up Linux filesystem hierarchy standard.
 
I am glad to be at your service. :)
Some additional notes:

If your program is named "foo", save user-specific configuration in $HOME/.foo (starting with a dot which hides it from normal directory listings). To see such files, type
ls -a​
in the shell or show hidden files in the file manager menu.

Typical Linux systems do not use installers but package management systems (search for linux package management) like rpm or dpkg.

You may distribute your software in source or binary tgz format as well and install them in "/opt/foo", put executables in "/usr/local/bin". Without root access, install executables to $HOME/bin which is usually in the search PATH.

You may also look up Linux filesystem hierarchy standard.

See..... :) This is why I Love the FOSS Community..... :D You're a good guy, you know that.....? :) So, then..... If I'm correct, does the Installation of Linux Programs simply mean that they are Written to something like: "/var/", or "/bin/".....? :) If so, then it will seem a LOT easier to redistribute my FOSS Programs I make..... :D Have a good day, and thank you for being YOU..... :)
 
See..... :) This is why I Love the FOSS Community..... :D You're a good guy, you know that.....? :) So, then..... If I'm correct, does the Installation of Linux Programs simply mean that they are Written to something like: "/var/", or "/bin/".....? :) If so, then it will seem a LOT easier to redistribute my FOSS Programs I make..... :D Have a good day, and thank you for being YOU..... :)
Fellow, let me explain the whole process.

Assuming you have a project named foo, that resides in your home directory. Inside foo folder you have these files:
  • foo.c - the source code, written in C
  • foo.1 - a man page (depending on the programme, the name can be different, such as foo.6 or foo.7, for manual sections take a look at this)
  • config.h - a configuration file, that is read during compilation and that is included in foo.c
  • Makefile - a makefile, obviously. It contains comprehensive rules, that describe compiling target, installing to and removal from the installation directory
  • config.mk - a configuration file for Makefile, that is short and easy to edit. It contains some simple statements; e.g. installation directory, compiling flags, the compiler itself. 'tis included in Makefile (by simply stating include config.mk in the beginning of the Makefile)
  • LICENSE or COPYING - a license, with which you provide the following code (considering foo is an open-source programme)
  • README - description of foo
So, inside the foo directory you run make, and it compiles foo.c and then it becomes an executable with the name foo. Then you run make install as root, and foo installs to (usually, depends on the installation directory you've declared in config.mk):
  • /usr/local/bin - binary itself
  • /usr/local/share/man - the man page
Installation (make install) is simply a copying of the executable foo and the man page to the target directories.

And then you can run it just by typing foo or read the man page by typing man foo.

Of course, this is very simplified, and with larger projects you usually see that endless configure scripts, HTML documentation, screenshots... This is, certainly, not necessary.

Hope it helps.
 
Fellow, let me explain the whole process.

Assuming you have a project named foo, that resides in your home directory. Inside foo folder you have these files:
  • foo.c - the source code, written in C
  • foo.1 - a man page (depending on the programme, the name can be different, such as foo.6 or foo.7, for manual sections take a look at this)
  • config.h - a configuration file, that is read during compilation and that is included in foo.c
  • Makefile - a makefile, obviously. It contains comprehensive rules, that describe compiling target, installing to and removal from the installation directory
  • config.mk - a configuration file for Makefile, that is short and easy to edit. It contains some simple statements; e.g. installation directory, compiling flags, the compiler itself. 'tis included in Makefile (by simply stating include config.mk in the beginning of the Makefile)
  • LICENSE or COPYING - a license, with which you provide the following code (considering foo is an open-source programme)
  • README - description of foo
So, inside the foo directory you run make, and it compiles foo.c and then it becomes an executable with the name foo. Then you run make install as root, and foo installs to (usually, depends on the installation directory you've declared in config.mk):
  • /usr/local/bin - binary itself
  • /usr/local/share/man - the man page
Installation (make install) is simply a copying of the executable foo and the man page to the target directories.

And then you can run it just by typing foo or read the man page by typing man foo.

Of course, this is very simplified, and with larger projects you usually see that endless configure scripts, HTML documentation, screenshots... This is, certainly, not necessary.

Hope it helps.
Thank you for taking the time to explain that to me..... You all are so nice..... :D But when you want to include your own Header File, don't you put '#include "example_file.h"'.....? :) Have a good day, okay, buddy.....? :)
 
But when you want to include your own Header File, don't you put '#include "example_file.h"'.....?
If writing C code, then without quotes, e.g.:
Code:
#include <example_file.h>
Makefile is kind of a script (not C code) with a set of rules, and, as in scripts, "#" starts a comment and the rest of the line is ignored. make searches for Makefile in the current directory. Let's look at some simple project examples.

Let's, again, assume that you have foo folder in your home; it contains the following:
foo.c:
Code:
#include <stdio.h>

int
main (void)
{
         printf ("Hello, World!\n");
         return 0;
}

foo.1:
Code:
.\" man page for foo
.TH man 1 "03 May 2016" "1.0" "foo man page"
.SH NAME
foo - a real life example
.SH DESCRIPTION
foo is a "Hello, World!"
.SH BUGS
This is a "Hello, World!"!!!
.SH AUTHOR
Mitt Green

config.mk:
Code:
VERSION = 1.0

PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man

CC = cc

Makefile:
Code:
include config.mk

SRC = foo.c
OBJ = ${SRC:.c=.o}

all: foo

.c.o:
  @${CC} -c $<

${OBJ}: config.mk

foo: foo.o
  @${CC} -o $@ foo.o

install: all
  @mkdir -p ${DESTDIR}${PREFIX}/bin
  @cp -f foo ${DESTDIR}${PREFIX}/bin
  @chmod 755 ${DESTDIR}${PREFIX}/bin/foo
  @mkdir -p ${DESTDIR}${MANPREFIX}/man1
  @cp -f foo.1 ${DESTDIR}${MANPREFIX}/man1
  @chmod 644 ${DESTDIR}${MANPREFIX}/man1/foo.1

uninstall:
  @rm -f ${DESTDIR}${PREFIX}/bin/foo
  @rm -f ${DESTDIR}${MANPREFIX}/man1/foo.1

.PHONY: all install uninstall

Everything is pretty simple and easy to understand. Hope it helps.

Cheers
 
If writing C code, then without quotes, e.g.:
Code:
#include <example_file.h>
Makefile is kind of a script (not C code) with a set of rules, and, as in scripts, "#" starts a comment and the rest of the line is ignored. make searches for Makefile in the current directory. Let's look at some simple project examples.

Let's, again, assume that you have foo folder in your home; it contains the following:
foo.c:
Code:
#include <stdio.h>

int
main (void)
{
         printf ("Hello, World!\n");
         return 0;
}

foo.1:
Code:
.\" man page for foo
.TH man 1 "03 May 2016" "1.0" "foo man page"
.SH NAME
foo - a real life example
.SH DESCRIPTION
foo is a "Hello, World!"
.SH BUGS
This is a "Hello, World!"!!!
.SH AUTHOR
Mitt Green

config.mk:
Code:
VERSION = 1.0

PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man

CC = cc

Makefile:
Code:
include config.mk

SRC = foo.c
OBJ = ${SRC:.c=.o}

all: foo

.c.o:
  @${CC} -c $<

${OBJ}: config.mk

foo: foo.o
  @${CC} -o $@ foo.o

install: all
  @mkdir -p ${DESTDIR}${PREFIX}/bin
  @cp -f foo ${DESTDIR}${PREFIX}/bin
  @chmod 755 ${DESTDIR}${PREFIX}/bin/foo
  @mkdir -p ${DESTDIR}${MANPREFIX}/man1
  @cp -f foo.1 ${DESTDIR}${MANPREFIX}/man1
  @chmod 644 ${DESTDIR}${MANPREFIX}/man1/foo.1

uninstall:
  @rm -f ${DESTDIR}${PREFIX}/bin/foo
  @rm -f ${DESTDIR}${MANPREFIX}/man1/foo.1

.PHONY: all install uninstall

Everything is pretty simple and easy to understand. Hope it helps.

Cheers
Oh, ok..... :) But why do I see some Header Files with quotes around them, and not others.....? :\ Also, thanks for explaining all that to me..... :) It REALLY helps, good sir..... :3
 
Oh, ok..... :) But why do I see some Header Files with quotes around them, and not others.....? :\ Also, thanks for explaining all that to me..... :) It REALLY helps, good sir..... :3
Headers with quotes are generally user made while non-quoted are available system wide. It depends on how the linker has to find the files.
 
Headers with quotes are generally user made while non-quoted are available system wide. It depends on how the linker has to find the files.
Ah, I see!.... :3 Thank you, good sir!!..... ^^ Also, I may need some help with this POS System I'm making, but I think I'll do my best to solve that little issue myself....... :)
 

Members online


Latest posts

Top