summaryrefslogtreecommitdiffstats
path: root/lsb_release
blob: 97be219ac7ee08bf9eaeb08cfff21443170dbd26 (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
#!/bin/sh
#
# lsb_release - collect LSB conformance status about a system
#
# Copyright (C) 2000, 2002, 2004 Free Standards Group, Inc.
# Originally by Dominique MASSONIE <mdomi@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# * Changes in 2.0
# - Support LSB 2.0 module layout (Mats Wichmann)
#   The LSB_VERSION is now a colon-separated field of supported module versions
#   An /etc/lsb-release.d is searched for modules beyond the core.
#   Only the filenames in this directory is looked at, those names are added
#   to LSB_VERSION.  This allows module support to be handled easily by
#   package install/removal without a need to edit lsb-release on the fly.
# - Correct license: FSG == Free Standards Group, Inc.
#
# * Changes in 1.4
# - "awk" not needed anymore (Loic Lefort)
# - fixed bug #121879 reported by Chris D. Faulhaber,
#   some shells doesn't support local variables
# - fixed a bug when single parameter sets many args including -s
# - function DisplayProgramVersion (undocumented) now exits script like Usage
# - cosmetic changes in comments/outputs
#
# * Changes in 1.3
# - No changes in script, only in build infrastructure
#
# * Changes in 1.2
# - Fixed more bash'isms
# - LSB_VERSION is no longer required in /etc/lsb-release file
# 
# * Changes in 1.1
# - removed some bash-ism and typos
#   Notice: script remains broken with ash because of awk issues
# - changed licence to FSG - "Free Software Group, Inc"
# - fixed problem with --short single arg call
# - changed Debian specifics, codename anticipates release num
#
# Description:
# Collect information from sourceable /etc/lsb-release file (present on
# LSB-compliant systems) : LSB_VERSION, DISTRIB_ID, DISTRIB_RELEASE,
# DISTRIB_CODENAME, DISTRIB_DESCRIPTION (all optional)
# Then (if needed) find and add names from /etc/lsb-release.d
# Then (if needed) find and parse the /etc/[distro]-release file


###############################################################################
#     DECLARATIONS
###############################################################################

# This script version
SCRIPTVERSION="2.0"

# Defines the data files
INFO_ROOT="/etc"                              # directory of config files
INFO_LSB_FILE="lsb-release"                   # where to get LSB version
INFO_LSB_DIR="lsb-release.d"                  # where to get LSB addon modules
INFO_DISTRIB_SUFFIX="release"                 # <distrib>-<suffix>
ALTERNATE_DISTRIB_FILE="/etc/debian_version"  # for Debian [based distrib]
ALTERNATE_DISTRIB_NAME="Debian"               #     "
CHECKFIRST="/etc/redhat-release"              # check it before file search

# Defines our exit codes
EXIT_STATUS="0"                           # default = Ok :)
ERROR_UNKNOWN="10"                        # unknown error
ERROR_USER="1"                            # program misuse
ERROR_PROGRAM="2"                         # internal error
ERROR_NOANSWER="3"                        # all required info not available
                                          # typically non LSB compliant distro!

# Defines our messages
MSG_LSBVER="LSB Version:\t"
MSG_DISTID="Distributor ID:\t"
MSG_DISTDESC="Description:\t"
MSG_DISTREL="Release:\t"
MSG_DISTCODE="Codename:\t"
MSG_NA="n/a"
MSG_NONE="(none)"
MSG_RESULT="" # contains the result in case short output selected

# Description string delimiter
DESCSTR_DELI="release"


###############################################################################
#     FUNCTIONS
###############################################################################

# Display Program Version for internal use (needed by help2man)
DisplayProgramVersion() { 
    echo "FSG $(basename $0) v$SCRIPTVERSION"
    echo
    echo "Copyright (C) 2000, 2002, 2004 Free Standards Group, Inc."
    echo "This is free software; see the source for copying conditions.  There\
 is NO"
    echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR\
 PURPOSE."
    echo
    echo "Originally written by Dominique MASSONIE."

    exit $EXIT_STATUS
}

# defines the Usage for lsb_release
Usage() {
    echo "FSG $(basename $0) v$SCRIPTVERSION prints certain LSB (Linux\
 Standard Base) and"
    echo "Distribution information."
    echo
    echo "Usage: $(basename $0) [OPTION]..."
    echo "With no OPTION specified defaults to -v."
    echo
    echo "Options:"
    echo "  -v, --version"
    echo "    Display the version of the LSB specification against which the distribution is compliant."
    echo "  -i, --id"
    echo "    Display the string id of the distributor."
    echo "  -d, --description"
    echo "    Display the single line text description of the distribution."
    echo "  -r, --release"
    echo "    Display the release number of the distribution."
    echo "  -c, --codename"
    echo "    Display the codename according to the distribution release."
    echo "  -a, --all"
    echo "    Display all of the above information."
    echo "  -s, --short"
    echo "    Use short output format for information requested by other options (or version if none)."
    echo "  -h, --help"
    echo "    Display this message."

    exit $EXIT_STATUS
}

# Handles the enhanced args (i.e. --something)
EnhancedGetopt() {
    getopt -T >/dev/null 2>&1             # is getopt the enhanced one ?
    if [ $? = 4 ]
    then                                  # Yes, advanced args ALLOWED
        OPT=$(getopt -o acdhirsvp                                             \
--long all,codename,description,help,id,release,short,version,program_version \
              -n 'lsb_release'                                                \
              -- "$@")
    else                                  # No, advanced args NOT allowed
        # convert (if needed) the enhanced options into basic ones
        MYARGS=$(echo "$@" | sed -e "/--/s/-\(-[[:alnum:]]\)[[:alnum:]]*/\1/g")
        OPT=$(getopt -o acdhirsvp                                             \
                     -n 'lsb_release'                                         \
                     -- "$MYARGS")
    fi
    if [ $? != 0 ]
    then
        exit $ERROR_PROGRAM
    fi

    NB_ARG=""       # enabled if many args set in one parameter (i.e. -dris)
    eval set -- "$OPT"
    while true ; do
        case "$1" in
        -a|--all) ARG_A="y"; NB_ARG="y"; shift;;
        -c|--codename) ARG_C="y"; NB_ARG="y"; shift;;
        -d|--description) ARG_D="y"; NB_ARG="y"; shift;;
        -i|--id) ARG_I="y"; NB_ARG="y"; shift;;
        -r|--release) ARG_R="y"; NB_ARG="y"; shift;;
        -s|--short) ARG_S="y"; shift;;
        -v|--version) ARG_V="y"; NB_ARG="y"; shift;;
        -p|--program_version) DisplayProgramVersion;;
	-h|--help) Usage;;
        --) shift; break;;
        *)  EXIT_STATUS=$ERROR_USER
            Usage;;
        esac
    done
}

