Port of issue8451 to python3: Syslog use sys.argv[0] for ident.
diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c
index c6a3b36..2281c1d 100644
--- a/Modules/syslogmodule.c
+++ b/Modules/syslogmodule.c
@@ -26,6 +26,11 @@
 
 Revision history:
 
+2010/04/20 (Sean Reifschneider)
+  - Use basename(sys.argv[0]) for the default "ident".
+  - Arguments to openlog() are now keyword args and are all optional.
+  - syslog() calls openlog() if it hasn't already been called.
+
 1998/04/28 (Sean Reifschneider)
   - When facility not specified to syslog() method, use default from openlog()
     (This is how it was claimed to work in the documentation)
@@ -45,6 +50,7 @@
 /* syslog module */
 
 #include "Python.h"
+#include "osdefs.h"
 
 #include <syslog.h>
 
@@ -52,30 +58,83 @@
 static PyObject *S_ident_o = NULL;			/*  identifier, held by openlog()  */
 
 
+static PyObject *
+syslog_get_argv(void)
+{
+	/* Figure out what to use for as the program "ident" for openlog().
+	 * This swallows exceptions and continues rather than failing out,
+	 * because the syslog module can still be used because openlog(3)
+	 * is optional.
+	 */
+
+	Py_ssize_t argv_len;
+	PyObject *scriptobj;
+	char *atslash;
+	PyObject *argv = PySys_GetObject("argv");
+
+	if (argv == NULL) {
+		return(NULL);
+	}
+
+	argv_len = PyList_Size(argv);
+	if (argv_len == -1) {
+		PyErr_Clear();
+		return(NULL);
+	}
+	if (argv_len == 0) {
+		return(NULL);
+	}
+
+	scriptobj = PyList_GetItem(argv, 0);
+	if (!PyUnicode_Check(scriptobj)) {
+		return(NULL);
+	}
+	if (PyUnicode_GET_SIZE(scriptobj) == 0) {
+		return(NULL);
+	}
+
+	atslash = strrchr(_PyUnicode_AsString(scriptobj), SEP);
+	if (atslash) {
+		return(PyUnicode_FromString(atslash + 1));
+	} else {
+		Py_INCREF(scriptobj);
+		return(scriptobj);
+	}
+
+	return(NULL);
+}
+
+
 static PyObject * 
-syslog_openlog(PyObject * self, PyObject * args)
+syslog_openlog(PyObject * self, PyObject * args, PyObject *kwds)
 {
 	long logopt = 0;
 	long facility = LOG_USER;
-	PyObject *new_S_ident_o;
-	const char *ident;
+	PyObject *new_S_ident_o = NULL;
+	static char *keywords[] = {"ident", "logoption", "facility", 0};
 
-	if (!PyArg_ParseTuple(args,
-			      "U|ll;ident string [, logoption [, facility]]",
-			      &new_S_ident_o, &logopt, &facility))
+	if (!PyArg_ParseTupleAndKeywords(args, kwds,
+			      "|Ull:openlog", keywords, &new_S_ident_o, &logopt, &facility))
 		return NULL;
 
-	/* This is needed because openlog() does NOT make a copy
-	 * and syslog() later uses it.. cannot trash it.
-	 */
+	if (new_S_ident_o) {
+		Py_INCREF(new_S_ident_o);
+		}
+
+	/*  get sys.argv[0] or NULL if we can't for some reason  */
+	if (!new_S_ident_o) {
+		new_S_ident_o = syslog_get_argv();
+		}
+
 	Py_XDECREF(S_ident_o);
 	S_ident_o = new_S_ident_o;
-	Py_INCREF(S_ident_o);
 
-	ident = _PyUnicode_AsString(S_ident_o);
-	if (ident == NULL)
-		return NULL;
-	openlog(ident, logopt, facility);
+	/* At this point, S_ident_o should be INCREF()ed.  openlog(3) does not
+	 * make a copy, and syslog(3) later uses it.  We can't garbagecollect it
+	 * If NULL, just let openlog figure it out (probably using C argv[0]).
+	 */
+ 
+	openlog(S_ident_o ? _PyUnicode_AsString(S_ident_o) : NULL, logopt, facility);
 
 	Py_INCREF(Py_None);
 	return Py_None;
@@ -100,6 +159,22 @@
 	message = _PyUnicode_AsString(message_object);
 	if (message == NULL)
 		return NULL;
+
+	/*  call openlog if no current identifier  */
+	if (!S_ident_o) {
+		PyObject *openargs;
+
+		/* Continue even if PyTuple_New fails, because openlog(3) is optional.
+		 * So, we can still do loggin in the unlikely event things are so hosed
+		 * that we can't do this tuple.
+		 */
+		if ((openargs = PyTuple_New(0))) {
+			PyObject *openlog_ret = syslog_openlog(self, openargs, NULL);
+			Py_XDECREF(openlog_ret);
+			Py_DECREF(openargs);
+		}
+	}
+
 	Py_BEGIN_ALLOW_THREADS;
 	syslog(priority, "%s", message);
 	Py_END_ALLOW_THREADS;
@@ -152,7 +227,7 @@
 /* List of functions defined in the module */
 
 static PyMethodDef syslog_methods[] = {
-	{"openlog",	syslog_openlog,		METH_VARARGS},
+	{"openlog",	(PyCFunction) syslog_openlog,		METH_VARARGS | METH_KEYWORDS},
 	{"closelog",	syslog_closelog,	METH_NOARGS},
 	{"syslog",	syslog_syslog,		METH_VARARGS},
 	{"setlogmask",	syslog_setlogmask,	METH_VARARGS},