aboutsummaryrefslogtreecommitdiffstats
path: root/remove-old-kernels
blob: 43d6d45adf058104fa2f1f131cab5da130df247f (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
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
#!/usr/bin/bash
# Remove old kernels safely and cleanly using urpme.
#
# LISTK contains the list of kernels to analyse
# The script keeps NBK most recent kernels
# (c) Pierre Jarillon - 2018-04-03 - 2021-11-27
# (c) Jean-Baptiste Biernacki 2021
# (c) Barry C Jackson 2022-2023
####################################
#
######################### Functions #########################

# Perform translations
i18n() {
gettext "$prog" "$1"
}

# Display -help
usage() {
echo "$(i18n "Usage: <remove-old kernels|rok> [-a] [-A 0|1] [-c] [-t] [-f 0-9] [-F 0-9] [-n number] [-N number] [-p] [-q] [-Q 0|1][-l] [-m] [-v] [-h|-?]")"
echo "$(i18n "    -a = automatic, no questions. Interactive if not specified. (must be root)")"
echo "$(i18n "    -A value = 1 or 0 to turn ON or OFF automatic weekly removal of kernels. (e.g. -A1)")"
echo "$(i18n "    -c = as automatic but also checks for CRON=1 in the cfg file or exits. (must be root)")"
echo "$(i18n "    -t = Test mode, nothing is removed, urpme is simulated.")"
echo "$(i18n "    -f value = number of the alternate .cfg file to use this time only. Exits if missing.")"
echo "$(i18n "    -F value = number of alt .cfg file to use. This changes the ALTCFG= setting in the main .cfg file.")"
echo "$(i18n "    -n value = number of kernels to keep this time only. (-n5 or -n 5 keep 5 kernels), Min=2, Default=3")"
echo "$(i18n "    -N value = number of kernels to keep. This changes the config file setting. (e.g. -N 5)")"
echo "$(i18n "    -p = preview the urpme commands which would be used.")"
echo "$(i18n "    -q = advanced mode, this time only - see man page.")"
echo "$(i18n "    -Q value = 1 or 0 (1 = ON) advanced mode, persistent. (e.g. -Q1)")"
echo "$(i18n "    -l = list the last 1000 lines of the log.")"
echo "$(i18n "    -m = mono. No colours in screen output.")"
echo "$(i18n "    -v = version.")"
echo "$(i18n "    -? or -h = show this help.")"
echo ""
echo "$(i18n "KEY for column 3:")"
echo "$(i18n "     U = currently (U)sed running kernel.")"
echo "$(i18n "     V = keeping for (V)irtualbox -latest. (only in advanced mode)")"
echo "$(i18n "     X = keeping for (X)tables-addons -latest. (only in advanced mode)")"
echo "$(i18n "     K = keeping kernel-*-devel for installed (K)ernel. (only advanced mode)")"
echo ""
}

# Function to check we are root or exit
chkroot() {
if (( UID > 0 )); then
   echo -e "${RemvCol}$(i18n "Must be root to edit configuration")${Normal}\n$(i18n "Tap spacebar")"
   read -r -n1; echo -en "${ClearLine}"
   exit 0
fi
}

# Function to handle -f or -F options
altcfg() {
cfgno=$1
# Called with f
if [[ $ed -ne 1 ]]; then
    # Check for cfg 0
    if (( cfgno == 0 )); then
        source "${maincfg}"
        ALTCFG="${cfgno}"
    else
        # If alt cfg file exists source it
        if [[ -f /etc/remove-old-kernels_"${cfgno}".cfg ]]; then
                source "/etc/remove-old-kernels_${cfgno}.cfg"
            ALTCFG=${cfgno}
        else
            echo -e "${RemvCol}$(i18n "No such alternative configuration file:")${Normal} /etc/remove-old-kernels_${cfgno}.cfg"
            exit 1
        fi
    fi
else
    # Called with F
    # If ALTCFG var is missing from the main .cfg file, add it
    if ! grep -qF "ALTCFG=" "${maincfg}"; then
        echo "ALTCFG=" >> "${maincfg}"
    fi
    # Switch back to .cfg 0
    if (( cfgno == 0 )); then
        /usr/bin/sed -i "s/ALTCFG=.*/ALTCFG=${cfgno}/" "${maincfg}"
        source "${maincfg}"; currcfg="${maincfg}"
    else
        # If alt cfg file exists
        if [[ -f /etc/remove-old-kernels_${cfgno}.cfg ]]; then
            # Add it in main .cfg
            /usr/bin/sed -i "s/ALTCFG=.*/ALTCFG=${cfgno}/" "${maincfg}"
            ALTCFG=${cfgno};
            currcfg="${cfgpath}${prog}_${ALTCFG}.cfg"
            source "$currcfg"
        else
            echo -e "${RemvCol}$(i18n "No such alternative configuration file:")${Normal} /etc/remove-old-kernels_${cfgno}.cfg"
            exit 1
        fi
    fi
fi
}

# Check cfg file(s) and source
chk_cfg() {
# Source main .cfg file if it exists, or issue warning and abort.
source ${maincfg} || { echo -e "${RemvCol}$(i18n "FATAL: Failed to read:")${Normal} ${maincfg}"; exit 1; }

# If an alt .cfg is set in main .cfg
if grep -qF "ALTCFG=" "${maincfg}" && (( ALTCFG > 0 )); then
    # Check it really exists
    if [[ -f "${cfgpath}${prog}_$ALTCFG.cfg" ]]; then
        # Set current cfg to it
        currcfg="${cfgpath}${prog}_${ALTCFG}.cfg"
        source "$currcfg"
    else
        echo -e "${RemvCol}$(i18n "Your alternative configuration file does not exist:")${Normal}/etc/remove-old-kernels_$ALTCFG.cfg\n$(i18n "Either replace it or set ALTCFG=0 in") /etc/remove-old-kernels.cfg"
        exit 1
    fi
fi

# The following config file checks need root to update files if needed
if (( UID == 0 )); then
# Check for CRON variable in config or add default. (Some users may have early versions)
    if ! grep -qF -e "CRON=" "${currcfg}"; then
        echo -e "\n# Allow cron to run remove-old-kernels. 0=OFF 1=ON.\nCRON=1" >> "${currcfg}"
    fi

# Update comment in config file if needed since $CRON change to 0|1
    /usr/bin/sed -i 's/^.*\blower case\b.*$/# Allow cron to run remove-old-kernels. 0=OFF 1=ON./' "${currcfg}"

# Check for CRON set to old y/n values and update cfg
    if  (( ${#CRON} == 1 )) && [[ "ny" =~ $CRON ]]; then
        [[ $CRON == y ]] && CRON=1
        [[ $CRON == n ]] && CRON=0
        /usr/bin/sed -i "s/CRON=.*/CRON=${CRON}/" "${currcfg}"
    fi
fi
}

################ Main program starts here #################
# Do not edit the values below unless you know 'exactly' what you are doing.
# You can pass parameters on the command line to acheive similar functionality,
# or edit the configuration file/s, See man rok or rok -h for more information.

NBK=3      # Default number of kernels to keep.
DEBUG=0    # 1 for test mode, urpme is simulated and not applied
MODE="I"   # mode A)utomatic, I)nteractve (DO NOT CHANGE THIS)
VISU=0     # If VISU=1, show commands which can be used
LANGUAGE="${LANG}:${LANGUAGE}"

# Colours for display     Defaults                  Used for
Normal="\e[0m"          # System default f/g colour
KeepCol="\e[92m"        # Light Green               Keep text
RemvCol="\e[91m"        # Light Red                 Remove text
InfoCol="\e[33m"        # Orange                    Information text
HdBgCol="\e[102;30m"    # Light Green Background    Heading background
WarnBgCol="\e[101m"     # Light Red Background      Warnings in heading
ClearLine="\r\e[2K"     # Clear the line

# List of kernel types to include.
# This list is only used if LISTK is omitted from the .cfg file in use.
LISTK=\
"kernel-desktop586
kernel-desktop
kernel-desktop-devel
kernel-server
kernel-server-devel
kernel-source
kernel-tmb-desktop
kernel-tmb-desktop-devel
kernel-tmb-source
kernel-linus
kernel-linus-devel
kernel-linus-source
"
prog="remove-old-kernels"
cfgpath="/etc/"
maincfg="${cfgpath}${prog}.cfg"
currcfg="${maincfg}"

# Check for -h option before running chk_cfg (issue10)
o=$(echo "$1"|cut -d- -f2)
[[ "$o" == "?" ]] && o="h"
if [[ ${#@} = 1 ]] && [[ "h" =~ $o ]]; then
        clear; usage; exit 0
fi

# Check dnf limit before option parsing
dnfNBK=0; dnfmsg=false
[[ -f /etc/dnf/dnf.conf ]] && dnfNBK=$(grep "installonly_limit=" /etc/dnf/dnf.conf|cut -d= -f2)

# Run all config file checks before option parsing
chk_cfg

# Parse command line options which take precedence over script and cfg file
if (( ${#} > 0 )) ; then
    while getopts aA:ctf:F:plmvn:N:qQ:?h NAME; do
        case ${NAME} in
            a)  MODE="A"
                ;;
            A)  chkroot
                # Allow y/n and 0/1 for compatability with older versions
                CRONN=${OPTARG}
                if [[ ${#CRONN} = 1 ]] && [[ "01ny" =~ $CRONN ]]; then
                    if [[ "ny" =~ $CRONN ]]; then
                        echo "$(i18n "Please use 0 or 1 for OFF and ON")"
                        exit 0
                    else
                        /usr/bin/sed -i "s/CRON=.*/CRON=${CRONN}/" "${currcfg}" && CRON=$CRONN
                    fi
                else
                    echo "$(i18n "Bad input value")"; exit 1
                fi
                ;;
            c)  MODE="A" && (( ${#CRON} > 0 )) && [[ "1y" =~ $CRON ]] || exit 0
                ;;
            t)  DEBUG=1
                ;;
            f)  [[ ${OPTARG} =~ ^[0-9] ]] && (( ${#OPTARG} == 1 )) && altcfg "${OPTARG}"
                ;;
            F)  chkroot
                [[ ${OPTARG} =~ ^[0-9] ]] && (( ${#OPTARG} == 1 )) && ed=1 && altcfg "${OPTARG}"
                ;;
            p)  VISU=1
                ;;
            q)  QA=1
                ;;
            Q)  chkroot
                [[ ${OPTARG} =~ ^[0-1] ]] && (( ${#OPTARG} == 1 )) && QAN="${OPTARG}"
                if grep -qF "QA=" "${currcfg}"; then
                    /usr/bin/sed -i "s/QA=.*/QA=${QAN}/" "${currcfg}" && QA="${QAN}"
                else
                    echo "QA=${QAN}" >> "${currcfg}" && QA="${QAN}"
                fi
                ;;
            n)  [[ ${OPTARG} =~ ^[0-9]+$ ]] && NBK="${OPTARG}"
                ;;
            N)  chkroot
                NBKN=${OPTARG}
                if [[ $NBKN =~ ^[0-9]+$ ]] && (( NBKN >= dnfNBK )); then
                    /usr/bin/sed -i "s/NBK=.*/NBK=$NBKN/" "${currcfg}" && NBK="$NBKN"
                else
                    dnfmsg=1
                fi
                ;;
            l)  tail -n1000 /var/log/remove-old-kernels.log && { echo -e "\n$(i18n "Tap spacebar to exit")\n"; read -r -n1; echo -en "${ClearLine}"; }
                ;;
            m)  Normal=""; RemvCol=""; KeepCol=""; InfoCol=""; HdBgCol=""; WarnBgCol=""; ClearLine=""
                ;;
            v)  printf '%s'"$(rpm -q remove-old-kernels)\n"
                exit 2
                ;;
            h|?)  clear; usage; exit 0
                ;;
         esac
    done
fi

# Don't allow NBK < 2 whether it comes from CLI, script edit, config file or the moon
if (( NBK < 2 )); then
    NBK=2
fi

# Only use greeting in interactive mode
if [[ "$MODE" == "I" ]]; then
clear
echo -e "                        $(i18n "Welcome to 'remove-old-kernels' Interactive")\n"
fi

# Use dnf kernel 'number to keep' if installed and greater than ours
if (( dnfNBK > NBK )) || (( dnfmsg == 1 )); then
    NBK=$dnfNBK
    dnfmssg="${InfoCol}$(i18n "INFO: Number to keep is restricted to ")${dnfNBK}\
$(i18n ", by the dnf 'installonly_limit' set in /etc/dnf/dnf.conf")${Normal}" 
fi

# Get info for status message
if (( CRON == 1 )); then autostat="1"; else autostat="${Normal}${WarnBgCol}0${HdBgCol}"; fi
if (( QA == 1 )) ; then qamssg="| Q "; fi
if (( ALTCFG > 0 )); then cfgmssg="|${Normal}${WarnBgCol}F:${ALTCFG}${HdBgCol} "; fi

# Check that the running kernel is still installed: https://bugs.mageia.org/show_bug.cgi?id=31015
[[ -e /lib/modules/$(uname -r) ]] || { echo -e "${RemvCol}$(i18n "FATAL: Has the running kernel been uninstalled since last boot? - Aborting.")"; exit 1; }

# Get the full name of the current running kernel
CURK=$(rpm -qf /lib/modules/"$(uname -r)")

# Storage for the list of kernels to remove
TMPKTR=$(mktemp)

# Check storage usage on root partition
OCCDISK1=$(df -B 1M -l --output=used / | tail -n1 | awk '{ print $1 }')

# Pad translated strings for column 2
    keepstr="$(i18n "Keep")"
    remstr="$(i18n "Remove")"
    if (( ${#keepstr} != ${#remstr} )); then
        if (( ${#keepstr} > ${#remstr} )); then
            while (( ${#remstr} < ${#keepstr} )); do remstr="${remstr} "; done
        else
            while (( ${#remstr} > ${#keepstr} )); do keepstr="${keepstr} "; done
        fi
    fi

#========================= Analyse /boot/ =============================

NK=$(find /boot -name "vmlinuz*.mga[0-9]" | wc -l)

# In automatic mode exit immediately if kernels in boot <= number allowed to be removed
   [[ "$MODE" = "A" ]] && (( NK < NBK )) && exit 0

#================================ Show status ==============================

echo -e "${HdBgCol} System: $(cat /etc/mageia-release) | $(i18n "Kernels in") /boot/:${NK} | AUTO:$autostat | $(i18n "KEEP"):$NBK ${qamssg}${cfgmssg}${Normal} "

#================================= Analyse rpms =============================
# Get master list from rpm -qa --last
allkernels="$(rpm -qa --last|grep "kernel-")"

# Get the kernel version and release required by the installed virtualbox-flavour-latest
get_vbox_kern() {
if echo "$allkernels"|grep -q "virtualbox-${kernelType}-latest"; then
     vb_latest_ver=$(echo "$allkernels"|cut -d' ' -f1|grep "virtualbox-${kernelType}-latest"|cut -d- -f5-|rev|cut -d. -f2-|rev)
else
     qavkern=; return
fi
depkern=$(echo "$allkernels"|cut -d' ' -f1|grep "$vb_latest_ver"|grep -v latest|grep "virtualbox-kernel-[0-9]")
kern_ver=$(echo "$depkern"|cut -d- -f3-|cut -d- -f1) 
kern_rel=$(echo "$depkern"|cut -d- -f5-|cut -d. -f1)
(( ${#kern_ver} > 0 )) && (( ${#kern_rel} > 0 )) && qavkern="${kern_ver}-${kern_rel}"
}

# Get the kernel version and release required by the installed xtables-addons-flavour-latest
get_xtables_kern() {
if echo "$allkernels"|grep -q "xtables-addons-${kernelType}-latest"; then
     xt_latest_ver=$(echo "$allkernels"|cut -d' ' -f1|grep kernel-|grep "xtables-addons-kernel"|grep "latest"|cut -d- -f6-|rev|cut -d. -f2-|rev)
else
     qaxkern=; return
fi
depkern=$(echo "$allkernels"|cut -d' ' -f1|grep "$xt_latest_ver"|grep "xtables-addons-kernel-[0-9]"|cut -d ' ' -f1)
kern_ver=$(echo "$depkern"|cut -d- -f4) 
kern_rel=$(echo "$depkern"|cut -d- -f6 -|cut -d. -f1)
(( ${#kern_ver} > 0 )) && (( ${#kern_rel} > 0 )) && qaxkern="${kern_ver}-${kern_rel}"
}

# Keep the -devel package for any installed kernel package
depdev()  {
# Reset some vars
pkg=; kpkgname=; nnk=""
    # Is current pkg a -devel
    if echo "${installedKernelPackage}" | grep -q "\-devel"; then
        # Get matching kernel package name
        kpkgname=$(echo "${installedKernelPackage}"| /usr/bin/sed -e 's/\-devel//')
        # Find kernel in installed list without timestamp
        for pkg in $(echo "$allkernels"|cut -d ' ' -f1); do
            # Look through installed kernels for kernel package
            if [[ ${pkg} == "${kpkgname}" ]]; then
                nnk="K"; REMVBL=0
                # Is kernel flagged for removal?
                if  grep -q "$kpkgname" "${TMPKTR}" ; then
                    # Then this -devel is also removable
                    nnk=""; REMVBL=1
                fi
            # We are done here
            break
            fi
        done
    fi
}

# Exclude 'latest' packages from installed kernel list
rpmqaList=$(echo "$allkernels"|grep -v latest)

# Loop through kernel types in LISTK
for kernelType in ${LISTK}; do
    (( QA == 1 )) && get_vbox_kern && get_xtables_kern
    installedKernelCounter=0;
# Scan through installed kernels to match with kernel type in LISTK
    echo "$rpmqaList"|grep "${kernelType}-[0-9]"|while read -r installedKernel; do
        # Clear these for each loop
        NOTA=""; REMVBL=1
# Increment installedKernelCounter
        installedKernelCounter=$(( installedKernelCounter + 1))

# Return to the line if there exists at least one installedKernel of this kernelType
        if (( installedKernelCounter == 1 )) ; then
                echo -ne "\r ==> ${kernelType}"
                echo ""
        fi

# Remove time stamp
        installedKernelPackage="$(echo "${installedKernel}" | cut -d ' ' -f 1 )"

# Check for current kernel
          if (( $(echo "${installedKernel}" | grep -c "${CURK}") == 1 )) ; then
            NOTA="U"       # current kernel
            REMVBL=0       # not removable
        fi

# Check if kernel is required by vbox latest kernel
        if (( QA == 1 )) && (( ${#qavkern} > 0 )) && (( $(echo "${installedKernel}" | grep -c "$qavkern") == 1 )); then
            NOTA="${NOTA}V"     # Required by VBox
            REMVBL=0            # not removable
        fi

# Check if kernel is required by xtables latest kernel
        if (( QA == 1 )) && (( ${#qaxkern} > 0 )) && (( $(echo "${installedKernel}" | grep -c "$qaxkern") == 1 )); then
            NOTA="${NOTA}X"     # Required by xtables
            REMVBL=0            # not removable
        fi

# If a kernel devel package has the corresponding kernel package keep it
        if (( QA == 1 )); then
            depdev
            NOTA="${NOTA}${nnk}"
        fi

# Pad NOTA to 4
        while (( ${#NOTA} < 4 )); do NOTA="${NOTA} "; done

# Pad installedKernelCounter (col 1) to 3
        while (( ${#installedKernelCounter} < 3 )); do installedKernelCounter="${installedKernelCounter} "; done

        if (( installedKernelCounter > NBK )); then
            if (( REMVBL != 1 )) ; then
                echo -e "\r ${installedKernelCounter}${KeepCol} : $keepstr: ${NOTA}: ${installedKernel} ${Normal}"
            else
                echo -e "\r ${installedKernelCounter}${RemvCol} : $remstr: ${NOTA}: ${installedKernel} ${Normal}"
                # Add package to removal list
                echo "${installedKernelPackage}" >> "${TMPKTR}"
            fi
        else
                echo -e "\r ${installedKernelCounter}${KeepCol} : $keepstr: ${NOTA}: ${installedKernel} ${Normal}"
        fi
    done
done

# Position 'in use' key under symbol below column 3
padUse=$((${#keepstr}+9)); padstr=""
while (( ${#padstr} < padUse )); do padstr="${padstr} "; done

echo -en "${ClearLine}"
echo -e "${padstr}${KeepCol}U${InfoCol} = $(i18n "In use now")${Normal}"
if (( ${#dnfmssg} > 0 ));then echo -e "${dnfmssg}"; fi

#================================= Mode of execution ===================

nbt=$(wc -l < "${TMPKTR}")
if (( nbt != 0 )) ; then
    if (( UID > 0 )); then
        echo -e "${RemvCol}$(i18n "Must be root to allow removal")\n${Normal}"
        if (( VISU == 1 )); then
            plural="s"; (( nbt == 1 )) && plural=""
            if [[ "$plural" == "s" ]]; then
                echo "$(i18n "Commands that would be used"):"
            else
                echo "$(i18n "Command that would be used"):"
            fi
            for f in $(tac "${TMPKTR}"); do
                echo "urpme ${f}"
            done
            echo "$(i18n "Tap spacebar to exit")"
            read -n1
            echo -en "${ClearLine}"
            rm -f "${TMPKTR}"
            exit 0
        fi

        if [[ "${MODE}" != "A" ]] ; then
            if (( DEBUG == 1 )) ; then
                echo -e "\n${KeepCol}>> $(i18n "Test mode is on - kernels will not be removed") <<${Normal}"
            fi
            plural="s"; (( nbt == 1 )) && plural=""
            if [[ "$plural" == "s" ]]; then
                kernstr="$(i18n "kernels"):"
            else
                kernstr="$(i18n "kernel"):"
            fi
            read -p "$(i18n "Remove") ${nbt} $kernstr ? $(i18n "y/N/i (i=confirm for each)") " -n 1 response
            if [[ -z ${response} ]] ; then response="n" ; fi
                case ${response} in
                    [Yy])
                        AUTO="--auto"
                        MODE="A"
                        echo -e " \n"
                        ;;
                    [Ii])
                        AUTO="--auto"
                        MODE="I"
                        echo " $(i18n "interactive")"
                        ;;
                    *)
                        echo -e "\n$(i18n "Aborted")\n"
                        rm -f "${TMPKTR}"
                        exit 0
                        ;;
                esac
        fi

#================================= Execution ===========================

        for installedKernelPackage in $(tac "${TMPKTR}") ; do
            if [[ ${MODE} = "I" ]] ; then    # --- interactive mode ---
                read -p "$(i18n "Remove") ${installedKernelPackage} ? $(i18n "y/N/q (q=quit)") " -n 1 response
                echo -e " \n"
                if [[ -z ${response} ]]; then
                    response="N"
                fi
                case ${response} in
                    [Yy])
                        if (( DEBUG == 1 )) ; then
                            echo -e "\n${InfoCol}$(i18n "DEBUG: Could execute: urpme") ${AUTO} ${installedKernelPackage}${Normal}"
                            ((nbt--))
                        else
                            urpme "${installedKernelPackage}"
                            ((nbt--))
                        fi
                        ;;
                    [qQ])
                        echo -e "\n$(i18n "Aborted")"
                        rm -f "${TMPKTR}";
                        exit 0
                        ;;
                       *)
                        echo " "
                        ;;
                esac
            else             # --- automatic mode ---
                if (( DEBUG == 1 )) ; then
                    echo -e "${InfoCol}$(i18n "DEBUG: Could execute: urpme") ${AUTO} ${installedKernelPackage}${Normal}"
                    ((nbt--))
                else
                    # echo "Auto execution"
                    echo -ne 'y\n' | urpme "${AUTO}" "${installedKernelPackage}"
                    ((nbt--))
                fi
            fi
        done
        NK=$(find /boot -name "vmlinuz*.mga[0-9]" | wc -l)
        OCCDISK2=$(df -B 1M -l --output=used / | tail -n1 | awk '{ print $1 }')
        echo -e "${HdBgCol} $(i18n "Gain"):$((OCCDISK1 - OCCDISK2)) MB - $(i18n "Kernels in") /boot/: ${NK} ${Normal}"
    fi
fi

[[ $MODE == "I" ]] && { echo "$(i18n "Tap spacebar to exit")"; read -n1; echo -en "${ClearLine}"; }

rm -f "${TMPKTR}"

# Run again if some removable kernels are left
(( UID > 0 )) && exit 0             # Not root user so exit
[[ ${MODE} != "I" ]] &&  exit 0     # Auto so exit
(( nbt > 0 )) && ${0}               # Root user and interactive so run again if removable kernels left