From 1954e60e950b3033130703c38790971fae176221 Mon Sep 17 00:00:00 2001
From: Dag Wieers <dag@wieers.com>
Date: Tue, 30 Oct 2012 10:36:11 +0100
Subject: [PATCH 1/2] Use return codes > 255 for Ansible-specific errors.

I had made and pushed this change after you already pulled the request.

@dhozac indicated that it would probably be better to use return codes > 255 for anything related to Ansible itself. Which makes sens :)
---
 command | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/command b/command
index 63f7cdc70b3..e1b5d0c240c 100755
--- a/command
+++ b/command
@@ -84,7 +84,7 @@ def main():
     args  = module.params['args']
 
     if args.strip() == '':
-        module.fail_json(rc=255, msg="no command given")
+        module.fail_json(rc=256, msg="no command given")
 
     if chdir:
         os.chdir(os.path.expanduser(chdir))
@@ -99,7 +99,7 @@ def main():
     except (OSError, IOError), e:
         module.fail_json(rc=e.errno, msg=str(e), cmd=args)
     except:
-        module.fail_json(rc=254, msg=traceback.format_exc(), cmd=args)
+        module.fail_json(rc=257, msg=traceback.format_exc(), cmd=args)
 
     endd = datetime.datetime.now()
     delta = endd - startd
@@ -178,9 +178,9 @@ class CommandModule(AnsibleModule):
             elif m.group(2) == "chdir":
                 v = os.path.expanduser(v)
                 if not (os.path.exists(v) and os.path.isdir(v)):
-                    self.fail_json(rc=253, msg="cannot change to directory '%s': path does not exist" % v)
+                    self.fail_json(rc=258, msg="cannot change to directory '%s': path does not exist" % v)
                 elif v[0] != '/':
-                    self.fail_json(rc=252, msg="the path for 'chdir' argument must be fully qualified")
+                    self.fail_json(rc=259, msg="the path for 'chdir' argument must be fully qualified")
                 params['chdir'] = v
         args = r.sub("", args)
         params['args'] = args

From e18ef3d640a99b79e26f2c5820007a5a9365c717 Mon Sep 17 00:00:00 2001
From: Brian Coca <briancoca+ansible@gmail.com>
Date: Tue, 30 Oct 2012 22:06:11 -0400
Subject: [PATCH 2/2] Now can handle rc.conf and init.d/rc.d based systems
 Signed-off-by: Brian Coca <briancoca+ansible@gmail.com>

---
 service | 86 ++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 70 insertions(+), 16 deletions(-)

