aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-10-18 19:33:06 +0000
committerEric Andersen <andersen@codepoet.org>2001-10-18 19:33:06 +0000
commitc2af1ee03667fbcf5bd456ea26e9f9e317a892a1 (patch)
treee25a68be710fe88ce6db0f4191caa47ba5f43d98
parentbcca3317b59a0180f0b42428e9c25405bc423520 (diff)
downloadbusybox-w32-c2af1ee03667fbcf5bd456ea26e9f9e317a892a1.tar.gz
busybox-w32-c2af1ee03667fbcf5bd456ea26e9f9e317a892a1.tar.bz2
busybox-w32-c2af1ee03667fbcf5bd456ea26e9f9e317a892a1.zip
Commit the start-stop-daemon applet. This was contributed by David
Kimdon <dwhedon@gordian.com> on october 7th -- the day I was fired from Lineo. So it seems I totally forgot about this patch until now. Sorry about that David!
-rw-r--r--Config.h1
-rw-r--r--applets.h3
-rw-r--r--applets/usage.h14
-rw-r--r--debianutils/start_stop_daemon.c271
-rw-r--r--include/applets.h3
-rw-r--r--include/usage.h14
-rw-r--r--init/start_stop_daemon.c271
-rw-r--r--start_stop_daemon.c271
-rw-r--r--usage.h14
9 files changed, 862 insertions, 0 deletions
diff --git a/Config.h b/Config.h
index 99a087165..a62e3fb73 100644
--- a/Config.h
+++ b/Config.h
@@ -114,6 +114,7 @@
114#define BB_SLEEP 114#define BB_SLEEP
115#define BB_SORT 115#define BB_SORT
116//#define BB_STTY 116//#define BB_STTY
117//#define BB_START_STOP_DAEMON
117#define BB_SWAPONOFF 118#define BB_SWAPONOFF
118#define BB_SYNC 119#define BB_SYNC
119#define BB_SYSLOGD 120#define BB_SYSLOGD
diff --git a/applets.h b/applets.h
index 461c878df..5ecfe3cba 100644
--- a/applets.h
+++ b/applets.h
@@ -386,6 +386,9 @@
386#ifdef BB_SORT 386#ifdef BB_SORT
387 APPLET(sort, sort_main, _BB_DIR_USR_BIN) 387 APPLET(sort, sort_main, _BB_DIR_USR_BIN)
388#endif 388#endif
389#ifdef BB_START_STOP_DAEMON
390 APPLET_ODDNAME("start-stop-daemon", start_stop_daemon_main, _BB_DIR_SBIN, start_stop_daemon)
391#endif
389#ifdef BB_STTY 392#ifdef BB_STTY
390 APPLET(stty, stty_main, _BB_DIR_BIN) 393 APPLET(stty, stty_main, _BB_DIR_BIN)
391#endif 394#endif
diff --git a/applets/usage.h b/applets/usage.h
index 0d830c9cc..5e514274a 100644
--- a/applets/usage.h
+++ b/applets/usage.h
@@ -1458,6 +1458,20 @@
1458 "e\n" \ 1458 "e\n" \
1459 "f\n" 1459 "f\n"
1460 1460
1461#define start_stop_daemon_trivial_usage \
1462 "[OPTIONS]"
1463#define start_stop_daemon_full_usage \
1464 "Program to start and stop services.\n"\
1465 "Options:\n" \
1466 "-S\t\t\tstart\n"\
1467 "-K\t\t\tstop\n"\
1468 "-x <executable>\t\tprogram to start/check if it is running\n"\
1469 "-p <pid-file>\t\tpid file to check\n"\
1470 "-u <username>|<uid>\tstop this user's processes\n"\
1471 "-n <process-name>\tstop processes with this name\n"\
1472 "-s <signal>\t\tsignal to send (default 15)\n"\
1473 "-a <pathname>\t\tprogram to start (default <executable>)\n"
1474
1461#define stty_trivial_usage \ 1475#define stty_trivial_usage \
1462 "[-a|g] [-F DEVICE] [SETTING]..." 1476 "[-a|g] [-F DEVICE] [SETTING]..."
1463#define stty_full_usage \ 1477#define stty_full_usage \
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c
new file mode 100644
index 000000000..0152283ad
--- /dev/null
+++ b/debianutils/start_stop_daemon.c
@@ -0,0 +1,271 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini start-stop-daemon implementation(s) for busybox
4 *
5 * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
6 * public domain.
7 * Adapted for busybox David Kimdon <dwhedon@gordian.com>
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <stdarg.h>
14#include <signal.h>
15#include <errno.h>
16#include <sys/stat.h>
17#include <dirent.h>
18#include <unistd.h>
19#include <pwd.h>
20
21#include "busybox.h"
22
23static int start = 0;
24static int stop = 0;
25static int signal_nr = 15;
26static int user_id = -1;
27static const char *userspec = NULL;
28static const char *cmdname = NULL;
29static char *execname = NULL;
30static char *startas = NULL;
31static const char *progname = "";
32
33struct pid_list {
34 struct pid_list *next;
35 int pid;
36};
37
38static struct pid_list *found = NULL;
39static struct pid_list *killed = NULL;
40
41static void
42push(struct pid_list **list, int pid)
43{
44 struct pid_list *p;
45
46 p = xmalloc(sizeof(*p));
47 p->next = *list;
48 p->pid = pid;
49 *list = p;
50}
51
52
53static void
54parse_options(int argc, char * const *argv)
55{
56
57 int c;
58
59 for (;;) {
60 c = getopt (argc, argv, "a:n:s:u:x:KS");
61 if (c == EOF)
62 break;
63 switch (c) {
64 case 'K':
65 stop = 1;
66 break;
67 case 'S':
68 start = 1;
69 break;
70 case 'a':
71 startas = optarg;
72 break;
73 case 'n':
74 cmdname = optarg;
75 break;
76 case 's':
77 if (sscanf(optarg, "%d", &signal_nr) != 1)
78 error_msg_and_die ("-s takes a numeric argument");
79 break;
80 case 'u':
81 userspec = optarg;
82 break;
83 case 'x':
84 execname = optarg;
85 break;
86 default:
87 show_usage();
88 exit(1);
89 }
90 }
91
92 if (start == stop)
93 error_msg_and_die ("need one of -S or -K");
94
95 if (!execname && !userspec)
96 error_msg_and_die ("need at least one of -x or -u");
97
98 if (!startas)
99 startas = execname;
100
101 if (start && !startas)
102 error_msg_and_die ("-S needs -x or -a");
103}
104
105
106static int
107pid_is_exec(int pid, const char *exec)
108{
109 char buf[PATH_MAX];
110 FILE *fp;
111
112 sprintf(buf, "/proc/%d/cmdline", pid);
113 fp = fopen(buf, "r");
114 if (fp && fgets (buf, sizeof (buf), fp) ) {
115 if (strncmp (buf, exec, strlen(exec)) == 0)
116 return 1;
117 }
118 return 0;
119}
120
121
122static int
123pid_is_user(int pid, int uid)
124{
125 struct stat sb;
126 char buf[32];
127
128 sprintf(buf, "/proc/%d", pid);
129 if (stat(buf, &sb) != 0)
130 return 0;
131 return (sb.st_uid == uid);
132}
133
134
135static int
136pid_is_cmd(int pid, const char *name)
137{
138 char buf[32];
139 FILE *f;
140 int c;
141
142 sprintf(buf, "/proc/%d/stat", pid);
143 f = fopen(buf, "r");
144 if (!f)
145 return 0;
146 while ((c = getc(f)) != EOF && c != '(')
147 ;
148 if (c != '(') {
149 fclose(f);
150 return 0;
151 }
152 /* this hopefully handles command names containing ')' */
153 while ((c = getc(f)) != EOF && c == *name)
154 name++;
155 fclose(f);
156 return (c == ')' && *name == '\0');
157}
158
159
160static void
161check(int pid)
162{
163 if (execname && !pid_is_exec(pid, execname)) {
164 return;
165 }
166 if (userspec && !pid_is_user(pid, user_id)) {
167 return;
168 }
169 if (cmdname && !pid_is_cmd(pid, cmdname)) {
170 return;
171 }
172 push(&found, pid);
173}
174
175
176
177static void
178do_procfs(void)
179{
180 DIR *procdir;
181 struct dirent *entry;
182 int foundany, pid;
183
184 procdir = opendir("/proc");
185 if (!procdir)
186 perror_msg_and_die ("opendir /proc");
187
188 foundany = 0;
189 while ((entry = readdir(procdir)) != NULL) {
190 if (sscanf(entry->d_name, "%d", &pid) != 1)
191 continue;
192 foundany++;
193 check(pid);
194 }
195 closedir(procdir);
196 if (!foundany)
197 error_msg_and_die ("nothing in /proc - not mounted?");
198}
199
200
201static void
202do_stop(void)
203{
204 char what[1024];
205 struct pid_list *p;
206
207 if (cmdname)
208 strcpy(what, cmdname);
209 else if (execname)
210 strcpy(what, execname);
211 else if (userspec)
212 sprintf(what, "process(es) owned by `%s'", userspec);
213 else
214 error_msg_and_die ("internal error, please report");
215
216 if (!found) {
217 printf("no %s found; none killed.\n", what);
218 exit(0);
219 }
220 for (p = found; p; p = p->next) {
221 if (kill(p->pid, signal_nr) == 0)
222 push(&killed, p->pid);
223 else
224 printf("%s: warning: failed to kill %d: %s\n",
225 progname, p->pid, strerror(errno));
226 }
227 if (killed) {
228 printf("stopped %s (pid", what);
229 for (p = killed; p; p = p->next)
230 printf(" %d", p->pid);
231 printf(").\n");
232 }
233}
234
235
236int
237start_stop_daemon_main(int argc, char **argv)
238{
239 progname = argv[0];
240
241 parse_options(argc, argv);
242 argc -= optind;
243 argv += optind;
244
245 if (userspec && sscanf(userspec, "%d", &user_id) != 1) {
246 struct passwd *pw;
247
248 pw = getpwnam(userspec);
249 if (!pw)
250 error_msg_and_die ("user `%s' not found\n", userspec);
251
252 user_id = pw->pw_uid;
253 }
254
255 do_procfs();
256
257 if (stop) {
258 do_stop();
259 exit(0);
260 }
261
262 if (found) {
263 printf("%s already running.\n", execname);
264 printf("%d\n",found->pid);
265 exit(0);
266 }
267 *--argv = startas;
268 execv(startas, argv);
269 perror_msg_and_die ("unable to start %s", startas);
270}
271
diff --git a/include/applets.h b/include/applets.h
index 461c878df..5ecfe3cba 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -386,6 +386,9 @@
386#ifdef BB_SORT 386#ifdef BB_SORT
387 APPLET(sort, sort_main, _BB_DIR_USR_BIN) 387 APPLET(sort, sort_main, _BB_DIR_USR_BIN)
388#endif 388#endif
389#ifdef BB_START_STOP_DAEMON
390 APPLET_ODDNAME("start-stop-daemon", start_stop_daemon_main, _BB_DIR_SBIN, start_stop_daemon)
391#endif
389#ifdef BB_STTY 392#ifdef BB_STTY
390 APPLET(stty, stty_main, _BB_DIR_BIN) 393 APPLET(stty, stty_main, _BB_DIR_BIN)
391#endif 394#endif
diff --git a/include/usage.h b/include/usage.h
index 0d830c9cc..5e514274a 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -1458,6 +1458,20 @@
1458 "e\n" \ 1458 "e\n" \
1459 "f\n" 1459 "f\n"
1460 1460
1461#define start_stop_daemon_trivial_usage \
1462 "[OPTIONS]"
1463#define start_stop_daemon_full_usage \
1464 "Program to start and stop services.\n"\
1465 "Options:\n" \
1466 "-S\t\t\tstart\n"\
1467 "-K\t\t\tstop\n"\
1468 "-x <executable>\t\tprogram to start/check if it is running\n"\
1469 "-p <pid-file>\t\tpid file to check\n"\
1470 "-u <username>|<uid>\tstop this user's processes\n"\
1471 "-n <process-name>\tstop processes with this name\n"\
1472 "-s <signal>\t\tsignal to send (default 15)\n"\
1473 "-a <pathname>\t\tprogram to start (default <executable>)\n"
1474
1461#define stty_trivial_usage \ 1475#define stty_trivial_usage \
1462 "[-a|g] [-F DEVICE] [SETTING]..." 1476 "[-a|g] [-F DEVICE] [SETTING]..."
1463#define stty_full_usage \ 1477#define stty_full_usage \
diff --git a/init/start_stop_daemon.c b/init/start_stop_daemon.c
new file mode 100644
index 000000000..0152283ad
--- /dev/null
+++ b/init/start_stop_daemon.c
@@ -0,0 +1,271 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini start-stop-daemon implementation(s) for busybox
4 *
5 * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
6 * public domain.
7 * Adapted for busybox David Kimdon <dwhedon@gordian.com>
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <stdarg.h>
14#include <signal.h>
15#include <errno.h>
16#include <sys/stat.h>
17#include <dirent.h>
18#include <unistd.h>
19#include <pwd.h>
20
21#include "busybox.h"
22
23static int start = 0;
24static int stop = 0;
25static int signal_nr = 15;
26static int user_id = -1;
27static const char *userspec = NULL;
28static const char *cmdname = NULL;
29static char *execname = NULL;
30static char *startas = NULL;
31static const char *progname = "";
32
33struct pid_list {
34 struct pid_list *next;
35 int pid;
36};
37
38static struct pid_list *found = NULL;
39static struct pid_list *killed = NULL;
40
41static void
42push(struct pid_list **list, int pid)
43{
44 struct pid_list *p;
45
46 p = xmalloc(sizeof(*p));
47 p->next = *list;
48 p->pid = pid;
49 *list = p;
50}
51
52
53static void
54parse_options(int argc, char * const *argv)
55{
56
57 int c;
58
59 for (;;) {
60 c = getopt (argc, argv, "a:n:s:u:x:KS");
61 if (c == EOF)
62 break;
63 switch (c) {
64 case 'K':
65 stop = 1;
66 break;
67 case 'S':
68 start = 1;
69 break;
70 case 'a':
71 startas = optarg;
72 break;
73 case 'n':
74 cmdname = optarg;
75 break;
76 case 's':
77 if (sscanf(optarg, "%d", &signal_nr) != 1)
78 error_msg_and_die ("-s takes a numeric argument");
79 break;
80 case 'u':
81 userspec = optarg;
82 break;
83 case 'x':
84 execname = optarg;
85 break;
86 default:
87 show_usage();
88 exit(1);
89 }
90 }
91
92 if (start == stop)
93 error_msg_and_die ("need one of -S or -K");
94
95 if (!execname && !userspec)
96 error_msg_and_die ("need at least one of -x or -u");
97
98 if (!startas)
99 startas = execname;
100
101 if (start && !startas)
102 error_msg_and_die ("-S needs -x or -a");
103}
104
105
106static int
107pid_is_exec(int pid, const char *exec)
108{
109 char buf[PATH_MAX];
110 FILE *fp;
111
112 sprintf(buf, "/proc/%d/cmdline", pid);
113 fp = fopen(buf, "r");
114 if (fp && fgets (buf, sizeof (buf), fp) ) {
115 if (strncmp (buf, exec, strlen(exec)) == 0)
116 return 1;
117 }
118 return 0;
119}
120
121
122static int
123pid_is_user(int pid, int uid)
124{
125 struct stat sb;
126 char buf[32];
127
128 sprintf(buf, "/proc/%d", pid);
129 if (stat(buf, &sb) != 0)
130 return 0;
131 return (sb.st_uid == uid);
132}
133
134
135static int
136pid_is_cmd(int pid, const char *name)
137{
138 char buf[32];
139 FILE *f;
140 int c;
141
142 sprintf(buf, "/proc/%d/stat", pid);
143 f = fopen(buf, "r");
144 if (!f)
145 return 0;
146 while ((c = getc(f)) != EOF && c != '(')
147 ;
148 if (c != '(') {
149 fclose(f);
150 return 0;
151 }
152 /* this hopefully handles command names containing ')' */
153 while ((c = getc(f)) != EOF && c == *name)
154 name++;
155 fclose(f);
156 return (c == ')' && *name == '\0');
157}
158
159
160static void
161check(int pid)
162{
163 if (execname && !pid_is_exec(pid, execname)) {
164 return;
165 }
166 if (userspec && !pid_is_user(pid, user_id)) {
167 return;
168 }
169 if (cmdname && !pid_is_cmd(pid, cmdname)) {
170 return;
171 }
172 push(&found, pid);
173}
174
175
176
177static void
178do_procfs(void)
179{
180 DIR *procdir;
181 struct dirent *entry;
182 int foundany, pid;
183
184 procdir = opendir("/proc");
185 if (!procdir)
186 perror_msg_and_die ("opendir /proc");
187
188 foundany = 0;
189 while ((entry = readdir(procdir)) != NULL) {
190 if (sscanf(entry->d_name, "%d", &pid) != 1)
191 continue;
192 foundany++;
193 check(pid);
194 }
195 closedir(procdir);
196 if (!foundany)
197 error_msg_and_die ("nothing in /proc - not mounted?");
198}
199
200
201static void
202do_stop(void)
203{
204 char what[1024];
205 struct pid_list *p;
206
207 if (cmdname)
208 strcpy(what, cmdname);
209 else if (execname)
210 strcpy(what, execname);
211 else if (userspec)
212 sprintf(what, "process(es) owned by `%s'", userspec);
213 else
214 error_msg_and_die ("internal error, please report");
215
216 if (!found) {
217 printf("no %s found; none killed.\n", what);
218 exit(0);
219 }
220 for (p = found; p; p = p->next) {
221 if (kill(p->pid, signal_nr) == 0)
222 push(&killed, p->pid);
223 else
224 printf("%s: warning: failed to kill %d: %s\n",
225 progname, p->pid, strerror(errno));
226 }
227 if (killed) {
228 printf("stopped %s (pid", what);
229 for (p = killed; p; p = p->next)
230 printf(" %d", p->pid);
231 printf(").\n");
232 }
233}
234
235
236int
237start_stop_daemon_main(int argc, char **argv)
238{
239 progname = argv[0];
240
241 parse_options(argc, argv);
242 argc -= optind;
243 argv += optind;
244
245 if (userspec && sscanf(userspec, "%d", &user_id) != 1) {
246 struct passwd *pw;
247
248 pw = getpwnam(userspec);
249 if (!pw)
250 error_msg_and_die ("user `%s' not found\n", userspec);
251
252 user_id = pw->pw_uid;
253 }
254
255 do_procfs();
256
257 if (stop) {
258 do_stop();
259 exit(0);
260 }
261
262 if (found) {
263 printf("%s already running.\n", execname);
264 printf("%d\n",found->pid);
265 exit(0);
266 }
267 *--argv = startas;
268 execv(startas, argv);
269 perror_msg_and_die ("unable to start %s", startas);
270}
271
diff --git a/start_stop_daemon.c b/start_stop_daemon.c
new file mode 100644
index 000000000..0152283ad
--- /dev/null
+++ b/start_stop_daemon.c
@@ -0,0 +1,271 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini start-stop-daemon implementation(s) for busybox
4 *
5 * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
6 * public domain.
7 * Adapted for busybox David Kimdon <dwhedon@gordian.com>
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <stdarg.h>
14#include <signal.h>
15#include <errno.h>
16#include <sys/stat.h>
17#include <dirent.h>
18#include <unistd.h>
19#include <pwd.h>
20
21#include "busybox.h"
22
23static int start = 0;
24static int stop = 0;
25static int signal_nr = 15;
26static int user_id = -1;
27static const char *userspec = NULL;
28static const char *cmdname = NULL;
29static char *execname = NULL;
30static char *startas = NULL;
31static const char *progname = "";
32
33struct pid_list {
34 struct pid_list *next;
35 int pid;
36};
37
38static struct pid_list *found = NULL;
39static struct pid_list *killed = NULL;
40
41static void
42push(struct pid_list **list, int pid)
43{
44 struct pid_list *p;
45
46 p = xmalloc(sizeof(*p));
47 p->next = *list;
48 p->pid = pid;
49 *list = p;
50}
51
52
53static void
54parse_options(int argc, char * const *argv)
55{
56
57 int c;
58
59 for (;;) {
60 c = getopt (argc, argv, "a:n:s:u:x:KS");
61 if (c == EOF)
62 break;
63 switch (c) {
64 case 'K':
65 stop = 1;
66 break;
67 case 'S':
68 start = 1;
69 break;
70 case 'a':
71 startas = optarg;
72 break;
73 case 'n':
74 cmdname = optarg;
75 break;
76 case 's':
77 if (sscanf(optarg, "%d", &signal_nr) != 1)
78 error_msg_and_die ("-s takes a numeric argument");
79 break;
80 case 'u':
81 userspec = optarg;
82 break;
83 case 'x':
84 execname = optarg;
85 break;
86 default:
87 show_usage();
88 exit(1);
89 }
90 }
91
92 if (start == stop)
93 error_msg_and_die ("need one of -S or -K");
94
95 if (!execname && !userspec)
96 error_msg_and_die ("need at least one of -x or -u");
97
98 if (!startas)
99 startas = execname;
100
101 if (start && !startas)
102 error_msg_and_die ("-S needs -x or -a");
103}
104
105
106static int
107pid_is_exec(int pid, const char *exec)
108{
109 char buf[PATH_MAX];
110 FILE *fp;
111
112 sprintf(buf, "/proc/%d/cmdline", pid);
113 fp = fopen(buf, "r");
114 if (fp && fgets (buf, sizeof (buf), fp) ) {
115 if (strncmp (buf, exec, strlen(exec)) == 0)
116 return 1;
117 }
118 return 0;
119}
120
121
122static int
123pid_is_user(int pid, int uid)
124{
125 struct stat sb;
126 char buf[32];
127
128 sprintf(buf, "/proc/%d", pid);
129 if (stat(buf, &sb) != 0)
130 return 0;
131 return (sb.st_uid == uid);
132}
133
134
135static int
136pid_is_cmd(int pid, const char *name)
137{
138 char buf[32];
139 FILE *f;
140 int c;
141
142 sprintf(buf, "/proc/%d/stat", pid);
143 f = fopen(buf, "r");
144 if (!f)
145 return 0;
146 while ((c = getc(f)) != EOF && c != '(')
147 ;
148 if (c != '(') {
149 fclose(f);
150 return 0;
151 }
152 /* this hopefully handles command names containing ')' */
153 while ((c = getc(f)) != EOF && c == *name)
154 name++;
155 fclose(f);
156 return (c == ')' && *name == '\0');
157}
158
159
160static void
161check(int pid)
162{
163 if (execname && !pid_is_exec(pid, execname)) {
164 return;
165 }
166 if (userspec && !pid_is_user(pid, user_id)) {
167 return;
168 }
169 if (cmdname && !pid_is_cmd(pid, cmdname)) {
170 return;
171 }
172 push(&found, pid);
173}
174
175
176
177static void
178do_procfs(void)
179{
180 DIR *procdir;
181 struct dirent *entry;
182 int foundany, pid;
183
184 procdir = opendir("/proc");
185 if (!procdir)
186 perror_msg_and_die ("opendir /proc");
187
188 foundany = 0;
189 while ((entry = readdir(procdir)) != NULL) {
190 if (sscanf(entry->d_name, "%d", &pid) != 1)
191 continue;
192 foundany++;
193 check(pid);
194 }
195 closedir(procdir);
196 if (!foundany)
197 error_msg_and_die ("nothing in /proc - not mounted?");
198}
199
200
201static void
202do_stop(void)
203{
204 char what[1024];
205 struct pid_list *p;
206
207 if (cmdname)
208 strcpy(what, cmdname);
209 else if (execname)
210 strcpy(what, execname);
211 else if (userspec)
212 sprintf(what, "process(es) owned by `%s'", userspec);
213 else
214 error_msg_and_die ("internal error, please report");
215
216 if (!found) {
217 printf("no %s found; none killed.\n", what);
218 exit(0);
219 }
220 for (p = found; p; p = p->next) {
221 if (kill(p->pid, signal_nr) == 0)
222 push(&killed, p->pid);
223 else
224 printf("%s: warning: failed to kill %d: %s\n",
225 progname, p->pid, strerror(errno));
226 }
227 if (killed) {
228 printf("stopped %s (pid", what);
229 for (p = killed; p; p = p->next)
230 printf(" %d", p->pid);
231 printf(").\n");
232 }
233}
234
235
236int
237start_stop_daemon_main(int argc, char **argv)
238{
239 progname = argv[0];
240
241 parse_options(argc, argv);
242 argc -= optind;
243 argv += optind;
244
245 if (userspec && sscanf(userspec, "%d", &user_id) != 1) {
246 struct passwd *pw;
247
248 pw = getpwnam(userspec);
249 if (!pw)
250 error_msg_and_die ("user `%s' not found\n", userspec);
251
252 user_id = pw->pw_uid;
253 }
254
255 do_procfs();
256
257 if (stop) {
258 do_stop();
259 exit(0);
260 }
261
262 if (found) {
263 printf("%s already running.\n", execname);
264 printf("%d\n",found->pid);
265 exit(0);
266 }
267 *--argv = startas;
268 execv(startas, argv);
269 perror_msg_and_die ("unable to start %s", startas);
270}
271
diff --git a/usage.h b/usage.h
index 0d830c9cc..5e514274a 100644
--- a/usage.h
+++ b/usage.h
@@ -1458,6 +1458,20 @@
1458 "e\n" \ 1458 "e\n" \
1459 "f\n" 1459 "f\n"
1460 1460
1461#define start_stop_daemon_trivial_usage \
1462 "[OPTIONS]"
1463#define start_stop_daemon_full_usage \
1464 "Program to start and stop services.\n"\
1465 "Options:\n" \
1466 "-S\t\t\tstart\n"\
1467 "-K\t\t\tstop\n"\
1468 "-x <executable>\t\tprogram to start/check if it is running\n"\
1469 "-p <pid-file>\t\tpid file to check\n"\
1470 "-u <username>|<uid>\tstop this user's processes\n"\
1471 "-n <process-name>\tstop processes with this name\n"\
1472 "-s <signal>\t\tsignal to send (default 15)\n"\
1473 "-a <pathname>\t\tprogram to start (default <executable>)\n"
1474
1461#define stty_trivial_usage \ 1475#define stty_trivial_usage \
1462 "[-a|g] [-F DEVICE] [SETTING]..." 1476 "[-a|g] [-F DEVICE] [SETTING]..."
1463#define stty_full_usage \ 1477#define stty_full_usage \