Unix/Linux编程实践教程--who在OS X的实现

环境:OS X 10.12.4

书中关于who程序的实现在我的OS X上好像跑不起来,首先看一下man who.

WHO(1)                    BSD General Commands Manual                   WHO(1)

NAME
     who -- display who is logged in

SYNOPSIS
     who [-abdHlmpqrsTtu] [file]
     who am i

DESCRIPTION
     The who utility displays a list of all users currently logged on,
     showing for each user the login name, tty name, the date and time
     of login, and hostname if not local.

     Available options:

     -a    Same as -bdlprTtu.

     -b    Time of last system boot.

     -d    Print dead processes.

     -H    Write column headings above the regular output.

     -l    Print system login processes (unsupported).

     -m    Only print information about the current terminal.  This is
           the POSIX way of saying who am i.

     -p    Print active processes spawned by launchd(8) (unsupported).

     -q    ``Quick mode'': List only the names and the number of users
           currently logged on.  When this option is used, all other
           options are ignored.

     -r    Print the current runlevel.  This is meaningless on Mac OS X.

     -s    List only the name, line and time fields.  This is the
           default.

     -T    Print a character after the user name indicating the state of
           the terminal line: `+' if the terminal is writable; `-' if it
           is not; and `?' if a bad line is encountered.

     -t    Print last system clock change (unsupported).

     -u    Print the idle time for each user, and the associated process
           ID.

     am I  Returns the invoker's real user name.

     file  By default, who gathers information from the file
           /var/run/utmpx.  An alternative file may be specified.

FILES
     /var/run/utmpx

SEE ALSO
     last(1), mesg(1), users(1), getuid(2), utmpx(5)

STANDARDS
     The who utility conforms to IEEE Std 1003.1-2001 (``POSIX.1'').

HISTORY
     A who utility appeared in Version 6 AT&T UNIX.

BSD                            January 17, 2007                            BSD

从这里可以看出OS X 使用的是utmpx,而不是utmp。而utmpx是utmp的扩展。

如果装了X Code之后,可以尝试找utmp.h这个头文件。

find / -name "utmp.h"

是可以找到一个对应的头文件,而且里面的代码和书中差别不大。

理论上书上的代码是可以正确执行的,但是/var/run/utmp 这个文件好像并不存在,我手动创建了一个,但系统并没有更新这个文件,当有新用户登入时。

后来我在man utmp的时候发现这么一段。

DESCRIPTION
     The interfaces in file  are all DEPRECATED and are only
     provided for compatibility with previous releases of Mac OS X.  See
     pututxline(3) and utmpx(5) for the supported interfaces.
...
FILES
     (These files no longer exist in 10.5 or later.)

     /var/run/utmp     The utmp file.
     /var/log/wtmp     The wtmp file.
     /var/log/lastlog  The lastlog file.

也就是说Apple不建议使用utmp了,而且几个文件在10.5之后不再存在,手动创建也不会更新。

其实在man who的时候会发现SEE ALSO里有这么一个玩意儿,utmpx(5)。

好的,那我们就man 进去, man 5 utmpx。

man进入之后,里面的DESCRIPTION有这么一段话。

The interface to the utmpx file is described in
     endutxent(3).

也就是系统直接提供了接口供我们使用,而不需要直接读文件。(直接读文件其实并不行)

好的,继续 man 3 endutxent。

ENDUTXENT(3)             BSD Library Functions Manual             ENDUTXENT(3)

NAME
     endutxent, getutxent, getutxid, getutxline, pututxline, setutxent
     -- user accounting database functions

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include 

     void
     endutxent(void);

     struct utmpx *
     getutxent(void);

     struct utmpx *
     getutxid(const struct utmpx *id);

     struct utmpx *
     getutxline(const struct utmpx *line);

     struct utmpx *
     pututxline(const struct utmpx *utx);

     void
     setutxent(void);

DESCRIPTION
     These functions provide access to the utmpx(5) user accounting
     database.

     getutxent() reads the next entry from the database; if the database
     was not yet open, it also opens it.  setutxent() resets the data-
     base, so that the next getutxent() call will get the first entry.
     endutxent() closes the database.

     getutxid() returns the next entry of the type specified in its
     argument's ut_type field, or NULL if none is found.  getutxline()
     returns the next LOGIN_PROCESS or USER_PROCESS entry which has the
     same name as specified in the ut_line field, or NULL if no match is
     found.

     pututxline() adds the argument utmpx(5) entry line to the account-
     ing database, replacing a previous entry for the same user if it
     exists.  Only the superuser may write to the accounting database.

   The utmpx structure
     The utmpx structure has the following definition:

     struct utmpx {
             char ut_user[_UTX_USERSIZE];    /* login name */
             char ut_id[_UTX_IDSIZE];        /* id */
             char ut_line[_UTX_LINESIZE];    /* tty name */
             pid_t ut_pid;                   /* process id creating the entry */
             short ut_type;                  /* type of this entry */
             struct timeval ut_tv;           /* time entry was created */
             char ut_host[_UTX_HOSTSIZE];    /* host name */
             __uint32_t ut_pad[16];          /* reserved for future use */
     };

     Valid entries for ut_type are:
           BOOT_TIME        Time of a system boot.
           DEAD_PROCESS     A session leader exited.
           EMPTY            No valid user accounting information.
           INIT_PROCESS     A process spawned by init(8).
           LOGIN_PROCESS    The session leader of a logged-in user.
           NEW_TIME         Time after system clock change.
           OLD_TIME         Time before system clock change.
           RUN_LVL          Run level.  Provided for compatibility, not
                            used.
           USER_PROCESS     A user process.
           SHUTDOWN_TIME    Time of system shutdown (extension to the
                            standards).

     For each value of ut_type, the other fields with meaningful values
     are as follows:
           BOOT_TIME        ut_tv
           DEAD_PROCESS     ut_id, ut_pid, ut_tv
           EMPTY            (no others)
           INIT_PROCESS     ut_id, ut_pid, ut_tv
           LOGIN_PROCESS    ut_id, ut_user (implementation-defined name
                            of the login process), ut_pid, ut_tv
           NEW_TIME         ut_tv
           OLD_TIME         ut_tv
           RUN_LVL          (no used)
           USER_PROCESS     ut_id, ut_user (login name of the user),
                            ut_line, ut_pid, ut_host (hostname of remote
                            user) ut_tv
           SHUTDOWN_TIME    ut_tv

   Other extensions to the standards
     The ut_type value may also be OR-ed with the following masks:
           UTMPX_AUTOFILL_MASK
                 Depending on the main part of ut_type value, other
                 fields are automatically filled in (as specified in the
                 meaningful fields table above).  In particular, the
                 ut_id field will be set using the convention of the
                 last four characters of the ut_line field (itself
                 filled in automatically from the tty name of the device
                 connected to the standard input, output or error,
                 whichever is available).  Note that it is more effi-
                 cient to fill in as many values as are already avail-
                 able beforehand, rather than have then automatically
                 filled in.
           UTMPX_DEAD_IF_CORRESPONDING_MASK
                 When ut_type value is DEAD_PROCESS, a call to
                 pututxline() will succeed only if a corresponding entry
                 already exists with a ut_type value of USER_PROCESS.

     Note that the above mask values do not show up in any file format,
     or in any subsequent reads of the data.

     To support wtmpx and lastlogx equivalent capability, pututxline()
     automatically writes to the appropriate files.  Additional APIs to
     read these files is available in endutxent_wtmp(3) and
     getlastlogx(3).

   Backward compatibility
     Successful calls to pututxline() will automatically write equiva-
     lent entries into the utmp, wtmp and lastlog files.  Programs that
     read these old files should work as expected.  However, directly
     writing to these files does not make corresponding entries in utmpx
     and the wtmpx and lastlogx equivalent files, so such write-access
     is deprecated.

RETURN VALUES
     getutxent() returns the next entry, or NULL on failure (end of
     database or problems reading from the database).  getutxid() and
     getutxline() return the matching structure on success, or NULL if
     no match was found.

     pututxline() returns the structure that was successfully written,
     or NULL is returned and the global variable errno is set to indi-
     cate the error.

ERRORS
     No errors are defined for the endutxent(), getutxent(), getutxid(),
     getutxline(), and setutxent() functions.

     The pututxline() function may fail if:

     [EPERM]            The process does not have appropriate privi-
                        leges.

     [EINVAL]           The UTMPX_DEAD_IF_CORRESPONDING_MASK flags was
                        specified along with DEAD_PROCESS, but no corre-
                        sponding entry with USER_PROCESS was found.

     Other errors may be returned if UTMPX_AUTOFILL_MASK was specified,
     and a field could not be auto-filled.

SEE ALSO
     endutxent_wtmp(3), getlastlogx(3), utmpx(5)

STANDARDS
     The endutxent(), getutxent(), getutxid(), getutxline(),
     pututxline(), setutxent() all conform to IEEE Std 1003.1-2001
     (``POSIX.1'') (XSI extension), and previously to X/Open Portability
     Guide Issue 4, Version 2 (``XPG4.2'').  The fields ut_user, ut_id,
     ut_line, ut_pid, ut_type, and ut_tv conform to IEEE Std 1003.1-2001
     (``POSIX.1'') (XSI extension), and previously to X/Open Portability
     Guide Issue 4, Version 2 (``XPG4.2'').

BSD                              June 29, 2006                             BSD

里面讲述了几个函数的作用,还有utmpx的结构,还有ut_type的常见取值,还有一些其它的东西。

其实只使用getutxent()这个函数就够用了,如果没有打开数据库的话,这个函数会自动打开。

关闭的话,我省略了,最好应该有。

以下就是我的实现:

效果:


a.out是我的实现,下面的who是系统提供的。

代码:

#include <stdio.h>
#include <utmpx.h>

int main(void)
{
	struct utmpx *tmp;
	while(tmp = getutxent())
	{
		/* format time */
		time_t t = tmp->ut_tv.tv_sec;
		struct tm *p = localtime(&t);
		char buf[55];
		strftime(buf, sizeof buf, "%b %d %H:%M", p);

		if(tmp->ut_type == USER_PROCESS)
			printf("%s %s %s %s\n", tmp->ut_user, tmp->ut_line, buf, tmp->ut_host);
		// printf("%d\n", tmp->ut_type);
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值