PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - sapi/cli - ps_title.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 65 88 73.9 %
Date: 2016-07-19 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * PostgreSQL is released under the PostgreSQL License, a liberal Open Source
       3             :  * license, similar to the BSD or MIT licenses.
       4             :  * PostgreSQL Database Management System (formerly known as Postgres, then as
       5             :  * Postgres95)
       6             :  *
       7             :  * Portions Copyright (c) 1996-2015, The PostgreSQL Global Development Group
       8             :  *
       9             :  * Portions Copyright (c) 1994, The Regents of the University of California
      10             :  *
      11             :  * Permission to use, copy, modify, and distribute this software and its
      12             :  * documentation for any purpose, without fee, and without a written
      13             :  * agreement is hereby granted, provided that the above copyright notice
      14             :  * and this paragraph and the following two paragraphs appear in all copies.
      15             :  *
      16             :  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
      17             :  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
      18             :  * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
      19             :  * EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
      20             :  * SUCH DAMAGE.
      21             :  *
      22             :  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
      23             :  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
      24             :  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
      25             :  * "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
      26             :  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
      27             :  *
      28             :  * The following code is adopted from the PostgreSQL's ps_status(.h/.c).
      29             :  */
      30             : 
      31             : #include "ps_title.h"
      32             : #include <stdio.h>
      33             : 
      34             : #ifdef HAVE_UNISTD_H
      35             : #include <unistd.h>
      36             : #endif
      37             : 
      38             : #include <string.h>
      39             : #include <stdlib.h>
      40             : 
      41             : #ifdef PHP_WIN32
      42             : #include "config.w32.h"
      43             : #include <windows.h>
      44             : #include <process.h>
      45             : #else
      46             : #include "php_config.h"
      47             : extern char** environ;
      48             : #endif
      49             : 
      50             : #ifdef HAVE_SYS_PSTAT_H
      51             : #include <sys/pstat.h> /* for HP-UX */
      52             : #endif
      53             : #ifdef HAVE_PS_STRINGS
      54             : #include <machine/vmparam.h> /* for old BSD */
      55             : #include <sys/exec.h>
      56             : #endif
      57             : #if defined(DARWIN)
      58             : #include <crt_externs.h>
      59             : #endif
      60             : 
      61             : /*
      62             :  * Ways of updating ps display:
      63             :  *
      64             :  * PS_USE_SETPROCTITLE
      65             :  *         use the function setproctitle(const char *, ...)
      66             :  *         (newer BSD systems)
      67             :  * PS_USE_PSTAT
      68             :  *         use the pstat(PSTAT_SETCMD, )
      69             :  *         (HPUX)
      70             :  * PS_USE_PS_STRINGS
      71             :  *         assign PS_STRINGS->ps_argvstr = "string"
      72             :  *         (some BSD systems)
      73             :  * PS_USE_CHANGE_ARGV
      74             :  *         assign argv[0] = "string"
      75             :  *         (some other BSD systems)
      76             :  * PS_USE_CLOBBER_ARGV
      77             :  *         write over the argv and environment area
      78             :  *         (Linux and most SysV-like systems)
      79             :  * PS_USE_WIN32
      80             :  *         push the string out as the name of a Windows event
      81             :  * PS_USE_NONE
      82             :  *         don't update ps display
      83             :  *         (This is the default, as it is safest.)
      84             :  */
      85             : #if defined(HAVE_SETPROCTITLE)
      86             : #define PS_USE_SETPROCTITLE
      87             : #elif defined(HAVE_SYS_PSTAT_H) && defined(PSTAT_SETCMD)
      88             : #define PS_USE_PSTAT
      89             : #elif defined(HAVE_PS_STRINGS)
      90             : #define PS_USE_PS_STRINGS
      91             : #elif defined(BSD) && !defined(DARWIN)
      92             : #define PS_USE_CHANGE_ARGV
      93             : #elif defined(__linux__) || defined(_AIX) || defined(__sgi) || (defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__osf__) || defined(DARWIN)
      94             : #define PS_USE_CLOBBER_ARGV
      95             : #elif defined(PHP_WIN32)
      96             : #define PS_USE_WIN32
      97             : #else
      98             : #define PS_USE_NONE
      99             : #endif
     100             : 
     101             : /* Different systems want the buffer padded differently */
     102             : #if defined(_AIX) || defined(__linux__) || defined(DARWIN)
     103             : #define PS_PADDING '\0'
     104             : #else
     105             : #define PS_PADDING ' '
     106             : #endif
     107             : 
     108             : #ifdef PS_USE_WIN32
     109             : static char windows_error_details[64];
     110             : static char ps_buffer[MAX_PATH];
     111             : static const size_t ps_buffer_size = MAX_PATH;
     112             : typedef BOOL (WINAPI *MySetConsoleTitle)(LPCTSTR);
     113             : typedef DWORD (WINAPI *MyGetConsoleTitle)(LPTSTR, DWORD);
     114             : #elif defined(PS_USE_CLOBBER_ARGV)
     115             : static char *ps_buffer;         /* will point to argv area */
     116             : static size_t ps_buffer_size;   /* space determined at run time */
     117             : static char *empty_environ[] = {0}; /* empty environment */
     118             : #else
     119             : #define PS_BUFFER_SIZE 256
     120             : static char ps_buffer[PS_BUFFER_SIZE];
     121             : static const size_t ps_buffer_size = PS_BUFFER_SIZE;
     122             : #endif
     123             : 
     124             : static size_t ps_buffer_cur_len; /* actual string length in ps_buffer */
     125             : 
     126             : /* save the original argv[] location here */
     127             : static int save_argc;
     128             : static char** save_argv;
     129             : 
     130             : /*
     131             :  * This holds the 'locally' allocated environ from the save_ps_args method.
     132             :  * This is subsequently free'd at exit.
     133             :  */
     134             : #if defined(PS_USE_CLOBBER_ARGV)
     135             : static char** frozen_environ, **new_environ;
     136             : #endif
     137             : 
     138             : /*
     139             :  * Call this method early, before any code has used the original argv passed in
     140             :  * from main().
     141             :  * If needed, this code will make deep copies of argv and environ and return
     142             :  * these to the caller for further use. The original argv is then 'clobbered'
     143             :  * to store the process title.
     144             :  */
     145       22936 : char** save_ps_args(int argc, char** argv)
     146             : {
     147       22936 :     save_argc = argc;
     148       22936 :     save_argv = argv;
     149             : 
     150             : #if defined(PS_USE_CLOBBER_ARGV)
     151             :     /*
     152             :      * If we're going to overwrite the argv area, count the available space.
     153             :      * Also move the environment to make additional room.
     154             :      */
     155             :     {
     156       22936 :         char* end_of_area = NULL;
     157       22936 :         int non_contiguous_area = 0;
     158             :         int i;
     159             : 
     160             :         /*
     161             :          * check for contiguous argv strings
     162             :          */
     163     1587635 :         for (i = 0; (non_contiguous_area == 0) && (i < argc); i++)
     164             :         {
     165     1564699 :             if (i != 0 && end_of_area + 1 != argv[i])
     166           0 :                 non_contiguous_area = 1;
     167     1564699 :             end_of_area = argv[i] + strlen(argv[i]);
     168             :         }
     169             : 
     170             :         /*
     171             :          * check for contiguous environ strings following argv
     172             :          */
     173     1151901 :         for (i = 0; (non_contiguous_area == 0) && (environ[i] != NULL); i++)
     174             :         {
     175     1128965 :             if (end_of_area + 1 != environ[i])
     176           0 :                 non_contiguous_area = 1;
     177     1128965 :             end_of_area = environ[i] + strlen(environ[i]);
     178             :         }
     179             : 
     180       22936 :         if (non_contiguous_area != 0)
     181           0 :             goto clobber_error;
     182             : 
     183       22936 :         ps_buffer = argv[0];
     184       22936 :         ps_buffer_size = end_of_area - argv[0];
     185             : 
     186             :         /*
     187             :          * move the environment out of the way
     188             :          */
     189       22936 :         new_environ = (char **) malloc((i + 1) * sizeof(char *));
     190       22936 :         frozen_environ = (char **) malloc((i + 1) * sizeof(char *));
     191       22936 :         if (!new_environ || !frozen_environ)
     192             :             goto clobber_error;
     193     1151901 :         for (i = 0; environ[i] != NULL; i++)
     194             :         {
     195     1128965 :             new_environ[i] = strdup(environ[i]);
     196     1128965 :             if (!new_environ[i])
     197           0 :                 goto clobber_error;
     198             :         }
     199       22936 :         new_environ[i] = NULL;
     200       22936 :         environ = new_environ;
     201       22936 :         memcpy((char *)frozen_environ, (char *)new_environ, sizeof(char *) * (i + 1));
     202             : 
     203             :     }
     204             : #endif /* PS_USE_CLOBBER_ARGV */
     205             : 
     206             : #if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
     207             :     /*
     208             :      * If we're going to change the original argv[] then make a copy for
     209             :      * argument parsing purposes.
     210             :      *
     211             :      * (NB: do NOT think to remove the copying of argv[]!
     212             :      * On some platforms, getopt() keeps pointers into the argv array, and
     213             :      * will get horribly confused when it is re-called to analyze a subprocess'
     214             :      * argument string if the argv storage has been clobbered meanwhile.
     215             :      * Other platforms have other dependencies on argv[].)
     216             :      */
     217             :     {
     218             :         char** new_argv;
     219             :         int i;
     220             : 
     221       22936 :         new_argv = (char **) malloc((argc + 1) * sizeof(char *));
     222       22936 :         if (!new_argv)
     223           0 :             goto clobber_error;
     224     1587635 :         for (i = 0; i < argc; i++)
     225             :         {
     226     1564699 :             new_argv[i] = strdup(argv[i]);
     227     1564699 :             if (!new_argv[i]) {
     228           0 :                 free(new_argv);
     229           0 :                 goto clobber_error;
     230             :             }
     231             :         }
     232       22936 :         new_argv[argc] = NULL;
     233             : 
     234             : #if defined(DARWIN)
     235             :         /*
     236             :          * Darwin (and perhaps other NeXT-derived platforms?) has a static
     237             :          * copy of the argv pointer, which we may fix like so:
     238             :          */
     239             :         *_NSGetArgv() = new_argv;
     240             : #endif
     241             : 
     242       22936 :         argv = new_argv;
     243             : 
     244             :     }
     245             : #endif /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */
     246             : 
     247             : #if defined(PS_USE_CLOBBER_ARGV)
     248             :     {
     249             :         /* make extra argv slots point at end_of_area (a NUL) */
     250             :         int i;
     251     1564699 :         for (i = 1; i < save_argc; i++)
     252     1541763 :             save_argv[i] = ps_buffer + ps_buffer_size;
     253             :     }
     254             : #endif /* PS_USE_CLOBBER_ARGV */
     255             : 
     256             : #ifdef PS_USE_CHANGE_ARGV
     257             :     save_argv[0] = ps_buffer; /* ps_buffer here is a static const array of size PS_BUFFER_SIZE */
     258             :     save_argv[1] = NULL;
     259             : #endif /* PS_USE_CHANGE_ARGV */
     260             : 
     261       22936 :     return argv;
     262             : 
     263             : #if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
     264             : clobber_error:
     265             :     /* probably can't happen?!
     266             :      * if we ever get here, argv still points to originally passed
     267             :      * in argument
     268             :      */
     269           0 :     save_argv = NULL;
     270           0 :     save_argc = 0;
     271           0 :     ps_buffer = NULL;
     272           0 :     ps_buffer_size = 0;
     273           0 :     return argv;
     274             : #endif /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */
     275             : }
     276             : 
     277             : /*
     278             :  * Returns PS_TITLE_SUCCESS if the OS supports this functionality
     279             :  * and the init function was called.
     280             :  * Otherwise returns NOT_AVAILABLE or NOT_INITIALIZED
     281             :  */
     282           2 : int is_ps_title_available()
     283             : {
     284             : #ifdef PS_USE_NONE
     285             :     return PS_TITLE_NOT_AVAILABLE; /* disabled functionality */
     286             : #endif
     287             : 
     288           2 :     if (!save_argv)
     289           0 :         return PS_TITLE_NOT_INITIALIZED;
     290             : 
     291             : #ifdef PS_USE_CLOBBER_ARGV
     292           2 :     if (!ps_buffer)
     293           0 :         return PS_TITLE_BUFFER_NOT_AVAILABLE;
     294             : #endif /* PS_USE_CLOBBER_ARGV */
     295             : 
     296           2 :     return PS_TITLE_SUCCESS;
     297             : }
     298             : 
     299             : /*
     300             :  * Convert error codes into error strings
     301             :  */
     302           0 : const char* ps_title_errno(int rc)
     303             : {
     304           0 :     switch(rc)
     305             :     {
     306             :     case PS_TITLE_SUCCESS:
     307           0 :         return "Success";
     308             : 
     309             :     case PS_TITLE_NOT_AVAILABLE:
     310           0 :         return "Not available on this OS";
     311             : 
     312             :     case PS_TITLE_NOT_INITIALIZED:
     313           0 :         return "Not initialized correctly";
     314             : 
     315             :     case PS_TITLE_BUFFER_NOT_AVAILABLE:
     316           0 :         return "Buffer not contiguous";
     317             : 
     318             : #ifdef PS_USE_WIN32
     319             :     case PS_TITLE_WINDOWS_ERROR:
     320             :         sprintf(windows_error_details, "Windows error code: %lu", GetLastError());
     321             :         return windows_error_details;
     322             : #endif
     323             :     }
     324             : 
     325           0 :     return "Unknown error code";
     326             : }
     327             : 
     328             : /*
     329             :  * Set a new process title.
     330             :  * Returns the appropriate error code if if there's an error
     331             :  * (like the functionality is compile time disabled, or the
     332             :  * save_ps_args() was not called.
     333             :  * Else returns 0 on success.
     334             :  */
     335           1 : int set_ps_title(const char* title)
     336             : {
     337           1 :     int rc = is_ps_title_available();
     338           1 :     if (rc != PS_TITLE_SUCCESS)
     339           0 :         return rc;
     340             : 
     341           1 :     strncpy(ps_buffer, title, ps_buffer_size);
     342           1 :     ps_buffer[ps_buffer_size - 1] = '\0';
     343           1 :     ps_buffer_cur_len = strlen(ps_buffer);
     344             : 
     345             : #ifdef PS_USE_SETPROCTITLE
     346             :     setproctitle("%s", ps_buffer);
     347             : #endif
     348             : 
     349             : #ifdef PS_USE_PSTAT
     350             :     {
     351             :         union pstun pst;
     352             : 
     353             :         pst.pst_command = ps_buffer;
     354             :         pstat(PSTAT_SETCMD, pst, ps_buffer_cur_len, 0, 0);
     355             :     }
     356             : #endif /* PS_USE_PSTAT */
     357             : 
     358             : #ifdef PS_USE_PS_STRINGS
     359             :     PS_STRINGS->ps_nargvstr = 1;
     360             :     PS_STRINGS->ps_argvstr = ps_buffer;
     361             : #endif /* PS_USE_PS_STRINGS */
     362             : 
     363             : #ifdef PS_USE_CLOBBER_ARGV
     364             :     /* pad unused memory */
     365           1 :     if (ps_buffer_cur_len < ps_buffer_size)
     366             :     {
     367           1 :         memset(ps_buffer + ps_buffer_cur_len, PS_PADDING,
     368             :                ps_buffer_size - ps_buffer_cur_len);
     369             :     }
     370             : #endif /* PS_USE_CLOBBER_ARGV */
     371             : 
     372             : #ifdef PS_USE_WIN32
     373             :     {
     374             :         MySetConsoleTitle set_title = NULL;
     375             :         HMODULE hMod = LoadLibrary("kernel32.dll");
     376             : 
     377             :         if (!hMod) {
     378             :             return PS_TITLE_WINDOWS_ERROR;
     379             :         }
     380             : 
     381             :         /* NOTE we don't use _UNICODE*/
     382             :         set_title = (MySetConsoleTitle)GetProcAddress(hMod, "SetConsoleTitleA");
     383             :         if (!set_title) {
     384             :             return PS_TITLE_WINDOWS_ERROR;
     385             :         }
     386             : 
     387             :         if (!set_title(ps_buffer)) {
     388             :             return PS_TITLE_WINDOWS_ERROR;
     389             :         }
     390             :     }
     391             : #endif /* PS_USE_WIN32 */
     392             : 
     393           1 :     return PS_TITLE_SUCCESS;
     394             : }
     395             : 
     396             : /*
     397             :  * Returns the current ps_buffer value into string.  On some platforms
     398             :  * the string will not be null-terminated, so return the effective
     399             :  * length into *displen.
     400             :  * The return code indicates the error.
     401             :  */
     402           1 : int get_ps_title(int *displen, const char** string)
     403             : {
     404           1 :     int rc = is_ps_title_available();
     405           1 :     if (rc != PS_TITLE_SUCCESS)
     406           0 :         return rc;
     407             : 
     408             : #ifdef PS_USE_WIN32
     409             :     {
     410             :         MyGetConsoleTitle get_title = NULL;
     411             :         HMODULE hMod = LoadLibrary("kernel32.dll");
     412             : 
     413             :         if (!hMod) {
     414             :             return PS_TITLE_WINDOWS_ERROR;
     415             :         }
     416             : 
     417             :         /* NOTE we don't use _UNICODE*/
     418             :         get_title = (MyGetConsoleTitle)GetProcAddress(hMod, "GetConsoleTitleA");
     419             :         if (!get_title) {
     420             :             return PS_TITLE_WINDOWS_ERROR;
     421             :         }
     422             : 
     423             :         if (!(ps_buffer_cur_len = get_title(ps_buffer, (DWORD)ps_buffer_size))) {
     424             :             return PS_TITLE_WINDOWS_ERROR;
     425             :         }
     426             :     }
     427             : #endif
     428           1 :     *displen = (int)ps_buffer_cur_len;
     429           1 :     *string = ps_buffer;
     430           1 :     return PS_TITLE_SUCCESS;
     431             : }
     432             : 
     433             : /*
     434             :  * Clean up the allocated argv and environ if applicable. Only call
     435             :  * this right before exiting.
     436             :  * This isn't needed per-se because the OS will clean-up anyway, but
     437             :  * having and calling this will ensure Valgrind doesn't output 'false
     438             :  * positives'.
     439             :  */
     440       22977 : void cleanup_ps_args(char **argv)
     441             : {
     442             : #ifndef PS_USE_NONE
     443       22977 :     if (save_argv)
     444             :     {
     445       22977 :         save_argv = NULL;
     446       22977 :         save_argc = 0;
     447             : 
     448             : #ifdef PS_USE_CLOBBER_ARGV
     449             :         {
     450             :             int i;
     451     1154033 :             for (i = 0; frozen_environ[i] != NULL; i++)
     452     1131056 :                 free(frozen_environ[i]);
     453       22977 :             free(frozen_environ);
     454       22977 :             free(new_environ);
     455             :             /* leave a sane environment behind since some atexit() handlers
     456             :                 call getenv(). */
     457       22977 :             environ = empty_environ;
     458             :         }
     459             : #endif /* PS_USE_CLOBBER_ARGV */
     460             : 
     461             : #if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
     462             :         {
     463             :             int i;
     464     1590382 :             for (i=0; argv[i] != NULL; i++)
     465     1567405 :                 free(argv[i]);
     466       22977 :             free(argv);
     467             :         }
     468             : #endif /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */
     469             :     }
     470             : #endif /* PS_USE_NONE */
     471             : 
     472       22977 :     return;
     473             : }

Generated by: LCOV version 1.10

Generated at Wed, 20 Jul 2016 02:56:34 +0000 (6 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.