~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to ksysguard/ksysguardd/Linux/ProcessList.c

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    KSysGuard, the KDE System Guard
 
3
 
 
4
    Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
 
5
 
 
6
    This program is free software; you can redistribute it and/or
 
7
    modify it under the terms of version 2 of the GNU General Public
 
8
    License as published by the Free Software Foundation.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with this program; if not, write to the Free Software
 
17
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 
 
19
*/
 
20
 
 
21
#include <ctype.h>
 
22
#include <dirent.h>
 
23
#include <errno.h>
 
24
#include <signal.h>
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
#include <sys/time.h>
 
29
#include <sys/resource.h>
 
30
#include <time.h>
 
31
#include <unistd.h>
 
32
#include <sys/ptrace.h>
 
33
#include <asm/unistd.h>
 
34
 
 
35
 
 
36
 
 
37
#include "../../gui/SignalIDs.h"
 
38
#include "Command.h"
 
39
#include "PWUIDCache.h"
 
40
#include "ccont.h"
 
41
#include "ksysguardd.h"
 
42
 
 
43
#include "ProcessList.h"
 
44
 
 
45
#define BUFSIZE 1024
 
46
#define TAGSIZE 32
 
47
#define KDEINITLEN sizeof( "kdeinit: " )
 
48
 
 
49
/* For ionice */
 
50
extern int sys_ioprio_set(int, int, int);
 
51
extern int sys_ioprio_get(int, int);
 
52
 
 
53
#define HAVE_IONICE
 
54
 
 
55
/* Check if this system has ionice */
 
56
#if !defined(SYS_ioprio_get) || !defined(SYS_ioprio_set)
 
57
/* All new kernels have SYS_ioprio_get and _set defined, but for the few that do not, here are the definitions */
 
58
#if defined(__i386__)
 
59
#define __NR_ioprio_set         289
 
60
#define __NR_ioprio_get         290
 
61
#elif defined(__ppc__) || defined(__powerpc__)
 
62
#define __NR_ioprio_set         273
 
63
#define __NR_ioprio_get         274
 
64
#elif defined(__x86_64__)
 
65
#define __NR_ioprio_set         251
 
66
#define __NR_ioprio_get         252
 
67
#elif defined(__ia64__)
 
68
#define __NR_ioprio_set         1274
 
69
#define __NR_ioprio_get         1275
 
70
#else
 
71
#ifdef __GNUC__
 
72
#warning "This architecture does not support IONICE.  Disabling ionice feature."
 
73
#endif
 
74
#undef HAVE_IONICE
 
75
#endif
 
76
/* Map these to SYS_ioprio_get */
 
77
#define SYS_ioprio_get                __NR_ioprio_get
 
78
#define SYS_ioprio_set                __NR_ioprio_set
 
79
 
 
80
#endif /* !SYS_ioprio_get */
 
81
 
 
82
/* Set up ionice functions */
 
83
#ifdef HAVE_IONICE
 
84
#define IOPRIO_WHO_PROCESS 1
 
85
#define IOPRIO_CLASS_SHIFT 13
 
86
 
 
87
/* Expose the kernel calls to usespace via syscall
 
88
 * See man ioprio_set  and man ioprio_get   for information on these functions */
 
89
static int ioprio_set(int which, int who, int ioprio)
 
90
{
 
91
  return syscall(SYS_ioprio_set, which, who, ioprio);
 
92
}
 
93
 
 
94
static int ioprio_get(int which, int who)
 
95
{
 
96
  return syscall(SYS_ioprio_get, which, who);
 
97
}
 
98
#endif
 
99
 
 
100
 
 
101
#ifndef bool
 
102
#define bool char
 
103
#define true 1
 
104
#define false 0
 
105
#endif
 
