1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Project.xs contains XS wrappers for the project database maniplulation
27  * functions as provided by libproject and described in getprojent(3EXACCT).
28  */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /* Solaris includes. */
33 #include <project.h>
34 #include <pool.h>
35 #include <rctl.h>
36 #include <stdio.h>
37 
38 /* Perl includes. */
39 #include "EXTERN.h"
40 #include "perl.h"
41 #include "XSUB.h"
42 
43 /*
44  * Convert and save a struct project on the perl XS return stack.
45  * In a void context it returns nothing, in a scalar context it returns just
46  * the name of the project and in a list context it returns a 6-element list
47  * consisting of (name, projid, comment, users, groups, attr), where users and
48  * groups are references to arrays containing the appropriate lists.
49  */
50 static int
51 pushret_project(const struct project *proj)
52 {
53 	char	**cp;
54 	AV	*ary;
55 
56 	dSP;
57 	if (GIMME_V == G_SCALAR) {
58 		EXTEND(SP, 1);
59 		PUSHs(sv_2mortal(newSVpv(proj->pj_name, 0)));
60 		PUTBACK;
61 		return (1);
62 	} else if (GIMME_V == G_ARRAY) {
63 		EXTEND(SP, 6);
64 		PUSHs(sv_2mortal(newSVpv(proj->pj_name, 0)));
65 		PUSHs(sv_2mortal(newSViv(proj->pj_projid)));
66 		PUSHs(sv_2mortal(newSVpv(proj->pj_comment, 0)));
67 		ary = newAV();
68 		for (cp = proj->pj_users; *cp != NULL; cp++) {
69 			av_push(ary, newSVpv(*cp, 0));
70 		}
71 		PUSHs(sv_2mortal(newRV_noinc((SV *)ary)));
72 		ary = newAV();
73 		for (cp = proj->pj_groups; *cp != NULL; cp++) {
74 			av_push(ary, newSVpv(*cp, 0));
75 		}
76 		PUSHs(sv_2mortal(newRV_noinc((SV *)ary)));
77 		PUSHs(sv_2mortal(newSVpv(proj->pj_attr, 0)));
78 		PUTBACK;
79 		return (6);
80 	} else {
81 		return (0);
82 	}
83 }
84 
85 static int
86 pwalk_cb(const projid_t project, void *walk_data)
87 {
88 	int *nitemsp;
89 
90 	dSP;
91 	nitemsp = (int *) walk_data;
92 	EXTEND(SP, 1);
93 	PUSHs(sv_2mortal(newSViv(project)));
94 	(*nitemsp)++;
95 	PUTBACK;
96 	return (0);
97 }
98 
99 /*
100  * The XS code exported to perl is below here.  Note that the XS preprocessor
101  * has its own commenting syntax, so all comments from this point on are in
102  * that form.  Note also that the PUTBACK; lines are necessary to synchronise
103  * the local and global views of the perl stack before calling pushret_project,
104  * as the code generated by the perl XS compiler twiddles with the stack on
105  * entry to an XSUB.
106  */
107 
108 MODULE = Sun::Solaris::Project PACKAGE = Sun::Solaris::Project
109 PROTOTYPES: ENABLE
110 
111  #
112  # Define any constants that need to be exported.  By doing it this way we can
113  # avoid the overhead of using the DynaLoader package, and in addition constants
114  # defined using this mechanism are eligible for inlining by the perl
115  # interpreter at compile time.
116  #
117 BOOT:
118 	{
119 	HV *stash;
120 	char buf[128];
121 	stash = gv_stashpv("Sun::Solaris::Project", TRUE);
122 	newCONSTSUB(stash, "MAXPROJID", newSViv(MAXPROJID));
123 	newCONSTSUB(stash, "PROJNAME_MAX", newSViv(PROJNAME_MAX));
124 	newCONSTSUB(stash, "PROJF_PATH",
125 	    newSVpv(PROJF_PATH, sizeof (PROJF_PATH) - 1));
126 	newCONSTSUB(stash, "PROJECT_BUFSZ", newSViv(PROJECT_BUFSZ));
127 	newCONSTSUB(stash, "SETPROJ_ERR_TASK", newSViv(SETPROJ_ERR_TASK));
128 	newCONSTSUB(stash, "SETPROJ_ERR_POOL", newSViv(SETPROJ_ERR_POOL));
129 	newCONSTSUB(stash, "RCTL_GLOBAL_NOBASIC",
130 		newSViv(RCTL_GLOBAL_NOBASIC));
131 	newCONSTSUB(stash, "RCTL_GLOBAL_LOWERABLE",
132 		newSViv(RCTL_GLOBAL_LOWERABLE));
133 	newCONSTSUB(stash, "RCTL_GLOBAL_DENY_ALWAYS",
134 		newSViv(RCTL_GLOBAL_DENY_ALWAYS));
135 	newCONSTSUB(stash, "RCTL_GLOBAL_DENY_NEVER",
136 		newSViv(RCTL_GLOBAL_DENY_NEVER));
137 	newCONSTSUB(stash, "RCTL_GLOBAL_FILE_SIZE",
138 		newSViv(RCTL_GLOBAL_FILE_SIZE));
139 	newCONSTSUB(stash, "RCTL_GLOBAL_CPU_TIME",
140 		newSViv(RCTL_GLOBAL_CPU_TIME));
141 	newCONSTSUB(stash, "RCTL_GLOBAL_SIGNAL_NEVER",
142 		newSViv(RCTL_GLOBAL_SIGNAL_NEVER));
143 	newCONSTSUB(stash, "RCTL_GLOBAL_INFINITE",
144 		newSViv(RCTL_GLOBAL_INFINITE));
145 	newCONSTSUB(stash, "RCTL_GLOBAL_UNOBSERVABLE",
146 		newSViv(RCTL_GLOBAL_UNOBSERVABLE));
147 	newCONSTSUB(stash, "RCTL_GLOBAL_BYTES",
148 		newSViv(RCTL_GLOBAL_BYTES));
149 	newCONSTSUB(stash, "RCTL_GLOBAL_SECONDS",
150 		newSViv(RCTL_GLOBAL_SECONDS));
151 	newCONSTSUB(stash, "RCTL_GLOBAL_COUNT",
152 		newSViv(RCTL_GLOBAL_COUNT));
153 	sprintf(buf, "%llu", UINT64_MAX);
154 	newCONSTSUB(stash, "RCTL_MAX_VALUE",
155 		newSVpv(buf, strlen(buf)));
156 	}
157 
158 projid_t
159 getprojid()
160 
161 int
162 setproject(name, user_name, flags)
163 	const char	*name;
164 	const char	*user_name
165 	uint_t		flags
166 
167 void
168 activeprojects()
169 PREINIT:
170 	int	nitems;
171 PPCODE:
172 	PUTBACK;
173 	nitems = 0;
174 	project_walk(&pwalk_cb, (void*)&nitems);
175 	XSRETURN(nitems);
176 
177 void
178 getprojent()
179 PREINIT:
180 	struct project	proj, *projp;
181 	char		buf[PROJECT_BUFSZ];
182 PPCODE:
183 	PUTBACK;
184 	if (projp = getprojent(&proj, buf, sizeof (buf))) {
185 		XSRETURN(pushret_project(projp));
186 	} else {
187 		XSRETURN_EMPTY;
188 	}
189 
190 void
191 setprojent()
192 
193 void
194 endprojent()
195 
196 void
197 getprojbyname(name)
198 	char	*name
199 PREINIT:
200 	struct project	proj, *projp;
201 	char		buf[PROJECT_BUFSZ];
202 PPCODE:
203 	PUTBACK;
204 	if (projp = getprojbyname(name, &proj, buf, sizeof (buf))) {
205 		XSRETURN(pushret_project(projp));
206 	} else {
207 		XSRETURN_EMPTY;
208 	}
209 
210 void
211 getprojbyid(id)
212 	projid_t	id
213 PREINIT:
214 	struct project	proj, *projp;
215 	char		buf[PROJECT_BUFSZ];
216 PPCODE:
217 	PUTBACK;
218 	if (projp = getprojbyid(id, &proj, buf, sizeof (buf))) {
219 		XSRETURN(pushret_project(projp));
220 	} else {
221 		XSRETURN_EMPTY;
222 	}
223 
224 void
225 getdefaultproj(user)
226 	char	*user
227 PREINIT:
228 	struct project	proj, *projp;
229 	char		buf[PROJECT_BUFSZ];
230 PPCODE:
231 	PUTBACK;
232 	if (projp = getdefaultproj(user, &proj, buf, sizeof (buf))) {
233 		XSRETURN(pushret_project(projp));
234 	} else {
235 		XSRETURN_EMPTY;
236 	}
237 
238 void
239 fgetprojent(fh)
240 	FILE	*fh
241 PREINIT:
242 	struct project	proj, *projp;
243 	char		buf[PROJECT_BUFSZ];
244 PPCODE:
245 	PUTBACK;
246 	if (projp = fgetprojent(fh, &proj, buf, sizeof (buf))) {
247 		XSRETURN(pushret_project(projp));
248 	} else {
249 		XSRETURN_EMPTY;
250 	}
251 
252 bool
253 inproj(user, proj)
254 	char	*user
255 	char	*proj
256 PREINIT:
257 	char	buf[PROJECT_BUFSZ];
258 CODE:
259 	RETVAL = inproj(user, proj, buf, sizeof (buf));
260 
261 
262 int
263 getprojidbyname(proj)
264 	char	*proj
265 PREINIT:
266 	int	id;
267 PPCODE:
268 	if ((id = getprojidbyname(proj)) == -1) {
269 		XSRETURN_UNDEF;
270 	} else {
271 		XSRETURN_IV(id);
272 	}
273 
274 
275 # rctl_get_info(name)
276 #
277 # For the given rctl name, returns the list
278 # ($max, $flags), where $max is the integer value
279 # of the system rctl, and $flags are the rctl's
280 # global flags, as returned by rctlblk_get_global_flags
281 #
282 # This function is private to Project.pm
283 void
284 rctl_get_info(name)
285 	char	*name
286 PREINIT:
287 	rctlblk_t *blk1 = NULL;
288 	rctlblk_t *blk2 = NULL;
289 	rctlblk_t *tmp = NULL;
290 	rctl_priv_t priv;
291 	rctl_qty_t value;
292 	int flags;
293 	int ret;
294 	int err = 0;
295 	char string[24];	/* 24 will always hold a uint64_t */
296 PPCODE:
297 	Newc(0, blk1, rctlblk_size(), char, rctlblk_t);
298 	if (blk1 == NULL) {
299 		err = 1;
300 		goto out;
301 	}
302 	Newc(1, blk2, rctlblk_size(), char, rctlblk_t);
303 	if (blk2 == NULL) {
304 		err = 1;
305 		goto out;
306 	}
307 	ret = getrctl(name, NULL, blk1, RCTL_FIRST);
308 	if (ret != 0) {
309 		err = 1;
310 		goto out;
311 	}
312 	priv = rctlblk_get_privilege(blk1);
313 	while (priv != RCPRIV_SYSTEM) {
314 		tmp = blk2;
315 		blk2 = blk1;
316 		blk1 = tmp;
317 		ret = getrctl(name, blk2, blk1, RCTL_NEXT);
318 		if (ret != 0) {
319 			err = 1;
320 			goto out;
321 		}
322 		priv = rctlblk_get_privilege(blk1);
323 	}
324 	value = rctlblk_get_value(blk1);
325 	flags = rctlblk_get_global_flags(blk1);
326 	ret = sprintf(string, "%llu", value);
327 	if (ret <= 0) {
328 		err = 1;
329 	}
330 	out:
331 	if (blk1)
332 		Safefree(blk1);
333 	if (blk2)
334 		Safefree(blk2);
335 	if (err)
336 		XSRETURN(0);
337 
338 	XPUSHs(sv_2mortal(newSVpv(string, 0)));
339 	XPUSHs(sv_2mortal(newSViv(flags)));
340 	XSRETURN(2);
341 
342 #
343 # pool_exists(name)
344 #
345 # Returns 0 a pool with the given name exists on the current system.
346 # Returns 1 if pools are disabled or the pool does not exist
347 #
348 # Used internally by project.pm to validate the project.pool attribute
349 #
350 # This function is private to Project.pm
351 void
352 pool_exists(name)
353 	char	*name
354 PREINIT:
355 	pool_conf_t *conf;
356 	pool_t *pool;
357 PPCODE:
358 	conf = pool_conf_alloc();
359 	if (conf == NULL) {
360 		XSRETURN_IV(1);
361 	}
362 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY)) {
363 		pool_conf_free(conf);
364 		XSRETURN_IV(1);
365 	}
366 	pool = pool_get_pool(conf, name);
367 	if (pool == NULL) {
368 		pool_conf_close(conf);
369 		pool_conf_free(conf);
370 		XSRETURN_IV(1);
371 	}
372 	pool_conf_close(conf);
373 	pool_conf_free(conf);
374 	XSRETURN_IV(0);
375 
376