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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2966 - (hide annotations) (download) (as text)
Tue Oct 2 09:04:10 2007 UTC (7 years, 2 months ago) by uberlord
File MIME type: text/x-csrc
File size: 10940 byte(s)
rc_set_service_daemon -> rc_service_daemon_set
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 2964 if ((kd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) {
185     fprintf (stderr, "kvm_open: %s", errbuf);
186     return (NULL);
187     }
188 uberlord 2547
189 uberlord 2549 #if defined(__DragonFly__) || defined( __FreeBSD__)
190 uberlord 2577 kp = kvm_getprocs (kd, KERN_PROC_PROC, 0, &processes);
191 uberlord 2549 #else
192 uberlord 2577 kp = kvm_getproc2 (kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2),
193     &processes);
194 uberlord 2549 #endif
195 uberlord 2577 for (i = 0; i < processes; i++) {
196     pid_t p = _GET_KINFO_PID (kp[i]);
197     if (pid != 0 && pid != p)
198     continue;
199 uberlord 2547
200 uberlord 2577 if (uid != 0 && uid != _GET_KINFO_UID (kp[i]))
201     continue;
202 uberlord 2547
203 uberlord 2577 if (cmd) {
204     if (! _GET_KINFO_COMM (kp[i]) ||
205     strcmp (cmd, _GET_KINFO_COMM (kp[i])) != 0)
206     continue;
207     }
208 uberlord 2547
209 uberlord 2577 if (exec && ! cmd) {
210     if ((argv = _KVM_GETARGV (kd, &kp[i], argc)) == NULL || ! *argv)
211     continue;
212 uberlord 2547
213 uberlord 2577 if (strcmp (*argv, exec) != 0)
214     continue;
215     }
216 uberlord 2547
217 uberlord 2957 tmp = realloc (pids, sizeof (pid_t) * (npids + 2));
218     if (! tmp) {
219     free (pids);
220     kvm_close (kd);
221     errno = ENOMEM;
222     return (NULL);
223     }
224     pids = tmp;
225 uberlord 2547
226 uberlord 2577 pids[npids] = p;
227     pids[npids + 1] = 0;
228     npids++;
229     }
230 uberlord 2957 kvm_close (kd);
231 uberlord 2547
232 uberlord 2577 return (pids);
233 uberlord 2547 }
234 vapier 2597 librc_hidden_def(rc_find_pids)
235 uberlord 2547
236     #else
237     # error "Platform not supported!"
238     #endif
239    
240 uberlord 2928 static bool _match_daemon (const char *path, const char *file,
241     const char *mexec, const char *mname,
242     const char *mpidfile)
243 uberlord 2547 {
244 uberlord 2577 char buffer[RC_LINEBUFFER];
245     char *ffile = rc_strcatpaths (path, file, (char *) NULL);
246     FILE *fp;
247     int lc = 0;
248     int m = 0;
249 uberlord 2547
250 uberlord 2577 if ((fp = fopen (ffile, "r")) == NULL) {
251     free (ffile);
252 uberlord 2928 return (false);
253 uberlord 2577 }
254 uberlord 2547
255 uberlord 2577 if (! mname)
256     m += 10;
257     if (! mpidfile)
258     m += 100;
259 uberlord 2547
260 uberlord 2577 memset (buffer, 0, sizeof (buffer));
261     while ((fgets (buffer, RC_LINEBUFFER, fp))) {
262     int lb = strlen (buffer) - 1;
263     if (buffer[lb] == '\n')
264     buffer[lb] = 0;
265 uberlord 2547
266 uberlord 2577 if (strcmp (buffer, mexec) == 0)
267     m += 1;
268     else if (mname && strcmp (buffer, mname) == 0)
269     m += 10;
270     else if (mpidfile && strcmp (buffer, mpidfile) == 0)
271     m += 100;
272 uberlord 2547
273 uberlord 2577 if (m == 111)
274     break;
275 uberlord 2547
276 uberlord 2577 lc++;
277     if (lc > 5)
278     break;
279     }
280     fclose (fp);
281     free (ffile);
282 uberlord 2547
283 uberlord 2928 return (m == 111 ? true : false);
284 uberlord 2547 }
285    
286 uberlord 2966 void rc_service_daemon_set (const char *service, const char *exec,
287 uberlord 2928 const char *name, const char *pidfile,
288     bool started)
289 uberlord 2547 {
290 uberlord 2607 char *svc = rc_xstrdup (service);
291     char *dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (svc),
292 uberlord 2577 (char *) NULL);
293     char **files = NULL;
294     char *file;
295     char *ffile = NULL;
296     int i;
297     char *mexec;
298     char *mname;
299     char *mpidfile;
300     int nfiles = 0;
301 uberlord 2547
302 uberlord 2607 free (svc);
303 uberlord 2577 if (! exec && ! name && ! pidfile)
304 uberlord 2928 return;
305 uberlord 2547
306 uberlord 2577 if (exec) {
307     i = strlen (exec) + 6;
308     mexec = rc_xmalloc (sizeof (char *) * i);
309     snprintf (mexec, i, "exec=%s", exec);
310     } else
311 uberlord 2634 mexec = rc_xstrdup ("exec=");
312 uberlord 2547
313 uberlord 2577 if (name) {
314     i = strlen (name) + 6;
315     mname = rc_xmalloc (sizeof (char *) * i);
316     snprintf (mname, i, "name=%s", name);
317     } else
318 uberlord 2634 mname = rc_xstrdup ("name=");
319 uberlord 2547
320 uberlord 2577 if (pidfile) {
321     i = strlen (pidfile) + 9;
322     mpidfile = rc_xmalloc (sizeof (char *) * i);
323     snprintf (mpidfile, i, "pidfile=%s", pidfile);
324     } else
325 uberlord 2634 mpidfile = rc_xstrdup ("pidfile=");
326 uberlord 2547
327 uberlord 2577 /* Regardless, erase any existing daemon info */
328 uberlord 2928 if (rc_is_dir (dirpath)) {
329 uberlord 2577 char *oldfile = NULL;
330 uberlord 2883 files = rc_ls_dir (dirpath, 0);
331 uberlord 2577 STRLIST_FOREACH (files, file, i) {
332     ffile = rc_strcatpaths (dirpath, file, (char *) NULL);
333     nfiles++;
334 uberlord 2547
335 uberlord 2577 if (! oldfile) {
336 uberlord 2928 if (_match_daemon (dirpath, file, mexec, mname, mpidfile)) {
337 uberlord 2577 unlink (ffile);
338     oldfile = ffile;
339     nfiles--;
340     }
341     } else {
342     rename (ffile, oldfile);
343     free (oldfile);
344     oldfile = ffile;
345     }
346     }
347 uberlord 2908 free (ffile);
348     rc_strlist_free (files);
349 uberlord 2577 }
350 uberlord 2547
351 uberlord 2577 /* Now store our daemon info */
352     if (started) {
353     char buffer[10];
354     FILE *fp;
355 uberlord 2547
356 uberlord 2957 if (mkdir (dirpath, 0755) == 0 || errno == EEXIST) {
357     snprintf (buffer, sizeof (buffer), "%03d", nfiles + 1);
358     file = rc_strcatpaths (dirpath, buffer, (char *) NULL);
359     if ((fp = fopen (file, "w")))
360     fprintf (fp, "%s\n%s\n%s\n", mexec, mname, mpidfile);
361 uberlord 2577 fclose (fp);
362 uberlord 2957 free (file);
363 uberlord 2577 }
364     }
365 uberlord 2547
366 uberlord 2577 free (mexec);
367     free (mname);
368     free (mpidfile);
369     free (dirpath);
370 uberlord 2547 }
371 uberlord 2966 librc_hidden_def(rc_service_daemon_set)
372 uberlord 2547
373 uberlord 2928 bool rc_service_started_daemon (const char *service, const char *exec,
374     int indx)
375 uberlord 2547 {
376 uberlord 2577 char *dirpath;
377     char *file;
378     int i;
379     char *mexec;
380 uberlord 2928 bool retval = false;
381 uberlord 2607 char *svc;
382 uberlord 2547
383 uberlord 2577 if (! service || ! exec)
384 uberlord 2928 return (false);
385 uberlord 2547
386 uberlord 2607 svc = rc_xstrdup (service);
387     dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (svc),
388 uberlord 2577 (char *) NULL);
389 uberlord 2607 free (svc);
390    
391 uberlord 2928 if (! rc_is_dir (dirpath)) {
392 uberlord 2577 free (dirpath);
393 uberlord 2928 return (false);
394 uberlord 2577 }
395 uberlord 2547
396 uberlord 2577 i = strlen (exec) + 6;
397     mexec = rc_xmalloc (sizeof (char *) * i);
398     snprintf (mexec, i, "exec=%s", exec);
399 uberlord 2547
400 uberlord 2577 if (indx > 0) {
401     int len = sizeof (char *) * 10;
402     file = rc_xmalloc (len);
403     snprintf (file, len, "%03d", indx);
404     retval = _match_daemon (dirpath, file, mexec, NULL, NULL);
405     free (file);
406     } else {
407 uberlord 2883 char **files = rc_ls_dir (dirpath, 0);
408 uberlord 2577 STRLIST_FOREACH (files, file, i) {
409     retval = _match_daemon (dirpath, file, mexec, NULL, NULL);
410 uberlord 2928 if (retval)
411 uberlord 2577 break;
412     }
413 uberlord 2908 rc_strlist_free (files);
414 uberlord 2577 }
415 uberlord 2547
416 uberlord 2577 free (mexec);
417     return (retval);
418 uberlord 2547 }
419 vapier 2597 librc_hidden_def(rc_service_started_daemon)
420 uberlord 2547
421 uberlord 2928 bool rc_service_daemons_crashed (const char *service)
422 uberlord 2547 {
423 uberlord 2577 char *dirpath;
424     char **files;
425     char *file;
426     char *path;
427     int i;
428     FILE *fp;
429     char buffer[RC_LINEBUFFER];
430     char *exec = NULL;
431     char *name = NULL;
432     char *pidfile = NULL;
433     pid_t pid = 0;
434     pid_t *pids = NULL;
435     char *p;
436     char *token;
437 uberlord 2928 bool retval = false;
438 uberlord 2607 char *svc;
439 uberlord 2547
440 uberlord 2577 if (! service)
441 uberlord 2928 return (false);
442 uberlord 2547
443 uberlord 2607 svc = rc_xstrdup (service);
444     dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (svc),
445 uberlord 2577 (char *) NULL);
446 uberlord 2607 free (svc);
447    
448 uberlord 2928 if (! rc_is_dir (dirpath)) {
449 uberlord 2577 free (dirpath);
450 uberlord 2928 return (false);
451 uberlord 2577 }
452 uberlord 2547
453 uberlord 2577 memset (buffer, 0, sizeof (buffer));
454 uberlord 2883 files = rc_ls_dir (dirpath, 0);
455 uberlord 2577 STRLIST_FOREACH (files, file, i) {
456     path = rc_strcatpaths (dirpath, file, (char *) NULL);
457     fp = fopen (path, "r");
458     free (path);
459 uberlord 2957 if (! fp)
460     break;
461 uberlord 2547
462 uberlord 2577 while ((fgets (buffer, RC_LINEBUFFER, fp))) {
463     int lb = strlen (buffer) - 1;
464     if (buffer[lb] == '\n')
465     buffer[lb] = 0;
466 uberlord 2547
467 uberlord 2577 p = buffer;
468     if ((token = strsep (&p, "=")) == NULL || ! p)
469     continue;
470 uberlord 2547
471 uberlord 2577 if (strlen (p) == 0)
472     continue;
473 uberlord 2547
474 uberlord 2577 if (strcmp (token, "exec") == 0) {
475     if (exec)
476     free (exec);
477 uberlord 2634 exec = rc_xstrdup (p);
478 uberlord 2577 } else if (strcmp (token, "name") == 0) {
479     if (name)
480     free (name);
481 uberlord 2634 name = rc_xstrdup (p);
482 uberlord 2577 } else if (strcmp (token, "pidfile") == 0) {
483     if (pidfile)
484     free (pidfile);
485 uberlord 2634 pidfile = rc_xstrdup (p);
486 uberlord 2577 }
487     }
488     fclose (fp);
489 uberlord 2547
490 uberlord 2577 pid = 0;
491     if (pidfile) {
492 uberlord 2928 if (! rc_exists (pidfile)) {
493     retval = true;
494 uberlord 2577 break;
495     }
496 uberlord 2547
497 uberlord 2577 if ((fp = fopen (pidfile, "r")) == NULL) {
498 uberlord 2928 retval = true;
499 uberlord 2577 break;
500     }
501 uberlord 2547
502 uberlord 2577 if (fscanf (fp, "%d", &pid) != 1) {
503     fclose (fp);
504 uberlord 2928 retval = true;
505 uberlord 2577 break;
506     }
507 uberlord 2547
508 uberlord 2577 fclose (fp);
509     free (pidfile);
510     pidfile = NULL;
511 uberlord 2822
512     /* We have the pid, so no need to match on name */
513     free (exec);
514     exec = NULL;
515     free (name);
516     name = NULL;
517 uberlord 2577 }
518 uberlord 2547
519 uberlord 2577 if ((pids = rc_find_pids (exec, name, 0, pid)) == NULL) {
520 uberlord 2928 retval = true;
521 uberlord 2577 break;
522     }
523     free (pids);
524 uberlord 2547
525 uberlord 2577 free (exec);
526     exec = NULL;
527     free (name);
528     name = NULL;
529     }
530 uberlord 2547
531 uberlord 2822 free (exec);
532     free (name);
533 uberlord 2577 free (dirpath);
534     rc_strlist_free (files);
535 uberlord 2547
536 uberlord 2577 return (retval);
537 uberlord 2547 }
538 vapier 2597 librc_hidden_def(rc_service_daemons_crashed)

  ViewVC Help
Powered by ViewVC 1.1.20