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