#!/usr/bin/env ruby ### Copyright 2023 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 | -help # # # == Author # Chris Lasell # ############################## 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 Write the numeric output from jamfHelper to the file at . 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