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