diff --git a/Misc/ACKS b/Misc/ACKS index 4c3844d0a7c..4d58f95d8a2 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -766,6 +766,7 @@ Greg Ward Barry Warsaw Steve Waterbury Bob Watson +David Watson Aaron Watters Henrik Weber Corran Webster diff --git a/Misc/NEWS b/Misc/NEWS index 1aafdec93ee..8cc76a258f0 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,8 @@ Core and Builtins Library ------- +- Issue #4859: Implement PEP 383 for pwd, spwd, and grp. + - smtplib 'login' and 'cram-md5' login are also fixed (see Issue #5259). - Issue #6121: pydoc now ignores leading and trailing spaces in the diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c index a58cb060a6e..e642731f834 100644 --- a/Modules/grpmodule.c +++ b/Modules/grpmodule.c @@ -46,8 +46,11 @@ mkgrent(struct group *p) Py_DECREF(v); return NULL; } +#define FSDECODE(val) PyUnicode_Decode(val, strlen(val),\ + Py_FileSystemDefaultEncoding,\ + "surrogateescape") for (member = p->gr_mem; *member != NULL; member++) { - PyObject *x = PyUnicode_FromString(*member); + PyObject *x = FSDECODE(*member); if (x == NULL || PyList_Append(w, x) != 0) { Py_XDECREF(x); Py_DECREF(w); @@ -58,13 +61,13 @@ mkgrent(struct group *p) } #define SET(i,val) PyStructSequence_SET_ITEM(v, i, val) - SET(setIndex++, PyUnicode_FromString(p->gr_name)); + SET(setIndex++, FSDECODE(p->gr_name)); #ifdef __VMS SET(setIndex++, Py_None); Py_INCREF(Py_None); #else if (p->gr_passwd) - SET(setIndex++, PyUnicode_FromString(p->gr_passwd)); + SET(setIndex++, FSDECODE(p->gr_passwd)); else { SET(setIndex++, Py_None); Py_INCREF(Py_None); @@ -104,25 +107,28 @@ grp_getgrgid(PyObject *self, PyObject *pyo_id) } static PyObject * -grp_getgrnam(PyObject *self, PyObject *pyo_name) +grp_getgrnam(PyObject *self, PyObject *args) { - PyObject *py_str_name; char *name; struct group *p; + PyObject *arg, *bytes, *retval = NULL; - py_str_name = PyObject_Str(pyo_name); - if (!py_str_name) - return NULL; - name = _PyUnicode_AsString(py_str_name); + if (!PyArg_ParseTuple(args, "U:getgrnam", &arg)) + return NULL; + if ((bytes = PyUnicode_AsEncodedString(arg, Py_FileSystemDefaultEncoding, + "surrogateescape")) == NULL) + return NULL; + if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1) + goto out; if ((p = getgrnam(name)) == NULL) { PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %s", name); - Py_DECREF(py_str_name); - return NULL; + goto out; } - - Py_DECREF(py_str_name); - return mkgrent(p); + retval = mkgrent(p); +out: + Py_DECREF(bytes); + return retval; } static PyObject * @@ -152,7 +158,7 @@ static PyMethodDef grp_methods[] = { "getgrgid(id) -> tuple\n\ Return the group database entry for the given numeric group ID. If\n\ id is not valid, raise KeyError."}, - {"getgrnam", grp_getgrnam, METH_O, + {"getgrnam", grp_getgrnam, METH_VARARGS, "getgrnam(name) -> tuple\n\ Return the group database entry for the given group name. If\n\ name is not valid, raise KeyError."}, diff --git a/Modules/pwdmodule.c b/Modules/pwdmodule.c index 061a0a5254f..5802818149a 100644 --- a/Modules/pwdmodule.c +++ b/Modules/pwdmodule.c @@ -49,8 +49,9 @@ static void sets(PyObject *v, int i, const char* val) { if (val) { - PyObject *o = - PyUnicode_DecodeUnicodeEscape(val, strlen(val), "strict"); + PyObject *o = PyUnicode_Decode(val, strlen(val), + Py_FileSystemDefaultEncoding, + "surrogateescape"); PyStructSequence_SET_ITEM(v, i, o); } else { @@ -129,14 +130,25 @@ pwd_getpwnam(PyObject *self, PyObject *args) { char *name; struct passwd *p; - if (!PyArg_ParseTuple(args, "s:getpwnam", &name)) + PyObject *arg, *bytes, *retval = NULL; + + if (!PyArg_ParseTuple(args, "U:getpwnam", &arg)) return NULL; + if ((bytes = PyUnicode_AsEncodedString(arg, + Py_FileSystemDefaultEncoding, + "surrogateescape")) == NULL) + return NULL; + if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1) + goto out; if ((p = getpwnam(name)) == NULL) { PyErr_Format(PyExc_KeyError, "getpwnam(): name not found: %s", name); - return NULL; + goto out; } - return mkpwent(p); + retval = mkpwent(p); +out: + Py_DECREF(bytes); + return retval; } #ifdef HAVE_GETPWENT diff --git a/Modules/spwdmodule.c b/Modules/spwdmodule.c index a6b9d93fedc..230b57cf3ea 100644 --- a/Modules/spwdmodule.c +++ b/Modules/spwdmodule.c @@ -59,9 +59,12 @@ static PyTypeObject StructSpwdType; static void sets(PyObject *v, int i, const char* val) { - if (val) - PyStructSequence_SET_ITEM(v, i, PyUnicode_FromString(val)); - else { + if (val) { + PyObject *o = PyUnicode_Decode(val, strlen(val), + Py_FileSystemDefaultEncoding, + "surrogateescape"); + PyStructSequence_SET_ITEM(v, i, o); + } else { PyStructSequence_SET_ITEM(v, i, Py_None); Py_INCREF(Py_None); } @@ -113,13 +116,24 @@ static PyObject* spwd_getspnam(PyObject *self, PyObject *args) { char *name; struct spwd *p; - if (!PyArg_ParseTuple(args, "s:getspnam", &name)) + PyObject *arg, *bytes, *retval = NULL; + + if (!PyArg_ParseTuple(args, "U:getspnam", &arg)) return NULL; + if ((bytes = PyUnicode_AsEncodedString(arg, + Py_FileSystemDefaultEncoding, + "surrogateescape")) == NULL) + return NULL; + if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1) + goto out; if ((p = getspnam(name)) == NULL) { PyErr_SetString(PyExc_KeyError, "getspnam(): name not found"); - return NULL; + goto out; } - return mkspent(p); + retval = mkspent(p); +out: + Py_DECREF(bytes); + return retval; } #endif /* HAVE_GETSPNAM */