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