Class: Solaris::Utmpx

Inherits:
BinData::Record
  • Object
show all
Defined in:
lib/solaris/utmpx.rb

Overview

See “struct futmpx” in /usr/include/utmpx.h:

struct futmpx {
    char    ut_user[32];        /* user login name */
    char    ut_id[4];       /* inittab id */
    char    ut_line[32];        /* device name (console, lnxx) */
    pid32_t ut_pid;         /* process id */
    int16_t ut_type;        /* type of entry */
    struct {
        int16_t e_termination;  /* process termination status */
        int16_t e_exit;     /* process exit status */
    } ut_exit;          /* exit status of a process */
    struct timeval32 ut_tv;     /* time entry was made */
    int32_t ut_session;     /* session ID, user for windowing */
    int32_t pad[5];         /* reserved for future use */
    int16_t ut_syslen;      /* significant length of ut_host */
    char    ut_host[257];       /* remote host name */
};

Constant Summary collapse

RECORD_LENGTH =

Length of a raw utmpx record in bytes.

372

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ Utmpx

Create a new Utmpx factory object. Options are:

  • :endian – mandatory, set to :big (SPARC) or :little (i386)

  • :trim_padding – trim terminating nulls from read strings

This will generate objects that are subclasses of BinData::Record.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/solaris/utmpx.rb', line 37

def initialize(opts)

  endianism = nil
  trim_padding = true
  opts.each do |key, value|
    case key
    when :endian
      endianism = value
    when :trim_padding
      trim_padding = value
    else
      raise ArgumentError, "Unknown option #{key.inspect}"
    end
  end

  @record_class = Class.new(BinData::Record) do

    endian endianism

    string :ut_user, :length => 32, :trim_padding => trim_padding
    string :ut_id, :length => 4, :trim_padding => trim_padding
    string :ut_line, :length => 32, :trim_padding => trim_padding
    uint32 :ut_pid
    uint16 :ut_type
    string :pad_word1, :length => 2 # align to 4 byte words
    uint16 :ut_termination
    uint16 :ut_exit
    uint32 :ut_tv_sec
    uint32 :ut_tv_usec
    uint32 :ut_session
    uint32 :pad0
    uint32 :pad1
    uint32 :pad2
    uint32 :pad3
    uint32 :pad4
    uint16 :ut_syslen
    string :ut_host, :length => 257, :trim_padding => trim_padding
    string :pad_word2, :length => 1 # align to 4 byte words

    # Return the timestamp of this record as a Time object in the local TZ.
    def localtime
      Time.at(self.ut_tv_sec + self.ut_tv_usec / 1_000_000.0)
    end

  end

end

Instance Attribute Details

#record_classObject (readonly)

The (anonymous) class of generated records.



28
29
30
# File 'lib/solaris/utmpx.rb', line 28

def record_class
  @record_class
end

Instance Method Details

#create(opts = {}) ⇒ Object

Create a new record. Interesting option keys are:

  • :ut_user

  • :ut_id

  • :ut_line

  • :ut_pid

  • :ut_type

  • :ut_termination

  • :ut_exit

  • :ut_tv_sec

  • :ut_tv_usec

  • :ut_session

  • :ut_syslen

  • :ut_host

Raises:

  • (ArgumentError)


98
99
100
101
102
103
# File 'lib/solaris/utmpx.rb', line 98

def create(opts={})
  # BinData silently discards unknown fields so we check.
  unknown_fields = opts.keys - self.record_class.fields.fields.map(&:name)
  raise ArgumentError, "Unknown fields #{unknown_fields.inspect}" unless unknown_fields.empty?
  @record_class.new(opts)
end

#read(io) ⇒ Object

Read a utmpx record from the given IO object.



106
107
108
# File 'lib/solaris/utmpx.rb', line 106

def read(io)
  @record_class.read(io)
end