#!/usr/bin/ruby

### Copyright 2017 Pixar

###
###    Licensed under the Apache License, Version 2.0 (the "Apache License")
###    with the following modification; you may not use this file except in
###    compliance with the Apache License and the following modification to it:
###    Section 6. Trademarks. is deleted and replaced with:
###
###    6. Trademarks. This License does not grant permission to use the trade
###       names, trademarks, service marks, or product names of the Licensor
###       and its affiliates, except as required to comply with Section 4(c) of
###       the License and to reproduce the content of the NOTICE file.
###
###    You may obtain a copy of the Apache License at
###
###        http://www.apache.org/licenses/LICENSE-2.0
###
###    Unless required by applicable law or agreed to in writing, software
###    distributed under the Apache License with the above modification is
###    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
###    KIND, either express or implied. See the Apache License for the specific
###    language governing permissions and limitations under the Apache License.

# == Synopsis
#   Run the jamfHelper program as a detached background process, optionally
#   writing its output to a file, and optionally running it as the console user
#   (if this script is being run by root).
#
#  WARNING: You shouldn't run this command directly as a launchd job. Rather
#  you should write a small script that runs this command, and use launchd
#  to run that.
#
#
# == Usage
#   jamfHelperBackgrounder <options> | -help
#
#
# == Author
#   Chris Lasell <chrisl@pixar.com>
#
# == Copyright
#   Copyright (c) 2017 Pixar Animation Studios
##############################

require 'ruby-jss'

# The app object
class App

  WIN_TYPE_PARAM = '-windowType'.freeze
  CONS_USER_PARAM = '-consoleUser'.freeze
  OUTPUT_FILE_PARAM = '-outputFile'.freeze

  # Set up
  #
  def initialize(args)
    if args.include? '-help'
      @help = true
      return
    end

    if args.include? CONS_USER_PARAM
      args.delete CONS_USER_PARAM
      @as_user = JSS::Client.console_user
    else

      wintype_idx = args.index { |a| a == WIN_TYPE_PARAM }
      raise 'missing option: -windowType' unless wintype_idx
      args.delete_at wintype_idx
      @window_type = args.delete_at(wintype_idx).to_sym

      if args.include? OUTPUT_FILE_PARAM
        outfile_idx = args.index { |a| a == OUTPUT_FILE_PARAM }
        args.delete_at outfile_idx
        @outfile = args.delete_at outfile_idx
      end

    end # if args.include? AS_USER_PARAM...else...

    @arg_string = ''
    args.each { |a| @arg_string << " #{Shellwords.escape a}" }
  end # init

  # Do the thing. Win the points.
  #
  # @return [void]
  #
  def run
    if @help
      show_help
      return
    end

    if @as_user
      raise 'Only root can do things as another user' unless JSS.superuser?
      cmd = ['su', '-l', @as_user, '-c', "#{Shellwords.escape __FILE__} #{@arg_string}"]
      exec(*cmd)
    end

    JSS::Client.jamf_helper @window_type, arg_string: @arg_string, abandon_process: true, output_file: @outfile
  end # run

  # Spew helpful info to output
  #
  # @return [void]
  #
  def show_help
    puts <<-ENDHELP
This command runs the jamfHelper command as a detached background process.
This means that you use this command in a policy (via script, usually) and the
Policy execution will continue, and exit properly, even while the jamfHelper window
is still open.

This is important because future Jamf checkins will not happen if an earlier checkin
policy is waiting for a jamfHelper window to close.

This command takes all the same commandline options as jamfHelper, plus these:

  -outputFile <path>      Write the numeric output from jamfHelper to the file
                          at <path>. The path must be writable by the user
                          running jamfHelper (see below).
                          This file can be examined later to determine what
                          the user clicked.

  -consoleUser            Run the jamfHelper process as the current console (GUI)
                          user. This is needed from most policies and other code
                          running as root, in order to show the window in the
                          current console user's UI. If no one is logged into the
                          console, nothing happens.
                          This can only be used by the root user.

  -help                   Show this help.

WARNING: You shouldn't run this command directly as a launchd job. Rather
you should write a small script that runs this command, and use launchd
to run that.
ENDHELP
  end # show help

end # app

##############################
# create the app and go

app = App.new(ARGV)
app.run