diff --git a/service b/service
index 3426e9becad..43b86ef5a53 100755
--- a/service
+++ b/service
@@ -66,20 +66,29 @@ examples:
 '''
 
 import platform
+import os
+import re
 
 SERVICE = None
 CHKCONFIG = None
 INITCTL = None
+INITSCRIPT = None
+RCCONF = None
+
 PS_OPTIONS = 'auxww'
 
-def _find_binaries(m):
+def _find_binaries(m,name):
     # list of possible paths for service/chkconfig binaries
     # with the most probable first
     global SERVICE
     global CHKCONFIG
     global INITCTL
+    global INITSCRIPT
+    global RCCONF
     paths = ['/sbin', '/usr/sbin', '/bin', '/usr/bin']
     binaries = [ 'service', 'chkconfig', 'update-rc.d', 'initctl', 'systemctl']
+    initpaths = [ '/etc/init.d','/etc/rc.d','/usr/local/etc/rc.d' ]
+    rcpaths = [ '/etc/rc.conf','/usr/local/etc/rc.conf' ]
     location = dict()
 
     for binary in binaries:
@@ -95,11 +104,20 @@ def _find_binaries(m):
     elif location.get('update-rc.d', None):
         CHKCONFIG = location['update-rc.d']
     else:
+        for rcfile in rcpaths:
+            if os.path.isfile(rcfile):
+                RCCONF = rcfile
+    if not CHKCONFIG and not RCCONF:
         m.fail_json(msg='unable to find chkconfig or update-rc.d binary')
     if location.get('service', None):
         SERVICE = location['service']
     else:
-        m.fail_json(msg='unable to find service binary')
+        for rcdir in initpaths:
+            initscript = "%s/%s" % (rcdir,name)
+            if os.path.isfile(initscript):
+                INITSCRIPT = initscript
+    if not SERVICE and not INITSCRIPT:
+        m.fail_json(msg='unable to find service binary nor initscript')
     if location.get('initctl', None):
         INITCTL = location['initctl']
     else:
@@ -196,19 +214,39 @@ def _do_enable(name, enable):
     if enable:
         on_off = "on"
         enable_disable = "enable"
+        rc = "YES"
     else:
         on_off = "off"
         enable_disable = "disable"
+        rc = "NO"
 
-    if CHKCONFIG.endswith("update-rc.d"):
-        args = (CHKCONFIG, name, enable_disable)
-    elif CHKCONFIG.endswith("systemctl"):
-        args = (CHKCONFIG, enable_disable, name + ".service")
+    if RCCONF:
+        entry = "%s_enable" % name
+        full_entry = '%s="%s"' % (entry,rc)
+        rc = open(RCCONF,"r+")
+        rctext = rc.read()
+        if re.search("^%s" % full_entry,rctext,re.M) is None:
+            if re.search("^%s" % entry,rctext,re.M) is None:
+                rctext += "\n%s" % full_entry
+            else:
+                rctext = re.sub("^%s.*" % entry,full_entry,rctext,1,re.M)
+            rc.truncate(0)
+            rc.seek(0)
+            rc.write(rctext)
+        rc.close()
+
+        rc=0
+        stderr=stdout=''
     else:
-        args = (CHKCONFIG, name, on_off)
+        if CHKCONFIG.endswith("update-rc.d"):
+            args = (CHKCONFIG, name, enable_disable)
+        elif CHKCONFIG.endswith("systemctl"):
+            args = (CHKCONFIG, enable_disable, name + ".service")
+        else:
+            args = (CHKCONFIG, name, on_off)
 
-    if enable is not None:
-        rc, stdout, stderr = _run("%s %s %s" % args)
+        if enable is not None:
+            rc, stdout, stderr = _run("%s %s %s" % args)
 
     return rc, stdout, stderr
 
@@ -235,7 +273,7 @@ def main():
 
     # ===========================================
     # find binaries locations on minion
-    _find_binaries(module)
+    _find_binaries(module,name)
 
     # ===========================================
     # get service status
@@ -248,6 +286,12 @@ def main():
     err = ''
     out = ''
 
+    # set command to run
+    if SERVICE:
+        svc_cmd = "%s %s" % (SERVICE, name)
+    elif INITSCRIPT:
+        svc_cmd = "%s" % INITSCRIPT
+
     if module.params['enabled']:
         rc_enable, out_enable, err_enable = _do_enable(name, enable)
         rc += rc_enable
@@ -273,15 +317,24 @@ def main():
         # run change commands if we need to
         if changed:
 
+            if platform.system() == 'FreeBSD':
+                start = "onestart"
+                stop = "onestop"
+                reload = "onereload"
+            else:
+                start = "start"
+                stop = "stop"
+                reload = "reload"
+
             if state in ['started', 'running']:
-                rc_state, stdout, stderr = _run("%s %s start" % (SERVICE, name))
+                rc_state, stdout, stderr = _run("%s %s" % (svc_cmd,start))
             elif state == 'stopped':
-                rc_state, stdout, stderr = _run("%s %s stop" % (SERVICE, name))
+                rc_state, stdout, stderr = _run("%s %s" % (svc_cmd,stop))
             elif state == 'reloaded':
-                rc_state, stdout, stderr = _run("%s %s reload" % (SERVICE, name))
+                rc_state, stdout, stderr = _run("%s %s" % (svc_cmd,reload))
             elif state == 'restarted':
-                rc1, stdout1, stderr1 = _run("%s %s stop" % (SERVICE, name))
-                rc2, stdout2, stderr2 = _run("%s %s start" % (SERVICE, name))
+                rc1, stdout1, stderr1 = _run("%s %s" % (svc_cmd,stop))
+                rc2, stdout2, stderr2 = _run("%s %s" % (svc_cmd,start))
                 if rc1 != 0 and rc2 == 0:
                     rc_state = rc + rc2
                     stdout = stdout2
@@ -303,7 +356,8 @@ def main():
         result['enabled'] = module.params['enabled']
     if state:
         result['state'] = state
-    rc, stdout, stderr = _run("%s %s status" % (SERVICE, name))
+
+    rc, stdout, stderr = _run("%s status" % (svc_cmd))
     module.exit_json(**result)
 
 # this is magic, see lib/ansible/module_common.py