106
 
 
107
typedef struct {
 
108
 
 
109
  /** The parent process ID */
 
110
  pid_t ppid;
 
111
 
 
112
  /** The real user ID */
 
113
  uid_t uid;
 
114
 
 
115
  /** The real group ID */
 
116
  gid_t gid;
 
117
 
 
118
  /** The process ID of any application that is debugging this one. 0 if none */
 
119
  pid_t tracerpid;
 
120
 
 
121
  /** A character description of the process status */
 
122
  char status[ 16 ];
 
123
 
 
124
  /** The tty the process owns */
 
125
  char tty[10];
 
126
 
 
127
  /**
 
128
    The nice level. The range should be -20 to 20. I'm not sure
 
129
    whether this is true for all platforms.
 
130
   */
 
131
  int niceLevel;
 
132
 
 
133
  /** The scheduling priority. */
 
134
  int priority;
 
135
 
 
136
  /** The i/o scheduling class and priority. */
 
137
  int ioPriorityClass;  /**< 0 for none, 1 for realtime, 2 for best-effort, 3 for idle.  -1 for error. */
 
138
  int ioPriority;       /**< Between 0 and 7.  0 is highest priority, 7 is lowest.  -1 for error. */
 
139
 
 
140
  /**
 
141
    The total amount of virtual memory space that this process uses. This includes shared and
 
142
    swapped memory, plus graphics memory and mmap'ed files and so on.
 
143
 
 
144
    This is in KiB
 
145
   */
 
146
  unsigned long vmSize;
 
147
 
 
148
  /**
 
149
    The amount of physical memory the process currently uses, including the physical memory used by any
 
150
    shared libraries that it uses.  Hence 2 processes sharing a library will both report their vmRss as including
 
151
    this shared memory, even though it's only allocated once. 
 
152
   
 
153
    This is in KiB
 
154
   */
 
155
  
 
156
  unsigned long vmRss;
 
157
 
 
158
  /** The amount of physical memory that is used by this process, not including any memory used by any shared libraries.
 
159
   *  This is in KiB */
 
160
  unsigned long vmURss;
 
161
 
 
162
  /**
 
163
    The number of 1/100 of a second the process has spend in user space.
 
164
    If a machine has an uptime of 1 1/2 years or longer this is not a
 
165
    good idea. I never thought that the stability of UNIX could get me
 
166
    into trouble! ;)
 
167
   */
 
168
  unsigned long userTime;
 
169
 
 
170
  /**
 
171
    The number of 1/100 of a second the process has spent in system space.
 
172
    If a machine has an uptime of 1 1/2 years or longer this is not a
 
173
    good idea. I never thought that the stability of UNIX could get me
 
174
    into trouble! ;)
 
175
   */
 
176
  unsigned long sysTime;
 
177
 
 
178
  /* NOTE:  To get the user/system percentage, record the userTime and sysTime from between calls, then use the difference divided by the difference in time measure in 100th's of a second */
 
179
 
 
180
  /** The name of the process */
 
181
  char name[ 64 ];
 
182
 
 
183
  /** The command used to start the process */
 
184
  char cmdline[ 256 ];
 
185
 
 
186
  /** The login name of the user that owns this process */
 
187
  char userName[ 32 ];
 
188
 
 
189
} ProcessInfo;
 
190
 
 
191
void getIOnice( int pid, ProcessInfo *ps );
 
192
void ioniceProcess( const char* cmd );
 
193
 
 
194
static unsigned ProcessCount;
 
195
static DIR* procDir;
 
196
static void validateStr( char* str )
 
197
{
 
198
  char* s = str;
 
199
 
 
200
  /* All characters that could screw up the communication will be removed. */
 
201
  while ( *s ) {
 
202
    if ( *s == '\t' || *s == '\n' || *s == '\r' )
 
203
      *s = ' ';
 
204
    ++s;
 
205
  }
 
206
 
 
207
  /* Make sure that string contains at least one character (blank). */
 
208
  if ( str[ 0 ] == '\0' )
 
209
    strcpy( str, " " );
 
210
}
 
211
 
 
212
static bool getProcess( int pid, ProcessInfo *ps )
 
