xref: /third_party/python/Modules/pwdmodule.c (revision 7db96d56)
17db96d56Sopenharmony_ci
27db96d56Sopenharmony_ci/* UNIX password file access module */
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ci#include "Python.h"
57db96d56Sopenharmony_ci#include "posixmodule.h"
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci#include <pwd.h>
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci#include "clinic/pwdmodule.c.h"
107db96d56Sopenharmony_ci/*[clinic input]
117db96d56Sopenharmony_cimodule pwd
127db96d56Sopenharmony_ci[clinic start generated code]*/
137db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=60f628ef356b97b6]*/
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_cistatic PyStructSequence_Field struct_pwd_type_fields[] = {
167db96d56Sopenharmony_ci    {"pw_name", "user name"},
177db96d56Sopenharmony_ci    {"pw_passwd", "password"},
187db96d56Sopenharmony_ci    {"pw_uid", "user id"},
197db96d56Sopenharmony_ci    {"pw_gid", "group id"},
207db96d56Sopenharmony_ci    {"pw_gecos", "real name"},
217db96d56Sopenharmony_ci    {"pw_dir", "home directory"},
227db96d56Sopenharmony_ci    {"pw_shell", "shell program"},
237db96d56Sopenharmony_ci    {0}
247db96d56Sopenharmony_ci};
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ciPyDoc_STRVAR(struct_passwd__doc__,
277db96d56Sopenharmony_ci"pwd.struct_passwd: Results from getpw*() routines.\n\n\
287db96d56Sopenharmony_ciThis object may be accessed either as a tuple of\n\
297db96d56Sopenharmony_ci  (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell)\n\
307db96d56Sopenharmony_cior via the object attributes as named in the above tuple.");
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_cistatic PyStructSequence_Desc struct_pwd_type_desc = {
337db96d56Sopenharmony_ci    "pwd.struct_passwd",
347db96d56Sopenharmony_ci    struct_passwd__doc__,
357db96d56Sopenharmony_ci    struct_pwd_type_fields,
367db96d56Sopenharmony_ci    7,
377db96d56Sopenharmony_ci};
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ciPyDoc_STRVAR(pwd__doc__,
407db96d56Sopenharmony_ci"This module provides access to the Unix password database.\n\
417db96d56Sopenharmony_ciIt is available on all Unix versions.\n\
427db96d56Sopenharmony_ci\n\
437db96d56Sopenharmony_ciPassword database entries are reported as 7-tuples containing the following\n\
447db96d56Sopenharmony_ciitems from the password database (see `<pwd.h>'), in order:\n\
457db96d56Sopenharmony_cipw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell.\n\
467db96d56Sopenharmony_ciThe uid and gid items are integers, all others are strings. An\n\
477db96d56Sopenharmony_ciexception is raised if the entry asked for cannot be found.");
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci
507db96d56Sopenharmony_citypedef struct {
517db96d56Sopenharmony_ci    PyTypeObject *StructPwdType;
527db96d56Sopenharmony_ci} pwdmodulestate;
537db96d56Sopenharmony_ci
547db96d56Sopenharmony_cistatic inline pwdmodulestate*
557db96d56Sopenharmony_ciget_pwd_state(PyObject *module)
567db96d56Sopenharmony_ci{
577db96d56Sopenharmony_ci    void *state = PyModule_GetState(module);
587db96d56Sopenharmony_ci    assert(state != NULL);
597db96d56Sopenharmony_ci    return (pwdmodulestate *)state;
607db96d56Sopenharmony_ci}
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_cistatic struct PyModuleDef pwdmodule;
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci#define DEFAULT_BUFFER_SIZE 1024
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_cistatic void
677db96d56Sopenharmony_cisets(PyObject *v, int i, const char* val)
687db96d56Sopenharmony_ci{
697db96d56Sopenharmony_ci  if (val) {
707db96d56Sopenharmony_ci      PyObject *o = PyUnicode_DecodeFSDefault(val);
717db96d56Sopenharmony_ci      PyStructSequence_SET_ITEM(v, i, o);
727db96d56Sopenharmony_ci  }
737db96d56Sopenharmony_ci  else {
747db96d56Sopenharmony_ci      PyStructSequence_SET_ITEM(v, i, Py_None);
757db96d56Sopenharmony_ci      Py_INCREF(Py_None);
767db96d56Sopenharmony_ci  }
777db96d56Sopenharmony_ci}
787db96d56Sopenharmony_ci
797db96d56Sopenharmony_cistatic PyObject *
807db96d56Sopenharmony_cimkpwent(PyObject *module, struct passwd *p)
817db96d56Sopenharmony_ci{
827db96d56Sopenharmony_ci    int setIndex = 0;
837db96d56Sopenharmony_ci    PyObject *v = PyStructSequence_New(get_pwd_state(module)->StructPwdType);
847db96d56Sopenharmony_ci    if (v == NULL)
857db96d56Sopenharmony_ci        return NULL;
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_ci#define SETS(i,val) sets(v, i, val)
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ci    SETS(setIndex++, p->pw_name);
907db96d56Sopenharmony_ci#if defined(HAVE_STRUCT_PASSWD_PW_PASSWD) && !defined(__ANDROID__)
917db96d56Sopenharmony_ci    SETS(setIndex++, p->pw_passwd);
927db96d56Sopenharmony_ci#else
937db96d56Sopenharmony_ci    SETS(setIndex++, "");
947db96d56Sopenharmony_ci#endif
957db96d56Sopenharmony_ci    PyStructSequence_SET_ITEM(v, setIndex++, _PyLong_FromUid(p->pw_uid));
967db96d56Sopenharmony_ci    PyStructSequence_SET_ITEM(v, setIndex++, _PyLong_FromGid(p->pw_gid));
977db96d56Sopenharmony_ci#if defined(HAVE_STRUCT_PASSWD_PW_GECOS)
987db96d56Sopenharmony_ci    SETS(setIndex++, p->pw_gecos);
997db96d56Sopenharmony_ci#else
1007db96d56Sopenharmony_ci    SETS(setIndex++, "");
1017db96d56Sopenharmony_ci#endif
1027db96d56Sopenharmony_ci    SETS(setIndex++, p->pw_dir);
1037db96d56Sopenharmony_ci    SETS(setIndex++, p->pw_shell);
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ci#undef SETS
1067db96d56Sopenharmony_ci
1077db96d56Sopenharmony_ci    if (PyErr_Occurred()) {
1087db96d56Sopenharmony_ci        Py_XDECREF(v);
1097db96d56Sopenharmony_ci        return NULL;
1107db96d56Sopenharmony_ci    }
1117db96d56Sopenharmony_ci
1127db96d56Sopenharmony_ci    return v;
1137db96d56Sopenharmony_ci}
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_ci/*[clinic input]
1167db96d56Sopenharmony_cipwd.getpwuid
1177db96d56Sopenharmony_ci
1187db96d56Sopenharmony_ci    uidobj: object
1197db96d56Sopenharmony_ci    /
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_ciReturn the password database entry for the given numeric user ID.
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ciSee `help(pwd)` for more on password database entries.
1247db96d56Sopenharmony_ci[clinic start generated code]*/
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_cistatic PyObject *
1277db96d56Sopenharmony_cipwd_getpwuid(PyObject *module, PyObject *uidobj)
1287db96d56Sopenharmony_ci/*[clinic end generated code: output=c4ee1d4d429b86c4 input=ae64d507a1c6d3e8]*/
1297db96d56Sopenharmony_ci{
1307db96d56Sopenharmony_ci    PyObject *retval = NULL;
1317db96d56Sopenharmony_ci    uid_t uid;
1327db96d56Sopenharmony_ci    int nomem = 0;
1337db96d56Sopenharmony_ci    struct passwd *p;
1347db96d56Sopenharmony_ci    char *buf = NULL, *buf2 = NULL;
1357db96d56Sopenharmony_ci
1367db96d56Sopenharmony_ci    if (!_Py_Uid_Converter(uidobj, &uid)) {
1377db96d56Sopenharmony_ci        if (PyErr_ExceptionMatches(PyExc_OverflowError))
1387db96d56Sopenharmony_ci            PyErr_Format(PyExc_KeyError,
1397db96d56Sopenharmony_ci                         "getpwuid(): uid not found");
1407db96d56Sopenharmony_ci        return NULL;
1417db96d56Sopenharmony_ci    }
1427db96d56Sopenharmony_ci#ifdef HAVE_GETPWUID_R
1437db96d56Sopenharmony_ci    int status;
1447db96d56Sopenharmony_ci    Py_ssize_t bufsize;
1457db96d56Sopenharmony_ci    /* Note: 'pwd' will be used via pointer 'p' on getpwuid_r success. */
1467db96d56Sopenharmony_ci    struct passwd pwd;
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci    Py_BEGIN_ALLOW_THREADS
1497db96d56Sopenharmony_ci    bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
1507db96d56Sopenharmony_ci    if (bufsize == -1) {
1517db96d56Sopenharmony_ci        bufsize = DEFAULT_BUFFER_SIZE;
1527db96d56Sopenharmony_ci    }
1537db96d56Sopenharmony_ci
1547db96d56Sopenharmony_ci    while(1) {
1557db96d56Sopenharmony_ci        buf2 = PyMem_RawRealloc(buf, bufsize);
1567db96d56Sopenharmony_ci        if (buf2 == NULL) {
1577db96d56Sopenharmony_ci            p = NULL;
1587db96d56Sopenharmony_ci            nomem = 1;
1597db96d56Sopenharmony_ci            break;
1607db96d56Sopenharmony_ci        }
1617db96d56Sopenharmony_ci        buf = buf2;
1627db96d56Sopenharmony_ci        status = getpwuid_r(uid, &pwd, buf, bufsize, &p);
1637db96d56Sopenharmony_ci        if (status != 0) {
1647db96d56Sopenharmony_ci            p = NULL;
1657db96d56Sopenharmony_ci        }
1667db96d56Sopenharmony_ci        if (p != NULL || status != ERANGE) {
1677db96d56Sopenharmony_ci            break;
1687db96d56Sopenharmony_ci        }
1697db96d56Sopenharmony_ci        if (bufsize > (PY_SSIZE_T_MAX >> 1)) {
1707db96d56Sopenharmony_ci            nomem = 1;
1717db96d56Sopenharmony_ci            break;
1727db96d56Sopenharmony_ci        }
1737db96d56Sopenharmony_ci        bufsize <<= 1;
1747db96d56Sopenharmony_ci    }
1757db96d56Sopenharmony_ci
1767db96d56Sopenharmony_ci    Py_END_ALLOW_THREADS
1777db96d56Sopenharmony_ci#else
1787db96d56Sopenharmony_ci    p = getpwuid(uid);
1797db96d56Sopenharmony_ci#endif
1807db96d56Sopenharmony_ci    if (p == NULL) {
1817db96d56Sopenharmony_ci        PyMem_RawFree(buf);
1827db96d56Sopenharmony_ci        if (nomem == 1) {
1837db96d56Sopenharmony_ci            return PyErr_NoMemory();
1847db96d56Sopenharmony_ci        }
1857db96d56Sopenharmony_ci        PyObject *uid_obj = _PyLong_FromUid(uid);
1867db96d56Sopenharmony_ci        if (uid_obj == NULL)
1877db96d56Sopenharmony_ci            return NULL;
1887db96d56Sopenharmony_ci        PyErr_Format(PyExc_KeyError,
1897db96d56Sopenharmony_ci                     "getpwuid(): uid not found: %S", uid_obj);
1907db96d56Sopenharmony_ci        Py_DECREF(uid_obj);
1917db96d56Sopenharmony_ci        return NULL;
1927db96d56Sopenharmony_ci    }
1937db96d56Sopenharmony_ci    retval = mkpwent(module, p);
1947db96d56Sopenharmony_ci#ifdef HAVE_GETPWUID_R
1957db96d56Sopenharmony_ci    PyMem_RawFree(buf);
1967db96d56Sopenharmony_ci#endif
1977db96d56Sopenharmony_ci    return retval;
1987db96d56Sopenharmony_ci}
1997db96d56Sopenharmony_ci
2007db96d56Sopenharmony_ci/*[clinic input]
2017db96d56Sopenharmony_cipwd.getpwnam
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_ci    name: unicode
2047db96d56Sopenharmony_ci    /
2057db96d56Sopenharmony_ci
2067db96d56Sopenharmony_ciReturn the password database entry for the given user name.
2077db96d56Sopenharmony_ci
2087db96d56Sopenharmony_ciSee `help(pwd)` for more on password database entries.
2097db96d56Sopenharmony_ci[clinic start generated code]*/
2107db96d56Sopenharmony_ci
2117db96d56Sopenharmony_cistatic PyObject *
2127db96d56Sopenharmony_cipwd_getpwnam_impl(PyObject *module, PyObject *name)
2137db96d56Sopenharmony_ci/*[clinic end generated code: output=359ce1ddeb7a824f input=a6aeb5e3447fb9e0]*/
2147db96d56Sopenharmony_ci{
2157db96d56Sopenharmony_ci    char *buf = NULL, *buf2 = NULL, *name_chars;
2167db96d56Sopenharmony_ci    int nomem = 0;
2177db96d56Sopenharmony_ci    struct passwd *p;
2187db96d56Sopenharmony_ci    PyObject *bytes, *retval = NULL;
2197db96d56Sopenharmony_ci
2207db96d56Sopenharmony_ci    if ((bytes = PyUnicode_EncodeFSDefault(name)) == NULL)
2217db96d56Sopenharmony_ci        return NULL;
2227db96d56Sopenharmony_ci    /* check for embedded null bytes */
2237db96d56Sopenharmony_ci    if (PyBytes_AsStringAndSize(bytes, &name_chars, NULL) == -1)
2247db96d56Sopenharmony_ci        goto out;
2257db96d56Sopenharmony_ci#ifdef HAVE_GETPWNAM_R
2267db96d56Sopenharmony_ci    int status;
2277db96d56Sopenharmony_ci    Py_ssize_t bufsize;
2287db96d56Sopenharmony_ci    /* Note: 'pwd' will be used via pointer 'p' on getpwnam_r success. */
2297db96d56Sopenharmony_ci    struct passwd pwd;
2307db96d56Sopenharmony_ci
2317db96d56Sopenharmony_ci    Py_BEGIN_ALLOW_THREADS
2327db96d56Sopenharmony_ci    bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
2337db96d56Sopenharmony_ci    if (bufsize == -1) {
2347db96d56Sopenharmony_ci        bufsize = DEFAULT_BUFFER_SIZE;
2357db96d56Sopenharmony_ci    }
2367db96d56Sopenharmony_ci
2377db96d56Sopenharmony_ci    while(1) {
2387db96d56Sopenharmony_ci        buf2 = PyMem_RawRealloc(buf, bufsize);
2397db96d56Sopenharmony_ci        if (buf2 == NULL) {
2407db96d56Sopenharmony_ci            p = NULL;
2417db96d56Sopenharmony_ci            nomem = 1;
2427db96d56Sopenharmony_ci            break;
2437db96d56Sopenharmony_ci        }
2447db96d56Sopenharmony_ci        buf = buf2;
2457db96d56Sopenharmony_ci        status = getpwnam_r(name_chars, &pwd, buf, bufsize, &p);
2467db96d56Sopenharmony_ci        if (status != 0) {
2477db96d56Sopenharmony_ci            p = NULL;
2487db96d56Sopenharmony_ci        }
2497db96d56Sopenharmony_ci        if (p != NULL || status != ERANGE) {
2507db96d56Sopenharmony_ci            break;
2517db96d56Sopenharmony_ci        }
2527db96d56Sopenharmony_ci        if (bufsize > (PY_SSIZE_T_MAX >> 1)) {
2537db96d56Sopenharmony_ci            nomem = 1;
2547db96d56Sopenharmony_ci            break;
2557db96d56Sopenharmony_ci        }
2567db96d56Sopenharmony_ci        bufsize <<= 1;
2577db96d56Sopenharmony_ci    }
2587db96d56Sopenharmony_ci
2597db96d56Sopenharmony_ci    Py_END_ALLOW_THREADS
2607db96d56Sopenharmony_ci#else
2617db96d56Sopenharmony_ci    p = getpwnam(name_chars);
2627db96d56Sopenharmony_ci#endif
2637db96d56Sopenharmony_ci    if (p == NULL) {
2647db96d56Sopenharmony_ci        if (nomem == 1) {
2657db96d56Sopenharmony_ci            PyErr_NoMemory();
2667db96d56Sopenharmony_ci        }
2677db96d56Sopenharmony_ci        else {
2687db96d56Sopenharmony_ci            PyErr_Format(PyExc_KeyError,
2697db96d56Sopenharmony_ci                         "getpwnam(): name not found: %R", name);
2707db96d56Sopenharmony_ci        }
2717db96d56Sopenharmony_ci        goto out;
2727db96d56Sopenharmony_ci    }
2737db96d56Sopenharmony_ci    retval = mkpwent(module, p);
2747db96d56Sopenharmony_ciout:
2757db96d56Sopenharmony_ci    PyMem_RawFree(buf);
2767db96d56Sopenharmony_ci    Py_DECREF(bytes);
2777db96d56Sopenharmony_ci    return retval;
2787db96d56Sopenharmony_ci}
2797db96d56Sopenharmony_ci
2807db96d56Sopenharmony_ci#ifdef HAVE_GETPWENT
2817db96d56Sopenharmony_ci/*[clinic input]
2827db96d56Sopenharmony_cipwd.getpwall
2837db96d56Sopenharmony_ci
2847db96d56Sopenharmony_ciReturn a list of all available password database entries, in arbitrary order.
2857db96d56Sopenharmony_ci
2867db96d56Sopenharmony_ciSee help(pwd) for more on password database entries.
2877db96d56Sopenharmony_ci[clinic start generated code]*/
2887db96d56Sopenharmony_ci
2897db96d56Sopenharmony_cistatic PyObject *
2907db96d56Sopenharmony_cipwd_getpwall_impl(PyObject *module)
2917db96d56Sopenharmony_ci/*[clinic end generated code: output=4853d2f5a0afac8a input=d7ecebfd90219b85]*/
2927db96d56Sopenharmony_ci{
2937db96d56Sopenharmony_ci    PyObject *d;
2947db96d56Sopenharmony_ci    struct passwd *p;
2957db96d56Sopenharmony_ci    if ((d = PyList_New(0)) == NULL)
2967db96d56Sopenharmony_ci        return NULL;
2977db96d56Sopenharmony_ci    setpwent();
2987db96d56Sopenharmony_ci    while ((p = getpwent()) != NULL) {
2997db96d56Sopenharmony_ci        PyObject *v = mkpwent(module, p);
3007db96d56Sopenharmony_ci        if (v == NULL || PyList_Append(d, v) != 0) {
3017db96d56Sopenharmony_ci            Py_XDECREF(v);
3027db96d56Sopenharmony_ci            Py_DECREF(d);
3037db96d56Sopenharmony_ci            endpwent();
3047db96d56Sopenharmony_ci            return NULL;
3057db96d56Sopenharmony_ci        }
3067db96d56Sopenharmony_ci        Py_DECREF(v);
3077db96d56Sopenharmony_ci    }
3087db96d56Sopenharmony_ci    endpwent();
3097db96d56Sopenharmony_ci    return d;
3107db96d56Sopenharmony_ci}
3117db96d56Sopenharmony_ci#endif
3127db96d56Sopenharmony_ci
3137db96d56Sopenharmony_cistatic PyMethodDef pwd_methods[] = {
3147db96d56Sopenharmony_ci    PWD_GETPWUID_METHODDEF
3157db96d56Sopenharmony_ci    PWD_GETPWNAM_METHODDEF
3167db96d56Sopenharmony_ci#ifdef HAVE_GETPWENT
3177db96d56Sopenharmony_ci    PWD_GETPWALL_METHODDEF
3187db96d56Sopenharmony_ci#endif
3197db96d56Sopenharmony_ci    {NULL,              NULL}           /* sentinel */
3207db96d56Sopenharmony_ci};
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_cistatic int
3237db96d56Sopenharmony_cipwdmodule_exec(PyObject *module)
3247db96d56Sopenharmony_ci{
3257db96d56Sopenharmony_ci    pwdmodulestate *state = get_pwd_state(module);
3267db96d56Sopenharmony_ci
3277db96d56Sopenharmony_ci    state->StructPwdType = PyStructSequence_NewType(&struct_pwd_type_desc);
3287db96d56Sopenharmony_ci    if (state->StructPwdType == NULL) {
3297db96d56Sopenharmony_ci        return -1;
3307db96d56Sopenharmony_ci    }
3317db96d56Sopenharmony_ci    if (PyModule_AddType(module, state->StructPwdType) < 0) {
3327db96d56Sopenharmony_ci        return -1;
3337db96d56Sopenharmony_ci    }
3347db96d56Sopenharmony_ci    return 0;
3357db96d56Sopenharmony_ci}
3367db96d56Sopenharmony_ci
3377db96d56Sopenharmony_cistatic PyModuleDef_Slot pwdmodule_slots[] = {
3387db96d56Sopenharmony_ci    {Py_mod_exec, pwdmodule_exec},
3397db96d56Sopenharmony_ci    {0, NULL}
3407db96d56Sopenharmony_ci};
3417db96d56Sopenharmony_ci
3427db96d56Sopenharmony_cistatic int pwdmodule_traverse(PyObject *m, visitproc visit, void *arg) {
3437db96d56Sopenharmony_ci    Py_VISIT(get_pwd_state(m)->StructPwdType);
3447db96d56Sopenharmony_ci    return 0;
3457db96d56Sopenharmony_ci}
3467db96d56Sopenharmony_cistatic int pwdmodule_clear(PyObject *m) {
3477db96d56Sopenharmony_ci    Py_CLEAR(get_pwd_state(m)->StructPwdType);
3487db96d56Sopenharmony_ci    return 0;
3497db96d56Sopenharmony_ci}
3507db96d56Sopenharmony_cistatic void pwdmodule_free(void *m) {
3517db96d56Sopenharmony_ci    pwdmodule_clear((PyObject *)m);
3527db96d56Sopenharmony_ci}
3537db96d56Sopenharmony_ci
3547db96d56Sopenharmony_cistatic struct PyModuleDef pwdmodule = {
3557db96d56Sopenharmony_ci    PyModuleDef_HEAD_INIT,
3567db96d56Sopenharmony_ci    .m_name = "pwd",
3577db96d56Sopenharmony_ci    .m_doc = pwd__doc__,
3587db96d56Sopenharmony_ci    .m_size = sizeof(pwdmodulestate),
3597db96d56Sopenharmony_ci    .m_methods = pwd_methods,
3607db96d56Sopenharmony_ci    .m_slots = pwdmodule_slots,
3617db96d56Sopenharmony_ci    .m_traverse = pwdmodule_traverse,
3627db96d56Sopenharmony_ci    .m_clear = pwdmodule_clear,
3637db96d56Sopenharmony_ci    .m_free = pwdmodule_free,
3647db96d56Sopenharmony_ci};
3657db96d56Sopenharmony_ci
3667db96d56Sopenharmony_ci
3677db96d56Sopenharmony_ciPyMODINIT_FUNC
3687db96d56Sopenharmony_ciPyInit_pwd(void)
3697db96d56Sopenharmony_ci{
3707db96d56Sopenharmony_ci    return PyModuleDef_Init(&pwdmodule);
3717db96d56Sopenharmony_ci}
372