2
* Host Resources MIB - Installed Software group implementation - hr_swinst.c
6
#include <net-snmp/net-snmp-config.h>
12
#if TIME_WITH_SYS_TIME
13
# include <sys/time.h>
17
# include <sys/time.h>
25
# define dirent direct
27
# include <sys/ndir.h>
44
#include <rpm/rpmlib.h>
45
#include <rpm/header.h>
49
#ifdef HAVE_RPMGETPATH
50
#include <rpm/rpmmacro.h>
60
#include "hr_swinst.h"
61
#include <net-snmp/utilities.h>
63
#define HRSWINST_MONOTONICALLY_INCREASING
65
/*********************
67
* Kernel & interface information,
68
* and internal forward declarations
70
*********************/
73
* Reorganize the global data into a single static structure.
76
*======================================================
77
* HRSW_directory swi->swi_directory
78
* HRSW_name[100] swi->swi_name[SNMP_MAXPATH]
79
* HRSW_index swi->swi_index
81
* swi->swi_dbpath (RPM only)
82
* swi->swi_maxrec (RPM only)
83
* swi->swi_nrec (RPM only)
84
* swi->swi_recs (RPM only)
85
* rpm_db swi->swi_rpmdb (RPM only)
86
* swi->swi_h (RPM only)
87
* swi->swi_prevx (RPM only)
96
const char *swi_directory;
98
char swi_name[SNMP_MAXPATH]; /* XXX longest file name */
102
const char *swi_dbpath;
104
time_t swi_timestamp; /* modify time on database */
105
int swi_maxrec; /* no. of allocations */
106
int swi_nrec; /* no. of valid offsets */
107
int *swi_recs; /* db record offsets */
113
struct dirent *swi_dep;
118
static SWI_t _myswi = { NULL, "", 0 }; /* XXX static for now */
120
int header_hrswinst(struct variable *, oid *, size_t *, int,
121
size_t *, WriteMethod **);
122
int header_hrswInstEntry(struct variable *, oid *, size_t *,
123
int, size_t *, WriteMethod **);
125
extern struct timeval starttime;
127
/*********************
129
* Initialisation & common implementation functions
131
*********************/
132
extern void Init_HR_SWInst(void);
133
extern int Get_Next_HR_SWInst(void);
134
extern void End_HR_SWInst(void);
135
extern void Save_HR_SW_info(int ix);
138
static void Mark_HRSW_token(void);
139
static void Release_HRSW_token(void);
141
#define Mark_HRSW_token()
142
#define Release_HRSW_token()
146
#define HRSWINST_CHANGE 1
147
#define HRSWINST_UPDATE 2
148
#define HRSWINST_INDEX 3
149
#define HRSWINST_NAME 4
150
#define HRSWINST_ID 5
151
#define HRSWINST_TYPE 6
152
#define HRSWINST_DATE 7
154
struct variable4 hrswinst_variables[] = {
155
{HRSWINST_CHANGE, ASN_TIMETICKS, RONLY, var_hrswinst, 1, {1}},
156
{HRSWINST_UPDATE, ASN_TIMETICKS, RONLY, var_hrswinst, 1, {2}},
157
{HRSWINST_INDEX, ASN_INTEGER, RONLY, var_hrswinst, 3, {3, 1, 1}},
158
{HRSWINST_NAME, ASN_OCTET_STR, RONLY, var_hrswinst, 3, {3, 1, 2}},
159
{HRSWINST_ID, ASN_OBJECT_ID, RONLY, var_hrswinst, 3, {3, 1, 3}},
160
{HRSWINST_TYPE, ASN_INTEGER, RONLY, var_hrswinst, 3, {3, 1, 4}},
161
{HRSWINST_DATE, ASN_OCTET_STR, RONLY, var_hrswinst, 3, {3, 1, 5}}
163
oid hrswinst_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 6 };
166
#ifdef PKGLOC /* Description from HRSW_dir/.../pkginfo: DESC= */
167
#define _PATH_HRSW_directory PKGLOC
169
#ifdef hpux9 /* Description from HRSW_dir/.../index: fd: */
170
#define _PATH_HRSW_directory "/system"
172
#ifdef hpux10 /* Description from HRSW_dir/.../pfiles/INDEX: title */
173
#define _PATH_HRSW_directory "/var/adm/sw/products"
175
#ifdef hpux11 /* Description from HRSW_dir/.../pfiles/INDEX: title */
176
#define _PATH_HRSW_directory "/var/adm/sw/products"
179
#define _PATH_HRSW_directory "/var/db/pkg"
185
#if defined(HAVE_LIBRPM) || defined(_PATH_HRSW_directory)
186
SWI_t *swi = &_myswi; /* XXX static for now */
189
struct stat stat_buf;
193
* Read settings from config file,
194
* or take system-specific defaults
198
if (swi->swi_directory == NULL) {
199
char path[SNMP_MAXPATH];
202
* XXX distinguish between rpm-2.5.x and rpm-2.9x
204
#ifdef HAVE_RPMGETPATH
205
rpmReadConfigFiles(NULL, NULL);
206
swi->swi_dbpath = rpmGetPath("%{_dbpath}", NULL);
208
rpmReadConfigFiles(NULL, NULL, NULL, 0);
209
swi->swi_dbpath = rpmGetVar(RPMVAR_DBPATH);
211
if (swi->swi_directory != NULL)
212
free(swi->swi_directory);
213
snprintf(path, sizeof(path), "%s/Packages", swi->swi_dbpath);
214
if (stat(path, &stat_buf) == -1)
215
snprintf(path, sizeof(path), "%s/packages.rpm", swi->swi_dbpath);
216
path[ sizeof(path)-1 ] = 0;
217
swi->swi_directory = strdup(path);
220
# ifdef _PATH_HRSW_directory
221
if (swi->swi_directory == NULL) {
222
swi->swi_directory = _PATH_HRSW_directory;
224
strcpy(swi->swi_name, "[installed name]"); /* default name */
227
* XXX SunOS4 package directory is ?? -MJS
229
return; /* packages not known - don't register */
233
REGISTER_MIB("host/hr_swinst", hrswinst_variables, variable4,
234
hrswinst_variables_oid);
238
* header_hrswinst(...
240
* vp IN - pointer to variable entry that points here
241
* name IN/OUT - IN/name requested, OUT/name found
242
* length IN/OUT - length of IN/OUT oid's
243
* exact IN - TRUE if an exact match was requested
244
* var_len OUT - length of variable or 0 if function returned
249
header_hrswinst(struct variable *vp,
252
int exact, size_t * var_len, WriteMethod ** write_method)
254
#define HRSWINST_NAME_LENGTH 9
255
oid newname[MAX_OID_LEN];
258
DEBUGMSGTL(("host/hr_swinst", "var_hrswinst: "));
259
DEBUGMSGOID(("host/hr_swinst", name, *length));
260
DEBUGMSG(("host/hr_swinst", " %d\n", exact));
262
memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid));
263
newname[HRSWINST_NAME_LENGTH] = 0;
264
result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
265
if ((exact && (result != 0)) || (!exact && (result >= 0)))
266
return (MATCH_FAILED);
267
memcpy((char *) name, (char *) newname,
268
(vp->namelen + 1) * sizeof(oid));
269
*length = vp->namelen + 1;
272
*var_len = sizeof(long); /* default to 'long' results */
273
return (MATCH_SUCCEEDED);
277
header_hrswInstEntry(struct variable *vp,
281
size_t * var_len, WriteMethod ** write_method)
283
#define HRSWINST_ENTRY_NAME_LENGTH 11
284
oid newname[MAX_OID_LEN];
285
int swinst_idx, LowIndex = -1;
288
DEBUGMSGTL(("host/hr_swinst", "var_hrswinstEntry: "));
289
DEBUGMSGOID(("host/hr_swinst", name, *length));
290
DEBUGMSG(("host/hr_swinst", " %d\n", exact));
292
memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid));
294
* Find "next" installed software entry
298
while ((swinst_idx = Get_Next_HR_SWInst()) != -1) {
299
DEBUGMSG(("host/hr_swinst", "(index %d ....", swinst_idx));
301
newname[HRSWINST_ENTRY_NAME_LENGTH] = swinst_idx;
302
DEBUGMSGOID(("host/hr_swinst", newname, *length));
303
DEBUGMSG(("host/hr_swinst", "\n"));
304
result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
305
if (exact && (result == 0)) {
306
LowIndex = swinst_idx;
307
Save_HR_SW_info(LowIndex);
310
if ((!exact && (result < 0)) &&
311
(LowIndex == -1 || swinst_idx < LowIndex)) {
312
LowIndex = swinst_idx;
313
Save_HR_SW_info(LowIndex);
314
#ifdef HRSWINST_MONOTONICALLY_INCREASING
323
if (LowIndex == -1) {
324
DEBUGMSGTL(("host/hr_swinst", "... index out of range\n"));
325
return (MATCH_FAILED);
328
memcpy((char *) name, (char *) newname,
329
(vp->namelen + 1) * sizeof(oid));
330
*length = vp->namelen + 1;
332
*var_len = sizeof(long); /* default to 'long' results */
334
DEBUGMSGTL(("host/hr_inst", "... get installed S/W stats "));
335
DEBUGMSGOID(("host/hr_inst", name, *length));
336
DEBUGMSG(("host/hr_inst", "\n"));
340
/*********************
342
* System specific implementation functions
344
*********************/
348
var_hrswinst(struct variable * vp,
351
int exact, size_t * var_len, WriteMethod ** write_method)
353
SWI_t *swi = &_myswi; /* XXX static for now */
355
static char string[SNMP_MAXPATH];
357
struct stat stat_buf;
359
if (vp->magic < HRSWINST_INDEX) {
360
if (header_hrswinst(vp, name, length, exact, var_len, write_method)
366
header_hrswInstEntry(vp, name, length, exact, var_len,
368
if (sw_idx == MATCH_FAILED)
373
case HRSWINST_CHANGE:
374
case HRSWINST_UPDATE:
377
if (swi->swi_directory != NULL) {
378
strncpy(string, swi->swi_directory, sizeof(string));
379
string[ sizeof(string)-1 ] = 0;
382
if (*string && (stat(string, &stat_buf) != -1)) {
383
if (stat_buf.st_mtime > starttime.tv_sec)
385
* changed 'recently' - i.e. since this agent started
387
long_return = (stat_buf.st_mtime - starttime.tv_sec) * 100;
389
long_return = 0; /* predates this agent */
394
long_return = 363136200;
396
ret = (u_char *) & long_return;
400
long_return = sw_idx;
401
ret = (u_char *) & long_return;
405
strncpy(string, swi->swi_name, sizeof(string) - 1);
407
* This will be unchanged from the initial "null"
408
* value, if swi->swi_name is not defined
410
string[sizeof(string) - 1] = '\0';
411
*var_len = strlen(string);
412
ret = (u_char *) string;
416
*var_len = nullOidLen;
417
ret = (u_char *) nullOid;
423
* at least on solaris2 this works
425
char *catg = pkgparam(swi->swi_name, "CATEGORY");
428
long_return = 1; /* unknown */
430
if (strstr(catg, "system") != NULL) {
431
long_return = 2; /* operatingSystem */
432
} else if (strstr(catg, "application") != NULL) {
433
long_return = 4; /* applcation */
435
long_return = 1; /* unknown */
440
long_return = 1; /* unknown */
442
ret = (u_char *) & long_return;
449
headerGetEntry(swi->swi_h, RPMTAG_INSTALLTIME, NULL,
450
(void **) &rpm_data, NULL);
451
if (rpm_data != NULL) {
452
time_t installTime = *rpm_data;
453
ret = date_n_time(&installTime, var_len);
455
ret = date_n_time(0, var_len);
458
if (swi->swi_directory != NULL) {
459
snprintf(string, sizeof(string), "%s/%s",
460
swi->swi_directory, swi->swi_name);
461
string[ sizeof(string)-1 ] = 0;
462
stat(string, &stat_buf);
463
ret = date_n_time(&stat_buf.st_mtime, var_len);
468
sprintf(string, "back in the mists of time");
469
*var_len = strlen(string);
470
ret = (u_char *) string;
476
DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrswinst\n",
481
Release_HRSW_token();
486
/*********************
488
* Internal implementation functions
490
*********************/
494
Check_HRSW_cache(void *xxx)
496
SWI_t *swi = (SWI_t *) xxx;
499
* Make sure cache is up-to-date
501
if (swi->swi_recs != NULL) {
503
lstat(swi->swi_directory, &sb);
504
if (swi->swi_timestamp == sb.st_mtime)
506
swi->swi_timestamp = sb.st_mtime;
516
#if defined(RPMDBI_PACKAGES)
517
rpmdbMatchIterator mi = NULL;
519
mi = rpmdbInitIterator(swi->swi_rpmdb, RPMDBI_PACKAGES, NULL, 0);
520
while ((h = rpmdbNextIterator(mi)) != NULL) {
521
offset = rpmdbGetIteratorOffset(mi);
523
for (offset = rpmdbFirstRecNum(swi->swi_rpmdb);
525
offset = rpmdbNextRecNum(swi->swi_rpmdb, offset)) {
528
if (ix >= swi->swi_maxrec) {
529
swi->swi_maxrec += 256;
530
swi->swi_recs = (swi->swi_recs == NULL)
531
? (int *) malloc(swi->swi_maxrec * sizeof(int))
532
: (int *) realloc(swi->swi_recs,
533
swi->swi_maxrec * sizeof(int));
535
swi->swi_recs[ix++] = offset;
537
#if !defined(RPMDBI_PACKAGES)
541
rpmdbFreeIterator(mi);
547
#endif /* HAVE_LIBRPM */
552
SWI_t *swi = &_myswi; /* XXX static for now */
556
if (swi->swi_rpmdb != NULL)
558
if (rpmdbOpen("", &swi->swi_rpmdb, O_RDONLY, 0644) != 0)
560
Check_HRSW_cache(swi);
562
if (swi->swi_directory != NULL) {
563
if (swi->swi_dp != NULL) {
564
closedir(swi->swi_dp);
567
if ((swi->swi_dp = opendir(swi->swi_directory)) == NULL)
575
Get_Next_HR_SWInst(void)
577
SWI_t *swi = &_myswi; /* XXX static for now */
579
if (swi->swi_index == -1)
584
* XXX Watchout: index starts with 1
586
if (0 <= swi->swi_index && swi->swi_index < swi->swi_nrec)
587
return ++swi->swi_index;
589
if (swi->swi_directory != NULL) {
590
while ((swi->swi_dep = readdir(swi->swi_dp)) != NULL) {
591
if (swi->swi_dep->d_name[0] == '.')
595
* Ought to check for "properly-formed" entry
598
return ++swi->swi_index;
607
Save_HR_SW_info(int ix)
609
SWI_t *swi = &_myswi; /* XXX static for now */
613
* XXX Watchout: ix starts with 1
615
if (1 <= ix && ix <= swi->swi_nrec && ix != swi->swi_prevx) {
620
offset = swi->swi_recs[ix - 1];
622
#if defined(RPMDBI_PACKAGES)
624
rpmdbMatchIterator mi;
625
mi = rpmdbInitIterator(swi->swi_rpmdb, RPMDBI_PACKAGES,
626
&offset, sizeof(offset));
627
if ((h = rpmdbNextIterator(mi)) != NULL)
629
rpmdbFreeIterator(mi);
632
h = rpmdbGetRecord(swi->swi_rpmdb, offset);
637
if (swi->swi_h != NULL)
638
headerFree(swi->swi_h);
642
headerGetEntry(swi->swi_h, RPMTAG_NAME, NULL, (void **) &n, NULL);
643
headerGetEntry(swi->swi_h, RPMTAG_VERSION, NULL, (void **) &v,
645
headerGetEntry(swi->swi_h, RPMTAG_RELEASE, NULL, (void **) &r,
647
snprintf(swi->swi_name, sizeof(swi->swi_name), "%s-%s-%s", n, v, r);
648
swi->swi_name[ sizeof(swi->swi_name)-1 ] = 0;
651
snprintf(swi->swi_name, sizeof(swi->swi_name), swi->swi_dep->d_name);
652
swi->swi_name[ sizeof(swi->swi_name)-1 ] = 0;
658
Mark_HRSW_token(void)
663
Release_HRSW_token(void)
665
SWI_t *swi = &_myswi; /* XXX static for now */
666
if (swi != NULL && swi->swi_h) {
667
headerFree(swi->swi_h);
672
#endif /* HAVE_LIBRPM */
677
SWI_t *swi = &_myswi; /* XXX static for now */
680
rpmdbClose(swi->swi_rpmdb); /* or only on finishing ? */
681
swi->swi_rpmdb = NULL;
683
if (swi->swi_dp != NULL)
684
closedir(swi->swi_dp);