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