solaris-utmpx 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bea80841580cccc83697be3b85853852a04fc799
4
+ data.tar.gz: a23e1f074cd99fbe8b488827deddfbafaed497dc
5
+ SHA512:
6
+ metadata.gz: df97be060d9ced25a54d277008531a3912243d14147b85b93b8e6340b5cd64267359fa93b4ff744e5e6b97f5a2af3a05a7198d3af1a90baef89ae0a7afb2abdb
7
+ data.tar.gz: 506f30185ec4434791475c8af09a515e500e3851cc83915109f6bd6f78164cef1724f4e1a70405e14b7f79d3fff8c121a974ca34f5553d6ac64661e58244f34e
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright 2013 Martin Carpenter. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are
4
+ permitted provided that the following conditions are met:
5
+
6
+ 1. Redistributions of source code must retain the above copyright notice, this list of
7
+ conditions and the following disclaimer.
8
+
9
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list
10
+ of conditions and the following disclaimer in the documentation and/or other materials
11
+ provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY Martin Carpenter ``AS IS'' AND ANY EXPRESS OR IMPLIED
14
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
15
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Martin Carpenter OR
16
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
21
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
+
23
+ The views and conclusions contained in the software and documentation are those of the
24
+ authors and should not be interpreted as representing official policies, either expressed
25
+ or implied, of Martin Carpenter.
26
+
@@ -0,0 +1,34 @@
1
+
2
+ = solaris-utmpx
3
+
4
+ Author:: Martin Carpenter
5
+ Email:: mcarpenter@free.fr
6
+ Copyright:: Copyright (c) Martin Carpenter 2013
7
+
8
+ == About
9
+ The solaris-utmpx gem helps with the reading and writing of Solaris
10
+ binary utmpx(4) and wtmpx(4) files.
11
+
12
+ == Examples
13
+
14
+ === Read and display all records in wtmpx
15
+
16
+ require 'solaris/utmpx'
17
+
18
+ io = File.open('/var/adm/wtmpx', 'r')
19
+ reader = Solaris::Wtmpx.new(:endian => :little)
20
+ while !io.eof? do
21
+ puts reader.read(io)
22
+ end
23
+
24
+ === Filter all root entries from wtmpx
25
+
26
+ require 'solaris/utmpx'
27
+
28
+ io = File.open('/var/adm/wtmpx', 'r')
29
+ reader = Solaris::Wtmpx.new(:endian => :little)
30
+ while !io.eof? do
31
+ record = reader.read(io)
32
+ print record.to_binary_s unless record.ut_user == 'root'
33
+ end
34
+
@@ -0,0 +1,28 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+ require 'rake/testtask'
4
+ require 'rdoc/task'
5
+ require 'rubygems/package_task'
6
+
7
+ desc 'Default task (package)'
8
+ task :default => [:package]
9
+
10
+ Rake::TestTask.new( 'test' )
11
+
12
+ SPECFILE = 'solaris-utmpx.gemspec'
13
+ if File.exist?( SPECFILE )
14
+ spec = eval( File.read( SPECFILE ) )
15
+ Gem::PackageTask.new( spec ).define
16
+ end
17
+
18
+ RDoc::Task.new do |rdoc|
19
+ rdoc.rdoc_dir = 'rdoc'
20
+ rdoc.title = 'solaris-utmpx'
21
+ rdoc.options << '--charset' << 'utf-8'
22
+ rdoc.options << '--main' << 'README.rdoc'
23
+ rdoc.options << '--all'
24
+ rdoc.rdoc_files.include( 'README.rdoc' )
25
+ rdoc.rdoc_files.include( FileList[ 'lib/**/*.rb' ] )
26
+ rdoc.rdoc_files.include( FileList[ 'test/**/*.rb' ] )
27
+ end
28
+
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'solaris/utmpx'
4
+
5
+ io = File.open(ARGV[0], 'r')
6
+ reader = Solaris::Utmpx.new(:endian => :little)
7
+ while !io.eof? do
8
+ record = reader.read(io)
9
+ print record.to_binary_s unless record.ut_user == 'root'
10
+ end
11
+
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'solaris/utmpx'
4
+
5
+ io = File.open(ARGV[0], 'r')
6
+ reader = Solaris::Utmpx.new(:endian => :little)
7
+ while !io.eof? do
8
+ puts reader.read(io)
9
+ end
10
+
@@ -0,0 +1,7 @@
1
+
2
+ # Namespace for child classes.
3
+ module Solaris
4
+
5
+ require 'solaris/utmpx'
6
+
7
+ end
@@ -0,0 +1,113 @@
1
+
2
+ require 'bindata'
3
+
4
+ module Solaris
5
+
6
+ # See "struct futmpx" in /usr/include/utmpx.h:
7
+ #
8
+ # struct futmpx {
9
+ # char ut_user[32]; /* user login name */
10
+ # char ut_id[4]; /* inittab id */
11
+ # char ut_line[32]; /* device name (console, lnxx) */
12
+ # pid32_t ut_pid; /* process id */
13
+ # int16_t ut_type; /* type of entry */
14
+ # struct {
15
+ # int16_t e_termination; /* process termination status */
16
+ # int16_t e_exit; /* process exit status */
17
+ # } ut_exit; /* exit status of a process */
18
+ # struct timeval32 ut_tv; /* time entry was made */
19
+ # int32_t ut_session; /* session ID, user for windowing */
20
+ # int32_t pad[5]; /* reserved for future use */
21
+ # int16_t ut_syslen; /* significant length of ut_host */
22
+ # char ut_host[257]; /* remote host name */
23
+ # };
24
+ #
25
+ class Utmpx < BinData::Record
26
+
27
+ # The (anonymous) class of generated records.
28
+ attr_reader :record_class
29
+
30
+ # Length of a raw utmpx record in bytes.
31
+ RECORD_LENGTH = 372
32
+
33
+ # Create a new Utmpx factory object. Options are:
34
+ # * :endian -- mandatory, set to :big (SPARC) or :little (i386)
35
+ # * :trim_padding -- trim terminating nulls from read strings
36
+ # This will generate objects that are subclasses of BinData::Record.
37
+ def initialize(opts)
38
+
39
+ endianism = nil
40
+ trim_padding = true
41
+ opts.each do |key, value|
42
+ case key
43
+ when :endian
44
+ endianism = value
45
+ when :trim_padding
46
+ trim_padding = value
47
+ else
48
+ raise ArgumentError, "Unknown option #{key.inspect}"
49
+ end
50
+ end
51
+
52
+ @record_class = Class.new(BinData::Record) do
53
+
54
+ endian endianism
55
+
56
+ string :ut_user, :length => 32, :trim_padding => trim_padding
57
+ string :ut_id, :length => 4, :trim_padding => trim_padding
58
+ string :ut_line, :length => 32, :trim_padding => trim_padding
59
+ uint32 :ut_pid
60
+ uint16 :ut_type
61
+ string :pad_word1, :length => 2 # align to 4 byte words
62
+ uint16 :ut_termination
63
+ uint16 :ut_exit
64
+ uint32 :ut_tv_sec
65
+ uint32 :ut_tv_usec
66
+ uint32 :ut_session
67
+ uint32 :pad0
68
+ uint32 :pad1
69
+ uint32 :pad2
70
+ uint32 :pad3
71
+ uint32 :pad4
72
+ uint16 :ut_syslen
73
+ string :ut_host, :length => 257, :trim_padding => trim_padding
74
+ string :pad_word2, :length => 1 # align to 4 byte words
75
+
76
+ # Return the timestamp of this record as a Time object in the local TZ.
77
+ def localtime
78
+ Time.at(self.ut_tv_sec + self.ut_tv_usec / 1_000_000.0)
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ # Create a new record. Interesting option keys are:
86
+ # * :ut_user
87
+ # * :ut_id
88
+ # * :ut_line
89
+ # * :ut_pid
90
+ # * :ut_type
91
+ # * :ut_termination
92
+ # * :ut_exit
93
+ # * :ut_tv_sec
94
+ # * :ut_tv_usec
95
+ # * :ut_session
96
+ # * :ut_syslen
97
+ # * :ut_host
98
+ def create(opts={})
99
+ # BinData silently discards unknown fields so we check.
100
+ unknown_fields = opts.keys - self.record_class.fields.fields.map(&:name)
101
+ raise ArgumentError, "Unknown fields #{unknown_fields.inspect}" unless unknown_fields.empty?
102
+ @record_class.new(opts)
103
+ end
104
+
105
+ # Read a utmpx record from the given IO object.
106
+ def read(io)
107
+ @record_class.read(io)
108
+ end
109
+
110
+ end # Utmpx
111
+
112
+ end # Solaris
113
+
@@ -0,0 +1,45 @@
1
+
2
+ require 'test/unit'
3
+ require 'solaris/utmpx'
4
+
5
+ class TestCreate < Test::Unit::TestCase #:nodoc:
6
+
7
+ def test_create
8
+ utmpx = Solaris::Utmpx.new(:endian => :big)
9
+ record = utmpx.create(
10
+ :ut_user => "root",
11
+ :ut_id => "co10",
12
+ :ut_line => "console",
13
+ :ut_pid => 1407,
14
+ :ut_type => 7,
15
+ :ut_termination => 0,
16
+ :ut_exit => 53726,
17
+ :ut_tv_sec => 1297338834,
18
+ :ut_tv_usec => 0,
19
+ :ut_session => 0,
20
+ :ut_syslen => 8,
21
+ :ut_host => "jupiter"
22
+ )
23
+ assert_equal("root", record.ut_user)
24
+ assert_equal("co10", record.ut_id)
25
+ assert_equal("console", record.ut_line)
26
+ assert_equal(1407, record.ut_pid)
27
+ assert_equal(7, record.ut_type)
28
+ assert_equal(0, record.ut_termination)
29
+ assert_equal(53726, record.ut_exit)
30
+ assert_equal(1297338834, record.ut_tv_sec)
31
+ assert_equal(0, record.ut_tv_usec)
32
+ assert_equal(0, record.ut_session)
33
+ assert_equal(8, record.ut_syslen)
34
+ assert_equal("jupiter", record.ut_host)
35
+ end
36
+
37
+ def test_create_invalid_fields
38
+ utmpx = Solaris::Utmpx.new(:endian => :big)
39
+ assert_raise(ArgumentError) do
40
+ utmpx.create(:quack => :boom)
41
+ end
42
+ end
43
+
44
+ end # TestCreate
45
+
@@ -0,0 +1,59 @@
1
+
2
+ require 'test/unit'
3
+ require 'solaris/utmpx'
4
+
5
+ class TestUtmpxI386 < Test::Unit::TestCase #:nodoc:
6
+
7
+ def setup
8
+ @reader = Solaris::Utmpx.new(:endian => :little)
9
+ @io = File.open(File.join(File.dirname(__FILE__), 'wtmpx.i386'), 'r')
10
+ @records = []
11
+ 4.times { @records << @reader.read(@io) }
12
+ end
13
+
14
+ def teardown
15
+ @io.close
16
+ end
17
+
18
+ def test_read
19
+ assert_equal("root", @records[3].ut_user)
20
+ assert_equal("co10", @records[3].ut_id)
21
+ assert_equal("console", @records[3].ut_line)
22
+ assert_equal(1407, @records[3].ut_pid)
23
+ assert_equal(7, @records[3].ut_type)
24
+ assert_equal(0, @records[3].ut_termination)
25
+ assert_equal(53726, @records[3].ut_exit)
26
+ assert_equal(1297338834, @records[3].ut_tv_sec)
27
+ assert_equal(0, @records[3].ut_tv_usec)
28
+ assert_equal(0, @records[3].ut_session)
29
+ assert_equal(0, @records[3].ut_syslen)
30
+ assert_equal("", @records[3].ut_host)
31
+ end
32
+
33
+ def test_record_length
34
+ @records.each do |record|
35
+ assert_equal(Solaris::Utmpx::RECORD_LENGTH, record.to_binary_s.length)
36
+ end
37
+ end
38
+
39
+ def test_ut_syslen
40
+ @records.each do |record|
41
+ # +1 since ut_syslen includes terminating null but only when non-zero
42
+ if record.ut_syslen == 0
43
+ assert_equal(record.ut_syslen, record.ut_host.length, "#{record}")
44
+ else
45
+ assert_equal(record.ut_syslen, record.ut_host.length + 1, "#{record}")
46
+ end
47
+ end
48
+ end
49
+
50
+ def test_to_binary_s
51
+ @io.rewind
52
+ @records.each do |record|
53
+ raw = @io.read(Solaris::Utmpx::RECORD_LENGTH)
54
+ assert_equal(raw, record.to_binary_s)
55
+ end
56
+ end
57
+
58
+ end # TestUtmpxI386
59
+
@@ -0,0 +1,59 @@
1
+
2
+ require 'test/unit'
3
+ require 'solaris/utmpx'
4
+
5
+ class TestUtmpxSparc < Test::Unit::TestCase #:nodoc:
6
+
7
+ def setup
8
+ @reader = Solaris::Utmpx.new(:endian => :big)
9
+ @io = File.open(File.join(File.dirname(__FILE__), 'wtmpx.sparc'), 'r')
10
+ @records = []
11
+ 4.times { @records << @reader.read(@io) }
12
+ end
13
+
14
+ def teardown
15
+ @io.close
16
+ end
17
+
18
+ def test_read
19
+ assert_equal("root", @records[3].ut_user)
20
+ assert_equal("co10", @records[3].ut_id)
21
+ assert_equal("console", @records[3].ut_line)
22
+ assert_equal(3944, @records[3].ut_pid)
23
+ assert_equal(7, @records[3].ut_type)
24
+ assert_equal(0, @records[3].ut_termination)
25
+ assert_equal(0, @records[3].ut_exit)
26
+ assert_equal(1230681969, @records[3].ut_tv_sec)
27
+ assert_equal(0, @records[3].ut_tv_usec)
28
+ assert_equal(0, @records[3].ut_session)
29
+ assert_equal(0, @records[3].ut_syslen)
30
+ assert_equal("", @records[3].ut_host)
31
+ end
32
+
33
+ def test_record_length
34
+ @records.each do |record|
35
+ assert_equal(Solaris::Utmpx::RECORD_LENGTH, record.to_binary_s.length)
36
+ end
37
+ end
38
+
39
+ def test_ut_syslen
40
+ @records.each do |record|
41
+ # +1 since ut_syslen includes terminating null but only when non-zero
42
+ if record.ut_syslen == 0
43
+ assert_equal(record.ut_syslen, record.ut_host.length, "#{record}")
44
+ else
45
+ assert_equal(record.ut_syslen, record.ut_host.length + 1, "#{record}")
46
+ end
47
+ end
48
+ end
49
+
50
+ def test_to_binary_s
51
+ @io.rewind
52
+ @records.each do |record|
53
+ raw = @io.read(Solaris::Utmpx::RECORD_LENGTH)
54
+ assert_equal(raw, record.to_binary_s)
55
+ end
56
+ end
57
+
58
+ end # TestUtmpxSparc
59
+
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: solaris-utmpx
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Martin Carpenter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bindata
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.5.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.5.0
27
+ description: Read and write Solaris utmpx and wtmpx files
28
+ email: mcarpenter@free.fr
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - Rakefile
34
+ - README.rdoc
35
+ files:
36
+ - examples/filter_root.rb
37
+ - examples/wtmpx.rb
38
+ - lib/solaris.rb
39
+ - lib/solaris/utmpx.rb
40
+ - test/test_create.rb
41
+ - test/test_utmpx_i386.rb
42
+ - test/test_utmpx_sparc.rb
43
+ - test/wtmpx.i386
44
+ - test/wtmpx.sparc
45
+ - LICENSE
46
+ - Rakefile
47
+ - README.rdoc
48
+ homepage: http://github.com/mcarpenter/solaris-utmpx
49
+ licenses:
50
+ - BSD
51
+ metadata: {}
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 2.0.3
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Read and write Solaris utmpx and wtmpx files
72
+ test_files:
73
+ - test/test_create.rb
74
+ - test/test_utmpx_i386.rb
75
+ - test/test_utmpx_sparc.rb