~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/lib/System/Unix/Process.inc

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
2
 
// 
3
 
//                     The LLVM Compiler Infrastructure
4
 
//
5
 
// This file is distributed under the University of Illinois Open Source
6
 
// License. See LICENSE.TXT for details.
7
 
// 
8
 
//===----------------------------------------------------------------------===//
9
 
//
10
 
// This file provides the generic Unix implementation of the Process class.
11
 
//
12
 
//===----------------------------------------------------------------------===//
13
 
 
14
 
#include "Unix.h"
15
 
#ifdef HAVE_SYS_TIME_H
16
 
#include <sys/time.h>
17
 
#endif
18
 
#ifdef HAVE_SYS_RESOURCE_H
19
 
#include <sys/resource.h>
20
 
#endif
21
 
// DragonFly BSD has deprecated <malloc.h> for <stdlib.h> instead,
22
 
//  Unix.h includes this for us already.
23
 
#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__)
24
 
#include <malloc.h>
25
 
#endif
26
 
#ifdef HAVE_MALLOC_MALLOC_H
27
 
#include <malloc/malloc.h>
28
 
#endif
29
 
#ifdef HAVE_SYS_IOCTL_H
30
 
#  include <sys/ioctl.h>
31
 
#endif
32
 
#ifdef HAVE_TERMIOS_H
33
 
#  include <termios.h>
34
 
#endif
35
 
 
36
 
//===----------------------------------------------------------------------===//
37
 
//=== WARNING: Implementation here must contain only generic UNIX code that
38
 
//===          is guaranteed to work on *all* UNIX variants.
39
 
//===----------------------------------------------------------------------===//
40
 
 
41
 
using namespace llvm;
42
 
using namespace sys;
43
 
 
44
 
unsigned 
45
 
Process::GetPageSize() 
46
 
{
47
 
#if defined(__CYGWIN__)
48
 
  // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
49
 
  // memory protection and mmap() is 4k.
50
 
  // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
51
 
  const int page_size = 0x1000;
52
 
#elif defined(HAVE_GETPAGESIZE)
53
 
  const int page_size = ::getpagesize();
54
 
#elif defined(HAVE_SYSCONF)
55
 
  long page_size = ::sysconf(_SC_PAGE_SIZE);
56
 
#else
57
 
#warning Cannot get the page size on this machine
58
 
#endif
59
 
  return static_cast<unsigned>(page_size);
60
 
}
61
 
 
62
 
/* ClamAV: we don't link with -lmalloc */
63
 
#undef HAVE_MALLINFO
64
 
size_t Process::GetMallocUsage() {
65
 
#if defined(HAVE_MALLINFO)
66
 
  struct mallinfo mi;
67
 
  mi = ::mallinfo();
68
 
  return mi.uordblks;
69
 
#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
70
 
  malloc_statistics_t Stats;
71
 
  malloc_zone_statistics(malloc_default_zone(), &Stats);
72
 
  return Stats.size_in_use;   // darwin
73
 
#elif defined(HAVE_SBRK)
74
 
  // Note this is only an approximation and more closely resembles
75
 
  // the value returned by mallinfo in the arena field.
76
 
  static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
77
 
  char *EndOfMemory = (char*)sbrk(0);
78
 
  if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
79
 
    return EndOfMemory - StartOfMemory;
80
 
  else
81
 
    return 0;
82
 
#else
83
 
#warning Cannot get malloc info on this platform
84
 
  return 0;
85
 
#endif
86
 
}
87
 
 
88
 
size_t
89
 
Process::GetTotalMemoryUsage()
90
 