213
{
 
214
  FILE* fd;
 
215
  char buf[ BUFSIZE ];
 
216
  char tag[ TAGSIZE ];
 
217
  char format[ 32 ];
 
218
  char tagformat[ 32 ];
 
219
  const char* uName;
 
220
  char status;
 
221
 
 
222
  snprintf( buf, BUFSIZE - 1, "/proc/%d/status", pid );
 
223
  if ( ( fd = fopen( buf, "r" ) ) == 0 ) {
 
224
    /* process has terminated in the mean time */
 
225
    return false;
 
226
  }
 
227
  ps->uid = 0;
 
228
  ps->gid = 0;
 
229
  ps->tracerpid = -1;
 
230
  
 
231
  sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 );
 
232
  sprintf( tagformat, "%%%ds", (int)sizeof( tag ) - 1 );
 
233
  for ( ;; ) {
 
234
    if ( fscanf( fd, format, buf ) != 1 )
 
235
      break;
 
236
    buf[ sizeof( buf ) - 1 ] = '\0';
 
237
    sscanf( buf, tagformat, tag );
 
238
    tag[ sizeof( tag ) - 1 ] = '\0';
 
239
    if ( strcmp( tag, "Name:" ) == 0 ) {
 
240
      sscanf( buf, "%*s %63s", ps->name );
 
241
      validateStr( ps->name );
 
242
    } else if ( strcmp( tag, "Uid:" ) == 0 ) {
 
243
      sscanf( buf, "%*s %d %*d %*d %*d", (int*)&ps->uid );
 
244
    } else if ( strcmp( tag, "Gid:" ) == 0 ) {
 
245
      sscanf( buf, "%*s %d %*d %*d %*d", (int*)&ps->gid );
 
246
    } else if ( strcmp( tag, "TracerPid:" ) == 0 ) {
 
247
      sscanf( buf, "%*s %d", (int*)&ps->tracerpid );
 
248
      if (ps->tracerpid == 0)
 
249
          ps->tracerpid = -1; /* ksysguard uses -1 to indicate no tracerpid, but linux uses 0 */
 
250
    }
 
251
  }
 
252
 
 
253
  if ( fclose( fd ) )
 
254
    return false;
 
255
 
 
256
  snprintf( buf, BUFSIZE - 1, "/proc/%d/stat", pid );
 
257
  buf[ BUFSIZE - 1 ] = '\0';
 
258
  if ( ( fd = fopen( buf, "r" ) ) == 0 )
 
259
    return false;
 
260
  int ttyNo;
 
261
  if ( fscanf( fd, "%*d %*s %c %d %*d %*d %d %*d %*u %*u %*u %*u %*u %lu %lu"
 
262
                   "%*d %*d %*d %d %*u %*u %*d %lu %lu",
 
263
                   &status, (int*)&ps->ppid, &ttyNo,
 
264
                   &ps->userTime, &ps->sysTime, &ps->niceLevel, &ps->vmSize,
 
265
                   &ps->vmRss) != 8 ) {
 
266
    fclose( fd );
 
267
    return false;
 
268
  }
 
269
  if (ps->ppid == 0) /* ksysguard uses -1 to indicate no parent, but linux uses 0 */
 
270
      ps->ppid = -1;
 
271
  int major = ttyNo >> 8;
 
272
  int minor = ttyNo & 0xff;
 
273
  switch(major) {
 
274
    case 136:
 
275
      snprintf(ps->tty, sizeof(ps->tty)-1, "pts/%d", minor);
 
276
      break;
 
277
    case 4:
 
278
      if(minor < 64)
 
279
        snprintf(ps->tty, sizeof(ps->tty)-1, "tty/%d", minor);
 
280
      else
 
281
        snprintf(ps->tty, sizeof(ps->tty)-1, "ttyS/%d", minor-64);
 
282
      break;
 
283
    default:
 
284
      ps->tty[0] = 0;
 
285
  }
 
286
 
 
287
  /*There was a "(ps->vmRss+3) * sysconf(_SC_PAGESIZE)" here originally.  I have no idea why!  After comparing it to
 
288
  meminfo and other tools, this means we report the RSS by 12 bytes different compared to them.  So I'm removing the +3
 
289
  to be consistent.  NEXT TIME COMMENT STRANGE THINGS LIKE THAT! :-)
 
290
  
 
291
    Update: I think I now know why.  The kernel reserves 3kb for process information.
 
292
  */
 