# Get/Init LSB infos (maybe Distrib infos too)
GetLSBInfo() {
	# if we found LSB_VERSION, continue to look in directory
	if [ -d "$INFO_ROOT/$INFO_LSB_DIR" ]
	then
	    for tag in "$INFO_ROOT/$INFO_LSB_DIR/"*
	    do
		LSB_VERSION=$LSB_VERSION:$(basename $tag)
	    done
	fi
}

# Get the whole distrib information string (from ARG $1 file)
InitDistribInfo() {
## Notice: Debian has a debian_version file
##         (at least) Mandrake has two files, a mandrake and a redhat one
    FILENAME=$1   # CHECKFIRST or finds' result in GetDistribInfo() or ""

    if [ -z "$FILENAME" ]
    then
        if [ -f "$ALTERNATE_DISTRIB_FILE" ]
        then # For Debian only
            [ -z "$DISTRIB_ID" ] && DISTRIB_ID="$ALTERNATE_DISTRIB_NAME"
            [ -z "$DISTRIB_RELEASE" ]                                         \
                && DISTRIB_RELEASE=$(cat $ALTERNATE_DISTRIB_FILE)
            [ -z "$DISTRIB_CODENAME" ] && [ "$DISTRIB_RELEASE" = "2.1" ]      \
                && DISTRIB_CODENAME="Slink"
            [ -z "$DISTRIB_CODENAME" ] && [ "$DISTRIB_RELEASE" = "2.2" ]      \
                && DISTRIB_CODENAME="Potato"
#           [ -z "$DISTRIB_CODENAME" ] && [ "$DISTRIB_RELEASE" = "2.3" ]      \
#               && DISTRIB_CODENAME="Woody"
            [ -z "$DISTRIB_CODENAME" ] && DISTRIB_CODENAME=$DISTRIB_RELEASE
            # build the DISTRIB_DESCRIPTION string (never need to be parsed)
            [ -z "$DISTRIB_DESCRIPTION" ]                                     \
                && DISTRIB_DESCRIPTION="$DISTRIB_ID $DESCSTR_DELI $DISTRIB_REL\
EASE ($DISTRIB_CODENAME)"
        else # Only for nothing known compliant distrib :(
            [ -z "$DISTRIB_ID" ] && DISTRIB_ID=$MSG_NA
            [ -z "$DISTRIB_RELEASE" ] && DISTRIB_RELEASE=$MSG_NA
            [ -z "$DISTRIB_CODENAME" ] && DISTRIB_CODENAME=$MSG_NA
            [ -z "$DISTRIB_DESCRIPTION" ] && DISTRIB_DESCRIPTION=$MSG_NONE

            EXIT_STATUS=$ERROR_NOANSWER
        fi
    else
        NO=""                    # is Description string syntax correct ?
        if [ -z "$DISTRIB_DESCRIPTION" ]                                      \
            || [ -n "$(echo $DISTRIB_DESCRIPTION |                            \
                       sed -e "s/.*$DESCSTR_DELI.*//")" ]
        then
            TMP_DISTRIB_DESC=$(head -n 1 $FILENAME 2>/dev/null)
            [ -z "$DISTRIB_DESCRIPTION" ]                                     \
                && DISTRIB_DESCRIPTION=$TMP_DISTRIB_DESC
        else
            TMP_DISTRIB_DESC=$DISTRIB_DESCRIPTION
        fi

        if [ -z "$TMP_DISTRIB_DESC" ]  # head or lsb-release init
        then                           # file contains no data
            DISTRIB_DESCRIPTION=$MSG_NONE
            NO="y"
        else                           # Do simple check
            [ -n "$(echo $TMP_DISTRIB_DESC |                                  \
                    sed -e "s/.*$DESCSTR_DELI.*//")" ]                        \
                && NO="y"
        fi

        if [ -n "$NO" ]
        then                           # does not contain "release" delimiter
            [ -z "$DISTRIB_ID" ] && DISTRIB_ID=$MSG_NA
            [ -z "$DISTRIB_RELEASE" ] && DISTRIB_RELEASE=$MSG_NA
            [ -z "$DISTRIB_CODENAME" ] && DISTRIB_CODENAME=$MSG_NA
        fi
    fi
}

# Check missing and requested infos, then find the file and get infos
GetDistribInfo() {
    NO=""  # /etc/lsb-release data are enough to reply what is requested?
    [ -n "$ARG_D" ] && [ -z "$DISTRIB_DESCRIPTION" ] && NO="y"
    [ -z "$NO" ] && [ -n "$ARG_I" ] && [ -z "$DISTRIB_ID" ] && NO="y"
    [ -z "$NO" ] && [ -n "$ARG_R" ] && [ -z "$DISTRIB_RELEASE" ] && NO="y"
    [ -z "$NO" ] && [ -n "$ARG_C" ] && [ -z "$DISTRIB_CODENAME" ] && NO="y"

    if [ -n "$NO" ]
    then
        if [ ! -f "$CHECKFIRST" ]
        then
            CHECKFIRST=$(find $INFO_ROOT/ -maxdepth 1                         \
                   -name \*$INFO_DISTRIB_SUFFIX                               \
                   -and ! -name $INFO_LSB_FILE                                \
                   -and -type f                                               \
                   2>/dev/null                                                \
                   | head -n 1 ) # keep one of the files found (if many)
        fi
        InitDistribInfo $CHECKFIRST
    fi
}

# Display version of LSB against which distribution is compliant
DisplayVersion() {
    if [ -z "$ARG_S" ]
    then
        echo -e "$MSG_LSBVER$LSB_VERSION"          # at least "n/a"
    else
        MSG_RESULT="$MSG_RESULT${MSG_RESULT:+ }$LSB_VERSION"
    fi
}

# Display string id of distributor ( i.e. a single word! )
DisplayID() {
    if [ -z "$DISTRIB_ID" ]
    then
## Linux could be part of the distro name (i.e. Turbolinux) or a separate word
## set before, after...
## also expect a delimiter ( i.e. "release" )
        if [ -n "$(echo $TMP_DISTRIB_DESC | sed "s/.*$DESCSTR_DELI.*//")" ]
        then
            DISTRIB_ID=$MSG_NA
        else
            DISTRIB_ID=$(echo " $TMP_DISTRIB_DESC"                            \
            | sed -e "s/[[:blank:]][Ll][Ii][Nn][Uu][Xx][[:blank:]]/ /g"       \
            -e "s/\(.*\)[[:blank:]]$DESCSTR_DELI.*/\1/" -e "s/[[:blank:]]//g")
        fi
    fi
    if [ -z "$ARG_S" ]
    then
        echo -e "$MSG_DISTID$DISTRIB_ID"
    else
        MSG_RESULT="$MSG_RESULT${MSG_RESULT:+ }$DISTRIB_ID"
    fi
}

# Diplay single line text description of distribution
DisplayDescription() {
    if [ -z "$DISTRIB_DESCRIPTION" ]
    then
        # should not be empty since GetDistribInfo called on Initialization !
        EXIT_STATUS=$ERROR_PROGRAM
    fi
    if [ -z "$ARG_S" ]
    then
        echo -e "$MSG_DISTDESC$DISTRIB_DESCRIPTION"
    else
        MSG_RESULT="$MSG_RESULT${MSG_RESULT:+ }\"$DISTRIB_DESCRIPTION\""
    fi
}

# Display release number of distribution.
DisplayRelease() {
    if [ -z "$DISTRIB_RELEASE" ]
    then                       # parse the "$DISTRIB_DESCRIPTION" string
        DISTRIB_RELEASE=$(echo "$TMP_DISTRIB_DESC" |                          \
      sed -e "s/.*$DESCSTR_DELI[[:blank:]]*\([[:digit:]][[:graph:]]*\).*/\1/" )
        [ "$DISTRIB_RELEASE" = "$TMP_DISTRIB_DESC" ]                          \
            || [ -z "$DISTRIB_RELEASE" ]                                      \
            && DISTRIB_RELEASE=$MSG_NA
    fi
    if [ -z "$ARG_S" ]
    then
        echo -e "$MSG_DISTREL$DISTRIB_RELEASE"
    else
        MSG_RESULT="$MSG_RESULT${MSG_RESULT:+ }$DISTRIB_RELEASE"
    fi
}

# Display codename according to distribution version.
DisplayCodename() {
    if [ -z "$DISTRIB_CODENAME" ]
    then                       # parse the "$DISTRIB_DESCRIPTION" string
        DISTRIB_CODENAME=$(echo "$TMP_DISTRIB_DESC" |                         \
                           sed -e "s/.*$DESCSTR_DELI.*(\(.*\)).*/\1/")
        [ "$DISTRIB_CODENAME" = "$TMP_DISTRIB_DESC" ]                         \
            || [ -z "$DISTRIB_CODENAME" ]                                     \
            && DISTRIB_CODENAME=$MSG_NA
    fi
    if [ -z "$ARG_S" ]
    then
        echo -e "$MSG_DISTCODE$(echo "$DISTRIB_CODENAME" |                    \
                                tr -d "[:blank:]")" # Remove blanks
    else
        MSG_RESULT="$MSG_RESULT${MSG_RESULT:+ }$(echo "$DISTRIB_CODENAME" |   \
                                                 tr -d "[:blank:]")"
    fi
}


###############################################################################
#     MAIN
###############################################################################

# Check if any prog argument
if [ -z "$1" ]
then
    ARG_V="y"           # default set to Display LSB Version (not Usage)
else
    EnhancedGetopt "$@" # Parse program args
    if [ -n "$ARG_S" ] && [ -z "$NB_ARG" ]
    then
        ARG_V="y"       # set also default for --short when single arg
    fi
fi

# Update args to All if requested 
if [ -n "$ARG_A" ]
then
    [ -z "$ARG_C" ] && ARG_C="y"
    [ -z "$ARG_D" ] && ARG_D="y"
    [ -z "$ARG_I" ] && ARG_I="y"
    [ -z "$ARG_R" ] && ARG_R="y"
    [ -z "$ARG_V" ] && ARG_V="y"
fi

# Initialization
GetLSBInfo
GetDistribInfo

# Display requested infos (order as follow)
[ -n "$ARG_V" ] && DisplayVersion
[ -n "$ARG_I" ] && DisplayID
[ -n "$ARG_D" ] && DisplayDescription
[ -n "$ARG_R" ] && DisplayRelease
[ -n "$ARG_C" ] && DisplayCodename

[ -n "$ARG_S" ] && echo "$MSG_RESULT"

exit $EXIT_STATUS