{
91
 
#if defined(HAVE_MALLINFO)
92
 
  struct mallinfo mi = ::mallinfo();
93
 
  return mi.uordblks + mi.hblkhd;
94
 
#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
95
 
  malloc_statistics_t Stats;
96
 
  malloc_zone_statistics(malloc_default_zone(), &Stats);
97
 
  return Stats.size_allocated;   // darwin
98
 
#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__)
99
 
  struct rusage usage;
100
 
  ::getrusage(RUSAGE_SELF, &usage);
101
 
  return usage.ru_maxrss;
102
 
#else
103
 
#warning Cannot get total memory size on this platform
104
 
  return 0;
105
 
#endif
106
 
}
107
 
 
108
 
void
109
 
Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time, 
110
 
                      TimeValue& sys_time)
111
 
{
112
 
  elapsed = TimeValue::now();
113
 
#if defined(HAVE_GETRUSAGE)
114
 
  struct rusage usage;
115
 
  ::getrusage(RUSAGE_SELF, &usage);
116
 
  user_time = TimeValue( 
117
 
    static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ), 
118
 
    static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec * 
119
 
      TimeValue::NANOSECONDS_PER_MICROSECOND ) );
120
 
  sys_time = TimeValue( 
121
 
    static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ), 
122
 
    static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec * 
123
 
      TimeValue::NANOSECONDS_PER_MICROSECOND ) );
124
 
#else
125
 
#warning Cannot get usage times on this platform
126
 
  user_time.seconds(0);
127
 
  user_time.microseconds(0);
128
 
  sys_time.seconds(0);
129
 
  sys_time.microseconds(0);
130
 
#endif
131
 
}
132
 
 
133
 
int Process::GetCurrentUserId() {
134
 
  return getuid();
135
 
}
136
 
 
137
 
int Process::GetCurrentGroupId() {
138
 
  return getgid();
139
 
}
140
 
 
141
 
#ifdef HAVE_MACH_MACH_H
142
 
#include <mach/mach.h>
143
 
#endif
144
 
 
145
 
// Some LLVM programs such as bugpoint produce core files as a normal part of
146
 
// their operation. To prevent the disk from filling up, this function
147
 
// does what's necessary to prevent their generation.
148
 
void Process::PreventCoreFiles() {
149
 
#if HAVE_SETRLIMIT
150
 
  struct rlimit rlim;
151
 
  rlim.rlim_cur = rlim.rlim_max = 0;
152
 
  setrlimit(RLIMIT_CORE, &rlim);
153
 
#endif
154
 
 
155
 
#ifdef HAVE_MACH_MACH_H
156
 
  // Disable crash reporting on Mac OS X 10.0-10.4
157
 
 
158
 
  // get information about the original set of exception ports for the task
159
 
  mach_msg_type_number_t Count = 0;
160
 
  exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
161
 
  exception_port_t OriginalPorts[EXC_TYPES_COUNT];
162
 
  exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
163
 
  thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
164
 
  kern_return_t err = 
165
 
    task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
166
 
                             &Count, OriginalPorts, OriginalBehaviors,
167
 
                             OriginalFlavors);
168
 
  if (err == KERN_SUCCESS) {
169
 
    // replace each with MACH_PORT_NULL.
170
 
    for (unsigned i = 0; i != Count; ++i)
171
 
      task_set_exception_ports(mach_task_self(), OriginalMasks[i], 
172
 
                               MACH_PORT_NULL, OriginalBehaviors[i],
173
 
                               OriginalFlavors[i]);
174
 
  }
175
 
 
176
 
  // Disable crash reporting on Mac OS X 10.5
177
 
  signal(SIGABRT, _exit);
178
 
  signal(SIGILL,  _exit);
179
 
  signal(SIGFPE,  _exit);
180
 
  signal(SIGSEGV, _exit);
181
 
  signal(SIGBUS,  _exit);
182
 
#endif
183
 
}
184
 
 
185
 
bool Process::StandardInIsUserInput() {
186
 
  return FileDescriptorIsDisplayed(STDIN_FILENO);
187
 
}
188
 
 
189
 
bool Process::StandardOutIsDisplayed() {
190
 
  return FileDescriptorIsDisplayed(STDOUT_FILENO);
191
 
}
192
 
 
193
 
