/[baselayout]/trunk/src/librc-daemon.c
Gentoo

Contents of /trunk/src/librc-daemon.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2957 - (hide annotations) (download) (as text)
Sat Sep 29 16:42:08 2007 UTC (7 years, 9 months ago) by uberlord
File MIME type: text/x-csrc
File size: 10910 byte(s)
librc no longer uses libeinfo. deptree function names are now all under rc_deptree_
1 uberlord 2547 /*
2     librc-daemon
3     Finds PID for given daemon criteria
4     Copyright 2007 Gentoo Foundation
5     Released under the GPLv2
6     */
7    
8 vapier 2597 #include "librc.h"
9 uberlord 2547
10     #if defined(__linux__)
11     static bool pid_is_cmd (pid_t pid, const char *cmd)
12     {
13 uberlord 2577 char buffer[32];
14     FILE *fp;
15     int c;
16 uberlord 2547
17 uberlord 2577 snprintf(buffer, sizeof (buffer), "/proc/%d/stat", pid);
18     if ((fp = fopen (buffer, "r")) == NULL)
19     return (false);
20 uberlord 2547
21 uberlord 2577 while ((c = getc (fp)) != EOF && c != '(')
22     ;
23 uberlord 2547
24 uberlord 2577 if (c != '(') {
25     fclose(fp);
26     return (false);
27     }
28 uberlord 2547
29 uberlord 2577 while ((c = getc (fp)) != EOF && c == *cmd)
30     cmd++;
31 uberlord 2547
32 uberlord 2577 fclose (fp);
33 uberlord 2547
34 uberlord 2577 return ((c == ')' && *cmd == '\0') ? true : false);
35 uberlord 2547 }
36    
37     static bool pid_is_exec (pid_t pid, const char *exec)
38     {
39 uberlord 2577 char cmdline[32];
40     char buffer[PATH_MAX];
41     char *p;
42     int fd = -1;
43     int r;
44 uberlord 2547
45 uberlord 2577 snprintf (cmdline, sizeof (cmdline), "/proc/%u/exe", pid);
46     memset (buffer, 0, sizeof (buffer));
47     if (readlink (cmdline, buffer, sizeof (buffer)) != -1) {
48     if (strcmp (exec, buffer) == 0)
49     return (true);
50 uberlord 2547
51 uberlord 2577 /* We should cater for deleted binaries too */
52     if (strlen (buffer) > 10) {
53     p = buffer + (strlen (buffer) - 10);
54     if (strcmp (p, " (deleted)") == 0) {
55     *p = 0;
56     if (strcmp (buffer, exec) == 0)
57     return (true);
58     }
59     }
60     }
61 uberlord 2547
62 uberlord 2577 snprintf (cmdline, sizeof (cmdline), "/proc/%u/cmdline", pid);
63     if ((fd = open (cmdline, O_RDONLY)) < 0)
64     return (false);
65 uberlord 2547
66 uberlord 2577 r = read(fd, buffer, sizeof (buffer));
67     close (fd);
68 uberlord 2547
69 uberlord 2577 if (r == -1)
70     return 0;
71 uberlord 2547
72 uberlord 2577 buffer[r] = 0;
73     return (strcmp (exec, buffer) == 0 ? true : false);
74 uberlord 2547 }
75    
76     pid_t *rc_find_pids (const char *exec, const char *cmd,
77 uberlord 2577 uid_t uid, pid_t pid)
78 uberlord 2547 {
79 uberlord 2577 DIR *procdir;
80     struct dirent *entry;
81     int npids = 0;
82     pid_t p;
83     pid_t *pids = NULL;
84 uberlord 2957 pid_t *tmp = NULL;
85 uberlord 2577 char buffer[PATH_MAX];
86     struct stat sb;
87     pid_t runscript_pid = 0;
88     char *pp;
89 uberlord 2547
90 uberlord 2577 if ((procdir = opendir ("/proc")) == NULL)
91 uberlord 2957 return (NULL);
92 uberlord 2547
93 uberlord 2577 /*
94     We never match RC_RUNSCRIPT_PID if present so we avoid the below
95     scenario
96 uberlord 2547
97 uberlord 2577 /etc/init.d/ntpd stop does
98     start-stop-daemon --stop --name ntpd
99     catching /etc/init.d/ntpd stop
100 uberlord 2547
101 uberlord 2577 nasty
102     */
103 uberlord 2547
104 uberlord 2577 if ((pp = getenv ("RC_RUNSCRIPT_PID"))) {
105     if (sscanf (pp, "%d", &runscript_pid) != 1)
106     runscript_pid = 0;
107     }
108 uberlord 2547
109 uberlord 2577 while ((entry = readdir (procdir)) != NULL) {
110     if (sscanf (entry->d_name, "%d", &p) != 1)
111     continue;
112 uberlord 2547
113 uberlord 2577 if (runscript_pid != 0 && runscript_pid == p)
114     continue;
115 uberlord 2547
116 uberlord 2577 if (pid != 0 && pid != p)
117     continue;
118 uberlord 2547
119 uberlord 2577 if (uid) {
120 uberlord 2866 snprintf (buffer, sizeof (buffer), "/proc/%d", p);
121 uberlord 2577 if (stat (buffer, &sb) != 0 || sb.st_uid != uid)
122     continue;
123     }
124 uberlord 2547
125 uberlord 2577 if (cmd && ! pid_is_cmd (p, cmd))
126     continue;
127 uberlord 2569
128 uberlord 2577 if (exec && ! cmd && ! pid_is_exec (p, exec))
129     continue;
130 uberlord 2547
131 uberlord 2957 tmp = realloc (pids, sizeof (pid_t) * (npids + 2));
132     if (! tmp) {
133     free (pids);
134     closedir (procdir);
135     errno = ENOMEM;
136     return (NULL);
137     }
138     pids = tmp;
139 uberlord 2547
140 uberlord 2577 pids[npids] = p;
141     pids[npids + 1] = 0;
142     npids++;
143     }
144     closedir (procdir);
145 uberlord 2547
146 uberlord 2577 return (pids);
147 uberlord 2547 }
148 vapier 2597 librc_hidden_def(rc_find_pids)
149 uberlord 2547
150 uberlord 2549 #elif defined(__DragonFly__) || defined(__FreeBSD__) || \
151 uberlord 2928 defined(__NetBSD__) || defined(__OpenBSD__)
152 uberlord 2547
153 uberlord 2549 # if defined(__DragonFly__) || defined(__FreeBSD__)
154     # ifndef KERN_PROC_PROC
155     # define KERN_PROC_PROC KERN_PROC_ALL
156     # endif
157 uberlord 2547 # define _KINFO_PROC kinfo_proc
158     # define _KVM_GETARGV kvm_getargv
159     # define _GET_KINFO_UID(kp) (kp.ki_ruid)
160     # define _GET_KINFO_COMM(kp) (kp.ki_comm)
161     # define _GET_KINFO_PID(kp) (kp.ki_pid)
162     # else
163     # define _KINFO_PROC kinfo_proc2
164     # define _KVM_GETARGV kvm_getargv2
165     # define _GET_KINFO_UID(kp) (kp.p_ruid)
166     # define _GET_KINFO_COMM(kp) (kp.p_comm)
167     # define _GET_KINFO_PID(kp) (kp.p_pid)
168     # endif
169    
170     pid_t *rc_find_pids (const char *exec, const char *cmd,
171 uberlord 2577 uid_t uid, pid_t pid)
172 uberlord 2547 {
173 uberlord 2577 static kvm_t *kd = NULL;
174     char errbuf[_POSIX2_LINE_MAX];
175     struct _KINFO_PROC *kp;
176     int i;
177     int processes = 0;
178     int argc = 0;
179     char **argv;
180     pid_t *pids = NULL;
181 uberlord 2957 pid_t *tmp;
182 uberlord 2577 int npids = 0;
183 uberlord 2547
184 uberlord 2577 if ((kd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL)
185     eerrorx ("kvm_open: %s", errbuf);
186 uberlord 2547
187 uberlord 2549 #if defined(__DragonFly__) || defined( __FreeBSD__)
188 uberlord 2577 kp = kvm_getprocs (kd, KERN_PROC_PROC, 0, &processes);
189 uberlord 2549 #else
190 uberlord 2577 kp = kvm_getproc2 (kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2),
191     &processes);
192 uberlord 2549 #endif
193 uberlord 2577 for (i = 0; i < processes; i++) {
194     pid_t p = _GET_KINFO_PID (kp[i]);
195     if (pid != 0 && pid != p)
196     continue;
197 uberlord 2547
198 uberlord 2577 if (uid != 0 && uid != _GET_KINFO_UID (kp[i]))
199     continue;
200 uberlord 2547
201 uberlord 2577 if (cmd) {
202     if (! _GET_KINFO_COMM (kp[i]) ||
203     strcmp (cmd, _GET_KINFO_COMM (kp[i])) != 0)
204     continue;
205     }
206 uberlord 2547
207 uberlord 2577 if (exec && ! cmd) {
208     if ((argv = _KVM_GETARGV (kd, &kp[i], argc)) == NULL || ! *argv)
209     continue;
210 uberlord 2547
211 uberlord 2577 if (strcmp (*argv, exec) != 0)
212     continue;
213     }
214 uberlord 2547
215 uberlord 2957 tmp = realloc (pids, sizeof (pid_t) * (npids + 2));
216     if (! tmp) {
217     free (pids);
218     kvm_close (kd);
219     errno = ENOMEM;
220     return (NULL);
221     }
222     pids = tmp;
223 uberlord 2547
224 uberlord 2577 pids[npids] = p;
225     pids[npids + 1] = 0;
226     npids++;
227     }
228 uberlord 2957 kvm_close (kd);
229 uberlord 2547
230 uberlord 2577 return (pids);
231 uberlord 2547 }
232 vapier 2597 librc_hidden_def(rc_find_pids)
233 uberlord 2547
234     #else
235     # error "Platform not supported!"
236     #endif
237    
238 uberlord 2928 static bool _match_daemon (const char *path, const char *file,
239     const char *mexec, const char *mname,
240     const char *mpidfile)
241 uberlord 2547 {
242 uberlord 2577 char buffer[RC_LINEBUFFER];
243     char *ffile = rc_strcatpaths (path, file, (char *) NULL);
244     FILE *fp;
245     int lc = 0;
246     int m = 0;
247 uberlord 2547
248 uberlord 2577 if ((fp = fopen (ffile, "r")) == NULL) {
249     free (ffile);
250 uberlord 2928 return (false);
251 uberlord 2577 }
252 uberlord 2547
253 uberlord 2577 if (! mname)
254     m += 10;
255     if (! mpidfile)
256     m += 100;
257 uberlord 2547
258 uberlord 2577 memset (buffer, 0, sizeof (buffer));
259     while ((fgets (buffer, RC_LINEBUFFER, fp))) {
260     int lb = strlen (buffer) - 1;
261     if (buffer[lb] == '\n')
262     buffer[lb] = 0;
263 uberlord 2547
264 uberlord 2577 if (strcmp (buffer, mexec) == 0)
265     m += 1;
266     else if (mname && strcmp (buffer, mname) == 0)
267     m += 10;
268     else if (mpidfile && strcmp (buffer, mpidfile) == 0)
269     m += 100;
270 uberlord 2547
271 uberlord 2577 if (m == 111)
272     break;
273 uberlord 2547
274 uberlord 2577 lc++;
275     if (lc > 5)
276     break;
277     }
278     fclose (fp);
279     free (ffile);
280 uberlord 2547
281 uberlord 2928 return (m == 111 ? true : false);
282 uberlord 2547 }
283    
284 uberlord 2928 void rc_set_service_daemon (const char *service, const char *exec,
285     const char *name, const char *pidfile,
286     bool started)
287 uberlord 2547 {
288 uberlord 2607 char *svc = rc_xstrdup (service);
289     char *dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (svc),
290 uberlord 2577 (char *) NULL);
291     char **files = NULL;
292     char *file;
293     char *ffile = NULL;
294     int i;
295     char *mexec;
296     char *mname;
297     char *mpidfile;
298     int nfiles = 0;
299 uberlord 2547
300 uberlord 2607 free (svc);
301 uberlord 2577 if (! exec && ! name && ! pidfile)
302 uberlord 2928 return;
303 uberlord 2547
304 uberlord 2577 if (exec) {
305     i = strlen (exec) + 6;
306     mexec = rc_xmalloc (sizeof (char *) * i);
307     snprintf (mexec, i, "exec=%s", exec);
308     } else
309 uberlord 2634 mexec = rc_xstrdup ("exec=");
310 uberlord 2547
311 uberlord 2577 if (name) {
312     i = strlen (name) + 6;
313     mname = rc_xmalloc (sizeof (char *) * i);
314     snprintf (mname, i, "name=%s", name);
315     } else
316 uberlord 2634 mname = rc_xstrdup ("name=");
317 uberlord 2547
318 uberlord 2577 if (pidfile) {
319     i = strlen (pidfile) + 9;
320     mpidfile = rc_xmalloc (sizeof (char *) * i);
321     snprintf (mpidfile, i, "pidfile=%s", pidfile);
322     } else
323 uberlord 2634 mpidfile = rc_xstrdup ("pidfile=");
324 uberlord 2547
325 uberlord 2577 /* Regardless, erase any existing daemon info */
326 uberlord 2928 if (rc_is_dir (dirpath)) {
327 uberlord 2577 char *oldfile = NULL;
328 uberlord 2883 files = rc_ls_dir (dirpath, 0);
329 uberlord 2577 STRLIST_FOREACH (files, file, i) {
330     ffile = rc_strcatpaths (dirpath, file, (char *) NULL);
331     nfiles++;
332 uberlord 2547
333 uberlord 2577 if (! oldfile) {
334 uberlord 2928 if (_match_daemon (dirpath, file, mexec, mname, mpidfile)) {
335 uberlord 2577 unlink (ffile);
336     oldfile = ffile;
337     nfiles--;
338     }
339     } else {
340     rename (ffile, oldfile);
341     free (oldfile);
342     oldfile = ffile;
343     }
344     }
345 uberlord 2908 free (ffile);
346     rc_strlist_free (files);
347 uberlord 2577 }
348 uberlord 2547
349 uberlord 2577 /* Now store our daemon info */
350     if (started) {
351     char buffer[10];
352     FILE *fp;
353 uberlord 2547
354 uberlord 2957 if (mkdir (dirpath, 0755) == 0 || errno == EEXIST) {
355     snprintf (buffer, sizeof (buffer), "%03d", nfiles + 1);
356     file = rc_strcatpaths (dirpath, buffer, (char *) NULL);
357     if ((fp = fopen (file, "w")))
358     fprintf (fp, "%s\n%s\n%s\n", mexec, mname, mpidfile);
359 uberlord 2577 fclose (fp);
360 uberlord 2957 free (file);
361 uberlord 2577 }
362     }
363 uberlord 2547
364 uberlord 2577 free (mexec);
365     free (mname);
366     free (mpidfile);
367     free (dirpath);
368 uberlord 2547 }
369 vapier 2597 librc_hidden_def(rc_set_service_daemon)
370 uberlord 2547
371 uberlord 2928 bool rc_service_started_daemon (const char *service, const char *exec,
372     int indx)
373 uberlord 2547 {
374 uberlord 2577 char *dirpath;
375     char *file;
376     int i;
377     char *mexec;
378 uberlord 2928 bool retval = false;
379 uberlord 2607 char *svc;
380 uberlord 2547
381 uberlord 2577 if (! service || ! exec)
382 uberlord 2928 return (false);
383 uberlord 2547
384 uberlord 2607 svc = rc_xstrdup (service);
385     dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (svc),
386 uberlord 2577 (char *) NULL);
387 uberlord 2607 free (svc);
388    
389 uberlord 2928 if (! rc_is_dir (dirpath)) {
390 uberlord 2577 free (dirpath);
391 uberlord 2928 return (false);
392 uberlord 2577 }
393 uberlord 2547
394 uberlord 2577 i = strlen (exec) + 6;
395     mexec = rc_xmalloc (sizeof (char *) * i);
396     snprintf (mexec, i, "exec=%s", exec);
397 uberlord 2547
398 uberlord 2577 if (indx > 0) {
399     int len = sizeof (char *) * 10;
400     file = rc_xmalloc (len);
401     snprintf (file, len, "%03d", indx);
402     retval = _match_daemon (dirpath, file, mexec, NULL, NULL);
403     free (file);
404     } else {
405 uberlord 2883 char **files = rc_ls_dir (dirpath, 0);
406 uberlord 2577 STRLIST_FOREACH (files, file, i) {
407     retval = _match_daemon (dirpath, file, mexec, NULL, NULL);
408 uberlord 2928 if (retval)
409 uberlord 2577 break;
410     }
411 uberlord 2908 rc_strlist_free (files);
412 uberlord 2577 }
413 uberlord 2547
414 uberlord 2577 free (mexec);
415     return (retval);
416 uberlord 2547 }
417 vapier 2597 librc_hidden_def(rc_service_started_daemon)
418 uberlord 2547
419 uberlord 2928 bool rc_service_daemons_crashed (const char *service)
420 uberlord 2547 {
421 uberlord 2577 char *dirpath;
422     char **files;
423     char *file;
424     char *path;
425     int i;
426     FILE *fp;
427     char buffer[RC_LINEBUFFER];
428     char *exec = NULL;
429     char *name = NULL;
430     char *pidfile = NULL;
431     pid_t pid = 0;
432     pid_t *pids = NULL;
433     char *p;
434     char *token;
435 uberlord 2928 bool retval = false;
436 uberlord 2607 char *svc;
437 uberlord 2547
438 uberlord 2577 if (! service)
439 uberlord 2928 return (false);
440 uberlord 2547
441 uberlord 2607 svc = rc_xstrdup (service);
442     dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (svc),
443 uberlord 2577 (char *) NULL);
444 uberlord 2607 free (svc);
445    
446 uberlord 2928 if (! rc_is_dir (dirpath)) {
447 uberlord 2577 free (dirpath);
448 uberlord 2928 return (false);
449 uberlord 2577 }
450 uberlord 2547
451 uberlord 2577 memset (buffer, 0, sizeof (buffer));
452 uberlord 2883 files = rc_ls_dir (dirpath, 0);
453 uberlord 2577 STRLIST_FOREACH (files, file, i) {
454     path = rc_strcatpaths (dirpath, file, (char *) NULL);
455     fp = fopen (path, "r");
456     free (path);
457 uberlord 2957 if (! fp)
458     break;
459 uberlord 2547
460 uberlord 2577 while ((fgets (buffer, RC_LINEBUFFER, fp))) {
461     int lb = strlen (buffer) - 1;
462     if (buffer[lb] == '\n')
463     buffer[lb] = 0;
464 uberlord 2547
465 uberlord 2577 p = buffer;
466     if ((token = strsep (&p, "=")) == NULL || ! p)
467     continue;
468 uberlord 2547
469 uberlord 2577 if (strlen (p) == 0)
470     continue;
471 uberlord 2547
472 uberlord 2577 if (strcmp (token, "exec") == 0) {
473     if (exec)
474     free (exec);
475 uberlord 2634 exec = rc_xstrdup (p);
476 uberlord 2577 } else if (strcmp (token, "name") == 0) {
477     if (name)
478     free (name);
479 uberlord 2634 name = rc_xstrdup (p);
480 uberlord 2577 } else if (strcmp (token, "pidfile") == 0) {
481     if (pidfile)
482     free (pidfile);
483 uberlord 2634 pidfile = rc_xstrdup (p);
484 uberlord 2577 }
485     }
486     fclose (fp);
487 uberlord 2547
488 uberlord 2577 pid = 0;
489     if (pidfile) {
490 uberlord 2928 if (! rc_exists (pidfile)) {
491     retval = true;
492 uberlord 2577 break;
493     }
494 uberlord 2547
495 uberlord 2577 if ((fp = fopen (pidfile, "r")) == NULL) {
496 uberlord 2928 retval = true;
497 uberlord 2577 break;
498     }
499 uberlord 2547
500 uberlord 2577 if (fscanf (fp, "%d", &pid) != 1) {
501     fclose (fp);
502 uberlord 2928 retval = true;
503 uberlord 2577 break;
504     }
505 uberlord 2547
506 uberlord 2577 fclose (fp);
507     free (pidfile);
508     pidfile = NULL;
509 uberlord 2822
510     /* We have the pid, so no need to match on name */
511     free (exec);
512     exec = NULL;
513     free (name);
514     name = NULL;
515 uberlord 2577 }
516 uberlord 2547
517 uberlord 2577 if ((pids = rc_find_pids (exec, name, 0, pid)) == NULL) {
518 uberlord 2928 retval = true;
519 uberlord 2577 break;
520     }
521     free (pids);
522 uberlord 2547
523 uberlord 2577 free (exec);
524     exec = NULL;
525     free (name);
526     name = NULL;
527     }
528 uberlord 2547
529 uberlord 2822 free (exec);
530     free (name);
531 uberlord 2577 free (dirpath);
532     rc_strlist_free (files);
533 uberlord 2547
534 uberlord 2577 return (retval);
535 uberlord 2547 }
536 vapier 2597 librc_hidden_def(rc_service_daemons_crashed)

  ViewVC Help
Powered by ViewVC 1.1.20