1+ #
2+ # Author:: AJ Christensen (<aj@junglist.gen.nz>)
3+ # Copyright:: Copyright (c) 2008 OpsCode, Inc.
4+ # License:: Apache License, Version 2.0
5+ #
6+ # Licensed under the Apache License, Version 2.0 (the "License");
7+ # you may not use this file except in compliance with the License.
8+ # You may obtain a copy of the License at
9+ #
10+ # http://www.apache.org/licenses/LICENSE-2.0
11+ #
12+ # Unless required by applicable law or agreed to in writing, software
13+ # distributed under the License is distributed on an "AS IS" BASIS,
14+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+ # See the License for the specific language governing permissions and
16+ # limitations under the License.
17+
18+ # I love you Merb (lib/merb-core/server.rb)
19+
20+ require 'chef/config'
21+ require 'etc'
22+
23+ class Chef
24+ class Daemon
25+ class << self
26+ attr_accessor :name
27+ =begin
28+ def daemonize(name)
29+ exit if fork
30+ Process.setsid
31+ exit if fork
32+ $stdin.reopen("/dev/null")
33+ $stdout.reopen("/tmp/log", "a")
34+ $stderr.reopen($stdout)
35+ end
36+ =end
37+
38+ def daemonize ( name )
39+ @name = name
40+ pid = pid_from_file
41+ unless running?
42+ remove_pid_file ( )
43+ Chef ::Log . info ( "Daemonizing.." )
44+ begin
45+ exit if fork
46+ Process . setsid
47+ exit if fork
48+ Chef ::Log . info ( "Forked, in #{ Process . pid } " )
49+ File . umask 0000
50+ $stdin. reopen ( "/dev/null" )
51+ $stdout. reopen ( "/dev/null" , "a" )
52+ $stdout. reopen ( $stdout)
53+ at_exit { remove_pid_file }
54+ rescue NotImplementedError => e
55+ Chef . fatal! ( "There is no fork: #{ e . message } " )
56+ end
57+ else
58+ Chef . fatal! ( "Chef is already running pid #{ pid } " )
59+ end
60+ end
61+
62+ def running?
63+ if pid_from_file . nil?
64+ false
65+ else
66+ Process . kill ( 0 , pid_from_file )
67+ true
68+ end
69+ rescue Errno ::ESRCH , Errno ::ENOENT
70+ false
71+ #rescue Errno::EACCESS => e
72+ # Chef.fatal!("You don't have access to the PID file at #{pid_file}: #{e.message}")
73+ end
74+
75+ def pid_file
76+ Chef ::Config [ :pid_file ] or "/tmp/#{ @name } .pid"
77+ end
78+
79+ def pid_from_file
80+ File . read ( pid_file ) . chomp . to_i
81+ rescue Errno ::ENOENT => e
82+ nil
83+ end
84+
85+ def save_pid_file
86+ file = pid_file
87+ begin
88+ FileUtils . mkdir_p ( File . dirname ( file ) )
89+ rescue Errno ::EACCESS => e
90+ Chef . fatal! ( "Failed store pid in #{ File . dirname ( file ) } , permission denied: #{ e . message } " )
91+ end
92+
93+ begin
94+ File . open ( file , "w" ) { |f | f . write ( Process . pid . to_s ) }
95+ rescue Errno ::EACCESS => e
96+ Chef . fatal! ( "Couldn't write to pidfile #{ file } , permission denied: #{ e . message } " )
97+ end
98+ end
99+
100+ def remove_pid_file
101+ FileUtils . rm ( pid_file ) if File . exists? ( pid_file )
102+ end
103+
104+ def change_privilege
105+ if Chef ::Config [ :user ] and Chef ::Config [ :group ]
106+ Chef ::Log . info ( "About to change privilege to #{ Chef ::Config [ :user ] } :#{ Chef ::Config [ :group ] } " )
107+ _change_privilege ( Chef ::Config [ :user ] , Chef ::Config [ :group ] )
108+ elsif Chef ::Config [ :user ]
109+ Chef ::Log . info ( "About to change privilege to #{ Chef ::Config [ :user ] } " )
110+ _change_privilege ( Chef ::Config [ :user ] )
111+ end
112+ end
113+
114+ def _change_privilege ( user , group = user )
115+ uid , gid = Process . euid , Process . egid
116+
117+ begin
118+ target_uid = Etc . getpwnam ( user ) . uid
119+ rescue ArgumentError => e
120+ Chef . fatal! ( "Failed to get UID for user #{ user } , does it exist? #{ e . message } " )
121+ return false
122+ end
123+
124+ begin
125+ target_gid = Etc . getgrnam ( group ) . gid
126+ rescue ArgumentERror => e
127+ Chef . fatal! ( "Failed to get GID for group #{ group } , does it exist? #{ e . message } " )
128+ return false
129+ end
130+
131+ if ( uid != target_uid ) or ( gid != target_gid )
132+ Process . initgroups ( user , target_gid )
133+ Process ::GID . change_privilege ( target_gid )
134+ Process ::UID . change_privilege ( target_uid )
135+ end
136+ true
137+ rescue Errno ::EPERM => e
138+ Chef . fatal! ( "Permission denied when trying to change #{ uid } :#{ gid } to #{ user } :#{ group } . #{ e . message } " )
139+ end
140+ end
141+ end
142+ end
0 commit comments