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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2822 - (hide annotations) (download) (as text)
Wed Aug 8 03:07:09 2007 UTC (6 years, 11 months ago) by uberlord
File MIME type: text/x-csrc
File size: 11319 byte(s)
    If given a pidfile, just match on that for seeing if we have crashed
    or not, #186159.
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     int foundany = false;
83     pid_t p;
84     pid_t *pids = NULL;
85     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     eerrorx ("opendir `/proc': %s", strerror (errno));
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     foundany = true;
113 uberlord 2547
114 uberlord 2577 if (runscript_pid != 0 && runscript_pid == p)
115     continue;
116 uberlord 2547
117 uberlord 2577 if (pid != 0 && pid != p)
118     continue;
119 uberlord 2547
120 uberlord 2577 if (uid) {
121     snprintf (buffer, sizeof (buffer), "/proc/%d", pid);
122     if (stat (buffer, &sb) != 0 || sb.st_uid != uid)
123     continue;
124     }
125 uberlord 2547
126 uberlord 2577 if (cmd && ! pid_is_cmd (p, cmd))
127     continue;
128 uberlord 2569
129 uberlord 2577 if (exec && ! cmd && ! pid_is_exec (p, exec))
130     continue;
131 uberlord 2547
132 uberlord 2577 pids = realloc (pids, sizeof (pid_t) * (npids + 2));
133     if (! pids)
134     eerrorx ("memory exhausted");
135 uberlord 2547
136 uberlord 2577 pids[npids] = p;
137     pids[npids + 1] = 0;
138     npids++;
139     }
140     closedir (procdir);
141 uberlord 2547
142 uberlord 2577 if (! foundany)
143     eerrorx ("nothing in /proc");
144 uberlord 2547
145 uberlord 2577 return (pids);
146 uberlord 2547 }
147 vapier 2597 librc_hidden_def(rc_find_pids)
148 uberlord 2547
149 uberlord 2549 #elif defined(__DragonFly__) || defined(__FreeBSD__) || \
150 uberlord 2577 defined(__NetBSD__) || defined(__OpenBSD__)
151 uberlord 2547
152 uberlord 2549 # if defined(__DragonFly__) || defined(__FreeBSD__)
153     # ifndef KERN_PROC_PROC
154     # define KERN_PROC_PROC KERN_PROC_ALL
155     # endif
156 uberlord 2547 # define _KINFO_PROC kinfo_proc
157     # define _KVM_GETARGV kvm_getargv
158     # define _GET_KINFO_UID(kp) (kp.ki_ruid)
159     # define _GET_KINFO_COMM(kp) (kp.ki_comm)
160     # define _GET_KINFO_PID(kp) (kp.ki_pid)
161     # else
162     # define _KINFO_PROC kinfo_proc2
163     # define _KVM_GETARGV kvm_getargv2
164     # define _GET_KINFO_UID(kp) (kp.p_ruid)
165     # define _GET_KINFO_COMM(kp) (kp.p_comm)
166     # define _GET_KINFO_PID(kp) (kp.p_pid)
167     # endif
168    
169     pid_t *rc_find_pids (const char *exec, const char *cmd,
170 uberlord 2577 uid_t uid, pid_t pid)
171 uberlord 2547 {
172 uberlord 2577 static kvm_t *kd = NULL;
173     char errbuf[_POSIX2_LINE_MAX];
174     struct _KINFO_PROC *kp;
175     int i;
176     int processes = 0;
177     int argc = 0;
178     char **argv;
179     pid_t *pids = NULL;
180     int npids = 0;
181 uberlord 2547
182 uberlord 2577 if ((kd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL)
183     eerrorx ("kvm_open: %s", errbuf);
184 uberlord 2547
185 uberlord 2549 #if defined(__DragonFly__) || defined( __FreeBSD__)
186 uberlord 2577 kp = kvm_getprocs (kd, KERN_PROC_PROC, 0, &processes);
187 uberlord 2549 #else
188 uberlord 2577 kp = kvm_getproc2 (kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2),
189     &processes);
190 uberlord 2549 #endif
191 uberlord 2577 for (i = 0; i < processes; i++) {
192     pid_t p = _GET_KINFO_PID (kp[i]);
193     if (pid != 0 && pid != p)
194     continue;
195 uberlord 2547
196 uberlord 2577 if (uid != 0 && uid != _GET_KINFO_UID (kp[i]))
197     continue;
198 uberlord 2547
199 uberlord 2577 if (cmd) {
200     if (! _GET_KINFO_COMM (kp[i]) ||
201     strcmp (cmd, _GET_KINFO_COMM (kp[i])) != 0)
202     continue;
203     }
204 uberlord 2547
205 uberlord 2577 if (exec && ! cmd) {
206     if ((argv = _KVM_GETARGV (kd, &kp[i], argc)) == NULL || ! *argv)
207     continue;
208 uberlord 2547
209 uberlord 2577 if (strcmp (*argv, exec) != 0)
210     continue;
211     }
212 uberlord 2547
213 uberlord 2577 pids = realloc (pids, sizeof (pid_t) * (npids + 2));
214     if (! pids)
215     eerrorx ("memory exhausted");
216 uberlord 2547
217 uberlord 2577 pids[npids] = p;
218     pids[npids + 1] = 0;
219     npids++;
220     }
221     kvm_close(kd);
222 uberlord 2547
223 uberlord 2577 return (pids);
224 uberlord 2547 }
225 vapier 2597 librc_hidden_def(rc_find_pids)
226 uberlord 2547
227     #else
228     # error "Platform not supported!"
229     #endif
230    
231     static bool _match_daemon (const char *path, const char *file,
232 uberlord 2577 const char *mexec, const char *mname,
233     const char *mpidfile)
234 uberlord 2547 {
235 uberlord 2577 char buffer[RC_LINEBUFFER];
236     char *ffile = rc_strcatpaths (path, file, (char *) NULL);
237     FILE *fp;
238     int lc = 0;
239     int m = 0;
240 uberlord 2547
241 uberlord 2577 if (! rc_exists (ffile)) {
242     free (ffile);
243     return (false);
244     }
245 uberlord 2547
246 uberlord 2577 if ((fp = fopen (ffile, "r")) == NULL) {
247     eerror ("fopen `%s': %s", ffile, strerror (errno));
248     free (ffile);
249     return (false);
250     }
251 uberlord 2547
252 uberlord 2577 if (! mname)
253     m += 10;
254     if (! mpidfile)
255     m += 100;
256 uberlord 2547
257 uberlord 2577 memset (buffer, 0, sizeof (buffer));
258     while ((fgets (buffer, RC_LINEBUFFER, fp))) {
259     int lb = strlen (buffer) - 1;
260     if (buffer[lb] == '\n')
261     buffer[lb] = 0;
262 uberlord 2547
263 uberlord 2577 if (strcmp (buffer, mexec) == 0)
264     m += 1;
265     else if (mname && strcmp (buffer, mname) == 0)
266     m += 10;
267     else if (mpidfile && strcmp (buffer, mpidfile) == 0)
268     m += 100;
269 uberlord 2547
270 uberlord 2577 if (m == 111)
271     break;
272 uberlord 2547
273 uberlord 2577 lc++;
274     if (lc > 5)
275     break;
276     }
277     fclose (fp);
278     free (ffile);
279 uberlord 2547
280 uberlord 2577 return (m == 111 ? true : false);
281 uberlord 2547 }
282    
283     void rc_set_service_daemon (const char *service, const char *exec,
284 uberlord 2577 const char *name, const char *pidfile,
285     bool started)
286 uberlord 2547 {
287 uberlord 2607 char *svc = rc_xstrdup (service);
288     char *dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (svc),
289 uberlord 2577 (char *) NULL);
290     char **files = NULL;
291     char *file;
292     char *ffile = NULL;
293     int i;
294     char *mexec;
295     char *mname;
296     char *mpidfile;
297     int nfiles = 0;
298 uberlord 2547
299 uberlord 2607 free (svc);
300 uberlord 2577 if (! exec && ! name && ! pidfile)
301     return;
302 uberlord 2547
303 uberlord 2577 if (exec) {
304     i = strlen (exec) + 6;
305     mexec = rc_xmalloc (sizeof (char *) * i);
306     snprintf (mexec, i, "exec=%s", exec);
307     } else
308 uberlord 2634 mexec = rc_xstrdup ("exec=");
309 uberlord 2547
310 uberlord 2577 if (name) {
311     i = strlen (name) + 6;
312     mname = rc_xmalloc (sizeof (char *) * i);
313     snprintf (mname, i, "name=%s", name);
314     } else
315 uberlord 2634 mname = rc_xstrdup ("name=");
316 uberlord 2547
317 uberlord 2577 if (pidfile) {
318     i = strlen (pidfile) + 9;
319     mpidfile = rc_xmalloc (sizeof (char *) * i);
320     snprintf (mpidfile, i, "pidfile=%s", pidfile);
321     } else
322 uberlord 2634 mpidfile = rc_xstrdup ("pidfile=");
323 uberlord 2547
324 uberlord 2577 /* Regardless, erase any existing daemon info */
325     if (rc_is_dir (dirpath)) {
326     char *oldfile = NULL;
327     files = rc_ls_dir (NULL, dirpath, 0);
328     STRLIST_FOREACH (files, file, i) {
329     ffile = rc_strcatpaths (dirpath, file, (char *) NULL);
330     nfiles++;
331 uberlord 2547
332 uberlord 2577 if (! oldfile) {
333     if (_match_daemon (dirpath, file, mexec, mname, mpidfile)) {
334     unlink (ffile);
335     oldfile = ffile;
336     nfiles--;
337     }
338     } else {
339     rename (ffile, oldfile);
340     free (oldfile);
341     oldfile = ffile;
342     }
343     }
344     if (ffile)
345     free (ffile);
346     free (files);
347     }
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 2577 if (! rc_is_dir (dirpath))
355     if (mkdir (dirpath, 0755) != 0)
356     eerror ("mkdir `%s': %s", dirpath, strerror (errno));
357 uberlord 2547
358 uberlord 2577 snprintf (buffer, sizeof (buffer), "%03d", nfiles + 1);
359     file = rc_strcatpaths (dirpath, buffer, (char *) NULL);
360     if ((fp = fopen (file, "w")) == NULL)
361     eerror ("fopen `%s': %s", file, strerror (errno));
362     else {
363     fprintf (fp, "%s\n%s\n%s\n", mexec, mname, mpidfile);
364     fclose (fp);
365     }
366     free (file);
367     }
368 uberlord 2547
369 uberlord 2577 free (mexec);
370     free (mname);
371     free (mpidfile);
372     free (dirpath);
373 uberlord 2547 }
374 vapier 2597 librc_hidden_def(rc_set_service_daemon)
375 uberlord 2547
376     bool rc_service_started_daemon (const char *service, const char *exec,
377 uberlord 2577 int indx)
378 uberlord 2547 {
379 uberlord 2577 char *dirpath;
380     char *file;
381     int i;
382     char *mexec;
383     bool retval = false;
384 uberlord 2607 char *svc;
385 uberlord 2547
386 uberlord 2577 if (! service || ! exec)
387     return (false);
388 uberlord 2547
389 uberlord 2607 svc = rc_xstrdup (service);
390     dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (svc),
391 uberlord 2577 (char *) NULL);
392 uberlord 2607 free (svc);
393    
394 uberlord 2577 if (! rc_is_dir (dirpath)) {
395     free (dirpath);
396     return (false);
397     }
398 uberlord 2547
399 uberlord 2577 i = strlen (exec) + 6;
400     mexec = rc_xmalloc (sizeof (char *) * i);
401     snprintf (mexec, i, "exec=%s", exec);
402 uberlord 2547
403 uberlord 2577 if (indx > 0) {
404     int len = sizeof (char *) * 10;
405     file = rc_xmalloc (len);
406     snprintf (file, len, "%03d", indx);
407     retval = _match_daemon (dirpath, file, mexec, NULL, NULL);
408     free (file);
409     } else {
410     char **files = rc_ls_dir (NULL, dirpath, 0);
411     STRLIST_FOREACH (files, file, i) {
412     retval = _match_daemon (dirpath, file, mexec, NULL, NULL);
413     if (retval)
414     break;
415     }
416     free (files);
417     }
418 uberlord 2547
419 uberlord 2577 free (mexec);
420     return (retval);
421 uberlord 2547 }
422 vapier 2597 librc_hidden_def(rc_service_started_daemon)
423 uberlord 2547
424     bool rc_service_daemons_crashed (const char *service)
425     {
426 uberlord 2577 char *dirpath;
427     char **files;
428     char *file;
429     char *path;
430     int i;
431     FILE *fp;
432     char buffer[RC_LINEBUFFER];
433     char *exec = NULL;
434     char *name = NULL;
435     char *pidfile = NULL;
436     pid_t pid = 0;
437     pid_t *pids = NULL;
438     char *p;
439     char *token;
440     bool retval = false;
441 uberlord 2607 char *svc;
442 uberlord 2547
443 uberlord 2577 if (! service)
444     return (false);
445 uberlord 2547
446 uberlord 2607 svc = rc_xstrdup (service);
447     dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (svc),
448 uberlord 2577 (char *) NULL);
449 uberlord 2607 free (svc);
450    
451 uberlord 2577 if (! rc_is_dir (dirpath)) {
452     free (dirpath);
453     return (false);
454     }
455 uberlord 2547
456 uberlord 2577 memset (buffer, 0, sizeof (buffer));
457     files = rc_ls_dir (NULL, dirpath, 0);
458     STRLIST_FOREACH (files, file, i) {
459     path = rc_strcatpaths (dirpath, file, (char *) NULL);
460     fp = fopen (path, "r");
461     free (path);
462     if (! fp) {
463     eerror ("fopen `%s': %s", file, strerror (errno));
464     continue;
465     }
466 uberlord 2547
467 uberlord 2577 while ((fgets (buffer, RC_LINEBUFFER, fp))) {
468     int lb = strlen (buffer) - 1;
469     if (buffer[lb] == '\n')
470     buffer[lb] = 0;
471 uberlord 2547
472 uberlord 2577 p = buffer;
473     if ((token = strsep (&p, "=")) == NULL || ! p)
474     continue;
475 uberlord 2547
476 uberlord 2577 if (strlen (p) == 0)
477     continue;
478 uberlord 2547
479 uberlord 2577 if (strcmp (token, "exec") == 0) {
480     if (exec)
481     free (exec);
482 uberlord 2634 exec = rc_xstrdup (p);
483 uberlord 2577 } else if (strcmp (token, "name") == 0) {
484     if (name)
485     free (name);
486 uberlord 2634 name = rc_xstrdup (p);
487 uberlord 2577 } else if (strcmp (token, "pidfile") == 0) {
488     if (pidfile)
489     free (pidfile);
490 uberlord 2634 pidfile = rc_xstrdup (p);
491 uberlord 2577 }
492     }
493     fclose (fp);
494 uberlord 2547
495 uberlord 2577 pid = 0;
496     if (pidfile) {
497     if (! rc_exists (pidfile)) {
498     retval = true;
499     break;
500     }
501 uberlord 2547
502 uberlord 2577 if ((fp = fopen (pidfile, "r")) == NULL) {
503     eerror ("fopen `%s': %s", pidfile, strerror (errno));
504     retval = true;
505     break;
506     }
507 uberlord 2547
508 uberlord 2577 if (fscanf (fp, "%d", &pid) != 1) {
509     eerror ("no pid found in `%s'", pidfile);
510     fclose (fp);
511     retval = true;
512     break;
513     }
514 uberlord 2547
515 uberlord 2577 fclose (fp);
516     free (pidfile);
517     pidfile = NULL;
518 uberlord 2822
519     /* We have the pid, so no need to match on name */
520     free (exec);
521     exec = NULL;
522     free (name);
523     name = NULL;
524 uberlord 2577 }
525 uberlord 2547
526 uberlord 2577 if ((pids = rc_find_pids (exec, name, 0, pid)) == NULL) {
527     retval = true;
528     break;
529     }
530     free (pids);
531 uberlord 2547
532 uberlord 2577 free (exec);
533     exec = NULL;
534     free (name);
535     name = NULL;
536     }
537 uberlord 2547
538 uberlord 2822 free (exec);
539     free (name);
540 uberlord 2577 free (dirpath);
541     rc_strlist_free (files);
542 uberlord 2547
543 uberlord 2577 return (retval);
544 uberlord 2547 }
545 vapier 2597 librc_hidden_def(rc_service_daemons_crashed)

  ViewVC Help
Powered by ViewVC 1.1.20