last_patch_69, 8 bit clean and other fixes from Vladimir N. Oleynik
[oweals/busybox.git] / libbb / find_pid_by_name.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21
22 #include <stdio.h>
23 #include <ctype.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include "libbb.h"
27
28 #define READ_BUF_SIZE   50
29
30
31 /* For Erik's nifty devps device driver */
32 #ifdef CONFIG_FEATURE_USE_DEVPS_PATCH
33 #include <linux/devps.h> 
34
35 /* find_pid_by_name()
36  *  
37  *  This finds the pid of the specified process,
38  *  by using the /dev/ps device driver.
39  *
40  *  Returns a list of all matching PIDs
41  */
42 extern long* find_pid_by_name( const char* pidName)
43 {
44         int fd, i, j;
45         char device[] = "/dev/ps";
46         pid_t num_pids;
47         pid_t* pid_array = NULL;
48         long* pidList=NULL;
49
50         /* open device */ 
51         fd = open(device, O_RDONLY);
52         if (fd < 0)
53                 perror_msg_and_die("open failed for `%s'", device);
54
55         /* Find out how many processes there are */
56         if (ioctl (fd, DEVPS_GET_NUM_PIDS, &num_pids)<0) 
57                 perror_msg_and_die("\nDEVPS_GET_PID_LIST");
58         
59         /* Allocate some memory -- grab a few extras just in case 
60          * some new processes start up while we wait. The kernel will
61          * just ignore any extras if we give it too many, and will trunc.
62          * the list if we give it too few.  */
63         pid_array = (pid_t*) xcalloc( num_pids+10, sizeof(pid_t));
64         pid_array[0] = num_pids+10;
65
66         /* Now grab the pid list */
67         if (ioctl (fd, DEVPS_GET_PID_LIST, pid_array)<0) 
68                 perror_msg_and_die("\nDEVPS_GET_PID_LIST");
69
70         /* Now search for a match */
71         for (i=1, j=0; i<pid_array[0] ; i++) {
72                 char* p;
73                 struct pid_info info;
74
75             info.pid = pid_array[i];
76             if (ioctl (fd, DEVPS_GET_PID_INFO, &info)<0)
77                         perror_msg_and_die("\nDEVPS_GET_PID_INFO");
78
79                 /* Make sure we only match on the process name */
80                 p=info.command_line+1;
81                 while ((*p != 0) && !isspace(*(p)) && (*(p-1) != '\\')) { 
82                         (p)++;
83                 }
84                 if (isspace(*(p)))
85                                 *p='\0';
86
87                 if ((strstr(info.command_line, pidName) != NULL)
88                                 && (strlen(pidName) == strlen(info.command_line))) {
89                         pidList=xrealloc( pidList, sizeof(long) * (j+2));
90                         pidList[j++]=info.pid;
91                 }
92         }
93         if (pidList) {
94                 pidList[j]=0;
95         } else {
96                 pidList=xrealloc( pidList, sizeof(long));
97                 pidList[0]=-1;
98         }
99
100         /* Free memory */
101         free( pid_array);
102
103         /* close device */
104         if (close (fd) != 0) 
105                 perror_msg_and_die("close failed for `%s'", device);
106
107         return pidList;
108 }
109
110 #else           /* CONFIG_FEATURE_USE_DEVPS_PATCH */
111
112 /* find_pid_by_name()
113  *  
114  *  Modified by Vladimir Oleynik for use with libbb/procps.c
115  *  This finds the pid of the specified process.
116  *  Currently, it's implemented by rummaging through 
117  *  the proc filesystem.
118  *
119  *  Returns a list of all matching PIDs
120  */
121 extern long* find_pid_by_name( const char* pidName)
122 {
123         long* pidList;
124         int i=0;
125         procps_status_t * p;
126
127         pidList = xmalloc(sizeof(long));
128         while ((p = procps_scan(0)) != 0) {
129                 if (strcmp(p->short_cmd, pidName) == 0) {
130                         pidList=xrealloc( pidList, sizeof(long) * (i+2));
131                         pidList[i++]=p->pid;
132                 }
133         }
134
135         pidList[i] = i==0 ? -1 : 0;
136         return pidList;
137 }
138 #endif                                                  /* CONFIG_FEATURE_USE_DEVPS_PATCH */
139
140 /* END CODE */
141 /*
142 Local Variables:
143 c-file-style: "linux"
144 c-basic-offset: 4
145 tab-width: 4
146 End:
147 */