solaris-lastlog 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +26 -0
- data/README.rdoc +47 -0
- data/Rakefile +28 -0
- data/examples/lastlog.rb +16 -0
- data/examples/set_root_time.rb +16 -0
- data/lib/solaris.rb +7 -0
- data/lib/solaris/lastlog.rb +82 -0
- data/test/lastlog.i386 +0 -0
- data/test/lastlog.sparc +0 -0
- data/test/test_create.rb +31 -0
- data/test/test_lastlog_i386.rb +64 -0
- data/test/test_lastlog_sparc.rb +64 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0a32aafce3d78d5a27ccc119bda3f64a77bd6d84
|
4
|
+
data.tar.gz: 2e299e8826ecfbbb0267251b76a77225ffa6ace7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 75c104e82828bed23b5b5be98fa5e7288ead6030167d56a79ce1c1f30fddd856af0610c9aad4a703b765bc7bd9196c8a4bc84a2bc068562c5d925045024f8036
|
7
|
+
data.tar.gz: 00a7158310efd66306124570cb405cc4d639c7eb198ac97af9b559dc72a83b2b9547167deb1e5a40aa4d6ceb813eccf1396637dfa27722d8a0d34ac4a70421f4
|
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
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
= solaris-lastlog
|
3
|
+
|
4
|
+
Author:: Martin Carpenter
|
5
|
+
Email:: mcarpenter@free.fr
|
6
|
+
Copyright:: Copyright (c) Martin Carpenter 2013
|
7
|
+
|
8
|
+
== About
|
9
|
+
The solaris-lastlog gem helps with the reading and writing of Solaris
|
10
|
+
binary lastlog(4) files.
|
11
|
+
|
12
|
+
== Examples
|
13
|
+
|
14
|
+
See the examples subdirectory.
|
15
|
+
|
16
|
+
=== Read and display all non-null entries in the lastlog
|
17
|
+
|
18
|
+
require 'solaris/lastlog'
|
19
|
+
|
20
|
+
io = File.open('/var/adm/lastlog', 'r')
|
21
|
+
reader = Solaris::Lastlog.new(:endian => :little)
|
22
|
+
uid = 0
|
23
|
+
while !io.eof? do
|
24
|
+
record = reader.read(io)
|
25
|
+
unless record.ll_time.zero?
|
26
|
+
time = Time.at(record.ll_time)
|
27
|
+
puts "%-5s %s %-16s %-8s" % [uid, time, record.ll_host, record.ll_line]
|
28
|
+
end
|
29
|
+
uid += 1
|
30
|
+
end
|
31
|
+
|
32
|
+
=== Filter the lastlog and set root's last login time to the current time
|
33
|
+
|
34
|
+
require 'solaris/lastlog'
|
35
|
+
|
36
|
+
io = File.open('/var/adm/lastlog', 'r')
|
37
|
+
reader = Solaris::Lastlog.new(:endian => :little)
|
38
|
+
first_record = true
|
39
|
+
while !io.eof? do
|
40
|
+
record = reader.read(io)
|
41
|
+
if first_record
|
42
|
+
first_record = false
|
43
|
+
record.ll_time = Time.now.to_i
|
44
|
+
end
|
45
|
+
print record.to_binary_s
|
46
|
+
end
|
47
|
+
|
data/Rakefile
ADDED
@@ -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-lastlog.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-lastlog'
|
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
|
+
|
data/examples/lastlog.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'solaris/lastlog'
|
4
|
+
|
5
|
+
io = File.open(ARGV[0], 'r')
|
6
|
+
reader = Solaris::Lastlog.new(:endian => :little)
|
7
|
+
uid = 0
|
8
|
+
while !io.eof? do
|
9
|
+
record = reader.read(io)
|
10
|
+
unless record.ll_time.zero?
|
11
|
+
time = Time.at(record.ll_time)
|
12
|
+
puts "%-5s %s %-16s %-8s" % [uid, time, record.ll_host, record.ll_line]
|
13
|
+
end
|
14
|
+
uid += 1
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'solaris/lastlog'
|
4
|
+
|
5
|
+
io = File.open(ARGV[0], 'r')
|
6
|
+
reader = Solaris::Lastlog.new(:endian => :little)
|
7
|
+
first_record = true
|
8
|
+
while !io.eof? do
|
9
|
+
record = reader.read(io)
|
10
|
+
if first_record
|
11
|
+
record.ll_time = Time.now.to_i
|
12
|
+
first_record = false
|
13
|
+
end
|
14
|
+
print record.to_binary_s
|
15
|
+
end
|
16
|
+
|
data/lib/solaris.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
|
2
|
+
require 'bindata'
|
3
|
+
|
4
|
+
module Solaris
|
5
|
+
|
6
|
+
# See "struct lastlog" in /usr/include/lastlog.h:
|
7
|
+
#
|
8
|
+
# struct lastlog {
|
9
|
+
# #ifdef _LP64
|
10
|
+
# time32_t ll_time;
|
11
|
+
# #else
|
12
|
+
# time_t ll_time;
|
13
|
+
# #endif
|
14
|
+
# char ll_line[8];
|
15
|
+
# char ll_host[16]; /* same as in utmp */
|
16
|
+
# };
|
17
|
+
#
|
18
|
+
class Lastlog
|
19
|
+
|
20
|
+
# The (anonymous) class of generated records.
|
21
|
+
attr_reader :record_class
|
22
|
+
|
23
|
+
# Length of a raw lastlog record in bytes.
|
24
|
+
RECORD_LENGTH = 28
|
25
|
+
|
26
|
+
# Create a new Lastlog factory object. Options are:
|
27
|
+
# * :endian -- mandatory, set to :big (SPARC) or :little (i386)
|
28
|
+
# * :trim_padding -- trim terminating nulls from read strings
|
29
|
+
# This will generate objects of an anonymous class that is a subclass
|
30
|
+
# of BinData::Record.
|
31
|
+
def initialize(opts)
|
32
|
+
|
33
|
+
endianism = nil
|
34
|
+
trim_padding = true
|
35
|
+
opts.each do |key, value|
|
36
|
+
case key
|
37
|
+
when :endian
|
38
|
+
endianism = value
|
39
|
+
when :trim_padding
|
40
|
+
trim_padding = value
|
41
|
+
else
|
42
|
+
raise ArgumentError, "Unknown option #{key.inspect}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
@record_class = Class.new(BinData::Record) do
|
47
|
+
|
48
|
+
endian endianism
|
49
|
+
|
50
|
+
uint32 :ll_time
|
51
|
+
string :ll_line, :length => 8, :trim_padding => trim_padding
|
52
|
+
string :ll_host, :length => 16, :trim_padding => trim_padding
|
53
|
+
|
54
|
+
# Return the timestamp of this record as a Time object in the local TZ.
|
55
|
+
def localtime
|
56
|
+
Time.at(self.ll_time)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
# Create a new record. Option keys are:
|
64
|
+
# * :ll_time
|
65
|
+
# * :ll_line
|
66
|
+
# * :ll_host
|
67
|
+
def create(opts={})
|
68
|
+
# BinData silently discards unknown fields so we check.
|
69
|
+
unknown_fields = opts.keys - self.record_class.fields.fields.map(&:name)
|
70
|
+
raise ArgumentError, "Unknown fields #{unknown_fields.inspect}" unless unknown_fields.empty?
|
71
|
+
@record_class.new(opts)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Read a lastlog record from the given IO object.
|
75
|
+
def read(io)
|
76
|
+
@record_class.read(io)
|
77
|
+
end
|
78
|
+
|
79
|
+
end # Lastlog
|
80
|
+
|
81
|
+
end # Solaris
|
82
|
+
|
data/test/lastlog.i386
ADDED
Binary file
|
data/test/lastlog.sparc
ADDED
Binary file
|
data/test/test_create.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
require 'test/unit'
|
3
|
+
require 'solaris/lastlog'
|
4
|
+
|
5
|
+
class TestCreate < Test::Unit::TestCase #:nodoc:
|
6
|
+
|
7
|
+
def test_create
|
8
|
+
lastlog = Solaris::Lastlog.new(:endian => :big)
|
9
|
+
record = lastlog.create(:ll_time => 1375010633, :ll_host => "neptune", :ll_line => "pts/1")
|
10
|
+
assert_equal(1375010633, record.ll_time)
|
11
|
+
assert_equal("neptune", record.ll_host)
|
12
|
+
assert_equal("pts/1", record.ll_line)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_create_with_padding
|
16
|
+
lastlog = Solaris::Lastlog.new(:endian => :big, :trim_padding => false)
|
17
|
+
record = lastlog.create(:ll_time => 1375010633, :ll_host => "neptune", :ll_line => "pts/1")
|
18
|
+
assert_equal(1375010633, record.ll_time)
|
19
|
+
assert_equal("neptune\x00\x00\x00\x00\x00\x00\x00\x00\x00", record.ll_host)
|
20
|
+
assert_equal("pts/1\x00\x00\x00", record.ll_line)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_create_invalid_fields
|
24
|
+
lastlog = Solaris::Lastlog.new(:endian => :big)
|
25
|
+
assert_raise(ArgumentError) do
|
26
|
+
lastlog.create(:quack => :boom)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end # TestCreate
|
31
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
require 'test/unit'
|
3
|
+
require 'solaris/lastlog'
|
4
|
+
|
5
|
+
class TestLastlogI386 < Test::Unit::TestCase #:nodoc:
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@reader = Solaris::Lastlog.new(:endian => :little)
|
9
|
+
@io = File.open(File.join(File.dirname(__FILE__), 'lastlog.i386'), 'r')
|
10
|
+
@root_entry = @reader.read(@io)
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
@io.close
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_read
|
18
|
+
assert_equal(1366318982, @root_entry.ll_time)
|
19
|
+
assert_equal("console", @root_entry.ll_line)
|
20
|
+
assert_equal("jupiter", @root_entry.ll_host)
|
21
|
+
assert_equal(Solaris::Lastlog::RECORD_LENGTH, @root_entry.to_binary_s.length)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_trim_padding
|
25
|
+
@reader = Solaris::Lastlog.new(:endian => :little, :trim_padding => false)
|
26
|
+
@io.rewind
|
27
|
+
@root_entry = @reader.read(@io)
|
28
|
+
assert_equal(1366318982, @root_entry.ll_time)
|
29
|
+
assert_equal("console\x0", @root_entry.ll_line)
|
30
|
+
assert_equal("jupiter\x0\x0\x0\x0\x0\x0\x0\x0\x0", @root_entry.ll_host)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_host
|
34
|
+
assert_equal("jupiter", @root_entry.ll_host)
|
35
|
+
@root_entry.ll_host = "host"
|
36
|
+
assert_equal("host", @root_entry.ll_host)
|
37
|
+
@root_entry.ll_host = "12345678901234567" # too long
|
38
|
+
assert_equal("1234567890123456", @root_entry.ll_host)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_line
|
42
|
+
assert_equal("console", @root_entry.ll_line)
|
43
|
+
@root_entry.ll_line = "line"
|
44
|
+
assert_equal("line", @root_entry.ll_line)
|
45
|
+
assert_equal("line", @root_entry.ll_line)
|
46
|
+
@root_entry.ll_line = "123456789" # too long
|
47
|
+
assert_equal("12345678", @root_entry.ll_line)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_time
|
51
|
+
assert_equal(Time.at(1366318982).to_i, @root_entry.ll_time)
|
52
|
+
now = Time.now.to_i
|
53
|
+
@root_entry.ll_time = now
|
54
|
+
assert_equal(now, @root_entry.ll_time)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_to_binary_s
|
58
|
+
@io.rewind
|
59
|
+
raw = @io.read(Solaris::Lastlog::RECORD_LENGTH)
|
60
|
+
assert_equal(raw, @root_entry.to_binary_s)
|
61
|
+
end
|
62
|
+
|
63
|
+
end # TestLastlogI386
|
64
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
require 'test/unit'
|
3
|
+
require 'solaris/lastlog'
|
4
|
+
|
5
|
+
class TestLastlogSparc < Test::Unit::TestCase #:nodoc:
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@reader = Solaris::Lastlog.new(:endian => :big)
|
9
|
+
@io = File.open(File.join(File.dirname(__FILE__), 'lastlog.sparc'), 'r')
|
10
|
+
@root_entry = @reader.read(@io)
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
@io.close
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_read
|
18
|
+
assert_equal(1375005527, @root_entry.ll_time)
|
19
|
+
assert_equal("console", @root_entry.ll_line)
|
20
|
+
assert_equal("jupiter", @root_entry.ll_host)
|
21
|
+
assert_equal(Solaris::Lastlog::RECORD_LENGTH, @root_entry.to_binary_s.length)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_trim_padding
|
25
|
+
@reader = Solaris::Lastlog.new(:endian => :big, :trim_padding => false)
|
26
|
+
@io.rewind
|
27
|
+
@root_entry = @reader.read(@io)
|
28
|
+
assert_equal(1375005527, @root_entry.ll_time)
|
29
|
+
assert_equal("console\x0", @root_entry.ll_line)
|
30
|
+
assert_equal("jupiter\x0\x0\x0\x0\x0\x0\x0\x0\x0", @root_entry.ll_host)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_host
|
34
|
+
assert_equal("jupiter", @root_entry.ll_host)
|
35
|
+
@root_entry.ll_host = "host"
|
36
|
+
assert_equal("host", @root_entry.ll_host)
|
37
|
+
@root_entry.ll_host = "12345678901234567" # too long
|
38
|
+
assert_equal("1234567890123456", @root_entry.ll_host)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_line
|
42
|
+
assert_equal("console", @root_entry.ll_line)
|
43
|
+
@root_entry.ll_line = "line"
|
44
|
+
assert_equal("line", @root_entry.ll_line)
|
45
|
+
assert_equal("line", @root_entry.ll_line)
|
46
|
+
@root_entry.ll_line = "123456789" # too long
|
47
|
+
assert_equal("12345678", @root_entry.ll_line)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_time
|
51
|
+
assert_equal(Time.at(1375005527).to_i, @root_entry.ll_time)
|
52
|
+
now = Time.now.to_i
|
53
|
+
@root_entry.ll_time = now
|
54
|
+
assert_equal(now, @root_entry.ll_time)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_to_binary_s
|
58
|
+
@io.rewind
|
59
|
+
raw = @io.read(Solaris::Lastlog::RECORD_LENGTH)
|
60
|
+
assert_equal(raw, @root_entry.to_binary_s)
|
61
|
+
end
|
62
|
+
|
63
|
+
end # TestLastlogSparc
|
64
|
+
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: solaris-lastlog
|
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 lastlog 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/lastlog.rb
|
37
|
+
- examples/set_root_time.rb
|
38
|
+
- lib/solaris.rb
|
39
|
+
- lib/solaris/lastlog.rb
|
40
|
+
- test/lastlog.i386
|
41
|
+
- test/lastlog.sparc
|
42
|
+
- test/test_create.rb
|
43
|
+
- test/test_lastlog_i386.rb
|
44
|
+
- test/test_lastlog_sparc.rb
|
45
|
+
- LICENSE
|
46
|
+
- Rakefile
|
47
|
+
- README.rdoc
|
48
|
+
homepage: http://github.com/mcarpenter/solaris-lastlog
|
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 lastlog files
|
72
|
+
test_files:
|
73
|
+
- test/test_create.rb
|
74
|
+
- test/test_lastlog_i386.rb
|
75
|
+
- test/test_lastlog_sparc.rb
|