summaryrefslogtreecommitdiff
path: root/src/pmdas/linux/getinfo.c
blob: d5f7f29b00a75d61025fef5305602df4f8a5c8cc (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
/*
 * Copyright (c) 2014 Red Hat.
 * Copyright (c) 2010 Aconex.  All Rights Reserved.
 * Copyright (c) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
 *
 * 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.
 */

#include <sys/stat.h>
#include <sys/dir.h>
#include <ctype.h>
#include <fcntl.h>
#include "pmapi.h"
#include "pmda.h"
#include "indom.h"

char *
get_distro_info(void)
{
    /*
     * Heuristic guesswork ... add code here as we learn
     * more about how to identify each Linux distribution.
     */
    static char		*distro_name;
    struct stat		sbuf;
    int			r, sts, fd = -1, len = 0;
    char		path[MAXPATHLEN];
    char		prefix[16];
    enum {	/* rfiles array offsets */
	DEB_VERSION	= 0,
	LSB_RELEASE	= 6,
    };
    char *rfiles[] = { "debian_version", "oracle-release", "fedora-release",
	"redhat-release", "slackware-version", "SuSE-release", "lsb-release",
	/* insert any new distribution release variants here */
	NULL
    };

    if (distro_name)
	return distro_name;

    for (r = 0; rfiles[r] != NULL; r++) {
	snprintf(path, sizeof(path), "%s/etc/%s", linux_statspath, rfiles[r]);
	if (stat(path, &sbuf) == 0 && S_ISREG(sbuf.st_mode)) {
	    fd = open(path, O_RDONLY);
	    break;
	}
    }
    if (fd != -1) {
	if (r == DEB_VERSION) {	/* Debian, needs a prefix */
	    strncpy(prefix, "Debian ", sizeof(prefix));
	    len = 7;
	}
	/*
	 * at this point, assume sbuf is good and file contains
	 * the string we want, probably with a \n terminator
	 */
	distro_name = (char *)malloc(len + (int)sbuf.st_size + 1);
	if (distro_name != NULL) {
	    if (len)
		strncpy(distro_name, prefix, len);
	    sts = read(fd, distro_name + len, (int)sbuf.st_size);
	    if (sts <= 0) {
		free(distro_name);
		distro_name = NULL;
	    } else {
		char *nl;

		if (r == LSB_RELEASE) {	/* may be Ubuntu */
		    if (!strncmp(distro_name, "DISTRIB_ID = ", 13))
			distro_name += 13;	/* ick */
		    if (!strncmp(distro_name, "DISTRIB_ID=", 11))
			distro_name += 11;	/* more ick */
		}
		distro_name[sts + len] = '\0';
		if ((nl = strchr(distro_name, '\n')) != NULL)
		    *nl = '\0';
	    }
	}
	close(fd);
    }
    if (distro_name == NULL) 
	distro_name = "?";
    return distro_name;
}