293
  ps->vmRss = ps->vmRss * sysconf(_SC_PAGESIZE) / 1024; /*convert to KiB*/
 
294
  ps->vmSize /= 1024; /* convert to KiB */
 
295
 
 
296
  if ( fclose( fd ) )
 
297
    return false;
 
298
 
 
299
  snprintf( buf, BUFSIZE - 1, "/proc/%d/statm", pid );
 
300
  buf[ BUFSIZE - 1 ] = '\0';
 
301
  ps->vmURss = -1;
 
302
  if ( ( fd = fopen( buf, "r" ) ) != 0 )  {
 
303
    unsigned long shared;
 
304
    if ( fscanf( fd, "%*d %*u %lu",
 
305
                   &shared)==1) {
 
306
      /* we use the rss - shared  to find the amount of memory just this app uses */
 
307
      ps->vmURss = ps->vmRss - (shared * sysconf(_SC_PAGESIZE) / 1024);
 
308
    }
 
309
    fclose( fd );
 
310
  }
 
311
 
 
312
 
 
313
  /* status decoding as taken from fs/proc/array.c */
 
314
  if ( status == 'R' )
 
315
    strcpy( ps->status, "running" );
 
316
  else if ( status == 'S' )
 
317
    strcpy( ps->status, "sleeping" );
 
318
  else if ( status == 'D' )
 
319
    strcpy( ps->status, "disk sleep" );
 
320
  else if ( status == 'Z' )
 
321
    strcpy( ps->status, "zombie" );
 
322
  else if ( status == 'T' )
 
323
    strcpy( ps->status, "stopped" );
 
324
  else if ( status == 'W' )
 
325
    strcpy( ps->status, "paging" );
 
326
  else
 
327
    sprintf( ps->status, "Unknown: %c", status );
 
328
 
 
329
 
 
330
  snprintf( buf, BUFSIZE - 1, "/proc/%d/cmdline", pid );
 
331
  if ( ( fd = fopen( buf, "r" ) ) == 0 )
 
332
    return false;
 
333
 
 
334
  ps->cmdline[ 0 ] = '\0';
 
335
 
 
336
  unsigned int i =0;
 
337
  while( (ps->cmdline[i] = fgetc(fd)) != EOF && i < sizeof(ps->cmdline)-3) {
 
338
    if(ps->cmdline[i] == '\0')
 
339
      ps->cmdline[i] = ' ';
 
340
    i++;
 
341
  }
 
342
 
 
343
 
 
344
  if(i > 2) {
 
345
    if(ps->cmdline[i-2] == ' ') ps->cmdline[i-2] = '\0';
 
346
    else ps->cmdline[i-1] = '\0';
 
347
  } else {
 
348
    ps->cmdline[0] = '\0';
 
349
  }
 
350
 
 
351
  validateStr( ps->cmdline );
 
352
  if ( fclose( fd ) )
 
353
    return false;
 
354
 
 
355
  /* Ugly hack to "fix" program name for kdeinit launched programs. */
 
356
  if ( strcmp( ps->name, "kdeinit" ) == 0 &&
 
357
       strncmp( ps->cmdline, "kdeinit: ", KDEINITLEN ) == 0 &&
 
358
       strcmp( ps->cmdline + KDEINITLEN, "Running..." ) != 0 ) {
 
359
    size_t len;
 
360
    char* end = strchr( ps->cmdline + KDEINITLEN, ' ' );
 
361
    if ( end )
 
362
      len = ( end - ps->cmdline ) - KDEINITLEN;
 
363
    else
 
364
      len = strlen( ps->cmdline + KDEINITLEN );
 
365
    if ( len > 0 ) {
 
366
      if ( len > sizeof( ps->name ) - 1 )
 
367
        len = sizeof( ps->name ) - 1;
 
368
      strncpy( ps->name, ps->cmdline + KDEINITLEN, len );
 
369
      ps->name[ len ] = '\0';
 
370
    }
 
371
  }
 
372
  /* find out user name with the process uid */
 
