1% This file illustrates how to read a binary file into a structure.  In this
2% case, the file is the Unix utmp file.
3%
4% Note that the format of the utmp file will vary with the OS.  The format
5% encoded here is for glibc Linux, but even that may be version-dependent.
6
7variable format, size, fp, buf;
8
9variable is_glibc = 1;
10
11#ifeval is_glibc
12typedef struct
13{
14   ut_type, ut_pid, ut_line, ut_id,
15     ut_user, ut_host, ut_exit, ut_session, ut_tv, ut_addr
16} UTMP_Type;
17% The ut_tv is a timeval structure which has the format: l2
18% Also the ut_exit field is a struct of h2
19format = pad_pack_format ("h i S32 S4 S32 S256 h2 l l2 k4 x20");
20#else
21typedef struct
22{
23   ut_type, ut_pid, ut_line, ut_id,
24     ut_time, ut_user, ut_host, ut_addr
25} UTMP_Type;
26format = pad_pack_format ("h i S12 S2 l S8 S16 l");
27#endif
28
29size = sizeof_pack (format);
30vmessage ("Sizeof of utmp line: %d bytes", size);
31
32define print_utmp (u)
33{
34   () = fprintf (stdout, "%-16s %-12s %-16s %s\n",
35		 u.ut_user, u.ut_line, u.ut_host,
36#ifeval is_glibc
37		 ctime (u.ut_tv[0])
38#else
39		 ctime (u.ut_time)
40#endif
41		 );
42}
43
44variable Utmp_File;
45foreach (["/var/run/utmp", "/var/log/utmp"])
46{
47   Utmp_File = ();
48   fp = fopen (Utmp_File, "rb");
49   if (fp != NULL)
50     break;
51}
52
53if (fp == NULL) error ("Unable to open utmp file");
54
55() = fprintf (stdout, "%-16s %-12s %-16s %s\n",
56	      "USER", "TTY", "FROM", "LOGIN@");
57
58variable U = @UTMP_Type;
59
60while (size == fread_bytes (&buf, size, fp))
61{
62   set_struct_fields (U, unpack (format, buf));
63   print_utmp (U);
64}
65
66() = fclose (fp);
67
68