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

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

Update some UI strings and docs to use the MacPorts name, rather than darwinports.

  • 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.30 2006/08/10 02:54:25 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} "# MacPorts 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: MacPorts"
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# MacPorts 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.macports.${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} "# MacPorts 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.