373
  uName = getCachedPWUID( ps->uid );
 
374
  strncpy( ps->userName, uName, sizeof( ps->userName ) - 1 );
 
375
  ps->userName[ sizeof( ps->userName ) - 1 ] = '\0';
 
376
  validateStr( ps->userName );
 
377
 
 
378
  getIOnice(pid, ps);
 
379
 
 
380
  return true;
 
381
}
 
382
 
 
383
void printProcessList( const char* cmd)
 
384
{
 
385
  (void)cmd;
 
386
  struct dirent* entry;
 
387
 
 
388
  ProcessInfo ps;
 
389
  ProcessCount = 0;
 
390
  rewinddir(procDir);
 
391
  while ( ( entry = readdir( procDir ) ) ) {
 
392
    if ( isdigit( entry->d_name[ 0 ] ) ) {
 
393
      long pid;
 
394
      pid = atol( entry->d_name );
 
395
      if(getProcess( pid, &ps )) /* Print out the details of the process.  Because of a stupid bug in kde3 ksysguard, make sure cmdline and tty are not empty */
 
396
        output( "%s\t%ld\t%ld\t%lu\t%lu\t%s\t%lu\t%lu\t%d\t%lu\t%lu\t%lu\t%s\t%ld\t%s\t%s\t%d\t%d\n",
 
397
             ps.name, pid, (long)ps.ppid,
 
398
             (long)ps.uid, (long)ps.gid, ps.status, ps.userTime,
 
399
             ps.sysTime, ps.niceLevel, ps.vmSize, ps.vmRss, ps.vmURss,
 
400
             (ps.userName[0]==0)?" ":ps.userName, (long)ps.tracerpid,
 
401
             (ps.tty[0]==0)?" ":ps.tty, (ps.cmdline[0]==0)?" ":ps.cmdline,
 
402
             ps.ioPriorityClass, ps.ioPriority
 
403
        );
 
404
    }
 
405
  }
 
406
  output( "\n" );
 
407
  return;
 
408
}
 
409
 
 
410
void getIOnice( int pid, ProcessInfo *ps ) {
 
411
#ifdef HAVE_IONICE
 
412
  int ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid);  /* Returns from 0 to 7 for the iopriority, and -1 if there's an error */
 
413
  if(ioprio == -1) {
 
414
      ps->ioPriority = -1;
 
415
      ps->ioPriorityClass = -1;
 
416
      return; /* Error. Just give up. */
 
417
  }
 
418
  ps->ioPriority = ioprio & 0xff;  /* Bottom few bits are the priority */
 
419
  ps->ioPriorityClass = ioprio >> IOPRIO_CLASS_SHIFT; /* Top few bits are the class */
 
420
#else
 
421
  return;  /* Do nothing, if we do not support this architecture */
 
422
#endif
 
423
}
 
424
 
 
425
 
 
426
/*
 
427
================================ public part =================================
 
428
*/
 
429
 
 
430
void initProcessList( struct SensorModul* sm )
 
431
{
 
432
  initPWUIDCache();
 
433
 
 
434
  registerMonitor( "pscount", "integer", printProcessCount, printProcessCountInfo, sm );
 
435
  registerMonitor( "ps", "table", printProcessList, printProcessListInfo, sm );
 
436
 
 
437
  if ( !RunAsDaemon ) {
 
438
    registerCommand( "kill", killProcess );
 
439
    registerCommand( "setpriority", setPriority );
 
440
#ifdef HAVE_IONICE
 
441
    registerCommand( "ionice", ioniceProcess );
 
442
#endif
 
443
  }
 
444
 
 
445
  /*open /proc now in advance*/
 
446
  /* read in current process list via the /proc file system entry */
 
447
  if ( ( procDir = opendir( "/proc" ) ) == NULL ) {
 
448
    print_error( "Cannot open directory \'/proc\'!\n"
 
449
                 "The kernel needs to be compiled with support\n"
 
450
                 "for /proc file system enabled!\n" );
 
451
    return;
 
452
  }
 
453
}
 
454
 
 
455
void exitProcessList( void )
 