bool Process::StandardErrIsDisplayed() {
194
 
  return FileDescriptorIsDisplayed(STDERR_FILENO);
195
 
}
196
 
 
197
 
bool Process::FileDescriptorIsDisplayed(int fd) {
198
 
#if HAVE_ISATTY
199
 
  return isatty(fd);
200
 
#else
201
 
  // If we don't have isatty, just return false.
202
 
  return false;
203
 
#endif
204
 
}
205
 
 
206
 
static unsigned getColumns(int FileID) {
207
 
  // If COLUMNS is defined in the environment, wrap to that many columns.
208
 
  if (const char *ColumnsStr = std::getenv("COLUMNS")) {
209
 
    int Columns = std::atoi(ColumnsStr);
210
 
    if (Columns > 0)
211
 
      return Columns;
212
 
  }
213
 
 
214
 
  unsigned Columns = 0;
215
 
 
216
 
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
217
 
  // Try to determine the width of the terminal.
218
 
  struct winsize ws;
219
 
  if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
220
 
    Columns = ws.ws_col;
221
 
#endif
222
 
 
223
 
  return Columns;
224
 
}
225
 
 
226
 
unsigned Process::StandardOutColumns() {
227
 
  if (!StandardOutIsDisplayed())
228
 
    return 0;
229
 
 
230
 
  return getColumns(1);
231
 
}
232
 
 
233
 
unsigned Process::StandardErrColumns() {
234
 
  if (!StandardErrIsDisplayed())
235
 
    return 0;
236
 
 
237
 
  return getColumns(2);
238
 
}
239
 
 
240
 
static bool terminalHasColors() {
241
 
  if (const char *term = std::getenv("TERM")) {
242
 
    // Most modern terminals support ANSI escape sequences for colors.
243
 
    // We could check terminfo, or have a list of known terms that support
244
 
    // colors, but that would be overkill.
245
 
    // The user can always ask for no colors by setting TERM to dumb, or
246
 
    // using a commandline flag.
247
 
    return strcmp(term, "dumb") != 0;
248
 
  }
249
 
  return false;
250
 
}
251
 
 
252
 
bool Process::StandardOutHasColors() {
253
 
  if (!StandardOutIsDisplayed())
254
 
    return false;
255
 
  return terminalHasColors();
256
 
}
257
 
 
258
 
bool Process::StandardErrHasColors() {
259
 
  if (!StandardErrIsDisplayed())
260
 
    return false;
261
 
  return terminalHasColors();
262
 
}
263
 
 
264
 
bool Process::ColorNeedsFlush() {
265
 
  // No, we use ANSI escape sequences.
266
 
  return false;
267
 
}
268
 
 
269
 
#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
270
 
 
271
 
#define ALLCOLORS(FGBG,BOLD) {\
272
 
    COLOR(FGBG, "0", BOLD),\
273
 
    COLOR(FGBG, "1", BOLD),\
274
 
    COLOR(FGBG, "2", BOLD),\
275
 
    COLOR(FGBG, "3", BOLD),\
276
 
    COLOR(FGBG, "4", BOLD),\
277
 
    COLOR(FGBG, "5", BOLD),\
278
 
    COLOR(FGBG, "6", BOLD),\
279
 
    COLOR(FGBG, "7", BOLD)\
280
 
  }
281
 
 
282
 
static const char colorcodes[2][2][8][10] = {
283
 
 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
284
 
 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
285
 
};
286
 
 
287
 
const char *Process::OutputColor(char code, bool bold, bool bg) {
288
 
  return colorcodes[bg?1:0][bold?1:0][code&7];
289
 
}
290
 
 
291
 
const char *Process::OutputBold(bool bg) {
292
 
  return "\033[1m";
293
 
}
294
 
 
295
 
const char *Process::ResetColor() {
296
 
  return "\033[0m";
297
 
}