source: trunk/base/src/port1.0/portstartupitem.tcl @ 17477

Last change on this file since 17477 was 17477, checked in by jberry, 14 years ago

Update some comments, relative to bug #8372

  • Property svn:eol-style set to native
File size: 18.9 KB
Line 
1# et:ts=4
2# portstartupitem.tcl
3#
4# $Id: portstartupitem.tcl,v 1.29 2006/04/14 02:35:29 jberry Exp $
5#
6# Copyright (c) 2004, 2005 Markus W. Weissman <mww@opendarwin.org>,
7# Copyright (c) 2005 Robert Shaw <rshaw@opendarwin.org>,
8# All rights reserved.
9#
10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions are
12# met:
13#
14# 1. Redistributions of source code must retain the above copyright
15#    notice, this list of conditions and the following disclaimer.
16# 2. Redistributions in binary form must reproduce the above copyright
17#    notice, this list of conditions and the following disclaimer in the
18#    documentation and/or other materials provided with the distribution.
19# 3. Neither the name of Apple Computer, Inc. nor the names of its
20#    contributors may be used to endorse or promote products derived from
21#    this software without specific prior written permission.
22#
23# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34#
35
36
37#
38#       Newly added keys:
39#
40#       startupitem.executable  the command to start the executable
41#               This is exclusive of init, start, stop, restart
42#               - This may be composed of exec arguments only--not shell code
43#
44#       startupitem.pidfile             none
45#               There is no pidfile we can track
46#
47#       startupitem.pidfile             auto [filename.pid]
48#               The daemon is responsible for creating/deleting the pidfile
49#
50#       startupitem.pidfile             clean [filename.pid]
51#               The daemon creates the pidfile, but we must delete it
52#
53#       startupitem.pidfile             manual [filename.pid]
54#               We create and destroy the pidfile to track the pid we receive from the executable
55#
56#       startupitem.logfile             logpath
57#               Log to the specified file -- if not specified then output to /dev/null
58#               - for launchd, just set this as the standard out key
59#               - for systemstarter, redirect to this
60#
61#       startupitem.logevents   yes/no
62#               Log events to the log
63#               - for launchd, generate log messages inside daemondo
64#               - for systemstarter, generate log messages in our generated script
65#
66
67package provide portstartupitem 1.0
68package require portutil 1.0
69
70set_ui_prefix
71
72proc startupitem_create_rcng {args} {
73        global prefix destroot portname os.platform
74        global startupitem.name startupitem.requires
75        global startupitem.start startupitem.stop startupitem.restart
76        global startupitem.type
77
78        set scriptdir ${destroot}/${prefix}/etc/rc.d
79
80        if { ![exists startupitem.requires] } {
81                set startupitem.requires ""
82        }
83
84        # XXX We can't share defaults with startupitem_create_darwin
85        foreach item {startupitem.start startupitem.stop startupitem.restart} {
86                if {![info exists $item]} {
87                        return -code error "Missing required option $item"
88                }
89        }
90
91        file mkdir ${destroot} ${scriptdir}
92        set fd [open [file join ${scriptdir} ${startupitem.name}.sh] w 0755]
93
94        puts ${fd} "#!/bin/sh"
95        puts ${fd} "#"
96        puts ${fd} "# DarwinPorts generated RCng Script"
97        puts ${fd} "#"
98        puts ${fd} ""
99        puts ${fd} "# PROVIDE: ${startupitem.name}"
100        puts ${fd} "# REQUIRE: ${startupitem.requires}"
101        # TODO: Implement BEFORE support
102        puts ${fd} "# BEFORE:"
103        puts ${fd} "# KEYWORD: DarwinPorts"
104        puts ${fd} ""
105        puts ${fd} ". ${prefix}/etc/rc.subr"
106        puts ${fd} ""
107        puts ${fd} "name=\"${startupitem.name}\""
108        puts ${fd} "start_cmd=\"${startupitem.start}\""
109        puts ${fd} "stop_cmd=\"${startupitem.stop}\""
110        puts ${fd} "restart_cmd=\"${startupitem.restart}\""
111        puts ${fd} ""
112        puts ${fd} "load_rc_config \"${startupitem.name}\""
113        puts ${fd} ""
114        puts ${fd} "run_rc_command \"\$1\""
115        close ${fd}
116}
117
118proc startupitem_create_darwin_systemstarter {args} {
119        global UI_PREFIX prefix destroot destroot.keepdirs  portname os.platform
120        global startupitem.name startupitem.requires startupitem.init
121        global startupitem.start startupitem.stop startupitem.restart startupitem.executable
122        global startupitem.pidfile startupitem.logfile startupitem.logevents
123       
124        set scriptdir ${prefix}/etc/startup
125       
126        set itemname                    ${startupitem.name}
127        set uppername                   [string toupper ${startupitem.name}]
128        set itemdir                             /Library/StartupItems/${itemname}
129        set startupItemDir              ${destroot}${itemdir}
130        set startupItemScript   ${startupItemDir}/${itemname}
131        set startupItemPlist    ${startupItemDir}/StartupParameters.plist
132       
133        # Interpret the pidfile spec
134        #
135        # There are four cases:
136        #       (1) none (or none specified)
137        #       (2) auto [pidfilename]
138        #       (3) clean [pidfilename]
139        #       (4) manual [pidfilename]
140        #
141        set createPidFile false
142        set deletePidFile false
143        set pidFile ""
144        set pidfileArgCnt [llength ${startupitem.pidfile}]
145        if { ${pidfileArgCnt} > 0 } {
146                if { $pidfileArgCnt == 1 } {
147                        set pidFile "${prefix}/var/run/${itemname}.pid"
148                        lappend destroot.keepdirs "${destroot}${prefix}/var/run"
149                } else {
150                        set pidFile [lindex ${startupitem.pidfile} 1]
151                }
152                if { $pidfileArgCnt > 2 } {
153                        ui_error "$UI_PREFIX [msgcat::mc "Invalid parameter count to startupitem.pidfile: 2 expected, %d found" ${pidfileArgCnt}]"
154                }
155               
156                set pidStyle [lindex ${startupitem.pidfile} 0]
157                switch ${pidStyle} {
158                        none    { set createPidFile false; set deletePidFile false; set pidFile ""      }
159                        auto    { set createPidFile false; set deletePidFile false      }
160                        clean   { set createPidFile false; set deletePidFile true       }
161                        manual  { set createPidFile true;  set deletePidFile true       }
162                        default {
163                                ui_error "$UI_PREFIX [msgcat::mc "Unknown pidfile style %s presented to startupitem.pidfile" ${pidStyle}]"
164                        }
165                }
166        }
167
168        if { [llength ${startupitem.executable}] && 
169                        ![llength ${startupitem.init}] &&
170                        ![llength ${startupitem.start}] &&
171                        ![llength ${startupitem.stop}] &&
172                        ![llength ${startupitem.restart}] } {
173                # An executable is specified, and there is no init, start, stop, or restart
174        } else {
175                if { ![llength ${startupitem.start} ] } {
176                        set startupitem.start [list "sh ${scriptdir}/${portname}.sh start"]
177                }
178                if { ![llength ${startupitem.stop} ] } {
179                        set startupitem.stop [list "sh ${scriptdir}/${portname}.sh stop"]
180                }
181        }
182        if { ![llength ${startupitem.requires} ] } {
183                set startupitem.requires [list Disks NFS]
184        }
185        if { ![llength ${startupitem.logfile} ] } {
186                set startupitem.logfile "/dev/null"
187        }
188       
189        ########################
190        # Create the startup item directory
191        file mkdir ${startupItemDir}
192        file attributes ${startupItemDir} -owner root -group wheel
193       
194        ########################
195        # Generate the startup item script
196        set item [open "${startupItemScript}" w 0755]
197        file attributes "${startupItemScript}" -owner root -group wheel
198       
199        # Emit the header
200        puts ${item} {#!/bin/sh
201#
202# DarwinPorts generated StartupItem
203#
204
205}
206        puts ${item} "prefix=$prefix"
207        # Source the utilities package and the darwinports config file
208        puts ${item} {[ -r "/etc/rc.common" ] && . "/etc/rc.common"}
209        puts ${item} {[ -r "${prefix}/etc/rc.conf" ] && . "${prefix}/etc/rc.conf"}
210
211        # Emit the Configuration Section
212        puts ${item} "NAME=${itemname}"
213        puts ${item} "ENABLE_FLAG=\${${uppername}:=-NO-}"
214        puts ${item} "PIDFILE=\"${pidFile}\""
215        puts ${item} "LOGFILE=\"${startupitem.logfile}\""
216        puts ${item} "EXECUTABLE=\"${startupitem.executable}\""
217        puts ${item} ""
218        puts ${item} "HAVE_STARTCMDS=[expr [llength ${startupitem.start}] ? "true" : "false"]"
219        puts ${item} "HAVE_STOPCMDS=[expr [llength ${startupitem.stop}] ? "true" : "false"]"
220        puts ${item} "HAVE_RESTARTCMDS=[expr [llength ${startupitem.restart}] ? "true" : "false"]"
221        puts ${item} "DELETE_PIDFILE=${createPidFile}"
222        puts ${item} "CREATE_PIDFILE=${deletePidFile}"
223        puts ${item} "LOG_EVENTS=[expr [tbool ${startupitem.logevents}] ? "true" : "false"]"
224        puts ${item} ""
225
226        # Emit the init lines
227        foreach line ${startupitem.init} { puts ${item} ${line} }
228        puts ${item} ""
229       
230        # Emit the _Cmds
231        foreach kind { start stop restart } {
232                if {[llength [set "startupitem.$kind"]]} {
233                        puts ${item} "${kind}Cmds () {"
234                        foreach line [set "startupitem.$kind"] {
235                                puts ${item} "\t${line}"
236                        }
237                        puts ${item} "}\n"
238                }
239        }
240       
241        # vvvvv START BOILERPLATE vvvvvv
242        # Emit the static boilerplate section
243        puts ${item} {
244IsEnabled () {
245        [ "${ENABLE_FLAG}" = "-YES-" ]
246        return $?
247}
248
249CreatePIDFile () {
250        echo $1 > "$PIDFILE"
251}
252
253DeletePIDFile () {
254        rm -f "$PIDFILE"
255}
256
257ReadPID () {
258        if [ -r "$PIDFILE" ]; then
259                read pid < "$PIDFILE"
260        else
261                pid=0
262        fi
263        echo $pid
264}
265
266CheckPID () {
267        pid=$(ReadPID)
268        if (($pid)); then
269                kill -0 $pid >& /dev/null || pid=0
270        fi
271        echo $pid
272}
273
274NoteEvent () {
275        ConsoleMessage "$1"
276        $LOG_EVENTS && [ -n "$LOGFILE" ] && echo "$(date) $NAME: $1" >> $LOGFILE
277}
278
279StartService () {
280        if IsEnabled; then
281                NoteEvent "Starting $NAME"
282               
283                if $HAVE_STARTCMDS; then
284                        startCmds
285                elif [ -n "$EXECUTABLE" ]; then
286                        $EXECUTABLE &
287                        pid=$!
288                        if $CREATE_PIDFILE; then
289                                CreatePIDFile $pid
290                        fi
291                fi
292               
293        fi
294}
295
296StopService () {
297        NoteEvent "Stopping $NAME"
298       
299        gaveup=false
300        if $HAVE_STOPCMDS; then
301                # If we have stop cmds, use them
302                stopCmds
303        else           
304                # Otherwise, get the pid and try to stop the program
305                echo -n "Stopping $NAME..."
306               
307                pid=$(CheckPID)
308                if (($pid)); then
309                        # Try to kill the process with SIGTERM
310                        kill $pid
311                       
312                        # Wait for it to really stop
313                        for ((CNT=0; CNT < 15 && $(CheckPID); ++CNT)); do
314                                echo -n "."
315                                sleep 1
316                        done
317                       
318                        # Report status
319                        if (($(CheckPID))); then
320                                gaveup=true
321                                echo "giving up."
322                        else
323                                echo "stopped."
324                        fi
325                else
326                        echo "it's not running."
327                fi
328        fi
329       
330        # Cleanup the pidfile if we've been asked to
331        if ! $gaveup && $DELETE_PIDFILE; then
332                DeletePIDFile
333        fi
334}
335
336RestartService () {
337        if IsEnabled; then
338                NoteEvent "Restarting $NAME"
339               
340                if $HAVE_RESTARTCMDS; then
341                        # If we have restart cmds, use them
342                        restartCmds
343                else
344                        # Otherwise just stop/start it
345                        StopService
346                        StartService
347                fi
348               
349        fi
350}
351
352RunService "$1"
353}
354        # ^^^^^^ END BOILERPLATE ^^^^^^
355       
356        close ${item}
357       
358        ########################
359        # Generate the plist
360        set para [open "${startupItemPlist}" w 0644]
361        file attributes "${startupItemPlist}" -owner root -group wheel
362       
363        puts ${para} "\{"
364        puts ${para} "\tDescription\t= \"${itemname}\";"
365        puts ${para} "\tProvides\t= (\"${itemname}\");"
366        puts -nonewline ${para} "\tRequires\t= ("
367        puts -nonewline ${para} [format {"%s"} [join ${startupitem.requires} {", "}]]
368        puts ${para} ");"
369        puts ${para} "\tOrderPreference\t= \"None\";"
370        puts ${para} "\}"
371        close ${para}
372       
373        # Emit some information for the user
374        ui_msg "###########################################################"
375        ui_msg "# A startup item has been generated that will aid in"
376        ui_msg "# starting ${portname} with SystemStarter. It is disabled"
377        ui_msg "# by default. Add the following line to /etc/hostconfig"
378        ui_msg "# or ${prefix}/etc/rc.conf to start it at startup:"
379        ui_msg "#"
380        ui_msg "# ${uppername}=-YES-"
381        ui_msg "###########################################################"
382}
383
384proc startupitem_create_darwin_launchd {args} {
385        global UI_PREFIX prefix destroot destroot.keepdirs portname os.platform
386        global startupitem.name startupitem.requires startupitem.init
387        global startupitem.start startupitem.stop startupitem.restart startupitem.executable
388        global startupitem.pidfile startupitem.logfile startupitem.logevents
389
390        set scriptdir ${prefix}/etc/startup
391       
392        set itemname            ${startupitem.name}
393        set uniquename          org.darwinports.${itemname}
394        set plistname           ${uniquename}.plist
395        set daemondest          LaunchDaemons
396        set itemdir                     ${prefix}/etc/${daemondest}/${uniquename}
397        set args                        [list \
398                                                        "${prefix}/bin/daemondo" \
399                                                        "--label=${itemname}" \
400                                                        ]
401       
402        file mkdir ${destroot}${itemdir}
403        file attributes ${destroot}${itemdir} -owner root -group wheel
404               
405        if { [llength ${startupitem.executable}] && 
406                        ![llength ${startupitem.init}] &&
407                        ![llength ${startupitem.start}] &&
408                        ![llength ${startupitem.stop}] &&
409                        ![llength ${startupitem.restart}] } {
410                       
411                # An executable is specified, and there is no init, start, stop, or restart
412                # code; so we don't need a wrapper script
413                set args [concat $args "--start-cmd" ${startupitem.executable} ";"]
414               
415        } else {
416       
417                # No executable was specified, or there was an init, start, stop, or restart
418                # option, so we do need a wrapper script
419               
420                set wrappername         ${itemname}.wrapper
421                set wrapper                     "${itemdir}/${wrappername}"
422
423                if { ![llength ${startupitem.start}] } {
424                        set startupitem.start [list "sh ${scriptdir}/${portname}.sh start"]
425                }
426                if { ![llength ${startupitem.stop}] } {
427                        set startupitem.stop [list "sh ${scriptdir}/${portname}.sh stop"]
428                }
429                if { ![llength ${startupitem.restart}] } {
430                        set startupitem.restart [list Stop Start]
431                }
432
433                lappend args \
434                        "--start-cmd"   ${wrapper} start   ";" \
435                        "--stop-cmd"    ${wrapper} stop    ";" \
436                        "--restart-cmd" ${wrapper} restart ";"
437
438                # Create the wrapper script
439                set item [open "${destroot}${wrapper}" w 0755]
440                file attributes "${destroot}${wrapper}" -owner root -group wheel
441
442                puts ${item} "#!/bin/sh"
443                puts ${item} "#"
444                puts ${item} "# DarwinPorts generated daemondo support script"
445                puts ${item} "#"
446                puts ${item} ""
447               
448                puts ${item} "#"
449                puts ${item} "# Init"
450                puts ${item} "#"
451                puts ${item} "prefix=$prefix"
452                foreach line ${startupitem.init}        { puts ${item} ${line} }
453                puts ${item} ""
454
455                puts ${item} "#"
456                puts ${item} "# Start"
457                puts ${item} "#"
458                puts ${item} "Start()"
459                puts ${item} "\{"
460                foreach line ${startupitem.start}       { puts ${item} "\t${line}" }
461                puts ${item} "\}"
462                puts ${item} ""
463               
464                puts ${item} "#"
465                puts ${item} "# Stop"
466                puts ${item} "#"
467                puts ${item} "Stop()"
468                puts ${item} "\{"
469                foreach line ${startupitem.stop}        { puts ${item} "\t${line}" }
470                puts ${item} "\}"
471                puts ${item} ""
472       
473                puts ${item} "#"
474                puts ${item} "# Restart"
475                puts ${item} "#"
476                puts ${item} "Restart()"
477                puts ${item} "\{"
478                foreach line ${startupitem.restart} { puts ${item} "\t${line}" }
479                puts ${item} "\}"
480                puts ${item} ""
481
482                puts ${item} "#"
483                puts ${item} "# Run"
484                puts ${item} "#"
485                puts ${item} "Run()"
486                puts ${item} "\{"
487                puts ${item} "case \$1 in"
488                puts ${item} "  start  ) Start   ;;"
489                puts ${item} "  stop   ) Stop    ;;"
490                puts ${item} "  restart) Restart ;;"
491                puts ${item} "  *      ) echo \"\$0: unknown argument: \$1\";;"
492                puts ${item} "esac"
493                puts ${item} "\}"
494                puts ${item} ""
495
496                puts ${item} "#"
497                puts ${item} "# Run a phase based on the selector"
498                puts ${item} "#"
499                puts ${item} "Run \$1"
500                puts ${item} ""
501
502                close ${item}
503        }
504               
505        # To log events then tell daemondo to log at verbosity=1
506        if { [tbool startupitem.logevents] } {
507                lappend args "--verbosity=1"
508        }
509       
510        # If pidfile was specified, translate it for daemondo.
511        #
512        # There are four cases:
513        #       (1) none
514        #       (2) auto [pidfilename]
515        #       (3) cleanup [pidfilename]
516        #       (4) manual [pidfilename]
517        #
518        set pidfileArgCnt [llength ${startupitem.pidfile}]
519        if { ${pidfileArgCnt} > 0 } {
520                if { $pidfileArgCnt == 1 } {
521                        set pidFile "${prefix}/var/run/${itemname}.pid"
522                        lappend destroot.keepdirs "${destroot}${prefix}/var/run"
523                } else {
524                        set pidFile [lindex ${startupitem.pidfile} 1]
525                }
526
527                if { ${pidfileArgCnt} > 2 } {
528                        ui_error "$UI_PREFIX [msgcat::mc "Invalid parameter count to startupitem.pidfile: 2 expected, %d found" ${pidfileArgCnt}]"
529                }
530               
531                # Translate into appropriate arguments to daemondo
532                set pidStyle [lindex ${startupitem.pidfile} 0]
533                switch ${pidStyle} {
534                        none    { lappend args "--pid=none" }
535                        auto    { lappend args "--pid=fileauto" "--pidfile" ${pidFile} }
536                        clean   { lappend args "--pid=fileclean" "--pidfile" ${pidFile} }
537                        manual  { lappend args "--pid=exec" "--pidfile" ${pidFile} }
538                        default {
539                                ui_error "$UI_PREFIX [msgcat::mc "Unknown pidfile style %s presented to startupitem.pidfile" ${pidStyle}]"
540                        }
541                }
542        } else {
543                if { [llength ${startupitem.executable}] } {
544                        lappend args "--pid=exec"
545                } else {
546                        lappend args "--pid=none"
547                }
548        }
549       
550        # Create the plist file
551        set plist [open "${destroot}${itemdir}/${plistname}" w 0644]
552       
553        puts ${plist} "<?xml version='1.0' encoding='UTF-8'?>"
554        puts ${plist} "<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN"
555        puts ${plist} "http://www.apple.com/DTDs/PropertyList-1.0.dtd >"
556        puts ${plist} "<plist version='1.0'>"
557        puts ${plist} "<dict>"
558       
559        puts ${plist} "<key>Label</key><string>${uniquename}</string>"
560       
561        puts ${plist} "<key>ProgramArguments</key>"
562        puts ${plist} "<array>"
563        foreach arg ${args} { puts ${plist} "\t<string>${arg}</string>" }
564        puts ${plist} "</array>"
565       
566        puts ${plist} "<key>Debug</key><false/>"
567        puts ${plist} "<key>Disabled</key><false/>"
568        puts ${plist} "<key>OnDemand</key><false/>"
569        puts ${plist} "<key>RunAtLoad</key><false/>"
570       
571        if { [llength ${startupitem.logfile}] } {
572                puts ${plist} "<key>StandardOutPath</key><string>${startupitem.logfile}</string>"
573        }
574       
575        puts ${plist} "</dict>"
576        puts ${plist} "</plist>"
577
578        close ${plist}
579
580        # Make a symlink to the plist file
581        file mkdir "${destroot}/Library/${daemondest}"
582        system "cd ${destroot}/Library/${daemondest} && ln -sf ${itemdir}/${plistname}"
583       
584        # If launchd is not available, warn the user
585        set haveLaunchd ${portutil::autoconf::have_launchd}
586        if {![tbool haveLaunchd]} {
587                ui_msg "###########################################################"
588                ui_msg "# WARNING:"
589                ui_msg "# We're building a launchd startup item, but launchd wasn't"
590                ui_msg "# found by configure. Are you sure you didn't mess up your"
591                ui_msg "# ports.conf settings?"
592                ui_msg "###########################################################"
593        }
594       
595        # Emit some information for the user
596        ui_msg "###########################################################"
597        ui_msg "# A startup item has been generated that will aid in"
598        ui_msg "# starting ${portname} with launchd. It is disabled"
599        ui_msg "# by default. Execute the following command to start it,"
600        ui_msg "# and to cause it to launch at startup:"
601        ui_msg "#"
602        ui_msg "# sudo launchctl load -w /Library/${daemondest}/${plistname}"
603        ui_msg "###########################################################"
604}
605
606proc startupitem_create {args} {
607        global UI_PREFIX
608        global startupitem.type os.platform
609       
610        set startupitem.type [string tolower ${startupitem.type}]
611       
612        # Calculate a default value for startupitem.type
613        if {${startupitem.type} == "default" || ${startupitem.type} == ""} {
614                switch -exact ${os.platform} {
615                        darwin {
616                                set enableLaunchd ${portutil::autoconf::enable_launchd_support}
617                                set haveLaunchd ${portutil::autoconf::have_launchd}
618                               
619                                if { [tbool enableLaunchd] && [tbool haveLaunchd] } {
620                                        set startupitem.type "launchd"
621                                } else {
622                                        set startupitem.type "systemstarter"
623                                }
624                        }
625                        default {
626                                set startupitem.type "rcng"
627                        }
628                }
629        }
630
631        ui_msg "$UI_PREFIX [msgcat::mc "Creating ${startupitem.type} control script"]"
632
633        switch -- ${startupitem.type} {
634                launchd                 { startupitem_create_darwin_launchd }
635                systemstarter   { startupitem_create_darwin_systemstarter }
636                rcng                    { startupitem_create_rcng }
637                default                 { ui_error "$UI_PREFIX [msgcat::mc "Unrecognized startupitem type %s" ${startupitem.type}]" }
638        }
639}
Note: See TracBrowser for help on using the repository browser.