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

前端之家收集整理的这篇文章主要介绍了Unix/Linux编程实践教程--who在OS X的实现前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

环境:OS X10.12.4

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

  1. WHO(1) BSD General Commands Manual WHO(1)
  2.  
  3. NAME
  4. who -- display who is logged in
  5.  
  6. SYNOPSIS
  7. who [-abdHlmpqrsTtu] [file]
  8. who am i
  9.  
  10. DESCRIPTION
  11. 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
  12. of login,and hostname if not local.
  13.  
  14. Available options:
  15.  
  16. -a Same as -bdlprTtu.
  17.  
  18. -b Time of last system boot.
  19.  
  20. -d Print dead processes.
  21.  
  22. -H Write column headings above the regular output.
  23.  
  24. -l Print system login processes (unsupported).
  25.  
  26. -m Only print information about the current terminal. This is
  27. the POSIX way of saying who am i.
  28.  
  29. -p Print active processes spawned by launchd(8) (unsupported).
  30.  
  31. -q ``Quick mode'': List only the names and the number of users
  32. currently logged on. When this option is used,all other
  33. options are ignored.
  34.  
  35. -r Print the current runlevel. This is meaningless on Mac OS X.
  36.  
  37. -s List only the name,line and time fields. This is the
  38. default.
  39.  
  40. -T Print a character after the user name indicating the state of
  41. the terminal line: `+' if the terminal is writable; `-' if it
  42. is not; and `?' if a bad line is encountered.
  43.  
  44. -t Print last system clock change (unsupported).
  45.  
  46. -u Print the idle time for each user,and the associated process
  47. ID.
  48.  
  49. am I Returns the invoker's real user name.
  50.  
  51. file By default,who gathers information from the file
  52. /var/run/utmpx. An alternative file may be specified.
  53.  
  54. FILES
  55. /var/run/utmpx
  56.  
  57. SEE ALSO
  58. last(1),mesg(1),users(1),getuid(2),utmpx(5)
  59.  
  60. STANDARDS
  61. The who utility conforms to IEEE Std 1003.1-2001 (``POSIX.1'').
  62.  
  63. HISTORY
  64. A who utility appeared in Version 6 AT&T UNIX.
  65.  
  66. BSD January 17,2007 BSD

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

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

  1. find / -name "utmp.h"

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

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

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

  1. DESCRIPTION
  2. The interfaces in file are all DEPRECATED and are only
  3. provided for compatibility with prevIoUs releases of Mac OS X. See
  4. pututxline(3) and utmpx(5) for the supported interfaces.
  5. ...
  6. FILES
  7. (These files no longer exist in 10.5 or later.)
  8.  
  9. /var/run/utmp The utmp file.
  10. /var/log/wtmp The wtmp file.
  11. /var/log/lastlog The lastlog file.

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

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

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

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

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

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

好的,继续 man 3 endutxent。

  1. ENDUTXENT(3) BSD Library Functions Manual ENDUTXENT(3)
  2.  
  3. NAME
  4. endutxent,getutxent,getutxid,getutxline,pututxline,setutxent
  5. -- user accounting database functions
  6.  
  7. LIBRARY
  8. Standard C Library (libc,-lc)
  9.  
  10. SYNOPSIS
  11. #include
  12.  
  13. void
  14. endutxent(void);
  15.  
  16. struct utmpx *
  17. getutxent(void);
  18.  
  19. struct utmpx *
  20. getutxid(const struct utmpx *id);
  21.  
  22. struct utmpx *
  23. getutxline(const struct utmpx *line);
  24.  
  25. struct utmpx *
  26. pututxline(const struct utmpx *utx);
  27.  
  28. void
  29. setutxent(void);
  30.  
  31. DESCRIPTION
  32. These functions provide access to the utmpx(5) user accounting
  33. database.
  34.  
  35. getutxent() reads the next entry from the database; if the database
  36. was not yet open,it also opens it. setutxent() resets the data-
  37. base,so that the next getutxent() call will get the first entry.
  38. endutxent() closes the database.
  39.  
  40. getutxid() returns the next entry of the type specified in its
  41. argument's ut_type field,or NULL if none is found. getutxline()
  42. returns the next LOGIN_PROCESS or USER_PROCESS entry which has the
  43. same name as specified in the ut_line field,or NULL if no match is
  44. found.
  45.  
  46. pututxline() adds the argument utmpx(5) entry line to the account-
  47. ing database,replacing a prevIoUs entry for the same user if it
  48. exists. Only the superuser may write to the accounting database.
  49.  
  50. The utmpx structure
  51. The utmpx structure has the following definition:
  52.  
  53. struct utmpx {
  54. char ut_user[_UTX_USERSIZE]; /* login name */
  55. char ut_id[_UTX_IDSIZE]; /* id */
  56. char ut_line[_UTX_LINESIZE]; /* tty name */
  57. pid_t ut_pid; /* process id creating the entry */
  58. short ut_type; /* type of this entry */
  59. struct timeval ut_tv; /* time entry was created */
  60. char ut_host[_UTX_HOSTSIZE]; /* host name */
  61. __uint32_t ut_pad[16]; /* reserved for future use */
  62. };
  63.  
  64. Valid entries for ut_type are:
  65. BOOT_TIME Time of a system boot.
  66. DEAD_PROCESS A session leader exited.
  67. EMPTY No valid user accounting information.
  68. INIT_PROCESS A process spawned by init(8).
  69. LOGIN_PROCESS The session leader of a logged-in user.
  70. NEW_TIME Time after system clock change.
  71. OLD_TIME Time before system clock change.
  72. RUN_LVL Run level. Provided for compatibility,not
  73. used.
  74. USER_PROCESS A user process.
  75. SHUTDOWN_TIME Time of system shutdown (extension to the
  76. standards).
  77.  
  78. For each value of ut_type,the other fields with meaningful values
  79. are as follows:
  80. BOOT_TIME ut_tv
  81. DEAD_PROCESS ut_id,ut_pid,ut_tv
  82. EMPTY (no others)
  83. INIT_PROCESS ut_id,ut_tv
  84. LOGIN_PROCESS ut_id,ut_user (implementation-defined name
  85. of the login process),ut_tv
  86. NEW_TIME ut_tv
  87. OLD_TIME ut_tv
  88. RUN_LVL (no used)
  89. USER_PROCESS ut_id,ut_user (login name of the user),ut_line,ut_host (hostname of remote
  90. user) ut_tv
  91. SHUTDOWN_TIME ut_tv
  92.  
  93. Other extensions to the standards
  94. The ut_type value may also be OR-ed with the following masks:
  95. UTMPX_AUTOFILL_MASK
  96. Depending on the main part of ut_type value,other
  97. fields are automatically filled in (as specified in the
  98. meaningful fields table above). In particular,the
  99. ut_id field will be set using the convention of the
  100. last four characters of the ut_line field (itself
  101. filled in automatically from the tty name of the device
  102. connected to the standard input,output or error,whichever is available). Note that it is more effi-
  103. cient to fill in as many values as are already avail-
  104. able beforehand,rather than have then automatically
  105. filled in.
  106. UTMPX_DEAD_IF_CORRESPONDING_MASK
  107. When ut_type value is DEAD_PROCESS,a call to
  108. pututxline() will succeed only if a corresponding entry
  109. already exists with a ut_type value of USER_PROCESS.
  110.  
  111. Note that the above mask values do not show up in any file format,or in any subsequent reads of the data.
  112.  
  113. To support wtmpx and lastlogx equivalent capability,pututxline()
  114. automatically writes to the appropriate files. Additional APIs to
  115. read these files is available in endutxent_wtmp(3) and
  116. getlastlogx(3).
  117.  
  118. Backward compatibility
  119. Successful calls to pututxline() will automatically write equiva-
  120. lent entries into the utmp,wtmp and lastlog files. Programs that
  121. read these old files should work as expected. However,directly
  122. writing to these files does not make corresponding entries in utmpx
  123. and the wtmpx and lastlogx equivalent files,so such write-access
  124. is deprecated.
  125.  
  126. RETURN VALUES
  127. getutxent() returns the next entry,or NULL on failure (end of
  128. database or problems reading from the database). getutxid() and
  129. getutxline() return the matching structure on success,or NULL if
  130. no match was found.
  131.  
  132. pututxline() returns the structure that was successfully written,or NULL is returned and the global variable errno is set to indi-
  133. cate the error.
  134.  
  135. ERRORS
  136. No errors are defined for the endutxent(),getutxent(),getutxid(),getutxline(),and setutxent() functions.
  137.  
  138. The pututxline() function may fail if:
  139.  
  140. [EPERM] The process does not have appropriate privi-
  141. leges.
  142.  
  143. [EINVAL] The UTMPX_DEAD_IF_CORRESPONDING_MASK flags was
  144. specified along with DEAD_PROCESS,but no corre-
  145. sponding entry with USER_PROCESS was found.
  146.  
  147. Other errors may be returned if UTMPX_AUTOFILL_MASK was specified,and a field could not be auto-filled.
  148.  
  149. SEE ALSO
  150. endutxent_wtmp(3),getlastlogx(3),utmpx(5)
  151.  
  152. STANDARDS
  153. The endutxent(),pututxline(),setutxent() all conform to IEEE Std 1003.1-2001
  154. (``POSIX.1'') (XSI extension),and prevIoUsly to X/Open Portability
  155. 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
  156. (``POSIX.1'') (XSI extension),Version 2 (``XPG4.2'').
  157.  
  158. BSD June 29,2006 BSD

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

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

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

以下就是我的实现:

效果


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

代码

  1. #include <stdio.h>
  2. #include <utmpx.h>
  3.  
  4. int main(void)
  5. {
  6. struct utmpx *tmp;
  7. while(tmp = getutxent())
  8. {
  9. /* format time */
  10. time_t t = tmp->ut_tv.tv_sec;
  11. struct tm *p = localtime(&t);
  12. char buf[55];
  13. strftime(buf,sizeof buf,"%b %d %H:%M",p);
  14.  
  15. if(tmp->ut_type == USER_PROCESS)
  16. printf("%s %s %s %s\n",tmp->ut_user,tmp->ut_line,buf,tmp->ut_host);
  17. // printf("%d\n",tmp->ut_type);
  18. }
  19. return 0;
  20. }
  21.  

猜你在找的Bash相关文章