Ruby  1.9.3p551(2014-11-13revision48407)
setproctitle.c
Go to the documentation of this file.
1 /* Based on setproctitle.c from openssh-5.6p1 */
2 /* Based on conf.c from UCB sendmail 8.8.8 */
3 
4 /*
5  * Copyright 2003 Damien Miller
6  * Copyright (c) 1983, 1995-1997 Eric P. Allman
7  * Copyright (c) 1988, 1993
8  * The Regents of the University of California. All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include "ruby.h"
36 #include "ruby/util.h"
37 #define compat_init_setproctitle ruby_init_setproctitle
38 
39 #ifndef HAVE_SETPROCTITLE
40 
41 #include <stdarg.h>
42 #include <stdlib.h>
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46 #ifdef HAVE_SYS_PSTAT_H
47 #include <sys/pstat.h>
48 #endif
49 #include <string.h>
50 
51 #if defined(__APPLE__)
52 #include <crt_externs.h>
53 #undef environ
54 #define environ (*_NSGetEnviron())
55 #endif
56 
57 #define SPT_NONE 0 /* don't use it at all */
58 #define SPT_PSTAT 1 /* use pstat(PSTAT_SETCMD, ...) */
59 #define SPT_REUSEARGV 2 /* cover argv with title information */
60 
61 #ifndef SPT_TYPE
62 # define SPT_TYPE SPT_NONE
63 #endif
64 
65 #ifndef SPT_PADCHAR
66 # define SPT_PADCHAR '\0'
67 #endif
68 
69 #if SPT_TYPE == SPT_REUSEARGV
70 static char *argv_start = NULL;
71 static size_t argv_env_len = 0;
72 static size_t argv_len = 0;
73 #endif
74 
75 #endif /* HAVE_SETPROCTITLE */
76 
77 void
79 {
80 #if defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV
81  extern char **environ;
82  char *lastargv = NULL;
83  char *lastenvp = NULL;
84  char **envp = environ;
85  int i;
86 
87  /*
88  * NB: This assumes that argv has already been copied out of the
89  * way. This is true for sshd, but may not be true for other
90  * programs. Beware.
91  */
92 
93  if (argc == 0 || argv[0] == NULL)
94  return;
95 
96  /* Fail if we can't allocate room for the new environment */
97  for (i = 0; envp[i] != NULL; i++)
98  ;
99  if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) {
100  environ = envp; /* put it back */
101  return;
102  }
103 
104  /*
105  * Find the last argv string or environment variable within
106  * our process memory area.
107  */
108  for (i = 0; i < argc; i++) {
109  if (lastargv == NULL || lastargv + 1 == argv[i])
110  lastargv = argv[i] + strlen(argv[i]);
111  }
112  lastenvp = lastargv;
113  for (i = 0; envp[i] != NULL; i++) {
114  if (lastenvp + 1 == envp[i])
115  lastenvp = envp[i] + strlen(envp[i]);
116  }
117 
118  argv[1] = NULL;
119  argv_start = argv[0];
120  argv_len = lastargv - argv[0];
121  argv_env_len = lastenvp - argv[0];
122 
123  for (i = 0; envp[i] != NULL; i++)
124  environ[i] = ruby_strdup(envp[i]);
125  environ[i] = NULL;
126 #endif /* SPT_REUSEARGV */
127 }
128 
129 #ifndef HAVE_SETPROCTITLE
130 void
131 setproctitle(const char *fmt, ...)
132 {
133 #if SPT_TYPE != SPT_NONE
134  va_list ap;
135  char ptitle[1024];
136  size_t len;
137  size_t argvlen;
138 #if SPT_TYPE == SPT_PSTAT
139  union pstun pst;
140 #endif
141 
142 #if SPT_TYPE == SPT_REUSEARGV
143  if (argv_env_len <= 0)
144  return;
145 #endif
146 
147  va_start(ap, fmt);
148  if (fmt != NULL) {
149  vsnprintf(ptitle, sizeof(ptitle) , fmt, ap);
150  }
151  va_end(ap);
152 
153 #if SPT_TYPE == SPT_PSTAT
154  pst.pst_command = ptitle;
155  pstat(PSTAT_SETCMD, pst, strlen(ptitle), 0, 0);
156 #elif SPT_TYPE == SPT_REUSEARGV
157  len = strlcpy(argv_start, ptitle, argv_env_len);
158  argvlen = len > argv_len ? argv_env_len : argv_len;
159  for(; len < argvlen; len++)
160  argv_start[len] = SPT_PADCHAR;
161 #endif
162 
163 #endif /* SPT_NONE */
164 }
165 
166 #endif /* HAVE_SETPROCTITLE */
167