Skip to content
Browse files

Implemented Etc.

  • Loading branch information...
1 parent 139f9ea commit 7e925ea53239207f5dd9ac5daddda8e0f1f3b687 Tilman Sauerbeck committed
Showing with 292 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +5 −0 Rakefile
  3. +13 −0 kernel/platform/posix.rb
  4. +139 −0 lib/etc.rb.in
  5. +134 −0 spec/library/etc_spec.rb
View
1 .gitignore
@@ -37,6 +37,7 @@ attic/externals/syd-parser/pkg
kernel/.load_order.txt
kernel/core/dir.rb
+lib/etc.rb
lib/kernel.rb
lib/rbconfig.rb
View
5 Rakefile
@@ -250,6 +250,10 @@ Rake::StructGeneratorTask.new do |t|
t.dest = "kernel/core/dir.rb"
end
+Rake::StructGeneratorTask.new do |t|
+ t.dest = "lib/etc.rb"
+end
+
AllPreCompiled = Core.output + Bootstrap.output + Platform.output + Compiler.output
AllPreCompiled << "runtime/loader.rbc"
@@ -399,6 +403,7 @@ namespace :build do
task :all => %w[
build:shotgun
build:rbc
+ lib/etc.rb
lib/rbconfig.rb
build:extensions
]
View
13 kernel/platform/posix.rb
@@ -79,4 +79,17 @@ def self.add(ret, name, *args)
attach_function nil, 'getuid', [], :uint
attach_function nil, 'getgid', [], :uint
+
+ # password and group file access
+ attach_function nil, 'getpwnam', [:string], :pointer
+ attach_function nil, 'getpwuid', [:uint], :pointer
+ attach_function nil, 'setpwent', [], :void
+ attach_function nil, 'getpwent', [], :pointer
+ attach_function nil, 'endpwent', [], :void
+
+ attach_function nil, 'getgrnam', [:string], :pointer
+ attach_function nil, 'getgrgid', [:uint], :pointer
+ attach_function nil, 'setgrent', [], :void
+ attach_function nil, 'getgrent', [], :pointer
+ attach_function nil, 'endgrent', [], :void
end
View
139 lib/etc.rb.in
@@ -0,0 +1,139 @@
+module Etc
+ class Passwd < FFI::Struct
+ @@@
+ name "struct passwd"
+ include "sys/types.h"
+ include "pwd.h"
+ field :pw_name, :string
+ field :pw_passwd, :string
+ field :pw_uid, :uint
+ field :pw_gid, :uint
+ field :pw_dir, :string
+ field :pw_shell, :string
+ @@@
+
+ def name; self[:pw_name]; end
+ def passwd; self[:pw_passwd]; end
+ def uid; self[:pw_uid]; end
+ def gid; self[:pw_gid]; end
+ def dir; self[:pw_dir]; end
+ def shell; self[:pw_shell]; end
+ end
+
+ class Group < FFI::Struct
+ @@@
+ name "struct group"
+ include "sys/types.h"
+ include "grp.h"
+ field :gr_name, :string
+ field :gr_gid, :uint
+ @@@
+
+ def name; self[:gr_name]; end
+ def gid; self[:gr_gid]; end
+ end
+
+ def self.getlogin
+ getpwuid.name
+ end
+
+ def self.getpwnam(name)
+ login = StringValue(name)
+
+ passwd_ptr = Platform::POSIX.getpwnam(name)
+ if passwd_ptr.nil?
+ raise ArgumentError, "cannot find user - #{name}"
+ end
+
+ Passwd.new(passwd_ptr)
+ end
+
+ def self.getpwuid(uid = Process.uid)
+ uid = Type.coerce_to(uid, Integer, :to_int)
+
+ passwd_ptr = Platform::POSIX.getpwuid(uid)
+ if passwd_ptr.nil?
+ raise ArgumentError, "cannot find user - #{uid}"
+ end
+
+ Passwd.new(passwd_ptr)
+ end
+
+ def self.setpwent
+ Platform::POSIX.setpwent
+ end
+
+ def self.getpwent
+ passwd_ptr = Platform::POSIX.getpwent
+ return nil if passwd_ptr.nil?
+
+ Passwd.new(passwd_ptr)
+ end
+
+ def self.endpwent
+ Platform::POSIX.endpwent
+ end
+
+ def self.passwd
+ setpwent
+
+ loop do
+ pw = getpwent
+ return if pw.nil?
+
+ yield pw
+ end
+ ensure
+ endpwent
+ end
+
+ def self.getgrnam(name)
+ name = StringValue(name)
+
+ group_ptr = Platform::POSIX.getgrnam(name)
+ if group_ptr.nil?
+ raise ArgumentError, "cannot find group - #{name}"
+ end
+
+ Group.new(group_ptr)
+ end
+
+ def self.getgrgid(gid = Process.gid)
+ gid = Type.coerce_to(gid, Integer, :to_int)
+
+ group_ptr = Platform::POSIX.getgrgid(gid)
+ if group_ptr.nil?
+ raise ArgumentError, "cannot find group - #{gid}"
+ end
+
+ Group.new(group_ptr)
+ end
+
+ def self.setgrent
+ Platform::POSIX.setgrent
+ end
+
+ def self.getgrent
+ group_ptr = Platform::POSIX.getgrent
+ return nil if group_ptr.nil?
+
+ Group.new(group_ptr)
+ end
+
+ def self.endgrent
+ Platform::POSIX.endgrent
+ end
+
+ def self.group
+ setgrent
+
+ loop do
+ gr = getgrent
+ return if gr.nil?
+
+ yield gr
+ end
+ ensure
+ endgrent
+ end
+end
View
134 spec/library/etc_spec.rb
@@ -0,0 +1,134 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+require 'etc'
+
+describe "Etc.getlogin" do
+ it "returns the name of the user who runs this process" do
+ Etc.getlogin.should == `whoami`.strip
+ end
+end
+
+describe "Etc.getpwnam" do
+ it "returns a Passwd struct instance for the given user" do
+ pw = Etc.getpwnam(`whoami`.strip)
+
+ compliant :rbx do
+ pw.is_a?(Etc::Passwd).should == true
+ end
+
+ compliant :mri do
+ pw.is_a?(Struct::Passwd).should == true
+ end
+ end
+
+ it "only accepts strings as argument" do
+ should_raise(TypeError) do
+ Etc.getpwnam(123)
+ Etc.getpwnam(nil)
+ end
+ end
+end
+
+describe "Etc.getpwuid" do
+ it "returns a Passwd struct instance for the given user" do
+ pw = Etc.getpwuid(`id -u`.strip.to_i)
+
+ compliant :rbx do
+ pw.is_a?(Etc::Passwd).should == true
+ end
+
+ compliant :mri do
+ pw.is_a?(Struct::Passwd).should == true
+ end
+ end
+
+ it "only accepts integers as argument" do
+ should_raise(TypeError) do
+ Etc.getpwuid("foo")
+ Etc.getpwuid(nil)
+ end
+ end
+
+ compliant :rbx, :ruby19 do
+ it "uses Process.uid as the default value for the argument" do
+ pw = Etc.getpwuid
+ end
+ end
+end
+
+describe "Etc.getgrnam" do
+ it "returns a Group struct instance for the given group" do
+ gr = Etc.getgrnam("root")
+
+ compliant :rbx do
+ gr.is_a?(Etc::Group).should == true
+ end
+
+ compliant :mri do
+ gr.is_a?(Struct::Group).should == true
+ end
+ end
+
+ it "only accepts strings as argument" do
+ should_raise(TypeError) do
+ Etc.getgrnam(123)
+ Etc.getgrnam(nil)
+ end
+ end
+end
+
+describe "Etc.getgrgid" do
+ before(:all) do
+ @gid = `id -g`.strip.to_i
+ @name = `id -gn`.strip
+ end
+
+ compliant :rbx, :ruby19 do
+ it "returns a Group struct instance for the given user" do
+ gr = Etc.getgrgid(@gid)
+
+ compliant :rbx do
+ gr.is_a?(Etc::Group).should == true
+ end
+
+ compliant :ruby19 do
+ gr.is_a?(Struct::Group).should == true
+ end
+
+ gr.gid.should == @gid
+ gr.name.should == @name
+ end
+ end
+
+ compliant :mri do
+ it "ignores its argument" do
+ Etc.getgrgid("foo")
+ Etc.getgrgid(42)
+ Etc.getgrgid(9876)
+ end
+
+ it "returns a Group struct instance for the current user's group" do
+ gr = Etc.getgrgid(0)
+ gr.is_a?(Struct::Group).should == true
+ gr.gid.should == @gid
+ gr.name.should == @name
+ end
+ end
+
+ compliant :rbx, :ruby19 do
+ it "only accepts integers as argument" do
+ should_raise(TypeError) do
+ Etc.getgrgid("foo")
+ Etc.getgrgid(nil)
+ end
+ end
+ end
+
+ compliant :rbx, :ruby19 do
+ it "uses Process.gid as the default value for the argument" do
+ gr = Etc.getgrgid
+
+ gr.gid.should == @gid
+ gr.name.should == @name
+ end
+ end
+end

0 comments on commit 7e925ea

Please sign in to comment.
Something went wrong with that request. Please try again.