pax_global_header00006660000000000000000000000064140027126150014510gustar00rootroot0000000000000052 comment=491d16e4cddaeb15f174b95536900a001b9e933a py-setproctitle-version-1.2.2/000077500000000000000000000000001400271261500163445ustar00rootroot00000000000000py-setproctitle-version-1.2.2/.github/000077500000000000000000000000001400271261500177045ustar00rootroot00000000000000py-setproctitle-version-1.2.2/.github/FUNDING.yml000066400000000000000000000001111400271261500215120ustar00rootroot00000000000000--- github: - dvarrazzo custom: - "https://www.paypal.me/dvarrazzo" py-setproctitle-version-1.2.2/.github/workflows/000077500000000000000000000000001400271261500217415ustar00rootroot00000000000000py-setproctitle-version-1.2.2/.github/workflows/packages.yml000066400000000000000000000055651400271261500242550ustar00rootroot00000000000000--- name: Packages on: [workflow_dispatch] jobs: build-sdist: name: Build sdist package runs-on: ubuntu-20.04 steps: - name: Checkout repos uses: actions/checkout@v2 - name: Build sdist run: python setup.py sdist - name: Upload artifacts uses: actions/upload-artifact@v2 with: name: packages_sdist path: | dist/*.tar.gz build-linux-i686: name: Build Linux i686 packages runs-on: ubuntu-20.04 steps: - name: Checkout repos uses: actions/checkout@v2 - name: Build i686 packages uses: RalfG/python-wheels-manylinux-build@v0.3.3-manylinux2014_i686 with: python-versions: "cp36-cp36m cp37-cp37m cp38-cp38 cp39-cp39" - name: Upload artifacts uses: actions/upload-artifact@v2 with: name: packages_linux_i686 path: | dist/*-manylinux1_i686.whl build-x86_64: name: Build Linux x86_64 packages runs-on: ubuntu-20.04 steps: - name: Checkout repos uses: actions/checkout@v2 - name: Build x86_64 packages uses: RalfG/python-wheels-manylinux-build@v0.3.3-manylinux2014_x86_64 with: python-versions: "cp36-cp36m cp37-cp37m cp38-cp38 cp39-cp39" - name: Upload artifacts uses: actions/upload-artifact@v2 with: name: packages_linux_x86_64 path: | dist/*-manylinux1_x86_64.whl build-aarch64: name: Build Linux aarch64 packages runs-on: ubuntu-20.04 steps: - name: Checkout repos uses: actions/checkout@v2 - name: Set up QEMU id: qemu uses: docker/setup-qemu-action@v1 - name: Build aarch64 packages uses: RalfG/python-wheels-manylinux-build@v0.3.3-manylinux2014_aarch64 with: python-versions: "cp36-cp36m cp37-cp37m cp38-cp38 cp39-cp39" - name: Upload artifacts uses: actions/upload-artifact@v2 with: name: packages_linux_aarch64 path: | dist/*-manylinux2014_aarch64.whl build-windows: name: Build Windows packages runs-on: windows-latest strategy: matrix: python-version: [3.6, 3.7, 3.8, 3.9] architecture: ['x64', 'x86'] steps: - name: Checkout repos uses: actions/checkout@v2 - name: Set up Python ${{matrix.python-version}} uses: actions/setup-python@v2 with: python-version: ${{matrix.python-version}} architecture: ${{matrix.architecture}} - name: Install Python dependencies shell: cmd run: pip install wheel - name: Build x86_64 packages shell: cmd run: python setup.py bdist_wheel - name: Upload artifacts uses: actions/upload-artifact@v2 with: name: packages_windows path: dist py-setproctitle-version-1.2.2/.github/workflows/test.yml000066400000000000000000000024051400271261500234440ustar00rootroot00000000000000--- name: Tests on: [push] jobs: linux-tests: name: Python ${{matrix.python-version}} tests on Linux runs-on: ubuntu-20.04 strategy: matrix: python-version: ["3.6", "3.7", "3.8", "3.9", "pypy3"] steps: - name: Checkout repos uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: ${{matrix.python-version}} architecture: x64 - name: Install Tox run: pip install tox - name: Run tests run: tox -e ${{matrix.python-version}} -- -vrsx --color=yes windows-tests: name: Python ${{matrix.python-version}} tests on Windows ${{matrix.architecture}} runs-on: windows-latest strategy: matrix: python-version: [3.6, 3.7, 3.8, 3.9] architecture: ['x64', 'x86'] steps: - name: Checkout repos uses: actions/checkout@v2 - name: Set up Python ${{matrix.python-version}} uses: actions/setup-python@v2 with: python-version: ${{matrix.python-version}} architecture: ${{matrix.architecture}} - name: Install Tox run: pip install tox - name: Run tests run: tox -e ${{matrix.python-version}} -- -vrsx --color=yes py-setproctitle-version-1.2.2/.gitignore000066400000000000000000000002721400271261500203350ustar00rootroot00000000000000*.o *.sw[op] *.orig *.pyc *.rej *.html tools/pttest tools/sptdemo tools/prctl_demo tools/ps_status.[ch] build dist py3 tests/pyrun?.? env /setproctitle.egg-info /setproctitle.*.so /.tox py-setproctitle-version-1.2.2/.yamllint.yaml000066400000000000000000000001311400271261500211320ustar00rootroot00000000000000--- extends: default rules: truthy: check-keys: false line-length: max: 85 py-setproctitle-version-1.2.2/COPYRIGHT000066400000000000000000000027141400271261500176430ustar00rootroot00000000000000Copyright (c) 2009-2020, Daniele Varrazzo All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The name of Daniele Varrazzo may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. py-setproctitle-version-1.2.2/HISTORY.rst000066400000000000000000000060721400271261500202440ustar00rootroot00000000000000Releases history ---------------- Version 1.2.2 ------------- - Fixed Windows build (issues #89, #90). - Added wheel packages for Windows (issues #47, #90). - Added wheel packages for aarch64 (issues #95). Version 1.2.1 ------------- - Fixed segfault after ``os.environ.clear()`` (issue #88). Version 1.2 ~~~~~~~~~~~ - added ``getthreadtitle()`` and ``setthreadtitle()``. - Initialisation of the module moved to the first usage: importing the module doesn't cause side effects. - Manage much longer command lines (#52) - Improved build on BSD, dropped ancient versions (issue #67). - Fixed build for Python 3.8 (#66, #72) - Added support for Python 3.9 - Dropped support for Python < 3.6 Version 1.1.10 ~~~~~~~~~~~~~~ - Fixed building with certain ``prctl.h`` implementations (issue #44). - Use ``setuptools`` if available (issue #48). Version 1.1.9 ~~~~~~~~~~~~~ - Fixed build on VC (issues #20, #33). - Added ``MANIFEST.in`` to the source distribution to help with RPM building (issue #30). Version 1.1.8 ~~~~~~~~~~~~~ - Added support for Python "diehard" 2.4 (pull request #3). - Fixed build on Mac OS X 10.9 Maverick (issue #27). Version 1.1.7 ~~~~~~~~~~~~~ - Added PyPy support, courtesy of Ozan Turksever - http://www.logsign.net (pull request #2). Version 1.1.6 ~~~~~~~~~~~~~ - The module can be compiled again on Windows (issue #21). Version 1.1.5 ~~~~~~~~~~~~~ - No module bug, but a packaging issue: files ``README`` and ``HISTORY`` added back into the distribution. Version 1.1.4 ~~~~~~~~~~~~~ - The module works correctly in embedded Python. - ``setproctitle()`` accepts a keyword argument. - Debug output support always compiled in: the variable ``SPT_DEBUG`` can be used to emit debug log. Version 1.1.3 ~~~~~~~~~~~~~ - Don't clobber environ if the variable ``SPT_NOENV`` is set (issue #16). Version 1.1.2 ~~~~~~~~~~~~~ - Find the setproctitle include file on OpenBSD (issue #11). - Skip test with unicode if the file system encoding wouldn't make it pass (issue #13). Version 1.1.1 ~~~~~~~~~~~~~ - Fixed segfault when the module is imported under mod_wsgi (issue #9). Version 1.1 ~~~~~~~~~~~ - The module works correctly with Python 3. Version 1.0.1 ~~~~~~~~~~~~~ - ``setproctitle()`` works even when Python messes up with argv, e.g. when run with the -m option (issue #8). Version 1.0 ~~~~~~~~~~~ No major change since the previous version. The module has been heavily used in production environment without any problem reported, so it's time to declare it stable. Version 0.4 ~~~~~~~~~~~ - Module works on BSD (tested on FreeBSD 7.2). - Module works on Windows. Many thanks to `Develer`_ for providing a neat `GCC package for Windows with Python integration`__ that made the Windows porting painless. .. _Develer: http://www.develer.com/ .. __: http://www.develer.com/oss/GccWinBinaries Version 0.3 ~~~~~~~~~~~ - Module works on Mac OS X 10.2. Reported working on OS X 10.6 too. Version 0.2 ~~~~~~~~~~~ - Added ``prctl()`` call on Linux >= 2.6.9 to update ``/proc/self/status``. Version 0.1 ~~~~~~~~~~~ - Initial public release. py-setproctitle-version-1.2.2/MANIFEST.in000066400000000000000000000002431400271261500201010ustar00rootroot00000000000000include HISTORY.rst include README.rst include COPYRIGHT include MANIFEST.in include Makefile include src/*.c include src/*.h include tests/*.py include tests/*.c py-setproctitle-version-1.2.2/README.rst000066400000000000000000000106101400271261500200310ustar00rootroot00000000000000A Python module to customize the process title ============================================== .. image:: https://github.com/dvarrazzo/py-setproctitle/workflows/Tests/badge.svg :target: https://github.com/dvarrazzo/py-setproctitle/actions?query=workflow%3ATests :alt: Tests :author: Daniele Varrazzo The ``setproctitle`` module allows a process to change its title (as displayed by system tools such as ``ps`` and ``top``). Changing the title is mostly useful in multi-process systems, for example when a master process is forked: changing the children's title allows to identify the task each process is busy with. The technique is used by PostgreSQL_ and the `OpenSSH Server`_ for example. The procedure is hardly portable across different systems. PostgreSQL provides a good `multi-platform implementation`__: this module is a Python wrapper around PostgreSQL code. - `Homepage `__ - `Download `__ - `Bug tracker `__ .. _PostgreSQL: http://www.postgresql.org .. _OpenSSH Server: http://www.openssh.com/ .. __: http://doxygen.postgresql.org/ps__status_8c_source.html Installation ------------ ``setproctitle`` is a C extension: in order to build it you will need a C compiler and the Python development support (the ``python-dev`` or ``python3-dev`` package in most Linux distributions). No further external dependencies are required. You can use ``pip`` to install the module:: pip install setproctitle You can use ``pip -t`` or ``virtualenv`` for local installations, ``sudo pip`` for a system-wide one... the usual stuff. Read pip_ or virtualenv_ docs for all the details. .. _pip: https://pip.readthedocs.org/ .. _virtualenv: https://virtualenv.readthedocs.org/ Usage ----- .. note:: You should import and use the module (even just calling ``getproctitle()``) pretty early in your program lifetime: code writing env vars `may interfere`__ with the module initialisation. .. __: https://github.com/dvarrazzo/py-setproctitle/issues/42 The ``setproctitle`` module exports the following functions: ``setproctitle(title)`` Set *title* as the title for the current process. ``getproctitle()`` Return the current process title. The process title is usually visible in files such as ``/proc/PID/cmdline``, ``/proc/PID/status``, ``/proc/PID/comm``, depending on the operating system and kernel version. These information are used by user-space tools such as ``ps`` and ``top``. ``setthreadtitle(title)`` Set *title* as the title for the current thread. ``getthreadtitle()`` Get the current thread title. The thread title is exposed by some operating systems as the file ``/proc/PID/task/TID/comm``, which is used by certain tools such as ``htop``. Environment variables ~~~~~~~~~~~~~~~~~~~~~ A few environment variables can be used to customize the module behavior: ``SPT_NOENV`` Avoid clobbering ``/proc/PID/environ``. On many platforms, setting the process title will clobber the ``environ`` memory area. ``os.environ`` will work as expected from within the Python process, but the content of the file ``/proc/PID/environ`` will be overwritten. If you require this file not to be broken you can set the ``SPT_NOENV`` environment variable to any non-empty value: in this case the maximum length for the title will be limited to the length of the command line. ``SPT_DEBUG`` Print debug information on ``stderr``. If the module doesn't work as expected you can set this variable to a non-empty value to generate information useful for debugging. Note that the most useful information is printed when the module is imported, not when the functions are called. Module status ------------- The module can be currently compiled and effectively used on the following platforms: - GNU/Linux - BSD - MacOS X - Windows Note that on Windows there is no way to change the process string: what the module does is to create a *Named Object* whose value can be read using a tool such as `Process Explorer`_ (contribution of a more useful tool to be used together with ``setproctitle`` would be well accepted). The module can probably work on HP-UX, but I haven't found any to test with. It is unlikely that it can work on Solaris instead. .. _Process Explorer: http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx py-setproctitle-version-1.2.2/pyproject.toml000066400000000000000000000000361400271261500212570ustar00rootroot00000000000000[tool.black] line-length = 79 py-setproctitle-version-1.2.2/setup.py000066400000000000000000000053211400271261500200570ustar00rootroot00000000000000#!/usr/bin/env python """ setproctitle setup script. Copyright (c) 2009-2020 Daniele Varrazzo """ import sys try: from setuptools import setup, Extension except ImportError: from distutils.core import setup, Extension VERSION = "1.2.2" define_macros = {} define_macros["SPT_VERSION"] = VERSION if sys.platform.startswith("linux"): define_macros["HAVE_SYS_PRCTL_H"] = 1 elif sys.platform == "darwin": # __darwin__ symbol is not defined; __APPLE__ is instead. define_macros["__darwin__"] = 1 elif "bsd" in sys.platform: # OMG, how many of them are? define_macros["BSD"] = 1 define_macros["HAVE_SETPROCTITLE"] = 1 define_macros["HAVE_PS_STRING"] = 1 # NOTE: the module may work on HP-UX using pstat # thus setting define_macros['HAVE_SYS_PSTAT_H'] # see http://www.noc.utoronto.ca/~mikep/unix/HPTRICKS # But I have none handy to test with. mod_spt = Extension( "setproctitle", define_macros=list(define_macros.items()), sources=[ "src/setproctitle.c", "src/spt_debug.c", "src/spt_setup.c", "src/spt_status.c", "src/spt_strlcpy.c", ], ) # patch distutils if it can't cope with the "classifiers" or # "download_url" keywords if sys.version < "2.2.3": from distutils.dist import DistributionMetadata DistributionMetadata.classifiers = None DistributionMetadata.download_url = None # Try to include the long description in the setup kwargs = {} try: kwargs["long_description"] = ( open("README.rst").read() + "\n" + open("HISTORY.rst").read() ) kwargs["long_description_content_type"] = "text/x-rst" except Exception: pass classifiers = """\ Development Status :: 5 - Production/Stable Intended Audience :: Developers License :: OSI Approved :: BSD License Programming Language :: C Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Operating System :: POSIX :: Linux Operating System :: POSIX :: BSD Operating System :: MacOS :: MacOS X Operating System :: Microsoft :: Windows Topic :: Software Development """.splitlines() setup( name="setproctitle", description="A Python module to customize the process title", version=VERSION, author="Daniele Varrazzo", author_email="daniele.varrazzo@gmail.com", url="https://github.com/dvarrazzo/py-setproctitle", download_url="http://pypi.python.org/pypi/setproctitle/", license="BSD", platforms=["GNU/Linux", "BSD", "MacOS X", "Windows"], python_requires=">=3.6", classifiers=classifiers, ext_modules=[mod_spt], extras_require={"test": ["pytest>=6.1,<6.2"]}, **kwargs ) py-setproctitle-version-1.2.2/src/000077500000000000000000000000001400271261500171335ustar00rootroot00000000000000py-setproctitle-version-1.2.2/src/c.h000066400000000000000000000014611400271261500175300ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * c.h * A few fundamental C definitions. * * Copyright (c) 2009-2020 Daniele Varrazzo *------------------------------------------------------------------------- */ #ifndef C_H #define C_H #include "spt_config.h" #ifndef __cplusplus #ifndef bool typedef char bool; #endif #ifndef true #define true ((bool) 1) #endif #ifndef false #define false ((bool) 0) #endif #endif /* not C++ */ #include /* Let's use our version of strlcpy to avoid portability problems */ size_t spt_strlcpy(char *dst, const char *src, size_t siz); /* VC defines _WIN32, not WIN32 */ #ifdef _WIN32 #ifndef WIN32 #define WIN32 _WIN32 #endif #endif #ifdef WIN32 #include #endif #endif /* C_H */ py-setproctitle-version-1.2.2/src/setproctitle.c000066400000000000000000000075401400271261500220260ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * setproctitle.c * Python extension module to update and read the process title. * * Copyright (c) 2009-2020 Daniele Varrazzo * * The module allows Python code to access the functions get_ps_display() * and set_ps_display(). * *------------------------------------------------------------------------- */ #include "spt.h" #include "spt_setup.h" #include "spt_status.h" #ifndef SPT_VERSION #define SPT_VERSION unknown #endif /* macro trick to stringify a macro expansion */ #define xstr(s) str(s) #define str(s) #s /* ----------------------------------------------------- */ static PyObject *spt_version; static char spt_setproctitle__doc__[] = "setproctitle(title) -- Change the process title." ; static PyObject * spt_setproctitle(PyObject *self, PyObject *args, PyObject *kwargs) { const char *title = NULL; static char *kwlist[] = {"title", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &title)) return NULL; /* Initialize the process title */ if (0 <= spt_setup()) { set_ps_display(title, true); } else { spt_debug("failed to initialize setproctitle"); } Py_RETURN_NONE; } static char spt_getproctitle__doc__[] = "getproctitle() -- Get the current process title." ; static PyObject * spt_getproctitle(PyObject *self, PyObject *args) { size_t tlen; const char *title; spt_setup(); title = get_ps_display(&tlen); return Py_BuildValue("s#", title, (int)tlen); } static char spt_setthreadtitle__doc__[] = "setthreadtitle(title) -- Change the thread title." ; static PyObject * spt_setthreadtitle(PyObject *self, PyObject *args, PyObject *kwargs) { const char *title = NULL; static char *kwlist[] = {"title", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &title)) return NULL; set_thread_title(title); Py_RETURN_NONE; } static char spt_getthreadtitle__doc__[] = "getthreadtitle() -- Return the thread title." ; static PyObject * spt_getthreadtitle(PyObject *self, PyObject *args) { char title[16] = {'\0'}; get_thread_title(title); return Py_BuildValue("s", title); } /* List of methods defined in the module */ static struct PyMethodDef spt_methods[] = { {"setproctitle", (PyCFunction)spt_setproctitle, METH_VARARGS|METH_KEYWORDS, spt_setproctitle__doc__}, {"getproctitle", (PyCFunction)spt_getproctitle, METH_NOARGS, spt_getproctitle__doc__}, {"setthreadtitle", (PyCFunction)spt_setthreadtitle, METH_VARARGS|METH_KEYWORDS, spt_setthreadtitle__doc__}, {"getthreadtitle", (PyCFunction)spt_getthreadtitle, METH_NOARGS, spt_getthreadtitle__doc__}, {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ }; /* Initialization function for the module (*must* be called initsetproctitle) */ static char setproctitle_module_documentation[] = "Allow customization of the process title." ; #ifdef IS_PY3K static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "setproctitle", setproctitle_module_documentation, -1, spt_methods, NULL, NULL, NULL, NULL }; #endif PyMODINIT_FUNC INIT_MODULE(setproctitle)(void) { PyObject *m, *d; spt_debug("module init"); /* Create the module and add the functions */ #ifdef IS_PY3K m = PyModule_Create(&moduledef); #else m = Py_InitModule3("setproctitle", spt_methods, setproctitle_module_documentation); #endif if (m == NULL) { goto exit; } /* Add version string to the module*/ d = PyModule_GetDict(m); spt_version = Py_BuildValue("s", xstr(SPT_VERSION)); PyDict_SetItemString(d, "__version__", spt_version); exit: #ifdef IS_PY3K return m; #else return; #endif } py-setproctitle-version-1.2.2/src/spt.h000066400000000000000000000007501400271261500201140ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * spt.h * Definitions useful throughout all the extension. * * Copyright (c) 2010-2020 Daniele Varrazzo * *------------------------------------------------------------------------- */ #ifndef SPT_H #define SPT_H #include "spt_config.h" #include "spt_python.h" /* expose the debug function to the extension code */ HIDDEN void spt_debug(const char *fmt, ...); #endif py-setproctitle-version-1.2.2/src/spt_config.h000066400000000000000000000012521400271261500214370ustar00rootroot00000000000000/* Stub file: should be created in configuration phase */ /* This configuration was taken from an Ubuntu i386 installation. */ /* Define to 1 if you have the `setproctitle' function. */ /* #undef HAVE_SETPROCTITLE */ /* Define to 1 if the PS_STRINGS thing exists. */ /* #undef HAVE_PS_STRINGS */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_PSTAT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_PRCTL_H */ /* GCC 4.0 and later have support for specifying symbol visibility */ #if __GNUC__ >= 4 && !defined(__MINGW32__) # define HIDDEN __attribute__((visibility("hidden"))) #else # define HIDDEN #endif py-setproctitle-version-1.2.2/src/spt_debug.c000066400000000000000000000016631400271261500212610ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * spt_python.c * A simple function for the module debugging. * * Copyright (c) 2009-2020 Daniele Varrazzo * * Debug logging is enabled if the environment variable SPT_DEBUG is set to a * non-empty value at runtime. * *------------------------------------------------------------------------- */ #include #include #include #include "spt_config.h" HIDDEN void spt_debug(const char *fmt, ...) { static int enabled = -1; va_list ap; /* check if debug is enabled */ if (-1 == enabled) { char *d = getenv("SPT_DEBUG"); enabled = (d && *d) ? 1 : 0; } /* bail out if debug is not enabled */ if (0 == enabled) { return; } fprintf(stderr, "[SPT]: "); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); } py-setproctitle-version-1.2.2/src/spt_python.h000066400000000000000000000025031400271261500215130ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * spt_python.h * Include and customize Python definitions. * * Copyright (c) 2010-2020 Daniele Varrazzo * *------------------------------------------------------------------------- */ #ifndef SPT_PYTHON_H #define SPT_PYTHON_H #define PY_SSIZE_T_CLEAN #include /* Things change a lot here... */ #if PY_MAJOR_VERSION >= 3 #define IS_PY3K #endif /* Detect pypy */ #ifdef PYPY_VERSION #define IS_PYPY #endif /* The type returned by Py_GetArgcArgv */ #ifdef IS_PY3K typedef wchar_t argv_t; #else typedef char argv_t; #endif /* defined in Modules/main.c but not publically declared */ void Py_GetArgcArgv(int *argc, argv_t ***argv); /* Mangle the module name into the name of the module init function */ #ifdef IS_PY3K #define INIT_MODULE(m) PyInit_ ## m #else #define INIT_MODULE(m) init ## m #endif /* Py2/3 compatibility layer */ #ifdef IS_PY3K #define PyInt_AsLong PyLong_AsLong #define Bytes_Size PyBytes_Size #define Bytes_AsString PyBytes_AsString #else /* Python 2 */ #define Bytes_Size PyString_Size #define Bytes_AsString PyString_AsString #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) typedef int Py_ssize_t; #endif #endif /* IS_PY3K > 2 */ #endif /* SPT_PYTHON_H */ py-setproctitle-version-1.2.2/src/spt_setup.c000066400000000000000000000305361400271261500213340ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * spt_setup.c * Initalization code for the spt_status.c module functions. * * Copyright (c) 2009-2020 Daniele Varrazzo * *------------------------------------------------------------------------- */ #include "spt_setup.h" #include "spt.h" #include "spt_status.h" #include /* Darwin doesn't export environ */ #if defined(__darwin__) #include #define environ (*_NSGetEnviron()) #elif !defined(_WIN32) extern char **environ; #endif #ifndef WIN32 /* I don't expect it to be defined: should include limits.h. But then it's * another of those ./configure can of worms to find where it is... */ #ifndef ARG_MAX #define ARG_MAX (96 * 1024) #endif /* Return a concatenated version of a strings vector. * * Return newly allocated heap space: clean it up with free(). * * Return NULL and raise an exception on error. */ static char * join_argv(int argc, char **argv) { int i; size_t len = 0; char *buf; char *src; char *dest; /* Calculate the final string length */ for (i = 0; i < argc; i++) { len += strlen(argv[i]) + 1; } if (!(dest = buf = (char *)malloc(len))) { PyErr_NoMemory(); return NULL; } /* Copy the strings in the buffer joining with spaces */ for (i = 0; i < argc; i++) { src = argv[i]; while (*src) { *dest++ = *src++; } *dest++ = ' '; } *--dest = '\x00'; return buf; } #ifdef IS_PY3K /* Return a copy of argv[0] encoded in the default encoding. * * Return a newly allocated buffer to be released with free(). * * Return NULL in case of error. If the error shouldn't be ignored, also set * a Python exception. */ static char * get_encoded_arg0(wchar_t *argv0) { PyObject *ua = NULL, *ba = NULL; char *rv = NULL; if (!(ua = PyUnicode_FromWideChar(argv0, -1))) { spt_debug("failed to convert argv[0] to unicode"); PyErr_Clear(); goto exit; } if (!(ba = PyUnicode_AsEncodedString( ua, PyUnicode_GetDefaultEncoding(), "strict"))) { spt_debug("failed to encode argv[0]"); PyErr_Clear(); goto exit; } if (!(rv = strdup(PyBytes_AsString(ba)))) { PyErr_NoMemory(); } exit: Py_XDECREF(ua); Py_XDECREF(ba); return rv; } #else /* !IS_PY3K */ /* Return a copy of argv referring to the original arg area. * * python -m messes up with arg (issue #8): ensure to have a vector to the * original args or save_ps_display_args() will stop processing too soon. * * Return a buffer allocated with malloc: should be cleaned up with free(). * * Return NULL in case of error. If the error shouldn't be ignored, also set * a Python exception. */ static char ** fix_argv(int argc, char **argv) { char **buf = NULL; int i; char *ptr = argv[0]; if (!(buf = (char **)malloc(argc * sizeof(char *)))) { PyErr_NoMemory(); return NULL; } for (i = 0; i < argc; ++i) { buf[i] = ptr; ptr += strlen(ptr) + 1; } return buf; } #endif /* IS_PY3K */ /* Find the original arg buffer starting from the env position. * * Return a malloc'd argv vector, pointing to the original arguments. * * Return NULL in case of error. If the error shouldn't be ignored, also set * a Python exception. * * Required on Python 3 as Py_GetArgcArgv doesn't return pointers to the * original area. It can be used on Python 2 too in case we can't get argv, * such as in embedded environment. */ static char ** find_argv_from_env(int argc, char *arg0) { int i; char **buf = NULL; char **rv = NULL; char *ptr; char *limit; spt_debug("walking from environ to look for the arguments"); if (!(buf = (char **)malloc((argc + 1) * sizeof(char *)))) { spt_debug("can't malloc %d args!", argc); PyErr_NoMemory(); goto exit; } buf[argc] = NULL; /* Walk back from environ until you find argc-1 null-terminated strings. * Don't look for argv[0] as it's probably not preceded by 0. */ ptr = environ[0]; if (!ptr) { /* It happens on os.environ.clear() */ spt_debug("environ pointer is NULL"); goto exit; } spt_debug("found environ at %p", ptr); limit = ptr - ARG_MAX; --ptr; for (i = argc - 1; i >= 1; --i) { if (*ptr) { spt_debug("zero %d not found", i); goto exit; } --ptr; while (*ptr && ptr > limit) { --ptr; } if (ptr <= limit) { spt_debug("failed to found arg %d start", i); goto exit; } buf[i] = (ptr + 1); spt_debug("found argv[%d] at %p: %s", i, buf[i], buf[i]); } /* The first arg has not a zero in front. But what we have is reliable * enough (modulo its encoding). Check if it is exactly what found. * * The check is known to fail on OS X with locale C if there are * non-ascii characters in the executable path. See Python issue #9167 */ ptr -= strlen(arg0); spt_debug("argv[0] should be at %p", ptr); if (ptr <= limit) { spt_debug("failed to found argv[0] start"); goto exit; } if (strcmp(ptr, arg0)) { spt_debug("argv[0] doesn't match '%s'", arg0); goto exit; } /* We have all the pieces of the jigsaw. */ buf[0] = ptr; spt_debug("found argv[0]: %s", buf[0]); rv = buf; buf = NULL; exit: if (buf) { free(buf); } return rv; } #ifdef IS_PY3K /* Come on, why is this missing?! this is just cruel! * I guess you club seal pups for hobby. */ PyObject * PyFile_FromString(const char *filename, const char *mode) { PyObject *io = NULL; PyObject *rv = NULL; if (!(io = PyImport_ImportModule("io"))) { spt_debug("failed to import io"); goto exit; } rv = PyObject_CallMethod(io, "open", "ss", filename, mode); exit: Py_XDECREF(io); return rv; } #endif /* IS_PY3K */ /* Read the number of arguments and the first argument from /proc/pid/cmdline * * Return 0 if found, else -1. Return arg0 in a malloc'd array. * * If the function fails in a way that shouldn't be ignored, also set * a Python exception. */ static int get_args_from_proc(int *argc_o, char **arg0_o) { /* allow /proc/PID/cmdline, with oversize max_pid, and them some. */ #define FNLEN 30 char fn[FNLEN]; PyObject *os = NULL; PyObject *pid_py = NULL; long pid; PyObject *f = NULL; PyObject *cl = NULL; PyObject *tmp = NULL; int rv = -1; spt_debug("looking for args into proc fs"); /* get the pid from os.getpid() */ if (!(os = PyImport_ImportModule("os"))) { spt_debug("failed to import os"); goto exit; } if (!(pid_py = PyObject_CallMethod(os, "getpid", NULL))) { spt_debug("calling os.getpid() failed"); /* os.getpid() may be not available, so ignore this error. */ PyErr_Clear(); goto exit; } if (-1 == (pid = PyInt_AsLong(pid_py))) { spt_debug("os.getpid() returned crap?"); /* Don't bother to check PyErr_Occurred as pid can't just be -1. */ goto exit; } /* get the content of /proc/PID/cmdline */ snprintf(fn, FNLEN, "/proc/%ld/cmdline", pid); if (!(f = PyFile_FromString(fn, "rb"))) { spt_debug("opening '%s' failed", fn); /* That's ok: procfs is easily not available on menomated unices */ PyErr_Clear(); goto exit; } /* the file has been open in binary mode, so we get bytes */ cl = PyObject_CallMethod(f, "read", NULL); if (!(tmp = PyObject_CallMethod(f, "close", NULL))) { spt_debug("closing failed"); } else { Py_DECREF(tmp); } if (!cl) { spt_debug("reading failed"); /* could there be some protected environment where a process cannot * read its own pid? Who knows, better not to risk. */ PyErr_Clear(); goto exit; } /* the cmdline is a buffer of null-terminated strings. We can strdup it to * get a copy of arg0, and count the zeros to get argc */ { char *ccl; Py_ssize_t i; if (!(ccl = Bytes_AsString(cl))) { spt_debug("failed to get cmdline string"); goto exit; } if (!(*arg0_o = strdup(ccl))) { spt_debug("arg0 strdup failed"); PyErr_NoMemory(); goto exit; } spt_debug("got argv[0] = '%s' from /proc", *arg0_o); *argc_o = 0; for (i = Bytes_Size(cl) - 1; i >= 0; --i) { if (ccl[i] == '\0') { (*argc_o)++; } } spt_debug("got argc = %d from /proc", *argc_o); } /* success */ rv = 0; exit: Py_XDECREF(cl); Py_XDECREF(f); Py_XDECREF(pid_py); Py_XDECREF(os); return rv; } /* Find the original arg buffer, return 0 if found, else -1. * * If found, set argc to the number of arguments, argv to an array * of pointers to the single arguments. The array is allocated via malloc. * * If the function fails in a way that shouldn't be ignored, also set * a Python exception. * * The function overcomes three Py_GetArgcArgv shortcomings: * - some python parameters mess up with the original argv, e.g. -m * (see issue #8) * - with Python 3, argv is a decoded copy and doesn't point to * the original area. * - If python is embedded, the function doesn't return anything. */ static int get_argc_argv(int *argc_o, char ***argv_o) { int argc = 0; argv_t **argv_py = NULL; char **argv = NULL; char *arg0 = NULL; int rv = -1; #ifndef IS_PYPY spt_debug("reading argc/argv from Python main"); Py_GetArgcArgv(&argc, &argv_py); #endif if (argc > 0) { spt_debug("found %d arguments", argc); #ifdef IS_PY3K if (!(arg0 = get_encoded_arg0(argv_py[0]))) { spt_debug("couldn't get a copy of argv[0]"); goto exit; } #else if (!(argv = fix_argv(argc, (char **)argv_py))) { spt_debug("failed to fix argv"); goto exit; } #endif /* we got argv: on py2 it points to the right place in memory; on py3 * we only got a copy of argv[0]: we will use it to look from environ */ } else { spt_debug("no good news from Py_GetArgcArgv"); /* get a copy of argv[0] from /proc, so we get back in the same * situation of Py3 */ if (0 > get_args_from_proc(&argc, &arg0)) { spt_debug("failed to get args from proc fs"); goto exit; } } /* If we don't know argv but we know the content of argv[0], we can walk * backwards from environ and see if we get it. */ if (arg0 && !argv) { if (!(argv = find_argv_from_env(argc, arg0))) { spt_debug("couldn't find argv from environ"); goto exit; } } /* success */ *argc_o = argc; *argv_o = argv; argv = NULL; rv = 0; exit: if (arg0) { free(arg0); } if (argv) { free(argv); } return rv; } #endif /* !WIN32 */ /* Initialize the module internal functions. * * The function reproduces the initialization performed by PostgreSQL * to be able to call the functions in pg_status.c * * Return 0 in case of success, else -1. In case of failure with an error that * shouldn't be ignored, also set a Python exception. * * The function should be called only once in the process lifetime. * so is called at module initialization. After the function is called, * set_ps_display() can be used. */ int spt_setup(void) { const int not_happened = 3; static int rv = 3; /* Make sure setup happens just once, either successful or failed */ if (rv != not_happened) { return rv; } rv = -1; #ifndef WIN32 int argc = 0; char **argv = NULL; char *init_title; if (0 > get_argc_argv(&argc, &argv)) { spt_debug("get_argc_argv failed"); goto exit; } save_ps_display_args(argc, argv); /* Set up the first title to fully initialize the code */ if (!(init_title = join_argv(argc, argv))) { goto exit; } init_ps_display(init_title); free(init_title); #else /* On Windows save_ps_display_args is a no-op * This is a good news, because Py_GetArgcArgv seems not usable. */ LPTSTR init_title = GetCommandLine(); init_ps_display(init_title); #endif rv = 0; exit: return rv; } py-setproctitle-version-1.2.2/src/spt_setup.h000066400000000000000000000006441400271261500213360ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * spt_setup.h * Initalization code for the spt_status.c module functions. * * Copyright (c) 2009-2020 Daniele Varrazzo * *------------------------------------------------------------------------- */ #ifndef SPT_SETUP_H #define SPT_SETUP_H #include "spt_config.h" HIDDEN int spt_setup(void); #endif py-setproctitle-version-1.2.2/src/spt_status.c000066400000000000000000000315231400271261500215140ustar00rootroot00000000000000/*-------------------------------------------------------------------- * spt_status.c * * Routines to support changing the ps display of a process. * Mechanism differs wildly across platforms. * * Copyright (c) 2000-2009, PostgreSQL Global Development Group * Copyright (c) 2009-2020 Daniele Varrazzo * various details abducted from various places * * This file was taken from PostgreSQL. The PostgreSQL copyright terms follow. *-------------------------------------------------------------------- */ /* * PostgreSQL Database Management System * (formerly known as Postgres, then as Postgres95) * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * * Portions Copyright (c) 1994, The Regents of the University of California * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without a written agreement * is hereby granted, provided that the above copyright notice and this * paragraph and the following two paragraphs appear in all copies. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ #include "spt_config.h" /* note: VC doesn't have this, but it was working on mingw instead * so check on _WIN32 (defined by VC) instead of WIN32 */ #ifndef _WIN32 #include #endif #ifdef HAVE_SYS_PSTAT_H #include /* for HP-UX */ #endif #ifdef HAVE_PS_STRINGS #include /* for old BSD */ #include #endif #ifdef HAVE_SYS_PRCTL_H #include /* for Linux >= 2.6.9 */ #endif #if defined(__darwin__) #include #endif #include "spt_status.h" #include #include #include /* Darwin doesn't export environ */ #if defined(__darwin__) #define environ (*_NSGetEnviron()) #else extern char **environ; #endif bool update_process_title = true; /* * Alternative ways of updating ps display: * * PS_USE_SETPROCTITLE * use the function setproctitle(const char *, ...) * (newer BSD systems) * PS_USE_PSTAT * use the pstat(PSTAT_SETCMD, ) * (HPUX) * PS_USE_PS_STRINGS * assign PS_STRINGS->ps_argvstr = "string" * (some BSD systems) * PS_USE_CHANGE_ARGV * assign argv[0] = "string" * (some other BSD systems) * PS_USE_PRCTL * use prctl(PR_SET_NAME, ) * (Linux >= 2.6.9) * PS_USE_CLOBBER_ARGV * write over the argv and environment area * (most SysV-like systems) * PS_USE_WIN32 * push the string out as the name of a Windows event * PS_USE_NONE * don't update ps display * (This is the default, as it is safest.) */ #if defined(HAVE_SETPROCTITLE) #define PS_USE_SETPROCTITLE #elif defined(HAVE_PSTAT) && defined(PSTAT_SETCMD) #define PS_USE_PSTAT #elif defined(HAVE_PS_STRINGS) #define PS_USE_PS_STRINGS #elif (defined(BSD) || defined(__bsdi__) || defined(__hurd__)) && !defined(__darwin__) #define PS_USE_CHANGE_ARGV #elif defined(__linux__) || defined(_AIX) || defined(__sgi) || (defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__ksr__) || defined(__osf__) || defined(__svr4__) || defined(__svr5__) || defined(__darwin__) #define PS_USE_CLOBBER_ARGV #elif defined(WIN32) #define PS_USE_WIN32 #else #define PS_USE_NONE #endif /* we use this strategy together with another one (probably PS_USE_CLOBBER_ARGV) */ #if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_NAME) && !defined(PS_USE_NONE) #define PS_USE_PRCTL #endif /* Different systems want the buffer padded differently */ #if defined(_AIX) || defined(__linux__) || defined(__svr4__) || defined(__darwin__) #define PS_PADDING '\0' #else #define PS_PADDING ' ' #endif #ifndef PS_USE_CLOBBER_ARGV /* all but one options need a buffer to write their ps line in */ #define PS_BUFFER_SIZE 256 static char ps_buffer[PS_BUFFER_SIZE]; static const size_t ps_buffer_size = PS_BUFFER_SIZE; #else /* PS_USE_CLOBBER_ARGV */ static char *ps_buffer; /* will point to argv area */ static size_t ps_buffer_size; /* space determined at run time */ static size_t last_status_len; /* use to minimize length of clobber */ #endif /* PS_USE_CLOBBER_ARGV */ static size_t ps_buffer_fixed_size; /* size of the constant prefix */ /* save the original argv[] location here */ static int save_argc; static char **save_argv; /* * Call this early in startup to save the original argc/argv values. * If needed, we make a copy of the original argv[] array to preserve it * from being clobbered by subsequent ps_display actions. * * (The original argv[] will not be overwritten by this routine, but may be * overwritten during init_ps_display. Also, the physical location of the * environment strings may be moved, so this should be called before any code * that might try to hang onto a getenv() result.) */ char ** save_ps_display_args(int argc, char **argv) { save_argc = argc; save_argv = argv; #if defined(PS_USE_CLOBBER_ARGV) /* * If we're going to overwrite the argv area, count the available space. * Also move the environment to make additional room. */ { char *end_of_area = NULL; char **new_environ; int i; /* * check for contiguous argv strings */ for (i = 0; i < argc; i++) { if (i == 0 || end_of_area + 1 == argv[i]) end_of_area = argv[i] + strlen(argv[i]); } if (end_of_area == NULL) /* probably can't happen? */ { ps_buffer = NULL; ps_buffer_size = 0; return argv; } { /* * Clobbering environ works fine from within the process, but some * external utils use /proc/PID/environ and they would find noting, * or mess, if we clobber it. An user can define SPT_NOENV to limit * clobbering to argv (see ticket #16). */ char *noenv; noenv = getenv("SPT_NOENV"); if (!noenv || !*noenv) { /* * check for contiguous environ strings following argv */ for (i = 0; environ[i] != NULL; i++) { if (end_of_area + 1 == environ[i]) end_of_area = environ[i] + strlen(environ[i]); } /* * move the environment out of the way */ new_environ = (char **) malloc((i + 1) * sizeof(char *)); for (i = 0; environ[i] != NULL; i++) new_environ[i] = strdup(environ[i]); new_environ[i] = NULL; environ = new_environ; } } ps_buffer = argv[0]; last_status_len = ps_buffer_size = end_of_area - argv[0]; } #endif /* PS_USE_CLOBBER_ARGV */ #if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV) /* * If we're going to change the original argv[] then make a copy for * argument parsing purposes. * * (NB: do NOT think to remove the copying of argv[], even though * postmaster.c finishes looking at argv[] long before we ever consider * changing the ps display. On some platforms, getopt() keeps pointers * into the argv array, and will get horribly confused when it is * re-called to analyze a subprocess' argument string if the argv storage * has been clobbered meanwhile. Other platforms have other dependencies * on argv[]. */ { char **new_argv; int i; new_argv = (char **) malloc((argc + 1) * sizeof(char *)); for (i = 0; i < argc; i++) new_argv[i] = strdup(argv[i]); new_argv[argc] = NULL; #if defined(__darwin__) /* * Darwin (and perhaps other NeXT-derived platforms?) has a static * copy of the argv pointer, which we may fix like so: */ *_NSGetArgv() = new_argv; #endif argv = new_argv; } #endif /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */ return argv; } /* * Call this once during subprocess startup to set the identification * values. At this point, the original argv[] array may be overwritten. */ void init_ps_display(const char *initial_str) { #ifndef PS_USE_NONE /* no ps display if you didn't call save_ps_display_args() */ if (!save_argv) return; #ifdef PS_USE_CLOBBER_ARGV /* If ps_buffer is a pointer, it might still be null */ if (!ps_buffer) return; #endif /* * Overwrite argv[] to point at appropriate space, if needed */ #ifdef PS_USE_CHANGE_ARGV save_argv[0] = ps_buffer; save_argv[1] = NULL; #endif /* PS_USE_CHANGE_ARGV */ #ifdef PS_USE_CLOBBER_ARGV { int i; /* make extra argv slots point at end_of_area (a NUL) */ for (i = 1; i < save_argc; i++) save_argv[i] = ps_buffer + ps_buffer_size; } #endif /* PS_USE_CLOBBER_ARGV */ /* * Make fixed prefix of ps display. */ ps_buffer[0] = '\0'; ps_buffer_fixed_size = strlen(ps_buffer); set_ps_display(initial_str, true); #endif /* not PS_USE_NONE */ } /* * Call this to update the ps status display to a fixed prefix plus an * indication of what you're currently doing passed in the argument. */ void set_ps_display(const char *activity, bool force) { if (!force && !update_process_title) return; #ifndef PS_USE_NONE #ifdef PS_USE_CLOBBER_ARGV /* If ps_buffer is a pointer, it might still be null */ if (!ps_buffer) return; #endif /* Update ps_buffer to contain both fixed part and activity */ spt_strlcpy(ps_buffer + ps_buffer_fixed_size, activity, ps_buffer_size - ps_buffer_fixed_size); /* Transmit new setting to kernel, if necessary */ #ifdef PS_USE_SETPROCTITLE setproctitle("%s", ps_buffer); #endif #ifdef PS_USE_PSTAT { union pstun pst; pst.pst_command = ps_buffer; pstat(PSTAT_SETCMD, pst, strlen(ps_buffer), 0, 0); } #endif /* PS_USE_PSTAT */ #ifdef PS_USE_PS_STRINGS PS_STRINGS->ps_nargvstr = 1; PS_STRINGS->ps_argvstr = ps_buffer; #endif /* PS_USE_PS_STRINGS */ #ifdef PS_USE_CLOBBER_ARGV { size_t buflen; /* pad unused memory */ buflen = strlen(ps_buffer); /* clobber remainder of old status string */ if (last_status_len > buflen) memset(ps_buffer + buflen, PS_PADDING, last_status_len - buflen); last_status_len = buflen; } #endif /* PS_USE_CLOBBER_ARGV */ #ifdef PS_USE_PRCTL prctl(PR_SET_NAME, ps_buffer); #endif #ifdef PS_USE_WIN32 { /* * Win32 does not support showing any changed arguments. To make it at * all possible to track which backend is doing what, we create a * named object that can be viewed with for example Process Explorer. */ static HANDLE ident_handle = INVALID_HANDLE_VALUE; char name[PS_BUFFER_SIZE + 32]; if (ident_handle != INVALID_HANDLE_VALUE) CloseHandle(ident_handle); sprintf(name, "python(%d): %s", _getpid(), ps_buffer); ident_handle = CreateEvent(NULL, TRUE, FALSE, name); } #endif /* PS_USE_WIN32 */ #endif /* not PS_USE_NONE */ } /* * Returns what's currently in the ps display, in case someone needs * it. Note that only the activity part is returned. On some platforms * the string will not be null-terminated, so return the effective * length into *displen. */ const char * get_ps_display(size_t *displen) { #ifdef PS_USE_CLOBBER_ARGV size_t offset; /* If ps_buffer is a pointer, it might still be null */ if (!ps_buffer) { *displen = 0; return ""; } /* Remove any trailing spaces to offset the effect of PS_PADDING */ offset = ps_buffer_size; while (offset > ps_buffer_fixed_size && ps_buffer[offset - 1] == PS_PADDING) offset--; *displen = offset - ps_buffer_fixed_size; #else *displen = strlen(ps_buffer + ps_buffer_fixed_size); #endif return ps_buffer + ps_buffer_fixed_size; } void set_thread_title(const char *title) { #ifdef PS_USE_PRCTL prctl(PR_SET_NAME, title); #endif } void get_thread_title(char *title) { #ifdef PS_USE_PRCTL prctl(PR_GET_NAME, title); #endif } py-setproctitle-version-1.2.2/src/spt_status.h000066400000000000000000000013101400271261500215100ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * spt_status.h * * Declarations for spt_status.c * *------------------------------------------------------------------------- */ #ifndef SPT_STATUS_H #define SPT_STATUS_H #include "c.h" HIDDEN extern bool update_process_title; HIDDEN extern char **save_ps_display_args(int argc, char **argv); HIDDEN extern void init_ps_display(const char *initial_str); HIDDEN extern void set_ps_display(const char *activity, bool force); HIDDEN extern const char *get_ps_display(size_t *displen); HIDDEN extern void set_thread_title(const char *title); HIDDEN extern void get_thread_title(char *title); #endif /* SPT_STATUS_H */ py-setproctitle-version-1.2.2/src/spt_strlcpy.c000066400000000000000000000041351400271261500216700ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * strlcpy.c * strncpy done right * * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * * * IDENTIFICATION * $PostgreSQL: pgsql/src/port/strlcpy.c,v 1.4 2007/01/05 22:20:03 momjian Exp $ * * This file was taken from OpenBSD and is used on platforms that don't * provide strlcpy(). The OpenBSD copyright terms follow. *------------------------------------------------------------------------- */ /* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "c.h" /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. * Function creation history: http://www.gratisoft.us/todd/papers/strlcpy.html */ size_t spt_strlcpy(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0) { while (--n != 0) { if ((*d++ = *s++) == '\0') break; } } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return (s - src - 1); /* count does not include NUL */ } py-setproctitle-version-1.2.2/tests/000077500000000000000000000000001400271261500175065ustar00rootroot00000000000000py-setproctitle-version-1.2.2/tests/__init__.py000066400000000000000000000000001400271261500216050ustar00rootroot00000000000000py-setproctitle-version-1.2.2/tests/conftest.py000066400000000000000000000062701400271261500217120ustar00rootroot00000000000000import os import sys import subprocess as sp import pytest def pytest_configure(config): config.addinivalue_line( "markers", "embedded: the test create an embedded executable" ) @pytest.fixture(scope="session") def pyrun(pyconfig): """ Build the pyrun executable and return its path """ # poor man's make here = os.path.abspath(os.path.dirname(__file__)) ver2 = "%s.%s" % sys.version_info[:2] source = os.path.join(here, "pyrun.c") target = os.path.join(here, f"pyrun{ver2}") if ( os.path.exists(target) and os.stat(target).st_mtime > os.stat(source).st_mtime ): return target cmdline = ["cc"] # big punt cmdline.extend(pyconfig("includes")) cmdline.extend(["-o", target, source]) cmdline.extend(pyconfig("ldflags")) cmdline.append(f"-L{pyconfig('prefix')[0]}/lib") sp.check_call(cmdline) return target @pytest.fixture(scope="session") def pyconfig(): """Return the result of 'python-config --opt' as a list of strings""" pyexe = os.path.realpath(sys.executable) ver2 = "%s.%s" % sys.version_info[:2] for name in (f"python{ver2}-config", "python3-config", "python-config"): pyconfexe = os.path.join(os.path.dirname(pyexe), name) if os.path.exists(pyconfexe): break else: pytest.fail( f"can't find python-config from executable {sys.executable}" ) # Travis' Python 3.8 is not built with --embed help = sp.check_output([pyconfexe, "--help"]) has_embed = b"--embed" in help def pyconfig_func(opt): cmdline = [pyconfexe, f"--{opt}"] if has_embed: cmdline.append("--embed") bout = sp.check_output(cmdline) out = bout.decode( sys.getfilesystemencoding() # sounds like a good bet ) return out.split() return pyconfig_func @pytest.fixture(scope="session") def spt_directory(): """ Where is the setproctitle module installed? """ rv = run_script( """ import os import setproctitle print(os.path.dirname(setproctitle.__file__)) """ ) return rv.rstrip() @pytest.fixture(scope="function") def tmp_pypath(monkeypatch, tmp_path): """ return a tmp directory which has been added to the python path """ monkeypatch.setenv( "PYTHONPATH", str(tmp_path) + os.pathsep + os.environ.get("PYTHONPATH", ""), ) return tmp_path def run_script(script=None, args=None, executable=None, env=None): """run a script in a separate process. if the script completes successfully, return its ``stdout``, else fail the test. """ if executable is None: executable = sys.executable cmdline = str(executable) if args: cmdline = cmdline + " " + args proc = sp.Popen( cmdline, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, env=env, shell=True, close_fds=True, ) out, err = proc.communicate(script and script.encode()) if 0 != proc.returncode: print(out) print(err) pytest.fail("test script failed") # Py3 subprocess generates bytes strings. out = out.decode() return out py-setproctitle-version-1.2.2/tests/pyrun.c000066400000000000000000000011111400271261500210210ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * pyrun.c * Stand-alone program to test with embedded Python. * * Run a Python program read from stdin. In case of error return 1. * * Copyright (c) 2011-2020 Daniele Varrazzo * *------------------------------------------------------------------------- */ #include int main(int argc, char *argv[]) { int rv = 0; Py_Initialize(); if (0 != PyRun_SimpleFile(stdin, "stdin")) { rv = 1; } Py_Finalize(); return rv; } py-setproctitle-version-1.2.2/tests/setproctitle_test.py000066400000000000000000000322031400271261500236400ustar00rootroot00000000000000"""setproctitle module unit test. Use pytest to run this test suite. The tests are executed in external processes: setproctitle should never be imported directly from here. Copyright (c) 2009-2020 Daniele Varrazzo """ import os import re import sys import string import subprocess as sp import pytest from .conftest import run_script IS_PYPY = "__pypy__" in sys.builtin_module_names if sys.platform == 'win32': pytest.skip("skipping Posix tests on Windows", allow_module_level=True) def test_runner(): """Test the script execution method.""" rv = run_script( """ print(10 + 20) """ ) assert rv == "30\n" def test_no_import_side_effect(): """ Check that importing the module doesn't cause side effects. """ rv = run_script( """ import os def print_stuff(): for fn in "cmdline status comm".split(): if os.path.exists(f"/proc/self/{fn}"): with open(f"/proc/self/{fn}") as f: print(f.readline().rstrip()) print_stuff() print("---") import setproctitle print_stuff() """ ) before, after = rv.split("---\n") assert before == after def test_init_getproctitle(): """getproctitle() returns a sensible value at initial call.""" rv = run_script( """ import setproctitle print(setproctitle.getproctitle()) """, args="-u", ) assert rv == sys.executable + " -u\n" def test_setproctitle(): """setproctitle() can set the process title, duh.""" rv = run_script( r""" import setproctitle setproctitle.setproctitle('Hello, world!') import os print(os.getpid()) # ps can fail on kfreebsd arch # (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=460331) print(os.popen("ps -x -o pid,command 2> /dev/null").read()) """ ) lines = [line for line in rv.splitlines() if line] pid = lines.pop(0) pids = dict([r.strip().split(None, 1) for r in lines]) title = _clean_up_title(pids[pid]) assert title == "Hello, world!" def test_prctl(): """Check that prctl is called on supported platforms.""" linux_version = [] if sys.platform in ("linux", "linux2"): try: f = os.popen("uname -r") name = f.read() f.close() except Exception: pass else: linux_version = list( map(int, re.search("[.0-9]+", name).group().split(".")[:3]) ) if linux_version < [2, 6, 9]: pytest.skip("syscall not supported") rv = run_script( r""" import setproctitle setproctitle.setproctitle('Hello, prctl!') print(open('/proc/self/status').read()) """ ) status = dict([r.split(":", 1) for r in rv.splitlines() if ":" in r]) assert status["Name"].strip() == "Hello, prctl!" def test_getproctitle(): """getproctitle() can read the process title back.""" rv = run_script( r""" import setproctitle setproctitle.setproctitle('Hello, world!') print(setproctitle.getproctitle()) """ ) assert rv == "Hello, world!\n" def test_kwarg(): """setproctitle() supports keyword args.""" rv = run_script( r""" import setproctitle setproctitle.setproctitle(title='Hello, world!') print(setproctitle.getproctitle()) """ ) assert rv == "Hello, world!\n" def test_environ(): """Check that clobbering environ didn't break env.""" rv = run_script( r""" import setproctitle setproctitle.setproctitle('Hello, world! ' + 'X' * 1024) # set a new env variable, update another one import os os.environ['TEST_SETENV'] = "setenv-value" os.environ['PATH'] = os.environ.get('PATH', '') \ + os.pathsep + "fakepath" # read the environment from a spawned process inheriting the # updated env newenv = dict([r.split("=",1) for r in os.popen("env").read().splitlines() if '=' in r]) print(setproctitle.getproctitle()) print(newenv['TEST_SETENV']) print(newenv['PATH']) """ ) title, test, path = rv.splitlines() assert title.startswith("Hello, world! XXXXX"), title assert test == "setenv-value" assert path.endswith("fakepath"), path def test_issue_8(tmp_pypath): """Test that the module works with 'python -m'.""" module = "spt_issue_8" with open(tmp_pypath / f"{module}.py", "w") as f: f.write( r""" import setproctitle setproctitle.setproctitle("Hello, module!") import os print(os.getpid()) print(os.popen("ps -x -o pid,command 2> /dev/null").read()) """ ) rv = run_script(args="-m " + module) lines = [line for line in rv.splitlines() if line] pid = lines.pop(0) pids = dict([r.strip().split(None, 1) for r in lines]) title = _clean_up_title(pids[pid]) assert title == "Hello, module!" def test_large_cmdline(tmp_pypath): """Test with a 64KB command line.""" module = "longargs" with open(tmp_pypath / f"{module}.py", "w") as f: f.write( r""" import setproctitle setproctitle.setproctitle("Hello, long!") import os print(os.getpid()) print(os.popen("ps -x -o pid,command 2> /dev/null").read()) """ ) rv = run_script(args=f"-m {module} {' '.join(['X' * 1024] * 64)}") lines = [line for line in rv.splitlines() if line] pid = lines.pop(0) pids = dict([r.strip().split(None, 1) for r in lines]) title = _clean_up_title(pids[pid]) assert title == "Hello, long!" def test_unicode(): """Title can contain unicode characters.""" snowman = "\u2603" try: snowman.encode(sys.getdefaultencoding()) except UnicodeEncodeError: pytest.skip( "default encoding '%s' can't deal with snowmen" % sys.getdefaultencoding() ) try: snowman.encode(sys.getfilesystemencoding()) except UnicodeEncodeError: pytest.skip( "file system encoding '%s' can't deal with snowmen" % sys.getfilesystemencoding() ) rv = run_script( r""" snowman = u'\u2603' import setproctitle setproctitle.setproctitle("Hello, " + snowman + "!") import os import locale from subprocess import Popen, PIPE print(os.getpid()) proc = Popen("ps -x -o pid,command 2> /dev/null", shell=True, close_fds=True, stdout=PIPE, stderr=PIPE) buf = proc.stdout.read() print(buf.decode(locale.getpreferredencoding(), 'replace')) """ ) lines = [line for line in rv.splitlines() if line] pid = lines.pop(0) pids = dict([r.strip().split(None, 1) for r in lines]) snowmen = [ "\u2603", # ps supports unicode r"\M-b\M^X\M^C", # ps output on BSD r"M-bM^XM^C", # ps output on some Darwin < 11.2 "\ufffdM^XM^C", # ps output on Darwin 11.2 ] title = _clean_up_title(pids[pid]) for snowman in snowmen: if title == "Hello, " + snowman + "!": break else: pytest.fail("unexpected ps output: %r" % title) def test_weird_args(): """No problem with encoded arguments.""" euro = "\u20ac" snowman = "\u2603" try: rv = run_script( r""" import setproctitle setproctitle.setproctitle("Hello, weird args!") import os print(os.getpid()) print(os.popen("ps -x -o pid,command 2> /dev/null").read()) """, args=" ".join(["-", "hello", euro, snowman]), ) except TypeError: pytest.skip("apparently we can't pass unicode args to a program") lines = [line for line in rv.splitlines() if line] pid = lines.pop(0) pids = dict([r.strip().split(None, 1) for r in lines]) title = _clean_up_title(pids[pid]) assert title == "Hello, weird args!" def test_weird_path(tmp_path, spt_directory): """No problem with encoded argv[0] path.""" _check_4388() euro = "\u20ac" snowman = "\u2603" dir = tmp_path / euro / snowman try: os.makedirs(dir) except UnicodeEncodeError: pytest.skip("file system doesn't support unicode") exc = dir / "python" os.symlink(sys.executable, exc) rv = run_script( f""" import sys sys.path.insert(0, {repr(spt_directory)}) import setproctitle setproctitle.setproctitle("Hello, weird path!") import os print(os.getpid()) print(os.popen("ps -x -o pid,command 2> /dev/null").read()) """, args=" ".join(["-", "foo", "bar", "baz"]), executable=exc, ) lines = [line for line in rv.splitlines() if line] pid = lines.pop(0) pids = dict([r.strip().split(None, 1) for r in lines]) title = _clean_up_title(pids[pid]) assert title == "Hello, weird path!" @pytest.mark.embedded @pytest.mark.skipif(IS_PYPY, reason="skip test, pypy") def test_embedded(pyrun, spt_directory): """Check the module works with embedded Python. """ if not os.path.exists("/proc/%s/cmdline" % os.getpid()): pytest.skip("known failure: '/proc/PID/cmdline' not available") rv = run_script( f""" import sys sys.path.insert(0, {spt_directory!r}) import setproctitle setproctitle.setproctitle("Hello, embedded!") import os print(os.getpid()) print(os.popen("ps -x -o pid,command 2> /dev/null").read()) """, executable=pyrun, ) lines = [line for line in rv.splitlines() if line] pid = lines.pop(0) pids = dict([r.strip().split(None, 1) for r in lines]) title = _clean_up_title(pids[pid]) assert title == "Hello, embedded!" @pytest.mark.embedded @pytest.mark.skipif(IS_PYPY, reason="skip test, pypy") def test_embedded_many_args(pyrun, spt_directory): """Check more complex cmdlines are handled in embedded env too.""" if not os.path.exists("/proc/%s/cmdline" % os.getpid()): pytest.skip("known failure: '/proc/PID/cmdline' not available") rv = run_script( f""" import sys sys.path.insert(0, {spt_directory!r}) import setproctitle setproctitle.setproctitle("Hello, embedded!") import os print(os.getpid()) print(os.popen("ps -x -o pid,command 2> /dev/null").read()) """, executable=pyrun, args=" ".join(["foo", "bar", "baz"]), ) lines = [line for line in rv.splitlines() if line] pid = lines.pop(0) pids = dict([r.strip().split(None, 1) for r in lines]) title = _clean_up_title(pids[pid]) assert title == "Hello, embedded!" def test_noenv(): """Check that SPT_NOENV avoids clobbering environ.""" if not os.path.exists("/proc/self/environ"): pytest.skip("'/proc/self/environ' not available") env = os.environ.copy() env["SPT_TESTENV"] = "testenv" rv = run_script( """ import os os.environ['SPT_NOENV'] = "1" cmdline_len = len(open('/proc/self/cmdline').read()) print(cmdline_len) print('SPT_TESTENV=testenv' in open('/proc/self/environ').read()) import setproctitle setproctitle.setproctitle('X' * cmdline_len * 10) title = open('/proc/self/cmdline').read().rstrip() print(title) print(len(title)) print('SPT_TESTENV=testenv' in open('/proc/self/environ').read()) """, env=env, ) lines = rv.splitlines() cmdline_len = int(lines[0]) assert lines[1] == "True", "can't verify testenv" title = lines[2] assert "XXX" in _clean_up_title(title), "title not set as expected" title_len = int(lines[3]) assert lines[4] == "True", "env has been clobbered" assert ( title_len <= cmdline_len ), "title (len {title_len}) not limited to argv (len {cmdline_len})" def test_large_env(monkeypatch): """Check that large environment doesn't get clobbered. """ monkeypatch.setenv("SPT_NOENV", "1") for c in string.ascii_uppercase: monkeypatch.setenv( f"{c}_TEST_ENV", "X" * (ord(c) - ord("A") + 1) * 1024 ) rv = run_script( r"""\ import sys with open("/proc/self/environ", "rb") as f: env1 = f.read() sys.stdout.buffer.write(env1) sys.stdout.buffer.write(b"\n-----8<-----\n") import setproctitle setproctitle.setproctitle("hello") with open("/proc/self/environ", "rb") as f: env2 = f.read() sys.stdout.buffer.write(env2) """ ) parts = rv.split("\n-----8<-----\n") for i, part in enumerate(parts): parts[i] = dict( var.split("=", 1) for var in part.split("\0") if "=" in var ) assert parts[0] == parts[1] def test_clear_segfault(): rv = run_script( r"""\ import os from setproctitle import setproctitle os.environ.clear() setproctitle("Test") """) # Support functions def _clean_up_title(title): """Clean up a string from the prefix added by the platform. """ # BSD's setproctitle decorates the title with the process name. if "bsd" in sys.platform: procname = os.path.basename(sys.executable) title = " ".join([t for t in title.split(" ") if procname not in t]) return title def _check_4388(): """Check if the system is affected by bug #4388. If positive, unicode chars in the cmdline are not reliable, so bail out. see: http://bugs.python.org/issue4388 """ if sys.getfilesystemencoding() == "ascii": # in this case the char below would get translated in some # inconsistent way. # I'm not getting why the FS encoding is involved in process # spawning, the whole story just seems a gigantic can of worms. return p = sp.Popen([sys.executable, "-c", "ord('\xe9')"], stderr=sp.PIPE) p.communicate() if p.returncode: pytest.skip("bug #4388 detected") py-setproctitle-version-1.2.2/tests/setthreadtitle_test.py000066400000000000000000000034361400271261500241520ustar00rootroot00000000000000import os import pytest import sys from .conftest import run_script if sys.platform == 'win32': pytest.skip("skipping Posix tests on Windows", allow_module_level=True) def test_thread_title_unchanged(): if not os.path.isdir("/proc/self/task/"): pytest.skip("no task dir") rv = run_script( """ from glob import glob def print_stuff(): for fn in sorted(glob("/proc/self/task/*/comm")): with open(fn) as f: print(f.readline().rstrip()) print_stuff() print("---") import setproctitle print_stuff() print("---") print(setproctitle.getthreadtitle()) """ ) before, after, gtt = rv.split("---\n") assert before == after assert before == gtt def test_set_thread_title(): if not os.path.isdir("/proc/self/task/"): pytest.skip("no task dir") rv = run_script( """ from glob import glob import setproctitle setproctitle.setthreadtitle("hello" * 10) (fn,) = glob("/proc/self/task/*/comm") with open(fn) as f: assert f.read().rstrip() == "hello" * 3 """ ) def test_set_threads_title(): if not os.path.isdir("/proc/self/task/"): pytest.skip("no task dir") rv = run_script( """ import time import threading from glob import glob (fn,) = glob("/proc/self/task/*/comm") with open(fn) as f: orig = f.read().rstrip() import setproctitle def worker(title): setproctitle.setthreadtitle(title) while 1: time.sleep(1) t1 = threading.Thread(target=worker, args=('reader',), daemon=True) t2 = threading.Thread(target=worker, args=('writer',), daemon=True) t1.start() t2.start() comms = [] for fn in glob("/proc/self/task/*/comm"): with open(fn) as f: comms.append(f.read().rstrip()) comms.sort() assert comms == sorted([orig, "reader", "writer"]) """ ) py-setproctitle-version-1.2.2/tests/test_win32.py000066400000000000000000000007661400271261500220720ustar00rootroot00000000000000import pytest import setproctitle import sys if sys.platform != 'win32': pytest.skip("skipping Windows tests", allow_module_level=True) def test_setproctitle(): title = "setproctitle_test" setproctitle.setproctitle(title) assert title == setproctitle.getproctitle() def test_setthreadtitle(): title = "setproctitle_test" # This is currently a no-op on Windows. Let's make sure # that at least it doesn't error out. setproctitle.setthreadtitle(title) py-setproctitle-version-1.2.2/tools/000077500000000000000000000000001400271261500175045ustar00rootroot00000000000000py-setproctitle-version-1.2.2/tools/Makefile000066400000000000000000000011521400271261500211430ustar00rootroot00000000000000PTTEST_OBJS = pttest.o SPTDEMO_OBJS = spt_demo.o ../src/spt_status.o ../src/strlcpy.o PS_STATUS_C_URL = "http://git.postgresql.org/gitweb?p=postgresql.git;a=blob_plain;f=src/backend/utils/misc/ps_status.c;hb=HEAD" PS_STATUS_H_URL = "http://git.postgresql.org/gitweb?p=postgresql.git;a=blob_plain;f=src/include/utils/ps_status.h;hb=HEAD" CFLAGS = -g -Wall CURL = wget -O - all: pttest sptdemo prctl_demo pttest: $(PTTEST_OBJS) sptdemo: $(SPTDEMO_OBJS) $(CC) $(LDFLAGS) $^ -o $@ pgsources: ps_status.c ps_status.h ps_status.c : $(CURL) $(PS_STATUS_C_URL) > $@ ps_status.h : $(CURL) $(PS_STATUS_H_URL) > $@ py-setproctitle-version-1.2.2/tools/prctl_demo.c000066400000000000000000000014651400271261500220060ustar00rootroot00000000000000/* A test to check what happens using ``prctl()``. * * The ``prctl()`` call is available in Linux from 2.6.9. * * See http://www.kernel.org/doc/man-pages/online/pages/man2/prctl.2.html */ #include /* for prctl() */ #include /* for PR_SET_NAME */ #include #include int main(int argc, char **argv) { printf("Process PID: %i\n", getpid()); prctl(PR_SET_NAME, "Hello world"); printf("Title changed, press enter\n"); getchar(); /* The string set by prctl can be read in ``/proc/PID/stat`` * and ``/proc/PID/status``. It is displayed by ``ps`` but not by ``ps a`` * (which instead displays the content of ``/proc/PID/cmdline``). ``top`` * toggles between both visualizations pressing ``c``. */ return 0; } py-setproctitle-version-1.2.2/tools/pttest.c000066400000000000000000000010401400271261500211660ustar00rootroot00000000000000/* trying to understand why in order to clobber argv * postgres moves around environ too. */ #include extern char **environ; int main(int argc, char **argv) { char **p; printf("argv: %p\n", argv); printf("environ: %p\n", environ); for (p = argv; *p; ++p) { printf("argv[%i]: %p (%s)\n", p - argv, *p, *p); } for (p = environ; *p; ++p) { printf("environ[%i]: %p (%s)\n", p - environ, *p, *p); } /* My conclusion is that environ is contiguous to argv */ return 0; } py-setproctitle-version-1.2.2/tools/spt_demo.c000066400000000000000000000007411400271261500214640ustar00rootroot00000000000000/* A small demo to show how to use the display change */ #include "../src/spt_status.h" #include #include int main(int argc, char **argv) { printf("Process PID: %i\n", getpid()); argv = save_ps_display_args(argc, argv); init_ps_display("hello, world"); printf("Title changed, press enter\n"); getchar(); set_ps_display("new title!", true); printf("Title changed again, press enter to exit\n"); getchar(); return 0; } py-setproctitle-version-1.2.2/tox.ini000066400000000000000000000003771400271261500176660ustar00rootroot00000000000000[tox] envlist = 3.6, 3.7, 3.8, 3.9, pypy3 [testenv] commands = pytest {posargs} extras = test [testenv:3.6] basepython = python3.6 [testenv:3.7] basepython = python3.7 [testenv:3.8] basepython = python3.8 [testenv:3.9] basepython = python3.9