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

Last change on this file since 30086 was 30086, checked in by nox@…, 12 years ago

port1.0/startupitem (closes #12931): Added daemondo --restart-netchange flag (bool startupitem.netchange).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 21.7 KB
Line 
1# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:filetype=tcl:et:sw=4:ts=4:sts=4
2# portstartupitem.tcl
3#
4# $Id: portstartupitem.tcl 30086 2007-10-19 11:44:14Z nox@macports.org $
5#
6# Copyright (c) 2004, 2005 Markus W. Weissman <mww@macports.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 MacPorts 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 startupitem.netchange
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    if {[tbool startupitem.netchange]} {
506        lappend args "--restart-netchange"
507    }
508   
509    # To log events then tell daemondo to log at verbosity=1
510    if { [tbool startupitem.logevents] } {
511        lappend args "--verbosity=1"
512    }
513   
514    # If pidfile was specified, translate it for daemondo.
515    #
516    # There are four cases:
517    #   (1) none
518    #   (2) auto [pidfilename]
519    #   (3) cleanup [pidfilename]
520    #   (4) manual [pidfilename]
521    #
522    set pidfileArgCnt [llength ${startupitem.pidfile}]
523    if { ${pidfileArgCnt} > 0 } {
524        if { $pidfileArgCnt == 1 } {
525            set pidFile "${prefix}/var/run/${itemname}.pid"
526            lappend destroot.keepdirs "${destroot}${prefix}/var/run"
527        } else {
528            set pidFile [lindex ${startupitem.pidfile} 1]
529        }
530
531        if { ${pidfileArgCnt} > 2 } {
532            ui_error "$UI_PREFIX [msgcat::mc "Invalid parameter count to startupitem.pidfile: 2 expected, %d found" ${pidfileArgCnt}]"
533        }
534       
535        # Translate into appropriate arguments to daemondo
536        set pidStyle [lindex ${startupitem.pidfile} 0]
537        switch ${pidStyle} {
538            none    { lappend args "--pid=none" }
539            auto    { lappend args "--pid=fileauto" "--pidfile" ${pidFile} }
540            clean   { lappend args "--pid=fileclean" "--pidfile" ${pidFile} }
541            manual  { lappend args "--pid=exec" "--pidfile" ${pidFile} }
542            default {
543                ui_error "$UI_PREFIX [msgcat::mc "Unknown pidfile style %s presented to startupitem.pidfile" ${pidStyle}]"
544            }
545        }
546    } else {
547        if { [llength ${startupitem.executable}] } {
548            lappend args "--pid=exec"
549        } else {
550            lappend args "--pid=none"
551        }
552    }
553   
554    # Create the plist file
555    set plist [open "${destroot}${itemdir}/${plistname}" w 0644]
556   
557    puts ${plist} "<?xml version='1.0' encoding='UTF-8'?>"
558    puts ${plist} "<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN"
559    puts ${plist} "http://www.apple.com/DTDs/PropertyList-1.0.dtd >"
560    puts ${plist} "<plist version='1.0'>"
561    puts ${plist} "<dict>"
562   
563    puts ${plist} "<key>Label</key><string>${uniquename}</string>"
564   
565    puts ${plist} "<key>ProgramArguments</key>"
566    puts ${plist} "<array>"
567    foreach arg ${args} { puts ${plist} "\t<string>${arg}</string>" }
568    puts ${plist} "</array>"
569   
570    puts ${plist} "<key>Debug</key><false/>"
571    puts ${plist} "<key>Disabled</key><true/>"
572    puts ${plist} "<key>OnDemand</key><false/>"
573    puts ${plist} "<key>RunAtLoad</key><false/>"
574   
575    if { [llength ${startupitem.logfile}] } {
576        puts ${plist} "<key>StandardOutPath</key><string>${startupitem.logfile}</string>"
577    }
578   
579    puts ${plist} "</dict>"
580    puts ${plist} "</plist>"
581
582    close ${plist}
583
584    # Make a symlink to the plist file
585    file mkdir "${destroot}/Library/${daemondest}"
586    system "cd ${destroot}/Library/${daemondest} && ln -sf ${itemdir}/${plistname}"
587   
588    # If launchd is not available, warn the user
589    set haveLaunchd ${portutil::autoconf::have_launchd}
590    if {![tbool haveLaunchd]} {
591        ui_msg "###########################################################"
592        ui_msg "# WARNING:"
593        ui_msg "# We're building a launchd startup item, but launchd wasn't"
594        ui_msg "# found by configure. Are you sure you didn't mess up your"
595        ui_msg "# ports.conf settings?"
596        ui_msg "###########################################################"
597    }
598   
599    # Emit some information for the user
600    ui_msg "###########################################################"
601    ui_msg "# A startup item has been generated that will aid in"
602    ui_msg "# starting ${portname} with launchd. It is disabled"
603    ui_msg "# by default. Execute the following command to start it,"
604    ui_msg "# and to cause it to launch at startup:"
605    ui_msg "#"
606    ui_msg "# sudo launchctl load -w /Library/${daemondest}/${plistname}"
607    ui_msg "###########################################################"
608}
609
610proc startupitem_create {args} {
611    global UI_PREFIX
612    global startupitem.type os.platform
613   
614    set startupitem.type [string tolower ${startupitem.type}]
615   
616    # Calculate a default value for startupitem.type
617    if {${startupitem.type} == "default" || ${startupitem.type} == ""} {
618        switch -exact ${os.platform} {
619            darwin {
620                set haveLaunchd ${portutil::autoconf::have_launchd}
621                if { [tbool haveLaunchd] } {
622                    set startupitem.type "launchd"
623                } else {
624                    set startupitem.type "systemstarter"
625                }
626            }
627            default {
628                set startupitem.type "rcng"
629            }
630        }
631    }
632
633    ui_msg "$UI_PREFIX [msgcat::mc "Creating ${startupitem.type} control script"]"
634
635    switch -- ${startupitem.type} {
636        launchd         { startupitem_create_darwin_launchd }
637        systemstarter   { startupitem_create_darwin_systemstarter }
638        rcng            { startupitem_create_rcng }
639        default         { ui_error "$UI_PREFIX [msgcat::mc "Unrecognized startupitem type %s" ${startupitem.type}]" }
640    }
641}
Note: See TracBrowser for help on using the repository browser.