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