Updated with Tizen:Base source codes
[external/procps.git] / ps / select.c
1 /*
2  * Copyright 1998-2002 by Albert Cahalan; all rights resered.         
3  * This file may be used subject to the terms and conditions of the
4  * GNU Library General Public License Version 2, or any later version  
5  * at your option, as published by the Free Software Foundation.
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU Library General Public License for more details.
10  */                                 
11
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15
16 #include "common.h"
17 #include "../proc/readproc.h"
18 #include "../proc/procps.h"
19
20 //#define process_group_leader(p) ((p)->pgid    == (p)->tgid)
21 //#define some_other_user(p)      ((p)->euid    != cached_euid)
22 #define has_our_euid(p)         ((unsigned)(p)->euid    == (unsigned)cached_euid)
23 #define on_our_tty(p)           ((unsigned)(p)->tty == (unsigned)cached_tty)
24 #define running(p)              (((p)->state=='R')||((p)->state=='D'))
25 #define session_leader(p)       ((p)->session == (p)->tgid)
26 #define without_a_tty(p)        (!(p)->tty)
27
28 static unsigned long select_bits = 0;
29
30 /***** prepare select_bits for use */
31 const char *select_bits_setup(void){
32   int switch_val = 0;
33   /* don't want a 'g' screwing up simple_select */
34   if(!simple_select && !prefer_bsd_defaults){
35     select_bits = 0xaa00; /* the STANDARD selection */
36     return NULL;
37   }
38   /* For every BSD but SunOS, the 'g' option is a NOP. (enabled by default) */
39   if( !(personality & PER_NO_DEFAULT_g) && !(simple_select&(SS_U_a|SS_U_d)) )
40     switch_val = simple_select|SS_B_g;
41   else
42     switch_val = simple_select;
43   switch(switch_val){
44   /* UNIX options */
45   case SS_U_a | SS_U_d:           select_bits = 0x3f3f; break; /* 3333 or 3f3f */
46   case SS_U_a:                    select_bits = 0x0303; break; /* 0303 or 0f0f */
47   case SS_U_d:                    select_bits = 0x3333; break;
48   /* SunOS 4 only (others have 'g' enabled all the time) */
49   case 0:                         select_bits = 0x0202; break;
50   case                   SS_B_a:  select_bits = 0x0303; break;
51   case          SS_B_x         :  select_bits = 0x2222; break;
52   case          SS_B_x | SS_B_a:  select_bits = 0x3333; break;
53   /* General BSD options */
54   case SS_B_g                  :  select_bits = 0x0a0a; break;
55   case SS_B_g |          SS_B_a:  select_bits = 0x0f0f; break;
56   case SS_B_g | SS_B_x         :  select_bits = 0xaaaa; break;
57   case SS_B_g | SS_B_x | SS_B_a:  /* convert to -e instead of using 0xffff */
58     all_processes = 1;
59     simple_select = 0;
60     break;
61   default:
62     return "Process selection options conflict.";
63     break;
64   }
65   return NULL;
66 }
67
68 /***** selected by simple option? */
69 static int table_accept(proc_t *buf){
70   unsigned proc_index;
71   proc_index = (has_our_euid(buf)    <<0)
72              | (session_leader(buf)  <<1)
73              | (without_a_tty(buf)   <<2)
74              | (on_our_tty(buf)      <<3);
75   return (select_bits & (1<<proc_index));
76 }
77
78 /***** selected by some kind of list? */
79 static int proc_was_listed(proc_t *buf){
80   selection_node *sn = selection_list;
81   int i;
82   if(!sn) return 0;
83   while(sn){
84     switch(sn->typecode){
85     default:
86       printf("Internal error in ps! Please report this bug.\n");
87
88 #define return_if_match(foo,bar) \
89         i=sn->n; while(i--) \
90         if((unsigned)(buf->foo) == (unsigned)(*(sn->u+i)).bar) \
91         return 1
92
93     break; case SEL_RUID: return_if_match(ruid,uid);
94     break; case SEL_EUID: return_if_match(euid,uid);
95     break; case SEL_SUID: return_if_match(suid,uid);
96     break; case SEL_FUID: return_if_match(fuid,uid);
97
98     break; case SEL_RGID: return_if_match(rgid,gid);
99     break; case SEL_EGID: return_if_match(egid,gid);
100     break; case SEL_SGID: return_if_match(sgid,gid);
101     break; case SEL_FGID: return_if_match(fgid,gid);
102
103     break; case SEL_PGRP: return_if_match(pgrp,pid);
104     break; case SEL_PID : return_if_match(tgid,pid);
105     break; case SEL_PPID: return_if_match(ppid,ppid);
106     break; case SEL_TTY : return_if_match(tty,tty);
107     break; case SEL_SESS: return_if_match(session,pid);
108
109     break; case SEL_COMM: i=sn->n; while(i--)
110     if(!strncmp( buf->cmd, (*(sn->u+i)).cmd, 15 )) return 1;
111
112
113
114 #undef return_if_match
115
116     }
117     sn = sn->next;
118   }
119   return 0;
120 }
121
122
123 /***** This must satisfy Unix98 and as much BSD as possible */
124 int want_this_proc(proc_t *buf){
125   int accepted_proc = 1; /* assume success */
126   /* elsewhere, convert T to list, U sets x implicitly */
127
128   /* handle -e -A */
129   if(all_processes) goto finish;
130
131   /* use table for -a a d g x */
132   if((simple_select || !selection_list))
133     if(table_accept(buf)) goto finish;
134
135   /* search lists */
136   if(proc_was_listed(buf)) goto finish;
137
138   /* fail, fall through to loose ends */
139   accepted_proc = 0;
140
141   /* do r N */
142 finish:
143   if(running_only && !running(buf)) accepted_proc = 0;
144   if(negate_selection) return !accepted_proc;
145   return accepted_proc;
146 }