Lines 14-19
Link Here
|
14 |
|
14 |
|
15 |
#include <stdio.h> |
15 |
#include <stdio.h> |
16 |
#include <sys/types.h> |
16 |
#include <sys/types.h> |
|
|
17 |
#include <sys/cdefs.h> |
17 |
#include <sys/sysctl.h> |
18 |
#include <sys/sysctl.h> |
18 |
|
19 |
|
19 |
#include <sys/time.h> /* struct clockinfo */ |
20 |
#include <sys/time.h> /* struct clockinfo */ |
Lines 48-125
Link Here
|
48 |
#include <netinet6/raw_ip6.h> |
49 |
#include <netinet6/raw_ip6.h> |
49 |
#include "bsd-sysctl.h" |
50 |
#include "bsd-sysctl.h" |
50 |
|
51 |
|
|
|
52 |
void |
53 |
_iterator_first(HV *self) |
54 |
{ |
55 |
SV **headp; |
56 |
int name[CTL_MAXNAME]; |
57 |
size_t len; |
58 |
|
59 |
headp = hv_fetch(self, "head", 4, 0); |
60 |
if (headp == NULL || *headp == NULL) |
61 |
croak( "failed to fetch head in _iterator_first()\n" ); |
62 |
|
63 |
if (SvPOK(*headp)) { |
64 |
/* we were given starting node */ |
65 |
len = sizeof(name); |
66 |
if (sysctlnametomib(SvPV_nolen(*headp), name, &len) == -1) |
67 |
croak("sysctlnametomib(head) failed in _iterator_first\n"); |
68 |
} else { |
69 |
/* start at the top like sysctl -a */ |
70 |
name[0] = 1; |
71 |
len = 1; |
72 |
} |
73 |
|
74 |
hv_store(self, "_next", 5, newSVpvn((char const *) name, len * sizeof(int)), 0); |
75 |
hv_store(self, "_len0", 5, newSViv(len), 0); |
76 |
hv_store(self, "_name", 5, newSVpvn("", 0), 0); |
77 |
} |
78 |
|
51 |
int |
79 |
int |
52 |
_init_iterator(HV *self, int *mib, int *miblenp, int valid) { |
80 |
_iterator_next(HV *self) |
53 |
SV **headp; |
81 |
{ |
54 |
int qoid[CTL_MAXNAME]; |
82 |
SV *nextp, **len0p, *namep; |
55 |
u_int qoidlen; |
83 |
int *next, name1[CTL_MAXNAME + 2], name2[CTL_MAXNAME + 2]; |
56 |
SV *clen; |
84 |
size_t len0, next_len, len1, len2; |
57 |
SV **clenp; |
85 |
|
58 |
int cmplen; |
86 |
if (! hv_exists(self, "_len0", 5)) |
59 |
int j; |
87 |
_iterator_first(self); |
60 |
|
88 |
|
61 |
qoid[0] = 0; |
89 |
len0p = hv_fetch(self, "_len0", 5, 0); |
62 |
qoid[1] = 2; |
90 |
if (len0p == NULL || *len0p == NULL) |
63 |
if (valid) { |
91 |
croak("hv_fetch(_len0) failed in _iterator_next\n"); |
64 |
memcpy(qoid+2, mib, (*miblenp) * sizeof(int)); |
92 |
len0 = SvIV(*len0p); |
65 |
qoidlen = *miblenp + 2; |
93 |
|
66 |
*miblenp = (CTL_MAXNAME+2) * sizeof(int); |
94 |
nextp = hv_delete(self, "_next", 5, 0); |
67 |
clenp = hv_fetch(self, "_len", 4, 0); |
95 |
if (nextp == NULL) |
68 |
cmplen = SvIV(*clenp); |
96 |
return 0; |
69 |
} |
97 |
next = (int *) SvPV(nextp, next_len); |
70 |
else { |
98 |
next_len /= sizeof(int); |
71 |
headp = hv_fetch(self, "head", 4, 0); |
99 |
|
72 |
if (!(headp && *headp)) { |
100 |
namep = hv_delete(self, "_name", 5, 0); |
73 |
croak( "failed to get some head in _init_iterator()\n" ); |
101 |
if (namep == NULL) |
74 |
} |
102 |
return 0; |
75 |
if (SvPOK(*headp)) { |
103 |
|
76 |
/* begin where asked */ |
104 |
/* |
77 |
qoidlen = sizeof(qoid); |
105 |
* Get next (after _next): name1 = [ 0, 2, next ] |
78 |
if (sysctlnametomib( SvPV_nolen(*headp), qoid+2, (size_t*)&qoidlen) == -1) { |
106 |
*/ |
79 |
warn( "_init_iterator(%s): sysctlnametomib lookup failed\n", |
107 |
|
80 |
SvPV_nolen(*headp) |
108 |
name1[0] = 0; |
81 |
); |
109 |
name1[1] = 2; /* get next */ |
82 |
return 0; |
110 |
memcpy((name1 + 2), next, next_len * sizeof(int)); |
83 |
} |
111 |
len1 = next_len + 2; |
84 |
cmplen = qoidlen; |
112 |
|
85 |
qoidlen += 2; |
113 |
len2 = sizeof(name2); |
86 |
} |
114 |
if (sysctl(name1, len1, name2, &len2, 0, 0) < 0) { |
87 |
else { |
115 |
if (errno == ENOENT) |
88 |
/* begin at the beginning */ |
116 |
return (0); |
89 |
qoid[2] = 1; |
117 |
|
90 |
cmplen = 0; |
118 |
croak("sysctl(next) failed in _iterator_next()\n"); |
91 |
qoidlen = 3; |
119 |
} |
92 |
} |
120 |
len2 /= sizeof(int); |
93 |
clen = newSViv(cmplen); |
121 |
|
94 |
SvREFCNT_inc(clen); |
122 |
if (len2 < len0) |
95 |
hv_store(self, "_len", 4, clen, 0); |
123 |
return 0; /* shorter than first */ |
96 |
} |
124 |
if (memcmp(name2, next, len0 * sizeof(int)) != 0) |
97 |
|
125 |
return 0; /* does not match anymore */ |
98 |
/* |
126 |
|
99 |
printf( "next: " ); |
127 |
/* at this point, name2/len2 has next iterator, update _next here */ |
100 |
for (j = 0; j < qoidlen; ++j) { |
128 |
hv_store(self, "_next", 5, newSVpvn((char const *) name2, len2 * sizeof(int)), 0); |
101 |
if (j) printf("."); printf("%d", qoid[j]); |
129 |
|
102 |
} |
130 |
/* |
103 |
printf("\n"); |
131 |
* Get name (from name2): name1 = [ 0, 1, name2 ] |
104 |
*/ |
132 |
*/ |
105 |
|
133 |
|
106 |
/* load the mib */ |
134 |
name1[0] = 0; |
107 |
if (sysctl(qoid, qoidlen, mib, (size_t*)miblenp, 0, 0) == -1) { |
135 |
name1[1] = 1; /* get name */ |
108 |
return 0; |
136 |
memcpy((name1 + 2), name2, len2 * sizeof(int)); |
109 |
} |
137 |
len1 = len2 + 2; |
110 |
*miblenp /= sizeof(int); |
138 |
|
111 |
if (*miblenp < cmplen) { |
139 |
len2 = sizeof(name2); |
112 |
return 0 ; |
140 |
if (sysctl(name1, len1, name2, &len2, 0, 0) < 0) { |
113 |
} |
141 |
if (errno == ENOENT) |
114 |
|
142 |
return (0); |
115 |
for (j = 0; j < cmplen; ++j) { |
143 |
|
116 |
if (mib[j] != qoid[j+2]) { |
144 |
croak("sysctl(name) failed in _iterator_next()\n"); |
117 |
return 0; |
145 |
} |
118 |
} |
146 |
|
119 |
} |
147 |
/* at this point, name2/len2 has name, update _name here */ |
120 |
return 1; |
148 |
hv_store(self, "_name", 5, newSVpvn((char const *) name2, len2 - 1), 0); |
|
|
149 |
|
150 |
return 1; |
121 |
} |
151 |
} |
122 |
|
152 |
|
|
|
153 |
/* |
154 |
* The below two comparisons must be true for the 64-bit setting code to |
155 |
* work correctly. |
156 |
*/ |
157 |
_Static_assert(LLONG_MAX >= INT64_MAX, "compile-time assertion failed"); |
158 |
_Static_assert(ULLONG_MAX >= UINT64_MAX, "compile-time assertion failed"); |
159 |
|
123 |
MODULE = BSD::Sysctl PACKAGE = BSD::Sysctl |
160 |
MODULE = BSD::Sysctl PACKAGE = BSD::Sysctl |
124 |
|
161 |
|
125 |
PROTOTYPES: ENABLE |
162 |
PROTOTYPES: ENABLE |
Lines 127-193
Link Here
|
127 |
SV * |
164 |
SV * |
128 |
next (SV *refself) |
165 |
next (SV *refself) |
129 |
INIT: |
166 |
INIT: |
130 |
int mib[CTL_MAXNAME+2]; |
|
|
131 |
size_t miblen; |
132 |
int qoid[CTL_MAXNAME+2]; |
133 |
size_t qoidlen; |
134 |
char name[BUFSIZ]; |
135 |
size_t namelen; |
136 |
HV *self; |
167 |
HV *self; |
137 |
SV **ctxp; |
168 |
SV **namep; |
138 |
SV *ctx; |
|
|
139 |
SV *cname; |
140 |
int j; |
141 |
int *p; |
142 |
|
169 |
|
143 |
CODE: |
170 |
CODE: |
144 |
self = (HV *)SvRV(refself); |
171 |
self = (HV *)SvRV(refself); |
145 |
if ((ctxp = hv_fetch(self, "_ctx", 4, 0))) { |
|
|
146 |
p = (int *)SvPVX(*ctxp); |
147 |
miblen = *p++; |
148 |
memcpy(mib, p, miblen * sizeof(int)); |
149 |
|
150 |
if (!_init_iterator(self, mib, (int*)&miblen, 1)) { |
151 |
XSRETURN_UNDEF; |
152 |
} |
153 |
} |
154 |
else { |
155 |
miblen = sizeof(mib)/sizeof(mib[0]); |
156 |
if (!_init_iterator(self, mib, (int*)&miblen, 0)) { |
157 |
XSRETURN_UNDEF; |
158 |
} |
159 |
} |
160 |
|
161 |
qoid[0] = 0; |
162 |
qoid[1] = 1; |
163 |
memcpy(qoid+2, mib, miblen * sizeof(int)); |
164 |
qoidlen = miblen + 2; |
165 |
|
166 |
bzero(name, BUFSIZ); |
167 |
namelen = sizeof(name); |
168 |
j = sysctl(qoid, qoidlen, name, &namelen, 0, 0); |
169 |
if (j || !namelen) { |
170 |
warn("next(): sysctl name failure %d %zu %d", j, namelen, errno); |
171 |
XSRETURN_UNDEF; |
172 |
} |
173 |
cname = newSVpvn(name, namelen-1); |
174 |
SvREFCNT_inc(cname); |
175 |
hv_store(self, "_name", 5, cname, 0); |
176 |
RETVAL = cname; |
177 |
|
178 |
/* reuse qoid to build context store |
179 |
* - the length of the mib |
180 |
* - followed by the mib values |
181 |
* and copy to an SV to save in the self hash |
182 |
*/ |
183 |
p = qoid; |
184 |
memcpy(p++, (const void *)&miblen, sizeof(int)); |
185 |
memcpy(p, (const void *)mib, miblen * sizeof(int)); |
186 |
|
187 |
ctx = newSVpvn((const char *)qoid, (miblen+1) * sizeof(int)); |
188 |
SvREFCNT_inc(ctx); |
189 |
hv_store(self, "_ctx", 4, ctx, 0); |
190 |
|
172 |
|
|
|
173 |
if (_iterator_next(self) == 0) |
174 |
XSRETURN_UNDEF; |
175 |
|
176 |
namep = hv_fetch(self, "_name", 5, 0); |
177 |
SvREFCNT_inc(*namep); |
178 |
RETVAL = *namep; |
191 |
OUTPUT: |
179 |
OUTPUT: |
192 |
RETVAL |
180 |
RETVAL |
193 |
|
181 |
|
Lines 878-883
Link Here
|
878 |
SV **oidp; |
866 |
SV **oidp; |
879 |
SV *oid; |
867 |
SV *oid; |
880 |
char *oid_data; |
868 |
char *oid_data; |
|
|
869 |
int64_t int64val; |
870 |
long long llval; |
871 |
uint64_t uint64val; |
872 |
unsigned long long ullval; |
881 |
int oid_fmt; |
873 |
int oid_fmt; |
882 |
int oid_len; |
874 |
int oid_len; |
883 |
int intval; |
875 |
int intval; |
Lines 955-960
Link Here
|
955 |
newval = &ulongval; |
947 |
newval = &ulongval; |
956 |
newsize = sizeof(ulongval); |
948 |
newsize = sizeof(ulongval); |
957 |
break; |
949 |
break; |
|
|
950 |
|
951 |
case FMT_64: |
952 |
llval = strtoll(value, &endconvptr, 0); |
953 |
if (endconvptr == value || *endconvptr != '\0' || |
954 |
(llval == 0 && errno == EINVAL)) { |
955 |
warn("invalid 64-bit integer: '%s'", value); |
956 |
XSRETURN_UNDEF; |
957 |
} |
958 |
#if (LLONG_MAX > INT64_MAX) |
959 |
if (llval < INT64_MIN) |
960 |
int64val = INT64_MIN; |
961 |
else if (llval > INT64_MAX) |
962 |
int64val = INT64_MAX; |
963 |
else |
964 |
#endif |
965 |
int64val = (int64_t)llval; |
966 |
newval = &int64val; |
967 |
newsize = sizeof(int64val); |
968 |
break; |
969 |
|
970 |
case FMT_U64: |
971 |
ullval = strtoull(value, &endconvptr, 0); |
972 |
if (endconvptr == value || *endconvptr != '\0' || |
973 |
(ullval == 0 && errno == EINVAL)) { |
974 |
warn("invalid unsigned 64-bit integer: '%s'", value); |
975 |
XSRETURN_UNDEF; |
976 |
} |
977 |
#if (ULLONG_MAX > UINT64_MAX) |
978 |
if (ullval > UINT64_MAX) |
979 |
uint64val = UINT64_MAX; |
980 |
else |
981 |
#endif |
982 |
uint64val = (uint64_t)ullval; |
983 |
newval = &uint64val; |
984 |
newsize = sizeof(uint64val); |
985 |
break; |
958 |
} |
986 |
} |
959 |
|
987 |
|
960 |
if (sysctl((int *)oid_data, oid_len, 0, 0, newval, newsize) == -1) { |
988 |
if (sysctl((int *)oid_data, oid_len, 0, 0, newval, newsize) == -1) { |