source: trunk/src/sh_processcheck.c @ 539

Last change on this file since 539 was 539, checked in by katerina, 3 years ago

Fixes for tickets #431 (OpenBSD compatibility) and #432 (compiler warnings).

File size: 35.5 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 2006 Rainer Wichmann                                      */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20/***************************************************************************
21 *
22 * This file provides a module for samhain to check for hidden/faked/missing
23 * processes on the host.
24 *
25 */
26
27#include "config_xor.h"
28
29/* changed from 500 to 600 b/o FreeBSD (see sys/cdefs.h)
30 * which needs _POSIX_C_SOURCE >= 200112 for lstat()
31 */
32#if defined(__sun) || defined(__sun__) || defined(sun)
33#define _XOPEN_SOURCE 500
34#else
35#define _XOPEN_SOURCE 600
36#endif
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <ctype.h>
41#include <string.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <dirent.h>
45#include <signal.h>
46#include <unistd.h>
47
48#ifdef _POSIX_PRIORITY_SCHEDULING
49#include <sched.h>
50#endif
51
52#ifdef HAVE_GETPRIORITY
53#include <errno.h>
54#include <sys/resource.h>
55#endif
56
57#ifdef HAVE_SYS_STATVFS_H
58#include <sys/statvfs.h>
59#endif
60
61
62#ifdef HAVE_REGEX_H
63#include <regex.h>
64#endif
65
66#include "samhain.h"
67#include "sh_modules.h"
68#include "sh_processcheck.h"
69#include "sh_utils.h"
70#include "sh_error.h"
71#include "sh_extern.h"
72#include "sh_calls.h"
73#include "sh_pthread.h"
74
75#ifdef SH_USE_PROCESSCHECK
76
77#define FIL__  _("sh_processcheck.c")
78
79#ifdef __linux__
80#define PS_THREADS
81#endif
82
83/* We won't want to build this into yule
84 */
85#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
86
87SH_MUTEX_STATIC(mutex_proc_check, PTHREAD_MUTEX_INITIALIZER);
88
89/* sh_prochk_maxpid is one more than the largest pid
90 */
91static  size_t  sh_prochk_minpid = 0x0001;
92static  size_t  sh_prochk_maxpid = 0x8000;
93static  size_t  sh_prochk_size   = 0;
94
95static  int     ShProchkActive  = S_TRUE;
96static  short * sh_prochk_res   = NULL; 
97
98static  char  * sh_prochk_pspath = NULL;
99static  char  * sh_prochk_psarg  = NULL;
100
101#define SH_PROCHK_INTERVAL 300
102static time_t   sh_prochk_interval = SH_PROCHK_INTERVAL;
103static int      sh_prochk_severity = SH_ERR_SEVERE;
104static int      sh_prochk_openvz   = S_FALSE;
105
106static int sh_prochk_set_maxpid  (const char * str);
107static int sh_prochk_set_minpid  (const char * str);
108static int sh_prochk_set_active  (const char *str);
109static int sh_prochk_add_process (const char *str);
110static int sh_prochk_set_pspath  (const char *str);
111static int sh_prochk_set_psarg   (const char *str);
112static int sh_prochk_set_interval(const char *str);
113static int sh_prochk_set_severity(const char *str);
114static int sh_prochk_set_openvz  (const char *str);
115
116sh_rconf sh_prochk_table[] = {
117    {
118        N_("severityprocesscheck"),
119        sh_prochk_set_severity,
120    },
121    {
122        N_("processcheckexists"),
123        sh_prochk_add_process,
124    },
125    {
126        N_("processcheckactive"),
127        sh_prochk_set_active,
128    },
129    {
130        N_("processcheckminpid"),
131        sh_prochk_set_minpid,
132    },
133    {
134        N_("processcheckmaxpid"),
135        sh_prochk_set_maxpid,
136    },
137    {
138        N_("processcheckpspath"),
139        sh_prochk_set_pspath,
140    },
141    {
142        N_("processcheckpsarg"),
143        sh_prochk_set_psarg,
144    },
145    {
146        N_("processcheckinterval"),
147        sh_prochk_set_interval,
148    },
149    {
150        N_("processcheckisopenvz"),
151        sh_prochk_set_openvz,
152    },
153    {
154        NULL,
155        NULL
156    }
157};
158
159#define    SH_PROC_MISSING 1
160#define    SH_PROC_FAKED   2
161#define    SH_PROC_HIDDEN  4
162#define    SH_PROC_EXISTS  8
163
164#ifndef HAVE_LSTAT
165#define lstat(x,y) stat(x,y)
166#endif /* HAVE_LSTAT */
167
168#if defined(S_IFLNK) && !defined(S_ISLNK)
169#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
170#else
171#if !defined(S_ISLNK)
172#define S_ISLNK(mode) (0)
173#endif
174#endif
175
176static const short SH_PR_PS       = 0x0001;
177
178static const short SH_PR_GETSID   = 0x0002;
179static const short SH_PR_KILL     = 0x0004;
180static const short SH_PR_GETPGID  = 0x0008;
181
182static const short SH_PR_LSTAT    = 0x0010;
183static const short SH_PR_OPENDIR  = 0x0020;
184static const short SH_PR_CHDIR    = 0x0040;
185static const short SH_PR_SCHED    = 0x0080;
186
187static const short SH_PR_PRIORITY = 0x0100;
188static const short SH_PR_STATVSF  = 0x0200;
189
190static const short SH_PR_PS2      = 0x1000;
191static const short SH_PR_PS_ANY   = 0x2000;
192static const short SH_PR_ALL      = 0x4000;
193static const short SH_PR_ANY      = 0x8000;
194
195/* /proc:
196 *        linux:     /proc/pid/exe
197 *        freebsd:   /proc/pid/file
198 *        solaris10: /proc/pid/path/a.out
199 */
200static char * get_user_and_path (pid_t pid, char * user, size_t usrlen)
201{
202  extern char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
203
204  char        path[128];
205  char *      buf;
206  struct stat sbuf;
207  int         len;
208  char *      tmp;
209
210  sl_snprintf (path, sizeof(path), _("/proc/%ld/exe"), (unsigned long) pid);
211
212  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
213    {
214      goto linkread;
215    }
216
217  sl_snprintf (path, sizeof(path), _("/proc/%ld/file"), (unsigned long) pid);
218
219  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
220    {
221      goto linkread;
222    }
223
224  sl_snprintf (path, sizeof(path), _("/proc/%ld/path/a.out"), (unsigned long) pid);
225
226  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
227    {
228      goto linkread;
229    }
230
231  return NULL;
232
233 linkread:
234
235  buf = SH_ALLOC(PATH_MAX);
236  len = readlink(path, buf, PATH_MAX);   /* flawfinder: ignore */
237  len = (len >= PATH_MAX) ? (PATH_MAX-1) : len;
238
239  if (len > 0)
240    { 
241      buf[len] = '\0';
242    }
243  else
244    {
245      SH_FREE(buf);
246      return NULL;
247    }
248
249  tmp = sh_unix_getUIDname (SH_ERR_ALL, sbuf.st_uid, user, usrlen);
250
251  if (!tmp)
252    sl_snprintf (user, usrlen, "%ld", (unsigned long) sbuf.st_uid);
253
254  return buf;
255}
256
257
258struct watchlist {
259  char        * str;
260  unsigned long pid;
261#ifdef HAVE_REGEX_H
262  regex_t       preg;
263#endif
264  int           seen;
265
266  struct watchlist *next;
267};
268
269static struct watchlist * process_check = NULL;
270
271static struct watchlist * list_missing  = NULL;
272static struct watchlist * list_fake     = NULL;
273static struct watchlist * list_hidden   = NULL;
274
275/* recursively remove all list entries
276 */
277static void kill_list (struct watchlist * head)
278{
279  if (head->next)
280    kill_list (head->next);
281
282  if (head->str)
283    SH_FREE(head->str);
284  SH_FREE(head);
285
286  return;
287}
288
289 
290/* check the list for old entries; clean out old entries; reset others
291 * Return number of non-obsolete entries
292 */
293static size_t clean_list (struct watchlist ** head_ptr)
294{
295  size_t count = 0;
296  struct watchlist * ptr = *head_ptr;
297  struct watchlist * pre = *head_ptr;
298
299  while (ptr)
300    {
301      if (ptr->seen == S_FALSE) /* obsolete entry */
302        {
303          if (ptr == pre)       /* at head        */
304            {
305              ptr       = pre->next;
306              *head_ptr = pre->next;
307              if (pre->str) 
308                SH_FREE(pre->str);
309              SH_FREE(pre);
310              pre       = ptr;
311            }
312          else
313            {
314              pre->next = ptr->next;
315              if (ptr->str) 
316                SH_FREE(ptr->str);
317              SH_FREE(ptr);
318              ptr       = pre->next;
319            }
320        }
321      else
322        {
323          ++count;
324          ptr->seen = S_FALSE; /* reset status */
325          pre = ptr;
326          ptr = ptr->next;
327        }
328    }
329  return count;
330}
331
332/* check if process is in list; if not, add it and return false
333 */
334static int  is_in_list (struct watchlist ** head_ptr, 
335                        char * str, unsigned long pid)
336{
337  struct watchlist * ptr = *head_ptr;
338
339  if (str)
340    {
341      while (ptr)
342        {
343          if (ptr->str && (0 == strcmp(str, ptr->str)))
344            {
345              ptr->seen = S_TRUE;
346              return S_TRUE;
347            }
348          ptr = ptr->next;
349        }
350    }
351  else
352    {
353      while (ptr)
354        {
355          if (ptr->pid == pid)
356            {
357              ptr->seen = S_TRUE;
358              return S_TRUE;
359            }
360          ptr = ptr->next;
361        }
362    }
363
364  ptr = SH_ALLOC(sizeof(struct watchlist));
365
366  if (str)
367    {
368      ptr->str = sh_util_strdup(str);
369    }
370  else
371    {
372      ptr->str = NULL;
373      ptr->pid = pid;
374    }
375  ptr->next = *head_ptr;
376  ptr->seen = S_TRUE;
377  *head_ptr = ptr;
378
379  return S_FALSE;
380}
381
382static int is_in_watchlist (const char *str, unsigned long num)
383{
384  struct watchlist * list = process_check;
385
386  while (list) 
387    {
388#ifdef HAVE_REGEX_H
389      if (0 == regexec(&(list->preg), str, 0, NULL, 0))
390        {
391          list->seen = S_TRUE;
392          list->pid  = num;
393          return S_TRUE;
394        }
395#else
396      if (strstr(str, list->str)) 
397        {
398          list->seen = S_TRUE;
399          list->pid  = num;
400          return S_TRUE;
401        }
402#endif
403      list = list->next;
404    }
405  return S_FALSE;
406} 
407
408/* These variables are not used anywhere. They only exist
409 * to assign &userold, &user to them, which keeps gcc from
410 * putting them into a register, and avoids the 'clobbered
411 * by longjmp' warning. And no, 'volatile' proved insufficient.
412 */
413void * sh_dummy_413_watchlist = NULL;
414
415static void check_watchlist (short * res)
416{
417  struct watchlist * list = process_check;
418  char * tmp;
419  size_t indx;
420
421  /* Take the address to keep gcc from putting them into registers.
422   * Avoids the 'clobbered by longjmp' warning.
423   */
424  sh_dummy_413_watchlist = (void*) &list;
425
426  while (list) 
427    {
428      if (list->seen == S_FALSE)
429        {
430          /* avoid repetition of messages
431           */
432          if (S_FALSE == is_in_list(&list_missing, list->str, 0))
433            {
434              SH_MUTEX_LOCK(mutex_thread_nolog);
435              tmp = sh_util_safe_name (list->str);
436              sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0, 
437                              MSG_PCK_MISS,
438                              tmp);
439              SH_FREE(tmp);
440              SH_MUTEX_UNLOCK(mutex_thread_nolog);
441            }
442        }
443      else
444        {
445          indx = list->pid - sh_prochk_minpid;
446
447          if (list->pid < sh_prochk_maxpid && list->pid >= sh_prochk_minpid && 
448              ((res[indx] & SH_PR_ANY) == 0) && /* not found         */
449              ((res[indx] & SH_PR_PS)  != 0) && /* seen in first ps  */ 
450              ((res[indx] & SH_PR_PS2) != 0))   /* seen in second ps */
451            {
452              /* fake process, thus considered missing
453               */
454              if (S_FALSE == is_in_list(&list_missing, list->str, 0))
455                {
456                  SH_MUTEX_LOCK(mutex_thread_nolog);
457                  tmp = sh_util_safe_name (list->str);
458                  sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0, 
459                                  MSG_PCK_MISS, 
460                                  tmp);
461                  SH_FREE(tmp);
462                  SH_MUTEX_UNLOCK(mutex_thread_nolog);
463                }
464            }
465          list->seen = S_FALSE;
466        }
467      list = list->next;
468    }
469
470  sh_dummy_413_watchlist = NULL;
471  return;
472}
473
474/* Add 'str' to the list of watched processes for which
475 * existence should be checked.
476 */
477int sh_prochk_add_process (const char *str) 
478{
479  struct watchlist *new;
480  int               status;
481  char              errbuf[256];
482   
483  SL_ENTER(_("sh_prochk_add_process"));
484
485  if( str == NULL )
486    SL_RETURN(-1, _("sh_prochk_add_process") );
487
488  new       = SH_ALLOC(sizeof(struct watchlist));
489  new->next = process_check;
490  new->str  = sh_util_strdup(str);
491#ifdef HAVE_REGEX_H
492  status = regcomp(&(new->preg), str, REG_NOSUB|REG_EXTENDED);
493  if (status != 0)
494    {
495      regerror(status, &(new->preg), errbuf, sizeof(errbuf));
496      SH_MUTEX_LOCK(mutex_thread_nolog);
497      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, 
498                      errbuf, _("sh_processes_add_process"));
499      SH_MUTEX_UNLOCK(mutex_thread_nolog);
500      SH_FREE(new->str);
501      SH_FREE(new);
502      SL_RETURN(-1, _("sh_prochk_add_process") );
503    }
504#endif
505  new->pid  = 0;
506  new->seen = S_FALSE;
507
508  process_check = new;
509  SL_RETURN(0, _("sh_prochk_add_process") );
510}
511
512/* severity
513 */
514int sh_prochk_set_severity  (const char * c)
515{
516  char tmp[32];
517  tmp[0] = '='; tmp[1] = '\0';
518  sl_strlcat (tmp, c, 32);
519  return sh_error_set_level (tmp, &sh_prochk_severity);
520}
521
522
523
524/* Path to ps
525 */
526int sh_prochk_set_pspath(const char *str) 
527{
528  SL_ENTER(_("sh_prochk_set_pspath"));
529
530  if (!str || ('/' != str[0]))
531    SL_RETURN((-1), _("sh_prochk_set_pspath"));
532  if (sh_prochk_pspath)
533    SH_FREE(sh_prochk_pspath);
534#ifdef SH_EVAL_SHELL
535  sh_prochk_pspath = sh_util_strdup (str);
536  SL_RETURN((0), _("sh_prochk_set_pspath"));
537#else
538  sh_prochk_pspath = NULL;
539  SL_RETURN((-1), _("sh_prochk_set_pspath"));
540#endif
541}
542
543/* argument for ps
544 */
545int sh_prochk_set_psarg(const char *str) 
546{
547  SL_ENTER(_("sh_prochk_set_psarg"));
548
549  if (sh_prochk_psarg)
550    SH_FREE(sh_prochk_psarg);
551#ifdef SH_EVAL_SHELL
552  sh_prochk_psarg = sh_util_strdup (str);
553  SL_RETURN((0), _("sh_prochk_set_psarg"));
554#else
555  (void) str;
556  sh_prochk_psarg = NULL;
557  SL_RETURN((-1), _("sh_prochk_set_psarg"));
558#endif
559}
560
561
562/* Decide if we're active.
563 */
564int sh_prochk_set_active(const char *str) 
565{
566  int value;
567   
568  SL_ENTER(_("sh_prochk_set_active"));
569
570  value = sh_util_flagval(str, &ShProchkActive);
571
572  SL_RETURN((value), _("sh_prochk_set_active"));
573}
574
575/* Are we on openvz.
576 */
577static int openvz_hidden = 0;
578
579int sh_prochk_set_openvz(const char *str) 
580{
581  int value;
582   
583  SL_ENTER(_("sh_prochk_set_openvz"));
584
585  value = sh_util_flagval(str, &sh_prochk_openvz);
586
587  if (sh_prochk_openvz != S_FALSE) {
588    openvz_hidden = 1;
589  }
590
591  SL_RETURN((value), _("sh_prochk_set_openvz"));
592}
593
594/* Minimum PID
595 */
596int sh_prochk_set_minpid(const char * str)
597{
598  size_t  value;
599  char * foo;
600  int    retval = 0;
601
602  SL_ENTER(_("sh_prochk_set_minpid"));
603
604  value = (size_t) strtoul(str, &foo, 0);
605  if (*foo != '\0')
606    retval = -1;
607  else
608    sh_prochk_minpid = value;
609
610  SL_RETURN((retval), _("sh_prochk_set_minpid"));
611}
612
613/* Maximum PID
614 */
615static int userdef_maxpid = 0;
616
617int sh_prochk_set_maxpid(const char * str)
618{
619  size_t  value;
620  char * foo;
621  int    retval = -1;
622
623  SL_ENTER(_("sh_prochk_set_maxpid"));
624
625  value = (size_t) strtoul(str, &foo, 0);
626
627  if (*foo == '\0' && S_TRUE == sl_ok_adds(value, 1)) {
628    sh_prochk_maxpid = value + 1;
629    userdef_maxpid   = 1;
630    retval = 0;
631  }
632
633  SL_RETURN((retval), _("sh_prochk_set_maxpid"));
634}
635
636int sh_prochk_set_interval (const char * c)
637{
638  int retval = 0;
639  long val;
640
641  SL_ENTER(_("sh_prochk_set_interval"));
642  val = strtol (c, (char **)NULL, 10);
643  if (val <= 0)
644    {
645      SH_MUTEX_LOCK(mutex_thread_nolog);
646      sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
647                       _("process check interval"), c);
648      SH_MUTEX_UNLOCK(mutex_thread_nolog);
649      retval = -1;
650    }
651  else
652    {
653      sh_prochk_interval = (time_t) val;
654    }
655  SL_RETURN(retval, _("sh_prochk_set_interval"));
656}
657
658
659
660/* Recurse to the end of the list and then free the data as we return
661 * back up towards the start, making sure to free any strdupped strings
662 */
663static void sh_prochk_free_list(struct watchlist *head) 
664{
665  if ( head != NULL ) 
666    {
667      sh_prochk_free_list(head->next);
668      if (head->str)
669        SH_FREE(head->str);
670#ifdef HAVE_REGEX_H
671      regfree(&(head->preg));
672#endif
673      SH_FREE(head);
674    }
675  return;
676}
677
678#if defined(__linux__)
679#define PROC_PID_MAX _("/proc/sys/kernel/pid_max")
680
681static int proc_max_pid (size_t * procpid)
682{
683  char * ret;
684  unsigned long  pid;
685  FILE * fd;
686  char   str[128];
687  char * ptr;
688
689  SL_ENTER(_("proc_max_pid"));
690
691  if (userdef_maxpid != 0)
692    SL_RETURN((-1), _("proc_max_pid"));
693   
694  if (0 == access(PROC_PID_MAX, R_OK)) /* flawfinder: ignore */
695    {
696      if (NULL != (fd = fopen(PROC_PID_MAX, "r")))
697        {
698          str[0] = '\0';
699          ret = fgets(str, 128, fd);
700          if (ret && *str != '\0')
701            {
702              pid = strtoul(str, &ptr, 0);
703              if (*ptr == '\0' || *ptr == '\n')
704                {
705                  sl_fclose(FIL__, __LINE__, fd);
706                  *procpid = (size_t) pid;
707                  SL_RETURN(0, _("proc_max_pid"));
708                }
709            }
710          sl_fclose(FIL__, __LINE__, fd);
711        }
712    }
713  SL_RETURN((-1), _("proc_max_pid"));
714}
715#else
716static int proc_max_pid(size_t * dummy)
717{
718  (void) dummy;
719  return -1;
720}
721#endif
722
723static void sh_processes_tlist (char * list, size_t len, short res)
724{
725  if (res & SH_PR_PS)       sl_strlcat(list, _(" ps(initial)"), len);
726  if (res & SH_PR_CHDIR)    sl_strlcat(list, _(" chdir"), len);
727  if (res & SH_PR_OPENDIR)  sl_strlcat(list, _(" opendir"), len);
728  if (res & SH_PR_LSTAT)    sl_strlcat(list, _(" lstat"), len);
729  if (res & SH_PR_PRIORITY) sl_strlcat(list, _(" getpriority"), len);
730  if (res & SH_PR_SCHED)    sl_strlcat(list, _(" sched_getparam"), len);
731  if (res & SH_PR_GETSID)   sl_strlcat(list, _(" getsid"), len);
732  if (res & SH_PR_GETPGID)  sl_strlcat(list, _(" getpgid"), len);
733  if (res & SH_PR_KILL)     sl_strlcat(list, _(" kill"), len);
734  if (res & SH_PR_STATVSF)  sl_strlcat(list, _(" statvfs"), len);
735  if (res & SH_PR_PS2)      sl_strlcat(list, _(" ps(final)"), len);
736  return;
737}
738
739
740static short sh_processes_check (pid_t pid, short res)
741{
742  int  have_checks = 0;
743  int  need_checks = 0;
744#ifdef HAVE_PROCFS
745  char path[128];
746  struct stat buf;
747  DIR * dir;
748  int  retval;
749#if defined(HAVE_STATVFS) && !defined(__FreeBSD__)
750  struct statvfs vfsbuf;
751#endif
752#endif
753
754#if !defined(sun) && !defined(__sun) && !defined(__sun__)
755#ifdef _POSIX_PRIORITY_SCHEDULING
756  struct sched_param p;
757#endif
758#endif
759
760  if (0 == kill(pid, 0))
761    { 
762      res |= SH_PR_KILL;    res |= SH_PR_ANY; ++have_checks;
763      ++need_checks;
764    }
765  else if (errno != EPERM)
766    {
767      ++need_checks;
768    }
769
770
771#ifdef HAVE_GETPGID
772  if ((pid_t)-1 != getpgid(pid))
773    { 
774      res |= SH_PR_GETPGID; res |= SH_PR_ANY; ++have_checks;
775    }
776  ++need_checks;
777#endif
778
779#ifdef HAVE_GETSID
780  if ((pid_t)-1 != getsid(pid))
781    { 
782      res |= SH_PR_GETSID;  res |= SH_PR_ANY; ++have_checks;
783    }
784  ++need_checks;
785#endif
786
787  /* sched_getparam() is broken on solaris 10, may segfault in librt
788   */
789#if !defined(sun) && !defined(__sun) && !defined(__sun__) && !defined(__OpenBSD__)
790#ifdef _POSIX_PRIORITY_SCHEDULING
791  if (0 == sched_getparam (pid, &p))
792    { 
793      res |= SH_PR_SCHED;   res |= SH_PR_ANY; ++have_checks;
794    }
795  ++need_checks;
796#endif
797#endif
798
799#ifdef HAVE_GETPRIORITY
800  errno = 0;
801  if (((-1) == getpriority (PRIO_PROCESS, (int) pid)) && (errno == ESRCH));
802  else
803    { 
804      res |= SH_PR_PRIORITY; res |= SH_PR_ANY; ++have_checks;
805    }
806  ++need_checks;
807#endif
808
809#ifdef HAVE_PROCFS
810  sl_snprintf (path, sizeof(path), "/proc/%ld", (unsigned long) pid);
811
812  do {
813    retval = lstat (path, &buf);
814  } while (retval < 0 && errno == EINTR);
815
816  if (0 == retval)
817    { 
818      res |= SH_PR_LSTAT;   res |= SH_PR_ANY; ++have_checks;
819    }
820  ++need_checks;
821
822  if (NULL != (dir = opendir(path)))
823    {
824      res |= SH_PR_OPENDIR; res |= SH_PR_ANY; ++have_checks;
825      closedir(dir);
826    }
827  ++need_checks;
828
829#if defined(HAVE_STATVFS) && !defined(__FreeBSD__)
830  do {
831    retval = statvfs (path, &vfsbuf);
832  } while (retval < 0 && errno == EINTR);
833
834  if (0 == retval)
835    { 
836      res |= SH_PR_STATVSF;   res |= SH_PR_ANY; ++have_checks;
837    }
838  ++need_checks;
839#endif
840
841#if !defined(SH_PROFILE)
842  if (0 == chdir(path))
843    {
844      res |= SH_PR_CHDIR;   res |= SH_PR_ANY; ++have_checks;
845      do {
846        retval = chdir ("/");
847      } while (retval < 0 && errno == EINTR);
848    }
849  ++need_checks;
850#endif
851#endif
852
853  if (have_checks == need_checks)
854    {
855      res |= SH_PR_ALL;
856    }
857  return res;
858}
859
860extern int flag_err_debug;
861
862static int sh_processes_readps (FILE * in, short * res, 
863                                char * str, size_t len, 
864                                short flag, pid_t pid)
865{
866  int  cc; 
867  volatile unsigned int  lnum   = 0;
868  volatile unsigned long num    = 0;
869  char c;
870  unsigned int  pos = 0;
871#define SH_TWAIT_MAX 60
872  volatile unsigned int  twait = 0;
873  char tstr[256];
874  enum { SKIP_TO_WS, SKIP_WS, SKIP_TO_WS2, SKIP_WS2, GET_NUM, SKIP_END, GET_NUM2 } line;
875
876  SL_ENTER(_("sh_processes_readps"));
877
878  if (!in) {
879    SL_RETURN((-1), _("sh_processes_readps"));
880  }
881
882  tstr[(sizeof(tstr)-1)] = '\0';
883  tstr[0]                = '\0';
884  line = SKIP_END;              /* Skip 1st line */
885
886  do
887    {
888      cc = fgetc(in);
889
890      if (EOF == cc) 
891        {
892          if (feof(in))
893            {
894              break;
895            }
896          else if ((errno == EAGAIN) && (twait < SH_TWAIT_MAX))
897            {
898              clearerr(in);
899              retry_msleep(1, 0);
900              ++twait;
901              continue;
902            }
903#ifdef HOST_IS_OPENBSD
904          else if (errno == ENODEV)
905            {
906              clearerr(in);
907              continue;
908            }
909#endif
910          else
911            {
912              char errbuf[SH_ERRBUF_SIZE];
913
914              SH_MUTEX_LOCK(mutex_thread_nolog);
915              sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, errno, MSG_E_SUBGEN,
916                              sh_error_message(errno, errbuf, sizeof(errbuf)),
917                              _("sh_processes_readps"));
918              SH_MUTEX_UNLOCK(mutex_thread_nolog);
919              break;
920            }
921        }
922
923      c = (char) cc;
924
925      if (pos < (sizeof(tstr)-1))
926        { 
927          tstr[pos] = c; ++pos; 
928        }
929
930      switch(line)
931        {
932        case SKIP_END:
933          if (c == '\n')
934            { 
935              tstr[pos-1] = '\0';
936              if (flag_err_debug == S_TRUE)
937                {
938                  SH_MUTEX_LOCK(mutex_thread_nolog);
939                  sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, num, 
940                                  MSG_E_SUBGEN,
941                                  tstr,
942                                  _("sh_processes_readps"));
943                  SH_MUTEX_UNLOCK(mutex_thread_nolog);
944                }
945              /* fprintf(stderr, "<%ld> %s\n", num, tstr); */
946              line = SKIP_WS; pos = 0;
947              if (str != NULL && num == (unsigned long) pid)
948                sl_strlcpy(str, tstr, len);
949              if (lnum != 0)
950                is_in_watchlist (tstr, num);
951              ++lnum;
952            }
953          break;
954        case SKIP_TO_WS:
955          if (!isspace(cc))
956            break;
957          line = SKIP_WS;
958          /* fallthrough */
959        case SKIP_WS:
960          if (isspace(cc))
961            break;
962          num  = 0;
963          line = GET_NUM;
964          /* fallthrough */
965        case GET_NUM:
966          if (isdigit(cc))
967            {
968              num = num * 10 + (c - '0');
969              break;
970            }
971          else if (isspace(cc))
972            {
973#ifdef PS_THREADS
974              num  = 0;
975              line = SKIP_WS2;
976#else
977              if (num < sh_prochk_maxpid && num >= sh_prochk_minpid)
978                {
979                  res[num - sh_prochk_minpid] |= flag;
980                }
981              line = SKIP_END;
982#endif
983              break;
984            }
985          else
986            {
987              line = SKIP_TO_WS;
988              break;
989            }
990        case SKIP_TO_WS2:
991          if (!isspace(cc))
992            break;
993          line = SKIP_WS2;
994          /* fallthrough */
995        case SKIP_WS2:
996          if (isspace(cc))
997            break;
998          num  = 0;
999          line = GET_NUM2;
1000          /* fallthrough */
1001        case GET_NUM2:
1002          if (isdigit(cc))
1003            {
1004              num = num * 10 + (c - '0');
1005              break;
1006            }
1007          else if (isspace(cc))
1008            {
1009              if (num < sh_prochk_maxpid && num >= sh_prochk_minpid)
1010                {
1011                  res[num - sh_prochk_minpid] |= flag;
1012                }
1013              line = SKIP_END;
1014              break;
1015            }
1016          else
1017            {
1018              line = SKIP_TO_WS2;
1019              break;
1020            }
1021        default:
1022          SL_RETURN ((-1), _("sh_processes_readps"));
1023        }
1024    } while (1);
1025
1026  if (ferror(in))
1027    {
1028      SL_RETURN ((-1), _("sh_processes_readps"));
1029    }
1030
1031  SL_RETURN ((0), _("sh_processes_readps"));
1032}
1033
1034static int sh_processes_runps (short * res, char * str, size_t len, 
1035                               short flag, pid_t pid)
1036{
1037  sh_tas_t task;
1038
1039  int    status = 0;
1040  char * p;
1041  int retval = 0;
1042  char  dir[SH_PATHBUF];
1043
1044  SL_ENTER(_("sh_processes_runps"));
1045
1046  sh_ext_tas_init(&task);
1047  p = sh_unix_getUIDdir (SH_ERR_ERR, task.run_user_uid, dir, sizeof(dir));
1048  if (p)
1049    {
1050      (void) sh_ext_tas_add_envv (&task, _("HOME"), p);
1051    }
1052  (void) sh_ext_tas_add_envv (&task, _("SHELL"), 
1053                              _("/bin/sh")); 
1054  (void) sh_ext_tas_add_envv (&task, _("PATH"), 
1055                              _("/sbin:/usr/sbin:/bin:/usr/bin")); 
1056  if (sh.timezone != NULL)
1057    {
1058      (void) sh_ext_tas_add_envv(&task,  "TZ", sh.timezone);
1059    }
1060
1061  if (!sh_prochk_pspath)
1062    sh_ext_tas_command(&task,  PSPATH);
1063  else
1064    sh_ext_tas_command(&task,  sh_prochk_pspath);
1065
1066  (void) sh_ext_tas_add_argv(&task,  _("ps"));
1067
1068  if (!sh_prochk_psarg)
1069    {
1070#ifdef PS_THREADS
1071      (void) sh_ext_tas_add_argv(&task,  _("-eT"));
1072#else
1073      (void) sh_ext_tas_add_argv(&task,  PSARG);
1074#endif
1075    }
1076  else
1077    {
1078      (void) sh_ext_tas_add_argv(&task,  sh_prochk_psarg);
1079    }
1080
1081  task.rw = 'r';
1082  task.fork_twice = S_FALSE;
1083
1084  status = sh_ext_popen(&task);
1085  if (status != 0)
1086    {
1087      SH_MUTEX_LOCK(mutex_thread_nolog);
1088      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, 
1089                      _("Could not open pipe"), _("sh_processes_runps"));
1090      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1091      SL_RETURN ((-1), _("sh_processes_runps"));
1092    }
1093
1094  /* read from the open pipe
1095   */
1096  if (task.pipe != NULL)
1097    {
1098      retval = sh_processes_readps (task.pipe, res, str, len, flag, pid);
1099    }
1100
1101  /* close pipe and return exit status
1102   */
1103  (void) sh_ext_pclose(&task);
1104  sh_ext_tas_free (&task);
1105  SL_RETURN ((retval), _("sh_processes_runps"));
1106}
1107
1108/* Check whether there is a visible process
1109 * with PID = i + 1024
1110 */
1111static size_t p_store = 0;
1112
1113static int openvz_ok(short * res, size_t i)
1114{
1115
1116  if (sh_prochk_openvz == S_FALSE) {
1117    return 0;
1118  }
1119
1120  i += 1024;
1121
1122  if (i >= sh_prochk_size) {
1123    return 0;
1124  }
1125
1126  if ( ((res[i] & SH_PR_PS) || (res[i] & SH_PR_PS2)) && (res[i] & SH_PR_ANY))
1127    {
1128      /* This is a system process corresponding to a 'virtual'
1129       * process that has a PID offset by 1024
1130       */
1131      return 1;
1132    }
1133
1134  if (openvz_hidden > 0)
1135    {
1136      p_store = i;
1137      --openvz_hidden;
1138      return 1;
1139    }
1140  else if (i == p_store)
1141    {
1142      return 1;
1143    }
1144
1145  return 0;
1146}
1147
1148static int sh_process_check_int (short * res)
1149{
1150  volatile size_t i;
1151  size_t j;
1152  char  tests[512];
1153  volatile int   retval;
1154
1155  pid_t this_pid;
1156
1157  SL_ENTER(_("sh_process_check_int"));
1158
1159  this_pid = getpid();
1160
1161  if (!res)
1162    {
1163      SH_MUTEX_LOCK(mutex_thread_nolog);
1164      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1165                      _("Internal error: NULL argument, switching off"), 
1166                      _("sh_process_check_int"));
1167      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1168      SL_RETURN ((-1), _("sh_process_check_int"));
1169    }
1170
1171  retval = sh_processes_runps (res, NULL, 0, SH_PR_PS, 0);
1172
1173  for (i = sh_prochk_minpid; i != sh_prochk_maxpid; ++i)
1174    {
1175      j      = i - sh_prochk_minpid; 
1176      res[j] = sh_processes_check ((pid_t) i, res[j]);
1177    }
1178
1179  retval += sh_processes_runps (res, NULL, 0, SH_PR_PS2, 0);
1180
1181  if (retval != 0)
1182    {
1183      SH_MUTEX_LOCK(mutex_thread_nolog);
1184      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1185                      _("Failed to run ps, switching off"), 
1186                      _("sh_process_check_int"));
1187      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1188      SL_RETURN ((-1), _("sh_process_check_int"));
1189    }
1190
1191  /* Evaluate results
1192   */
1193  for (i = sh_prochk_minpid; i != sh_prochk_maxpid; ++i)
1194    {
1195      /* don't check the current process
1196       */
1197      if (i == (size_t) this_pid)
1198        continue;
1199
1200      j      = i - sh_prochk_minpid;
1201
1202      if (((res[j] & SH_PR_PS) != 0) || ((res[j] & SH_PR_PS2) != 0))
1203        {
1204          res[j] |= SH_PR_PS_ANY;
1205        }
1206      else
1207        {
1208          res[j] &= ~SH_PR_PS_ANY;
1209        }
1210
1211      tests[0] = '\0';
1212
1213      if ((res[j] & SH_PR_ANY) || (res[j] & SH_PR_PS_ANY))
1214        {
1215          /* list all tests where the pid was found
1216           */
1217          sh_processes_tlist (tests, sizeof(tests), res[j]);
1218
1219          /*
1220           * case 1: in ps and found
1221           */
1222          if ((res[j] & SH_PR_PS_ANY) && (res[j] & SH_PR_ANY))
1223            {
1224              SH_MUTEX_LOCK(mutex_thread_nolog);
1225              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_PCK_OK, 
1226                              (unsigned long) i, tests);
1227              SH_MUTEX_UNLOCK(mutex_thread_nolog);
1228            }
1229
1230          /*
1231           * case 2: not in ps and found
1232           */
1233          else if ((res[j] & SH_PR_PS_ANY) == 0) 
1234            {
1235              res[j] = sh_processes_check ((pid_t) i, 0);
1236              /*
1237               * if still there, it is real and hidden
1238               */
1239              if ((res[j] & SH_PR_ANY) && !openvz_ok(res, j))
1240                {
1241                  if (S_FALSE == is_in_list(&list_hidden, NULL, i))
1242                    {
1243                      char   user[16];
1244                      char * aout;
1245                      char * safe;
1246
1247                      SH_MUTEX_LOCK(mutex_thread_nolog);
1248                      aout = get_user_and_path ((pid_t) i, user, sizeof(user));
1249                      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1250
1251                      if (aout)
1252                        {
1253                          safe = sh_util_safe_name (aout);
1254                          SH_MUTEX_LOCK(mutex_thread_nolog);
1255                          sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0, 
1256                                          MSG_PCK_P_HIDDEN,
1257                                          (unsigned long) i, tests, safe, user);
1258                          SH_MUTEX_UNLOCK(mutex_thread_nolog);
1259                          SH_FREE(safe);
1260                          SH_FREE(aout);
1261                        }
1262                      else
1263                        {
1264                          SH_MUTEX_LOCK(mutex_thread_nolog);
1265                          sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0, 
1266                                          MSG_PCK_HIDDEN,
1267                                          (unsigned long) i, tests);
1268                          SH_MUTEX_UNLOCK(mutex_thread_nolog);
1269                        }
1270                    }
1271                }
1272            }
1273
1274          /*
1275           * case 3: in ps, but not found
1276           */
1277          else
1278            {
1279              if (((res[j] & SH_PR_PS) != 0) && ((res[j] & SH_PR_PS2) != 0))
1280                {
1281                  if (S_FALSE == is_in_list(&list_fake, NULL, i))
1282                    {
1283                      SH_MUTEX_LOCK(mutex_thread_nolog);
1284                      sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0, 
1285                                      MSG_PCK_FAKE, 
1286                                      (unsigned long) i, tests);
1287                      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1288                    }
1289                }
1290            }
1291        }
1292    } /* loop end */
1293
1294  check_watchlist (res);
1295
1296  SL_RETURN (0, _("sh_process_check_int"));
1297}
1298
1299/* Initialise.
1300 */
1301static int sh_prochk_init_internal(void) 
1302{
1303  SL_ENTER(_("sh_prochk_init"));
1304
1305  (void) proc_max_pid (&sh_prochk_maxpid);
1306
1307  if (sh_prochk_minpid > sh_prochk_maxpid)
1308    ShProchkActive = S_FALSE;
1309
1310  /* We need to free anything allocated by the configuration functions if
1311   * we find that the module is to be left inactive - otherwise _reconf()
1312   * won't quite work.
1313   */
1314  if( ShProchkActive == S_FALSE ) 
1315    {
1316      sh_prochk_free_list(process_check);
1317      process_check = NULL;
1318      SL_RETURN(-1, _("sh_prochk_init"));
1319    }
1320
1321  sh_prochk_size = sh_prochk_maxpid - sh_prochk_minpid;
1322
1323  if (sh_prochk_res == NULL)
1324    {
1325      sh_prochk_res  = SH_ALLOC(sizeof(short) * sh_prochk_size);
1326    }
1327  memset (sh_prochk_res, 0, sizeof(short) * sh_prochk_size);
1328 
1329  SL_RETURN(0, _("sh_prochk_init"));
1330}
1331
1332int sh_prochk_init (struct mod_type * arg)
1333{
1334#ifndef HAVE_PTHREAD
1335  (void) arg;
1336#endif
1337
1338  if (ShProchkActive == S_FALSE)
1339    return SH_MOD_FAILED;
1340#ifdef HAVE_PTHREAD
1341  if (arg != NULL && arg->initval < 0 &&
1342      (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1343    {
1344      if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
1345        return SH_MOD_THREAD;
1346      else
1347        return SH_MOD_FAILED;
1348    }
1349  else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
1350           (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1351    {
1352      sh_prochk_init_internal();
1353      return SH_MOD_THREAD;
1354    }
1355#endif
1356  return sh_prochk_init_internal();
1357}
1358
1359int sh_prochk_timer(time_t tcurrent) 
1360{
1361  static time_t lastcheck = 0;
1362
1363  SL_ENTER(_("sh_prochk_timer"));
1364  if ((time_t) (tcurrent - lastcheck) >= sh_prochk_interval)
1365    {
1366      lastcheck  = tcurrent;
1367      SL_RETURN((-1), _("sh_prochk_timer"));
1368    }
1369  SL_RETURN(0, _("sh_prochk_timer"));
1370}
1371
1372int sh_prochk_check(void) 
1373{
1374  int status;
1375
1376  SL_ENTER(_("sh_prochk_check"));
1377
1378  SH_MUTEX_LOCK(mutex_proc_check);
1379
1380  status = 0;
1381
1382  if( ShProchkActive != S_FALSE )
1383    {
1384      SH_MUTEX_LOCK(mutex_thread_nolog);
1385      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_PCK_CHECK, 
1386                      (unsigned long) sh_prochk_minpid, 
1387                      (unsigned long) (sh_prochk_maxpid-1));
1388      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1389
1390      if (sh_prochk_res) {
1391        memset (sh_prochk_res, 0, sizeof(short) * sh_prochk_size);
1392      }
1393      status = sh_process_check_int(sh_prochk_res);
1394
1395      if (status != 0)
1396        ShProchkActive = S_FALSE;
1397
1398      /* clean out old entries which are not marked
1399       * as missing/hidden/fake anymore
1400       */
1401      clean_list (&list_missing);
1402      clean_list (&list_hidden);
1403      clean_list (&list_fake);
1404    }
1405
1406  SH_MUTEX_UNLOCK(mutex_proc_check);
1407
1408  SL_RETURN(status, _("sh_prochk_check"));
1409}
1410
1411/* Free our lists and the associated memory
1412 */
1413int sh_prochk_cleanup(void) 
1414{
1415  SL_ENTER(_("sh_prochk_cleanup"));
1416
1417  sh_prochk_reconf();
1418
1419  if (list_missing) {
1420    kill_list(list_missing);
1421    list_missing = NULL;
1422  }
1423  if (list_hidden) {
1424    kill_list(list_hidden);
1425    list_hidden  = NULL;
1426  }
1427  if (list_fake) {
1428    kill_list(list_fake);
1429    list_fake    = NULL;
1430  }
1431 
1432  SL_RETURN(0, _("sh_prochk_cleanup"));
1433}
1434
1435/* Free our lists and the associated memory
1436 */
1437int sh_prochk_reconf(void) 
1438{
1439  SL_ENTER(_("sh_prochk_reconf"));
1440
1441  SH_MUTEX_LOCK(mutex_proc_check);
1442  userdef_maxpid     = 0;
1443  sh_prochk_maxpid   = 0x8000;
1444  sh_prochk_minpid   = 0x0001;
1445  sh_prochk_interval = SH_PROCHK_INTERVAL;
1446  sh_prochk_openvz   = S_FALSE;
1447  p_store            = 0;
1448  openvz_hidden      = 0;
1449
1450  sh_prochk_free_list(process_check);
1451  process_check = NULL;
1452  if (sh_prochk_res != NULL)
1453    SH_FREE(sh_prochk_res);
1454  sh_prochk_res = NULL;
1455
1456  if (sh_prochk_psarg)
1457    SH_FREE(sh_prochk_psarg);
1458  sh_prochk_psarg = NULL;
1459  if (sh_prochk_pspath)
1460    SH_FREE(sh_prochk_pspath);
1461  sh_prochk_pspath = NULL;
1462  SH_MUTEX_UNLOCK(mutex_proc_check);
1463
1464  SL_RETURN(0, _("sh_prochk_reconf"));
1465}
1466
1467/* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
1468#endif
1469
1470/* #ifdef SH_USE_PROCESSCHECK */
1471#endif
1472
1473
1474#ifdef SH_CUTEST
1475#include "CuTest.h"
1476
1477void Test_processcheck_watchlist_ok (CuTest *tc) {
1478#if defined(SH_USE_PROCESSCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
1479  CuAssertTrue(tc, 0 == sh_prochk_add_process("init"));
1480  CuAssertTrue(tc, 
1481               S_TRUE  == is_in_watchlist("    1 ?        00:00:00 init", 0));
1482  CuAssertTrue(tc, 
1483               S_FALSE == is_in_watchlist("    1 ?        00:00:00 flix", 0));
1484  CuAssertTrue(tc, 
1485               S_TRUE  == is_in_watchlist("25218 ?        SNs    0:01 /usr/sbin/init -k start -DSSL", 0));
1486  CuAssertTrue(tc, 
1487               S_FALSE  == is_in_watchlist("25218 ?        SNs    0:01 /usr/sbin/apache2 -k start -DSSL", 0));
1488
1489
1490  sh_prochk_free_list(process_check);
1491  process_check = NULL;
1492  CuAssertTrue(tc, S_FALSE == is_in_watchlist("init", 0));
1493
1494  CuAssertTrue(tc, 0 == sh_prochk_add_process("init"));
1495  CuAssertTrue(tc, 0 == sh_prochk_add_process("ssh"));
1496  CuAssertTrue(tc, 0 == sh_prochk_add_process("syslog"));
1497  CuAssertTrue(tc, S_TRUE  == is_in_watchlist("init", 0));
1498  CuAssertTrue(tc, S_TRUE  == is_in_watchlist("ssh", 0));
1499  CuAssertTrue(tc, S_TRUE  == is_in_watchlist("syslog", 0));
1500
1501  sh_prochk_free_list(process_check);
1502  process_check = NULL;
1503  CuAssertTrue(tc, S_FALSE == is_in_watchlist("init", 0));
1504  CuAssertTrue(tc, S_FALSE == is_in_watchlist("ssh", 0));
1505  CuAssertTrue(tc, S_FALSE == is_in_watchlist("syslog", 0));
1506#else
1507  (void) tc; /* fix compiler warning */
1508#endif
1509  return;
1510}
1511
1512void Test_processcheck_listhandle_ok (CuTest *tc) {
1513#if defined(SH_USE_PROCESSCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
1514  CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "init", 0));
1515  CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
1516  CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "foobar", 0));
1517  CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
1518
1519  if (list_missing)
1520    kill_list(list_missing);
1521  list_missing = NULL;
1522
1523  CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "init", 0));
1524  CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
1525  CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "foobar", 0));
1526  CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
1527
1528  if (list_missing)
1529    kill_list(list_missing);
1530  list_missing = NULL;
1531
1532  CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "init", 0));
1533  CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
1534  CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "foobar", 0));
1535  CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
1536
1537  CuAssertTrue(tc, 2  == clean_list(&list_missing));
1538  CuAssertPtrNotNull(tc, list_missing);
1539
1540  CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
1541  CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
1542
1543  CuAssertTrue(tc, 2  == clean_list(&list_missing));
1544  CuAssertPtrNotNull(tc, list_missing);
1545
1546  CuAssertTrue(tc, 0  == clean_list(&list_missing));
1547  CuAssertTrue(tc, NULL == list_missing);
1548#else
1549  (void) tc; /* fix compiler warning */
1550#endif
1551  return;
1552}
1553
1554
1555/* #ifdef SH_CUTEST */
1556#endif
1557
Note: See TracBrowser for help on using the repository browser.