456
{
 
457
  removeMonitor( "ps" );
 
458
  removeMonitor( "pscount" );
 
459
 
 
460
  if ( !RunAsDaemon ) {
 
461
    removeCommand( "kill" );
 
462
    removeCommand( "setpriority" );
 
463
  }
 
464
  closedir( procDir );
 
465
 
 
466
  exitPWUIDCache();
 
467
}
 
468
 
 
469
void printProcessListInfo( const char* cmd )
 
470
{
 
471
  (void)cmd;
 
472
  output( "Name\tPID\tPPID\tUID\tGID\tStatus\tUser Time\tSystem Time\tNice\tVmSize"
 
473
                          "\tVmRss\tVmURss\tLogin\tTracerPID\tTTY\tCommand\tIO Priority Class\tIO Priority\n" );
 
474
  output( "s\td\td\td\td\tS\td\td\td\tD\tD\tD\ts\td\ts\ts\td\td\n" );
 
475
}
 
476
 
 
477
void printProcessCount( const char* cmd )
 
478
{
 
479
  (void)cmd;
 
480
  struct dirent* entry;
 
481
  ProcessCount = 0;
 
482
  rewinddir(procDir);
 
483
  while ( ( entry = readdir( procDir ) ) )
 
484
    if ( isdigit( entry->d_name[ 0 ] ) )
 
485
      ProcessCount++;
 
486
 
 
487
 
 
488
  output( "%d\n", ProcessCount );
 
489
}
 
490
 
 
491
void printProcessCountInfo( const char* cmd )
 
492
{
 
493
  (void)cmd;
 
494
  output( "Number of Processes\t0\t0\t\n" );
 
495
}
 
496
 
 
497
void killProcess( const char* cmd )
 
498
{
 
499
  /* Sends a signal (not necessarily kill!) to the process.  cmd is a string containing "kill <pid> <signal>" */
 
500
  int sig, pid;
 
501
 
 
502
  sscanf( cmd, "%*s %d %d", &pid, &sig );
 
503
  switch( sig ) {
 
504
    case MENU_ID_SIGABRT:
 
505
      sig = SIGABRT;
 
506
      break;
 
507
    case MENU_ID_SIGALRM:
 
508
      sig = SIGALRM;
 
509
      break;
 
510
    case MENU_ID_SIGCHLD:
 
511
      sig = SIGCHLD;
 
512
      break;
 
513
    case MENU_ID_SIGCONT:
 
514
      sig = SIGCONT;
 
515
      break;
 
516
    case MENU_ID_SIGFPE:
 
517
      sig = SIGFPE;
 
518
      break;
 
519
    case MENU_ID_SIGHUP:
 
520
      sig = SIGHUP;
 
521
      break;
 
522
    case MENU_ID_SIGILL:
 
523
      sig = SIGILL;
 
524
      break;
 
525
    case MENU_ID_SIGINT:
 
526
      sig = SIGINT;
 
527
      break;
 
528
    case MENU_ID_SIGKILL:
 
529
      sig = SIGKILL;
 
530
      break;
 
531
    case MENU_ID_SIGPIPE:
 
532
      sig = SIGPIPE;
 
533
      break;
 
534
    case MENU_ID_SIGQUIT:
 
535
      sig = SIGQUIT;
 
536
      break;
 
537
    case MENU_ID_SIGSEGV:
 
538
      sig = SIGSEGV;
 
539
      break;
 
540
    case MENU_ID_SIGSTOP:
 
541
      sig = SIGSTOP;
 
542
      break;
 
543
    case MENU_ID_SIGTERM:
 
544
      sig = SIGTERM;
 
545
      break;
 
546
    case MENU_ID_SIGTSTP:
 
547
      sig = SIGTSTP;
 
548
      break;
 
549
    case MENU_ID_SIGTTIN:
 
550
      sig = SIGTTIN;
 
551
      break;
 
552
    case MENU_ID_SIGTTOU:
 
553
      sig = SIGTTOU;
 
554
      break;
 
555
    case MENU_ID_SIGUSR1:
 
556
      sig = SIGUSR1;
 
557
      break;
 
558
    case MENU_ID_SIGUSR2:
 
559
      sig = SIGUSR2;
 
560
      break;
 
561
  }
 
562
 
 
563
  if ( kill( (pid_t)pid, sig ) ) {
 
564
    switch ( errno ) {
 
565
      case EINVAL:
 
566
        output( "4\t%d\n", pid );
 
567
        break;
 
568
      case ESRCH:
 
569
        output( "3\t%d\n", pid );
 
570
        break;
 
571
      case EPERM:
 
572
        if(vfork() == 0) {
 
573
          exit(0);/* Won't execute unless execve fails.  Need this for the parent process to continue */
 
574
        }
 
575
        output( "2\t%d\n", pid );
 
576
        break;
 
577
      default: /* unknown error */
 
578
        output( "1\t%d\n", pid );
 
579
        break;
 
580
    }
 
581
  } else
 
582
    output( "0\t%d\n", pid );
 
583
}
 
