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

环境:OS X10.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_tv
           LOGIN_PROCESS    ut_id,ut_user (implementation-defined name
                            of the login process),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_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(),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_type,and ut_tv conform to IEEE Std 1003.1-2001
     (``POSIX.1'') (XSI extension),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;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2280端口映射到公网,发现经常被暴力破解,自己写了个临时封禁ip功能的脚本,实现5分钟内同一个ip登录密码错误10次就封禁这个ip5分钟,并且进行邮件通知使用步骤openwrt为19.07.03版本,其他版本没有测试过安装bashmsmtpopkg
#!/bin/bashcommand1&command2&wait从Shell脚本并行运行多个程序–杨河老李(kviccn.github.io)
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/phpls-ls 2.编辑修改.bash_profile文件(没有.bash_profile文件的情况下回自动创建)sudovim~/.bash_profile在文件的最后输入以下信息,然后保存退出exportPATH="/Applications/MAMP/bin/php/php7.2.20/b
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如zh_CN之类的语言包,进行中文语言包装:apt-getinstalllanguage-pack-zh-hans3、安装好后我们可以进行临时修改:然后添加中文支持: locale-genzh_CN.UTF-8临时修改> export LC_ALL='zh_CN.utf8'> locale永久
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexadecimalbash2#[0~1]0[0~7]0x[0~f]or0X[0~f]perl0b[0~1]0[0~7]0x[0~f]tcl0b[0~1]0o[0~7]0x[0~f]bashdifferentbaserepresntationreference2.StringlengthLanguageStr
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全命令补全方法:yum-yinstallbash-completionsource/usr/share/bash-completion/bash_completionsource<(kubectlcompletionbash)echo"source<(kubectlcompletionbash)">>~/.bashrc 
参考这里启动jar包shell脚本修改过来的#!/bin/bash#默认应用名称defaultAppName='./gadmin'appName=''if[[$1&&$1!=0]]thenappName=$1elseappName=$defaultAppNamefiecho">>>>>>本次重启的应用:$appName<
#一个数字的行#!/bin/bashwhilereadlinedon=`echo$line|sed's/[^0-9]//g'|wc-L`if[$n-eq1]thenecho$linefidone<1.txt#日志切割归档#!/bin/bashcd/data/logslog=1.logmv_log(){[-f$1]&&mv$1$2
#文件增加内容#!/bin/bashn=0cat1.txt|whilereadlinedon=[$n+1]if[$n-eq5]thenecho$lineecho-e"#Thisisatestfile.\n#Testinsertlineintothisfile."elseecho$linefidone#备份/etc目录#
# su - oraclesu: /usr/bin/ksh: No such file or directory根据报错信息:显示无法找到文件 /usr/bin/ksh果然没有该文件,但是发现存在文件/bin/ksh,于是创建了一个软连接,可以规避问题,可以成功切换到用户下,但无法执行系统自带命令。$. .bash_profile-ksh: .: .b
history显示历史指令记录内容,下达历史纪录中的指令主要的使用方法如果你想禁用history,可以将HISTSIZE设置为0:#exportHISTSIZE=0使用HISTIGNORE忽略历史中的特定命令下面的例子,将忽略pwd、ls、ls-ltr等命令:#exportHISTIGNORE=”pwd:ls:ls-ltr:”使用HIS
一.命令历史  1.history环境变量:    HISTSIZE:输出的命令历史条数,如history的记录数    HISTFILESIZE:~/.bash_history保存的命令历史记录数    HISTFILLE:历史记录的文件路径    HISTCONTROL:     ignorespace:忽略以空格开头的命令
之前在网上看到很多师傅们总结的linux反弹shell的一些方法,为了更熟练的去运用这些技术,于是自己花精力查了很多资料去理解这些命令的含义,将研究的成果记录在这里,所谓的反弹shell,指的是我们在自己的机器上开启监听,然后在被攻击者的机器上发送连接请求去连接我们的机器,将被攻击者的she
BashOne-LinersExplained,PartI:Workingwithfileshttps://catonmat.net/bash-one-liners-explained-part-oneBashOne-LinersExplained,PartII:Workingwithstringshttps://catonmat.net/bash-one-liners-explained-part-twoBashOne-LinersExplained,PartII
Shell中变量的作用域:在当前Shell会话中使用,全局变量。在函数内部使用,局部变量。可以在其他Shell会话中使用,环境变量。局部变量:默认情况下函数内的变量也是全局变量#!/bin/bashfunctionfunc(){a=99}funcecho$a输出>>99为了让全局变量变成局部变量
1、多命令顺序执行;  命令1;命令2  多个命令顺序执行,命令之间没有任何逻辑联系&&  命令1&&命令2  逻辑与,当命令1正确执行,才会执行命令2||  命令1||命令2  逻辑或,当命令1执行不正确,才会执行命令2例如:ls;date;cd/home/lsx;pwd;who ddif=输入文件of=输
原博文使用Linux或者unix系统的同学可能都对#!这个符号并不陌生,但是你真的了解它吗?首先,这个符号(#!)的名称,叫做"Shebang"或者"Sha-bang"。Linux执行文件时发现这个格式,会把!后的内容提取出来拼接在脚本文件或路径之前,当作实际执行的命令。 Shebang这个符号通常在Unix系统的脚本
1、历史命令history[选项][历史命令保存文件]选项:-c:  清空历史命令-w:  把缓存中的历史命令写入历史命令保存文件 ~/.bash_historyvim/etc/profile中的Histsize可改存储历史命令数量历史命令的调用使用上、下箭头调用以前的历史命令使用“!n”重复执行第n条历史
目录1.Shell脚本规范2.Shell脚本执行3.Shell脚本变量3.1环境变量3.1.1自定义环境变量3.1.2显示与取消环境变量3.1.3环境变量初始化与对应文件的生效顺序3.2普通变量3.2.1定义本地变量3.2.2shell调用变量3.2.3grep调用变量3.2.4awk调用变量3.3
   http://www.voidcn.com/blog/wszzdanm/article/p-6145895.html命令功能:显示登录用户的信息命令格式:常用选项:举例:w显示已经登录的用户及正在进行的操作[root@localhost~]#w 11:22:01up4days,21:22, 3users, loadaverage:0.00,0.00,0.00USER