/* Copyright (C) 2003 MandrakeSoft SA Daouda Lo (daouda at mandrakesoft dot com) * This program is free software; you can redistribute it and/or * modify it under the same terms as Perl itself. */ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #include #include #include #include #include #include #include typedef struct context USER__ADMIN; typedef struct lu_ent USER__ENT; typedef struct lu_error USER__ERR; static SV ** convert_value_array_list(register SV **sp, GValueArray *array) { GValue *value; int i; long l; const char *s; for (i = 0; (array != NULL) && (i < array->n_values); i++) { value = g_value_array_get_nth(array, i); /* If the item is a G_TYPE_LONG, add it as a double. */ if (G_VALUE_HOLDS_LONG(value)) { l = g_value_get_long(value); XPUSHs(sv_2mortal(newSViv(l))); } else if (G_VALUE_HOLDS_STRING(value)) { s = g_value_get_string(value); XPUSHs(sv_2mortal(newSVpv(s, 0))); } } return sp; } MODULE = USER PACKAGE = USER::ADMIN PREFIX = Admin_ USER::ADMIN * Admin_new(CLASS) char *CLASS CODE: USER__ERR *error = NULL; RETVAL = (USER__ADMIN *)lu_start(NULL, 0, NULL, NULL, lu_prompt_console_quiet, NULL, &error); if( RETVAL == NULL ){ warn("unable to malloc USER__ADMIN"); XSRETURN_UNDEF; } OUTPUT: RETVAL void Admin_DESTROY(self) USER::ADMIN *self CODE: printf("freeing ADMIN\n"); if (self) lu_end(self) ; safefree((char*)self); int Admin_UserAdd(self, is_system, dont_create_home, enthash) USER::ADMIN *self int is_system int dont_create_home SV * enthash PREINIT: SV **ssv; HV *hv; if ( SvROK(enthash) && (SvTYPE(SvRV(enthash)) == SVt_PVHV) ) hv = (HV*)SvRV(enthash); else{ warn("XS_UserAdd: enthash was not an HV ref"); } CODE: USER__ENT *ent; USER__ERR *error; GValue *value, val; long uidNumber, gidNumber; char *skeleton = "/etc/skel", *homeDirectory = NULL; GValueArray *values; ent = lu_ent_new(); memset(&val, 0, sizeof(val)); g_value_init(&val, G_TYPE_STRING); ssv = hv_fetch(hv, "username", 13, 0); if( ssv != NULL ){ if( SvPOK( *ssv ) ) lu_user_default(self, SvPV(*ssv,PL_na), is_system, ent); else{ warn("XS_UserAdd: Cannot add default ent"); RETVAL = 0; } } else warn("XS_UserAdd: hash elem username was null"); ssv = hv_fetch(hv, "gecos", 5, 0); if( ssv != NULL ){ if( SvPOK( *ssv ) ) { g_value_set_string(&val, SvPV(*ssv,PL_na)); lu_ent_clear(ent, LU_GECOS); lu_ent_add(ent, LU_GECOS, &val); } else { warn("XS_UserAdd: Cannot add gecos to ent"); } } else warn("XS_UserAdd: hash elem gecos was null"); ssv = hv_fetch(hv, "homedir", 7, 0); if( ssv != NULL ){ if( SvPOK( *ssv ) ) { g_value_set_string(&val, SvPV(*ssv,PL_na)); lu_ent_clear(ent, LU_HOMEDIRECTORY); lu_ent_add(ent, LU_HOMEDIRECTORY, &val); } else{ warn("XS_UserAdd: Cannot add Home Dir to ent"); } } else warn("XS_UserAdd: hash elem homedir was null"); ssv = hv_fetch(hv, "loginshell", 10, 0); if( ssv != NULL ){ if( SvPOK( *ssv ) ) { g_value_set_string(&val, SvPV(*ssv,PL_na)); lu_ent_clear(ent, LU_LOGINSHELL); lu_ent_add(ent, LU_LOGINSHELL, &val); } else { warn("XS_UserAdd: Cannot add Login Shell to ent"); } } else warn("XS_UserAdd: hash elem loginshell was null"); g_value_unset(&val); g_value_init(&val, G_TYPE_LONG); ssv = hv_fetch( hv, "uid", 3, 0); if( ssv != NULL ){ if( SvIOK( *ssv ) && *ssv != -1) { g_value_set_long(&val, (long)SvIV( *ssv )); lu_ent_clear(ent, LU_UIDNUMBER); lu_ent_add(ent, LU_UIDNUMBER, &val); } else { warn("XS_UserAdd: hash elem Uid was not IOK"); } } else warn("XS_UserAdd: hash elem uid was null"); ssv = hv_fetch( hv, "gid", 3, 0); if( ssv != NULL ){ if( SvIOK( *ssv ) && *ssv != -1) { g_value_set_long(&val, (long)SvIV( *ssv )); lu_ent_clear(ent, LU_GIDNUMBER); lu_ent_add(ent, LU_GIDNUMBER, &val); } else { warn("XS_UserAdd: hash elem Uid was not IOK"); } } else warn("XS_UserAdd: hash elem uid was null"); /* GMOT (Great Moment Of Truth) */ if (lu_user_add(self, ent, &error) == FALSE) { croak("Account creation failed: %s.\n", error ? error->string : "Unknown error"); RETVAL = 0; } else RETVAL = 1 ; if (!dont_create_home) { /* Read the user's UID. */ values = lu_ent_get(ent, LU_UIDNUMBER); value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_LONG(value)) { uidNumber = g_value_get_long(value); } else if (G_VALUE_HOLDS_STRING(value)) { uidNumber = atol(g_value_get_string(value)); } else { warn("Cannot get Uid number"); } /* Read the user's GID. */ values = lu_ent_get(ent, LU_GIDNUMBER); value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_LONG(value)) { gidNumber = g_value_get_long(value); } else if (G_VALUE_HOLDS_STRING(value)) { gidNumber = atol(g_value_get_string(value)); } else { warn("Cannot retrieve val"); } /* Read the user's home directory. */ values = lu_ent_get(ent, LU_HOMEDIRECTORY); value = g_value_array_get_nth(values, 0); homeDirectory = g_value_get_string(value); if (lu_homedir_populate(skeleton, homeDirectory, uidNumber, gidNumber, 0700, &error) == FALSE) { warn("Error creating %s: %s.\n", homeDirectory, error ? error->string : "unknown error"); RETVAL = 2; } /* Create a mail spool for the user. */ if (lu_mailspool_create_remove(self, ent, TRUE) != TRUE) { fprintf(stderr, _("Error creating mail spool.\n")); return 8; } } OUTPUT: RETVAL void Admin_GroupAdd(self, enthash) USER::ADMIN *self SV* enthash void Admin_UserDel(self, ent) USER::ADMIN *self USER::ENT *ent void Admin_UserEdit(self, ent) USER::ADMIN *self USER::ENT *ent void Admin_LookupUserByName(self, name) USER::ADMIN *self char *name PPCODE: USER__ENT *ent; USER__ERR *error = NULL; ent = lu_ent_new(); if (lu_user_lookup_name(self, name, ent, &error)) { XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(ent)), gv_stashpv("USER::ENT", 1)))); } else { lu_ent_free(ent); } void Admin_LookupUserById(self, id) USER::ADMIN *self long id PPCODE: USER__ENT *ent; USER__ERR *error = NULL; ent = lu_ent_new(); if (lu_user_lookup_id(self, id, ent, &error)) { XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(ent)), gv_stashpv("USER::ENT", 1)))); } else { lu_ent_free(ent); } void Admin_LookupGroupByName(self, name) USER::ADMIN *self char *name PPCODE: USER__ENT *ent; USER__ERR *error = NULL; ent = lu_ent_new(); if (lu_group_lookup_name(self, name, ent, &error)) { XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(ent)), gv_stashpv("USER::ENT", 1)))); } else { lu_ent_free(ent); } void Admin_LookupGroupById(self, id) USER::ADMIN *self int id PPCODE: USER__ENT *ent; USER__ERR *error = NULL; ent = lu_ent_new(); if (lu_group_lookup_id(self, id, ent, &error)) { XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(ent)), gv_stashpv("USER::ENT", 1)))); } else { lu_ent_free(ent); } AV * Admin_EnumerateUsersByGroup(self, name) USER::ADMIN *self char *name CODE: int c; USER__ERR *error = NULL; RETVAL = (AV*)sv_2mortal((SV*)newAV()); GValueArray *results; results = lu_users_enumerate_by_group(self, name, &error); for (c = 0; (results != NULL) && (c < results->n_values); c++) { if( av_store(RETVAL, c, newSVpv(g_value_get_string(g_value_array_get_nth(results, c)), 0)) == NULL ){ warn("XS_UsersEnumerateFull: failed to store elems"); } } g_value_array_free(results); OUTPUT: RETVAL AV * Admin_EnumerateGroupsByUser(self, name) USER::ADMIN *self char *name CODE: int c; USER__ERR *error = NULL; RETVAL = (AV*)sv_2mortal((SV*)newAV()); GValueArray *results; results = lu_groups_enumerate_by_user(self, name, &error); for (c = 0; (results != NULL) && (c < results->n_values); c++) { if( av_store(RETVAL, c, newSVpv(g_value_get_string(g_value_array_get_nth(results, c)), 0)) == NULL ){ warn("XS_UsersEnumerateFull: failed to store elems"); } } g_value_array_free(results); OUTPUT: RETVAL AV * Admin_UsersEnumerateFull(self) USER::ADMIN *self CODE: int c; USER__ERR *error = NULL; const char *pattern = NULL; RETVAL = (AV*)sv_2mortal((SV*)newAV()); GPtrArray *accounts; accounts = lu_users_enumerate_full(self, pattern, &error); for (c = 0; (accounts != NULL) && (c < accounts->len); c++) { if( av_store(RETVAL, c, sv_bless(newRV_noinc(newSViv(g_ptr_array_index(accounts, c))), gv_stashpv("USER::ENT", 1))) == NULL ){ warn("XS_UsersEnumerateFull: failed to store elems"); } } g_ptr_array_free(accounts, TRUE); OUTPUT: RETVAL AV * Admin_GroupsEnumerateFull(self) USER::ADMIN *self CODE: int c; USER__ERR *error = NULL; const char *pattern = NULL; RETVAL = (AV*)sv_2mortal((SV*)newAV()); GPtrArray *accounts; accounts = lu_groups_enumerate_full(self, pattern, &error); for (c = 0; (accounts != NULL) && (c < accounts->len); c++) { if( av_store(RETVAL, c, sv_bless(newRV_noinc(newSViv(g_ptr_array_index(accounts, c))), gv_stashpv("USER::ENT", 1))) == NULL ){ warn("XS_UsersEnumerateFull: failed to store elems"); } } g_ptr_array_free(accounts, TRUE); OUTPUT: RETVAL AV * Admin_GetUserShells(self) USER::ADMIN *self CODE: int i = 0; const char *shell; RETVAL = (AV*)sv_2mortal((SV*)newAV()); setusershell(); while ((shell = getusershell()) != NULL) { av_store(RETVAL, i, newSVpv(shell, 0)); i++; } endusershell(); OUTPUT: RETVAL MODULE = USER PACKAGE = USER::ENT PREFIX = Ent_ USER::ENT * Ent_new (CLASS) char *CLASS CODE: RETVAL = (USER__ENT *)lu_ent_new(); if( RETVAL == NULL ){ warn("unable to malloc USER__ENT"); XSRETURN_UNDEF; } OUTPUT: RETVAL void Ent_DESTROY(self) USER::ENT *self CODE: printf("freeing ENT\n"); if (self) lu_ent_free(self); void Ent_EntType(self) USER::ENT *self PPCODE: switch (self->type) { case lu_invalid: break; case lu_user: XPUSHs(sv_2mortal(newSVpv("user", 0))); break; case lu_group: XPUSHs(sv_2mortal(newSVpv("group", 0))); break; default: break; } void Ent_UserName(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_USERNAME); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSVpv(g_value_get_string(value), 0))); } else if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSVpv(g_strdup_printf("%ld", g_value_get_long(value)), 0))); } } void Ent_GroupName(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_GROUPNAME); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSVpv(g_value_get_string(value), 0))); } else if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSVpv(g_strdup_printf("%ld", g_value_get_long(value)), 0))); } } void Ent_Uid(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_UIDNUMBER); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSViv(g_value_get_long(value)))); } else if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSViv(atol(g_value_get_string(value))))); } } void Ent_Gid(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_GIDNUMBER); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSViv(g_value_get_long(value)))); } else if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSViv(atol(g_value_get_string(value))))); } } void Ent_Gecos(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_GECOS); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSVpv(g_value_get_string(value), 0))); } else if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSVpv(g_strdup_printf("%ld", g_value_get_long(value)), 0))); } } void Ent_HomeDir(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_HOMEDIRECTORY); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSVpv(g_value_get_string(value), 0))); } else if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSVpv(g_strdup_printf("%ld", g_value_get_long(value)), 0))); } } void Ent_LoginShell(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_LOGINSHELL); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSVpv(g_value_get_string(value), 0))); } else if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSVpv(g_strdup_printf("%ld", g_value_get_long(value)), 0))); } } void Ent_ShadowPass(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_SHADOWPASSWORD); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSVpv(g_value_get_string(value), 0))); } else if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSVpv(g_strdup_printf("%ld", g_value_get_long(value)), 0))); } } void Ent_ShadowWarn(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_SHADOWWARNING); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSVpv(g_value_get_string(value), 0))); } else if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSVpv(g_strdup_printf("%ld", g_value_get_long(value)), 0))); } } void Ent_ShadowLastChange(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_SHADOWLASTCHANGE); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSViv(g_value_get_long(value)))); } else if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSViv(atol(g_value_get_string(value))))); } } void Ent_ShadowMin(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_SHADOWMIN); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSViv(g_value_get_long(value)))); } else if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSViv(atol(g_value_get_string(value))))); } } void Ent_ShadowMax(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_SHADOWMAX); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSViv(g_value_get_long(value)))); } else if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSViv(atol(g_value_get_string(value))))); } } void Ent_ShadowInact(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_SHADOWINACTIVE); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSViv(g_value_get_long(value)))); } else if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSViv(atol(g_value_get_string(value))))); } } void Ent_ShadowExpire(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_SHADOWEXPIRE); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSViv(g_value_get_long(value)))); } else if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSViv(atol(g_value_get_string(value))))); } } void Ent_ShadowFlag(self) USER::ENT *self PPCODE: GValueArray *values; GValue *value; values = lu_ent_get(self, LU_SHADOWFLAG); if (values != NULL) { value = g_value_array_get_nth(values, 0); if (G_VALUE_HOLDS_LONG(value)) { XPUSHs(sv_2mortal(newSViv(g_value_get_long(value)))); } else if (G_VALUE_HOLDS_STRING(value)) { XPUSHs(sv_2mortal(newSViv(atol(g_value_get_string(value))))); } } HV * Ent_get_attributes(self) USER::ENT *self CODE: RETVAL = (HV*)sv_2mortal((SV*)newHV()); printf("%s", self->type); switch (self->type) { case lu_invalid: break; case lu_user: hv_store(RETVAL, "type", 4, newSVpv("user", 0), 0); hv_store(RETVAL, "username", 8, newSVpv(get_name(self, LU_USERNAME), 0), 0); hv_store(RETVAL, "uid", 3, newSViv(get_int(self, LU_UIDNUMBER)), 0); hv_store(RETVAL, "gid", 3, newSViv(get_int(self, LU_GIDNUMBER)), 0); hv_store(RETVAL, "gecos", 5, newSVpv(get_name(self, LU_GECOS), 0), 0); hv_store(RETVAL, "home", 4, newSVpv(get_name(self, LU_HOMEDIRECTORY), 0), 0); hv_store(RETVAL, "shell", 5, newSVpv(get_name(self, LU_LOGINSHELL), 0), 0); hv_store(RETVAL, "shadowpass", 10, newSVpv(get_name(self, LU_SHADOWPASSWORD), 0), 0); hv_store(RETVAL, "shadowlastchange", 16, newSViv(get_int(self, LU_SHADOWLASTCHANGE)), 0); hv_store(RETVAL, "shadowmin", 9, newSViv(get_int(self, LU_SHADOWMIN)), 0); hv_store(RETVAL, "shadowmax", 9, newSViv(get_int(self, LU_SHADOWMAX)), 0); hv_store(RETVAL, "shadowwarning", 13, newSVpv(get_name(self, LU_SHADOWWARNING), 0), 0); hv_store(RETVAL, "shadowinact", 11, newSViv(get_int(self, LU_SHADOWINACTIVE)), 0); hv_store(RETVAL, "shadowexpire", 12, newSViv(get_int(self, LU_SHADOWEXPIRE)), 0); hv_store(RETVAL, "shadowflag", 10, newSViv(get_int(self, LU_SHADOWFLAG)), 0); break; case lu_group: hv_store(RETVAL, "type", 4, newSVpv("group", 0), 0); hv_store(RETVAL, "groupname", 9, newSVpv(get_name(self, LU_GROUPNAME), 0), 0); hv_store(RETVAL, "gid", 3, newSViv(get_int(self, LU_GIDNUMBER)), 0); break; default: break; } OUTPUT: RETVAL MODULE = USER PACKAGE = USER PREFIX = User_ void User_ReadConfigFiles() CODE: /*force read of /etc/sysconfig/userdrakefilter*/