aboutsummaryrefslogtreecommitdiffstats
path: root/add-service
blob: 684d3dbddf9d4218b6e8c61378c5db39ecd8e4ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
#!/bin/bash
#---------------------------------------------------------------
# Project         : Mandriva Linux
# Module          : rpm-helper
# File            : add-service
# Version         : $Id$
# Authors         : Frederic Lepied, Andrey Borzenkov
# Created On      : Mon Jul  8 08:14:34 2002
# Purpose         : helper script for rpm scriptlets to add a
#                   service.
#---------------------------------------------------------------

if [ x$1 = x--no-sysv ]; then
    do_sysv=no
    shift
else
    do_sysv=yes
fi

if [ $# -lt 3 ]; then
    echo "usage: $0 [--no-sysv] <pkg name> <number installed> [<service name>] [<unit name> ...]" 1>&2
    exit 1
fi

# What init system are we currently using?
if /bin/mountpoint -q /sys/fs/cgroup/systemd; then
    init=systemd
else
    init=sysvinit
fi

pkg=$1				# name of the package
num=$2				# number of packages installed
if [ $do_sysv = yes ]; then
    srv=$3			# name of the SysV script
    shift 3
else
    srv=
    shift 2
fi
units="$*"			# systemd units
units_to_enable=		# units enabled by msec
systemd_migration_dir=/var/lib/rpm-helper/systemd-migration
mkdir -p "${systemd_migration_dir}"

USERUNITDIR=/etc/systemd/system
RUNTIMEUNITDIR=/run/systemd/system
SYSTEMUNITDIR=/lib/systemd/system

find_unit() {
    unit=$(basename $1)

    # We need to normalise the systemd unit name as the native unit may not have
    # the same filename (sans it's .service suffix) as sysvinit script.
    # In this case, symlinks are used to mask the sysvinit file, but for enabling
    # and disabling units we must use the official name.

    searchunit=
    if [ -L "$USERUNITDIR/$unit" ]; then
        searchunit=$(/usr/bin/readlink -m "$USERUNITDIR/$unit")
    elif [ -e "$USERUNITDIR/$unit" ]; then
        searchunit="$USERUNITDIR/$unit"
    elif [ -L "$RUNTIMEUNITDIR/$unit" ]; then
        searchunit=$(/usr/bin/readlink -m "$RUNTIMEUNITDIR/$unit")
    elif [ -e "$RUNTIMEUNITDIR/$unit" ]; then
        searchunit="$RUNTIMEUNITDIR/$unit"
    elif [ -L "$SYSTEMUNITDIR/$unit" ]; then
        searchunit=$(/usr/bin/readlink -m "$SYSTEMUNITDIR/$unit")
    elif [ -e "$SYSTEMUNITDIR/$unit" ]; then
        searchunit="$SYSTEMUNITDIR/$unit"
    fi
    if [ -n "$searchunit" ]; then
        echo -n $searchunit
    fi
}


# If only a sysvinit service is given, then deal with a systemd unit of the same
# name. Specific specs can enable specific unit names as needed but this should
# catch the most common usage.
if [ -z "$units" ]; then
  units="$srv.service"
  searchunit=$(find_unit $units)
  if [ -n "$searchunit" ]; then
    units=$(basename $searchunit)
  fi
fi

add_service() {
    # Add the service
    if [ -r /etc/sysconfig/msec ]; then
        . /etc/sysconfig/msec
    fi
    
    # High security: add only authorized services
    LIST=/etc/security/msec/server

    # during the install the symlink isn't done so find the right file
    # by ourselves
    if [ -n "$DURING_INSTALL" -a ! -f $LIST ]; then
        LIST=/etc/security/msec/server.$SECURE_LEVEL
    fi

    # This is half-hearted support for msec: we check "srv" for a unit
    # with name "srv.service". This should account for most(?) common
    # case when SysV script srv is replaced by single unit srv.service
    # If SysV name was supplied, we assume units are equivalent and do
    # not need to be checked.
    # TODO should msec support full unit name?
    if [ -f $LIST ]; then
        if [ -n "$srv" ]; then
            if fgrep -qx "${srv}" $LIST; then
                units_to_enable="$units"
            else
                srv=
            fi
        else
            for i in $units; do
                [ $i != ${i%.service} ] && ! fgrep -qx ${i%.service} $LIST && continue
                [ $i != ${i%.socket} ] && ! fgrep -qx ${i%.socket} $LIST && continue
                [ $i != ${i%.path} ] && ! fgrep -qx ${i%.path} $LIST && continue
                units_to_enable="$units_to_enable $i"
            done
        fi
    else
        units_to_enable="$units"
    fi

    # Actually do enable/disable foo
    if [ -n "$units_to_enable" ]; then
        /bin/systemctl --quiet enable $units_to_enable >/dev/null
        if [ -n "$srv" -a ! -f "${systemd_migration_dir}/$srv" ]; then
            touch "${systemd_migration_dir}/$srv"
        fi
    fi

    # When no native systemd unit exists, the above command will actually
    # just end up running chkconfig anyway, but if a native systemd unit exists
    # the legacy init script will not be enabled.
    # In order to enable switching back ot sysvinit, we should enable the
    # sysvinit scripts too.
    if [ -n "$srv" -a -f /etc/rc.d/init.d/$srv ]; then
        /sbin/chkconfig --add $srv

        if [ -r /etc/sysconfig/system ]; then
            . /etc/sysconfig/system
        fi

        # TODO what to do with system units here?
        if [ -z "$ADD_SERVICES_TO_CURRENT_PROFILE_ONLY" ]; then
            # add the service to all the profiles at once
            if [ -d /etc/netprofile/profiles/default/services ]; then
                for dir in /etc/netprofile/profiles/*/services; do
                    touch $dir/$srv
                done
            fi
        fi
    fi
}

check_sysvinit_service() {
    rl=$1
    srv=$2

    set -- /etc/rc${rl}.d/S??$srv
    if [ $# -gt 1 ]; then
        echo 1>&2 "add-service: Error: $srv appears multiple times at runlevel $rl: $*"
    fi

    echo -n $1
}
if [ $num = 1 ]; then
    # First install mode
    if [ "null" != "$units" ]; then
        add_service
    fi
else
    # Upgrade mode.
    reloaded=no

    # Handle migration to systemd.
    # If a previously installed package only had a sysvinit script, but an
    # updated package has a native systemd unit, we need to make sure we migrate
    # any service enablement for various targets (née runlevels)
    if [ -n "$srv" -a -n "$units" ]; then
        if [ ! -f "${systemd_migration_dir}/$srv" ]; then
            full_path_units=
            for unit in $units; do
                [ "null" = "$unit" ] && continue
                # We need a full path for the symlink. Also it's possible
                # that $unit contains "foo.service" where foo is actually
                # a sysvinit script and thus we'll not have anything native.
                # We only consider a "migration" to have taken place when
                # we genuinely have a native systemd unit.
                unit=$(find_unit $unit)
                if [ -n "$unit" ]; then
                    full_path_units="$full_path_units $unit"
                fi
            done

            if [ -n "$full_path_units" ]; then
                enable_targets=
                # We have not yet migrated this service
                # First we check in which runlevels the legacy service is enabled
                # Only bother checking runlevels 1 3 and 5
                script=$(check_sysvinit_service 1 $srv)

                # NB We only check that the link exists as the old sysvinit
                # script may have been removed during migration to systemd
                # native unit.
                if [ -L "$script" ]; then
                    enable_targets="$enable_targets rescue.target"
                fi

                script=$(check_sysvinit_service 3 $srv)
                if [ -L "$script" ]; then
                    enable_targets="$enable_targets multi-user.target"
                else
                    # As graphical.target includes everything in multi-user.target,
                    # we only need to check 5 when 3 does NOT give us a result.
                    script=$(check_sysvinit_service 5 $srv)
                    if [ -L "$script" ]; then
                        enable_targets="$enable_targets graphical.target"
                    fi
                fi

                if [ -n "$enable_targets" ]; then
                    for unit in $full_path_units; do
                        bn_unit="$(basename $unit)"
                        if grep -qE "^(WantedBy|Alias)=" $unit; then 
                            if [ x$init = xsystemd -a x$reloaded = xno ]; then
                                /bin/systemctl --system daemon-reload
                                reloaded=yes
                            fi
                            echo 1>&2 "Migrating sysvinit service '$srv' to systemd native unit '$bn_unit' via systemd install rules."
                            /bin/systemctl enable $bn_unit
                        elif [[ "$bn_unit" =~ "@.service" ]]; then
                            echo 1>&2 "Migrating sysvinit service '$srv' to systemd native template unit '$bn_unit': Failed - no install rules"
                        else
                            for enable_target in $enable_targets; do
                                wantsdir=$USERUNITDIR/${enable_target}.wants
                                mkdir -p $wantsdir
                                if [ ! -f $wantsdir/$bn_unit ]; then
                                    echo 1>&2 "Migrating sysvinit service '$srv' to systemd native unit '$bn_unit' for target '${enable_target}'"
                                    ln -s $unit $wantsdir/$bn_unit
                                    reloaded=no
                                fi
                            done
                        fi
                    done
                fi

                # It could be that a package is installed but not enabled.
                # If that is the case, we should still consider it "migrated"
                # even when we do not enable anything.
                touch "${systemd_migration_dir}/$srv"
            elif [ "null" = "$units" ]; then
                # New package masks the unit be we still consider this a migration
                echo 1>&2 "Migrating sysvinit service '$srv': Masked under systemd."
                touch "${systemd_migration_dir}/$srv"
            fi
        fi
    fi

    if [ x$init = xsystemd ]; then
        # Package install may have changed the unit file, so reload the daemon
        # before trying to restart anything
        if [ x$reloaded = xno ]; then
            /bin/systemctl --system daemon-reload
        fi
        # There may be template units, so attempt to find all instances and
        # restart them.
        for unit in $units; do
            if [[ "$unit" =~ "@.service" ]]; then
                instances=$(/bin/systemctl -a --full list-units | grep -E "${unit%@.service}@[^ ]+.service" | awk '{ print $1 }')
                if [ -n "$instances" ]; then
                    for iunit in $instances; do
                        /bin/systemctl --quiet try-restart $iunit
                    done
                fi
            elif [ "null" != "$unit" ]; then
                /bin/systemctl --quiet try-restart $unit
            fi
        done
    elif [ -f /etc/rc.d/init.d/$srv ]; then
        script=$(check_sysvinit_service 3 $srv);
        if [ -f "$script" ]; then
            /sbin/chkconfig --add $srv
        fi

        # restart the service if already running
        if [ -f /var/lock/subsys/$srv ]; then
            /sbin/service $srv restart > /dev/null || :
        fi
    fi
fi

# add-service ends here