1 /*
   2  * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 
   5 /* Solaris includes. */
   6 #include <priv.h>
   7 #include <ctype.h>
   8 
   9 /* Perl includes. */
  10 #include "EXTERN.h"
  11 #include "perl.h"
  12 #include "XSUB.h"
  13 
  14 #define IVCONST(s, c)   newCONSTSUB(s, #c, newSViv((int)(intptr_t)c));
  15 #define POFF            (sizeof ("PRIV_") - 1)
  16 
  17 typedef int sysret;
  18 
  19 typedef priv_set_t Sun__Solaris__Privilege__Privset;
  20 
  21 static priv_set_t *
  22 dupset(const priv_set_t *s)
  23 {
  24         priv_set_t *new = priv_allocset();
  25         if (new == NULL)
  26                 return (NULL);
  27 
  28         priv_copyset(s, new);
  29         return (new);
  30 }
  31 
  32 /*
  33  * Automatically derive the #define constant from the constant value.
  34  * This is the uppercase value of the constant with "PRIV_" prepended.
  35  * The (name, value) pair computed in that way is stored twice:
  36  *      once as constant subroutine in the module's hash table.
  37  *      once as (key, value) in a hash table.
  38  */
  39 
  40 static void
  41 PRIVconst(HV *sym, HV *var, const char *name)
  42 {
  43         char upname[128];
  44         ssize_t len;
  45         int i;
  46 
  47         len = snprintf(upname, sizeof (upname), "PRIV_%s", name);
  48         if (len >= sizeof (upname))
  49                 return;
  50 
  51         for (i = POFF; i < len; i++)
  52                 upname[i] = toupper(upname[i]);
  53         newCONSTSUB(sym, upname, newSVpv(name, len - POFF));
  54         hv_store(var, upname, len, newSVpv(name, len - POFF), 0);
  55 }
  56 
  57 /*
  58  * The XS code exported to perl is below here.  Note that the XS preprocessor
  59  * has its own commenting syntax, so all comments from this point on are in
  60  * that form.
  61  *
  62  * Inside perl, privilege sets are represented as expanded strings;
  63  * privileges and privilege sets are only known by name.
  64  */
  65 
  66 MODULE = Sun::Solaris::Privilege PACKAGE = Sun::Solaris::Privilege
  67 PROTOTYPES: ENABLE
  68 
  69  #
  70  # Define any constants that need to be exported.  By doing it this way we can
  71  # avoid the overhead of using the DynaLoader package, and in addition constants
  72  # defined using this mechanism are eligible for inlining by the perl
  73  # interpreter at compile time.
  74  #
  75 BOOT:
  76 {
  77         HV *stash;
  78         HV *privs;
  79         HV *privsets;
  80         const char *p;
  81         int i;
  82 
  83         stash = gv_stashpv("Sun::Solaris::Privilege", TRUE);
  84 
  85         /*
  86          * Global constants
  87          */
  88         IVCONST(stash, PRIV_STR_PORT);
  89         IVCONST(stash, PRIV_STR_LIT);
  90         IVCONST(stash, PRIV_STR_SHORT);
  91         IVCONST(stash, PRIV_ALLSETS);
  92         IVCONST(stash, PRIV_DEBUG);
  93         IVCONST(stash, PRIV_AWARE);
  94         IVCONST(stash, PRIV_ON);
  95         IVCONST(stash, PRIV_OFF);
  96         IVCONST(stash, PRIV_SET);
  97 
  98         /*
  99          * %PRIVILEGES hash and the privilege constants
 100          */
 101         privs = perl_get_hv("Sun::Solaris::Privilege::PRIVILEGES", TRUE);
 102         for (i = 0; (p = priv_getbynum(i++)) != NULL; )
 103                 PRIVconst(stash, privs, p);
 104 
 105         /*
 106          * %PRIVSETS hash and the privset constants
 107          */
 108         privsets = perl_get_hv("Sun::Solaris::Privilege::PRIVSETS", TRUE);
 109         for (i = 0; (p = priv_getsetbynum(i++)) != NULL; )
 110                 PRIVconst(stash, privsets, p);
 111 }
 112 
 113 
 114 Sun::Solaris::Privilege::Privset *
 115 getppriv(which)
 116         const char *which;
 117 CODE:
 118         RETVAL = priv_allocset();
 119         if (getppriv(which, RETVAL) != 0) {
 120                 priv_freeset(RETVAL);
 121                 XSRETURN_UNDEF;
 122         }
 123 OUTPUT:
 124         RETVAL
 125 CLEANUP:
 126         SvREADONLY_on(SvRV(ST(0)));
 127 
 128 sysret
 129 setppriv(op, which, set)
 130         int op;
 131         const char *which;
 132         Sun::Solaris::Privilege::Privset *set;
 133 
 134 Sun::Solaris::Privilege::Privset *
 135 priv_emptyset()
 136 CODE:
 137         RETVAL = priv_allocset();
 138         if (RETVAL == NULL) {
 139                 XSRETURN_UNDEF;
 140         }
 141         priv_emptyset(RETVAL);
 142 OUTPUT:
 143         RETVAL
 144 CLEANUP:
 145         SvREADONLY_on(SvRV(ST(0)));
 146 
 147 Sun::Solaris::Privilege::Privset *
 148 priv_fillset()
 149 CODE:
 150         RETVAL = priv_allocset();
 151         if (RETVAL == NULL) {
 152                 XSRETURN_UNDEF;
 153         }
 154         priv_fillset(RETVAL);
 155 OUTPUT:
 156         RETVAL
 157 CLEANUP:
 158         SvREADONLY_on(SvRV(ST(0)));
 159 
 160 boolean_t
 161 priv_isemptyset(set)
 162         Sun::Solaris::Privilege::Privset *set;
 163 
 164 boolean_t
 165 priv_isfullset(set)
 166         Sun::Solaris::Privilege::Privset *set;
 167 
 168 boolean_t
 169 priv_isequalset(set1, set2)
 170         Sun::Solaris::Privilege::Privset *set1;
 171         Sun::Solaris::Privilege::Privset *set2;
 172 
 173 boolean_t
 174 priv_issubset(set1, set2)
 175         Sun::Solaris::Privilege::Privset *set1;
 176         Sun::Solaris::Privilege::Privset *set2;
 177 
 178 boolean_t
 179 priv_ismember(set, priv)
 180         Sun::Solaris::Privilege::Privset *set;
 181         const char *priv;
 182 
 183 boolean_t
 184 priv_ineffect(priv)
 185         const char *priv;
 186 
 187 Sun::Solaris::Privilege::Privset *
 188 priv_intersect(set1, set2)
 189         Sun::Solaris::Privilege::Privset *set1;
 190         Sun::Solaris::Privilege::Privset *set2;
 191 CODE:
 192         RETVAL = dupset(set2);
 193         if (RETVAL == NULL) {
 194                 XSRETURN_UNDEF;
 195         }
 196         priv_intersect(set1, RETVAL);
 197 OUTPUT:
 198         RETVAL
 199 CLEANUP:
 200         SvREADONLY_on(SvRV(ST(0)));
 201 
 202 Sun::Solaris::Privilege::Privset *
 203 priv_union(set1, set2)
 204         Sun::Solaris::Privilege::Privset *set1;
 205         Sun::Solaris::Privilege::Privset *set2;
 206 CODE:
 207         RETVAL = dupset(set2);
 208         if (RETVAL == NULL) {
 209                 XSRETURN_UNDEF;
 210         }
 211         priv_union(set1, RETVAL);
 212 OUTPUT:
 213         RETVAL
 214 CLEANUP:
 215         SvREADONLY_on(SvRV(ST(0)));
 216 
 217 Sun::Solaris::Privilege::Privset *
 218 priv_inverse(set1)
 219         Sun::Solaris::Privilege::Privset *set1;
 220 CODE:
 221         RETVAL = dupset(set1);
 222         if (RETVAL == NULL) {
 223                 XSRETURN_UNDEF;
 224         }
 225         priv_inverse(RETVAL);
 226 OUTPUT:
 227         RETVAL
 228 CLEANUP:
 229         SvREADONLY_on(SvRV(ST(0)));
 230 
 231 
 232 sysret
 233 priv_addset(set, priv)
 234         Sun::Solaris::Privilege::Privset *set;
 235         const char *priv;
 236 
 237 Sun::Solaris::Privilege::Privset *
 238 priv_copyset(set1)
 239         Sun::Solaris::Privilege::Privset *set1;
 240 CODE:
 241         RETVAL = dupset(set1);
 242         if (RETVAL == NULL) {
 243                 XSRETURN_UNDEF;
 244         }
 245 OUTPUT:
 246         RETVAL
 247 CLEANUP:
 248         SvREADONLY_on(SvRV(ST(0)));
 249 
 250 
 251 sysret
 252 priv_delset(set, priv)
 253         Sun::Solaris::Privilege::Privset *set;
 254         const char *priv;
 255 
 256 const char *
 257 priv_getbynum(i)
 258         int i;
 259 
 260 const char *
 261 priv_getsetbynum(i)
 262         int i;
 263 
 264 char *
 265 priv_set_to_str(s, c, f)
 266         Sun::Solaris::Privilege::Privset *s;
 267         char c;
 268         int f;
 269 CLEANUP:
 270         free(RETVAL);
 271 
 272 Sun::Solaris::Privilege::Privset *
 273 priv_str_to_set(buf, sep);
 274         const char *buf;
 275         const char *sep;
 276 CODE:
 277         RETVAL = priv_str_to_set(buf, sep, NULL);
 278         if (RETVAL == NULL) {
 279                 XSRETURN_UNDEF;
 280         }
 281 OUTPUT:
 282         RETVAL
 283 CLEANUP:
 284         SvREADONLY_on(SvRV(ST(0)));
 285 
 286 char *
 287 priv_gettext(priv)
 288         const char *priv
 289 CLEANUP:
 290         free(RETVAL);
 291 
 292 sysret
 293 setpflags(flag, val)
 294         uint_t flag;
 295         uint_t val;
 296 
 297 sysret
 298 getpflags(flag)
 299         uint_t flag;
 300 
 301 MODULE = Sun::Solaris::Privilege PACKAGE = Sun::Solaris::Privilege::PrivsetPtr PREFIX = Privilege_
 302 
 303 void
 304 Privilege_DESTROY(ps)
 305         Sun::Solaris::Privilege::Privset *ps;
 306 CODE:
 307         if (ps != NULL)
 308                 priv_freeset(ps);
 309