584
 
 
585
void setPriority( const char* cmd )
 
586
{
 
587
  int pid, prio;
 
588
  /** as:  setpriority <pid> <priority> */
 
589
  sscanf( cmd, "%*s %d %d", &pid, &prio );
 
590
  if ( setpriority( PRIO_PROCESS, pid, prio ) ) {
 
591
    switch ( errno ) {
 
592
      case EINVAL:
 
593
        output( "4\t%d\t%d\n", pid, prio  );
 
594
        break;
 
595
      case ESRCH:
 
596
        output( "3\t%d\t%d\nn", pid, prio );
 
597
        break;
 
598
      case EPERM:
 
599
      case EACCES:
 
600
        output( "2\t%d\t%d\n", pid, prio );
 
601
        break;
 
602
      default: /* unknown error */
 
603
        output( "1\t%d\t%d\n", pid, prio );
 
604
        break;
 
605
    }
 
606
  } else
 
607
    output( "0\t%d\t%d\n",pid, prio );
 
608
}
 
609
 
 
610
void ioniceProcess( const char* cmd )
 
611
{
 
612
  /* Re-ionice's a process. cmd is a string containing:
 
613
   *
 
614
   * ionice <pid> <class> <priority>
 
615
   *
 
616
   * where c = 1 for real time, 2 for best-effort, 3 for idle
 
617
   * and priority is between 0 and 7, 0 being the highest priority, and ignored if c=3
 
618
   *
 
619
   * For more information, see:  man ionice
 
620
   *
 
621
   */
 
622
  int pid = 0;
 
623
  int class = 2;
 
624
  int priority = 0;
 
625
  if(sscanf( cmd, "%*s %d %d %d", &pid, &class, &priority ) < 2) {
 
626
    output( "4\t%d\n", pid ); /* 4 means error in values */
 
627
    return; /* Error with input. */
 
628
  }
 
629
 
 
630
#ifdef HAVE_IONICE
 
631
  if(pid < 1 || class < 0 || class > 3) {
 
632
    output( "4\t%d\n", pid ); /* 4 means error in values */
 
633
    return; /* Error with input. Just ignore. */
 
634
  }
 
635
 
 
636
  if (ioprio_set(IOPRIO_WHO_PROCESS, pid, priority | class << IOPRIO_CLASS_SHIFT) == -1) {
 
637
    switch ( errno ) {
 
638
      case EINVAL:
 
639
        output( "4\t%d\n", pid );
 
640
        break;
 
641
      case ESRCH:
 
642
        output( "3\t%d\n", pid );
 
643
        break;
 
644
      case EPERM:
 
645
        output( "2\t%d\n", pid );
 
646
        break;
 
647
      default: /* unknown error */
 
648
        output( "1\t%d\n", pid );
 
649
        break;
 
650
    }
 
651
  } else {
 
652
    /* Successful */
 
653
    output( "0\t%d\n", pid );
 
654
  }
 
655
  return;
 
656
#else
 
657
  /** should never reach here */
 
658
  output( "1\t%d\n", pid );
 
659
  return;
 
660
#endif
 
661
}