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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2597 - (hide annotations) (download) (as text)
Fri Apr 13 14:08:16 2007 UTC (7 years, 4 months ago) by vapier
File MIME type: text/x-csrc
File size: 11135 byte(s)
kill off internal relocations for librc.so
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 2577 char *dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (service),
288     (char *) NULL);
289     char **files = NULL;
290     char *file;
291     char *ffile = NULL;
292     int i;
293     char *mexec;
294     char *mname;
295     char *mpidfile;
296     int nfiles = 0;
297 uberlord 2547
298 uberlord 2577 if (! exec && ! name && ! pidfile)
299     return;
300 uberlord 2547
301 uberlord 2577 if (exec) {
302     i = strlen (exec) + 6;
303     mexec = rc_xmalloc (sizeof (char *) * i);
304     snprintf (mexec, i, "exec=%s", exec);
305     } else
306     mexec = strdup ("exec=");
307 uberlord 2547
308 uberlord 2577 if (name) {
309     i = strlen (name) + 6;
310     mname = rc_xmalloc (sizeof (char *) * i);
311     snprintf (mname, i, "name=%s", name);
312     } else
313     mname = strdup ("name=");
314 uberlord 2547
315 uberlord 2577 if (pidfile) {
316     i = strlen (pidfile) + 9;
317     mpidfile = rc_xmalloc (sizeof (char *) * i);
318     snprintf (mpidfile, i, "pidfile=%s", pidfile);
319     } else
320     mpidfile = strdup ("pidfile=");
321 uberlord 2547
322 uberlord 2577 /* Regardless, erase any existing daemon info */
323     if (rc_is_dir (dirpath)) {
324     char *oldfile = NULL;
325     files = rc_ls_dir (NULL, dirpath, 0);
326     STRLIST_FOREACH (files, file, i) {
327     ffile = rc_strcatpaths (dirpath, file, (char *) NULL);
328     nfiles++;
329 uberlord 2547
330 uberlord 2577 if (! oldfile) {
331     if (_match_daemon (dirpath, file, mexec, mname, mpidfile)) {
332     unlink (ffile);
333     oldfile = ffile;
334     nfiles--;
335     }
336     } else {
337     rename (ffile, oldfile);
338     free (oldfile);
339     oldfile = ffile;
340     }
341     }
342     if (ffile)
343     free (ffile);
344     free (files);
345     }
346 uberlord 2547
347 uberlord 2577 /* Now store our daemon info */
348     if (started) {
349     char buffer[10];
350     FILE *fp;
351 uberlord 2547
352 uberlord 2577 if (! rc_is_dir (dirpath))
353     if (mkdir (dirpath, 0755) != 0)
354     eerror ("mkdir `%s': %s", dirpath, strerror (errno));
355 uberlord 2547
356 uberlord 2577 snprintf (buffer, sizeof (buffer), "%03d", nfiles + 1);
357     file = rc_strcatpaths (dirpath, buffer, (char *) NULL);
358     if ((fp = fopen (file, "w")) == NULL)
359     eerror ("fopen `%s': %s", file, strerror (errno));
360     else {
361     fprintf (fp, "%s\n%s\n%s\n", mexec, mname, mpidfile);
362     fclose (fp);
363     }
364     free (file);
365     }
366 uberlord 2547
367 uberlord 2577 free (mexec);
368     free (mname);
369     free (mpidfile);
370     free (dirpath);
371 uberlord 2547 }
372 vapier 2597 librc_hidden_def(rc_set_service_daemon)
373 uberlord 2547
374     bool rc_service_started_daemon (const char *service, const char *exec,
375 uberlord 2577 int indx)
376 uberlord 2547 {
377 uberlord 2577 char *dirpath;
378     char *file;
379     int i;
380     char *mexec;
381     bool retval = false;
382 uberlord 2547
383 uberlord 2577 if (! service || ! exec)
384     return (false);
385 uberlord 2547
386 uberlord 2577 dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (service),
387     (char *) NULL);
388     if (! rc_is_dir (dirpath)) {
389     free (dirpath);
390     return (false);
391     }
392 uberlord 2547
393 uberlord 2577 i = strlen (exec) + 6;
394     mexec = rc_xmalloc (sizeof (char *) * i);
395     snprintf (mexec, i, "exec=%s", exec);
396 uberlord 2547
397 uberlord 2577 if (indx > 0) {
398     int len = sizeof (char *) * 10;
399     file = rc_xmalloc (len);
400     snprintf (file, len, "%03d", indx);
401     retval = _match_daemon (dirpath, file, mexec, NULL, NULL);
402     free (file);
403     } else {
404     char **files = rc_ls_dir (NULL, dirpath, 0);
405     STRLIST_FOREACH (files, file, i) {
406     retval = _match_daemon (dirpath, file, mexec, NULL, NULL);
407     if (retval)
408     break;
409     }
410     free (files);
411     }
412 uberlord 2547
413 uberlord 2577 free (mexec);
414     return (retval);
415 uberlord 2547 }
416 vapier 2597 librc_hidden_def(rc_service_started_daemon)
417 uberlord 2547
418     bool rc_service_daemons_crashed (const char *service)
419     {
420 uberlord 2577 char *dirpath;
421     char **files;
422     char *file;
423     char *path;
424     int i;
425     FILE *fp;
426     char buffer[RC_LINEBUFFER];
427     char *exec = NULL;
428     char *name = NULL;
429     char *pidfile = NULL;
430     pid_t pid = 0;
431     pid_t *pids = NULL;
432     char *p;
433     char *token;
434     bool retval = false;
435 uberlord 2547
436 uberlord 2577 if (! service)
437     return (false);
438 uberlord 2547
439 uberlord 2577 dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename (service),
440     (char *) NULL);
441     if (! rc_is_dir (dirpath)) {
442     free (dirpath);
443     return (false);
444     }
445 uberlord 2547
446 uberlord 2577 memset (buffer, 0, sizeof (buffer));
447     files = rc_ls_dir (NULL, dirpath, 0);
448     STRLIST_FOREACH (files, file, i) {
449     path = rc_strcatpaths (dirpath, file, (char *) NULL);
450     fp = fopen (path, "r");
451     free (path);
452     if (! fp) {
453     eerror ("fopen `%s': %s", file, strerror (errno));
454     continue;
455     }
456 uberlord 2547
457 uberlord 2577 while ((fgets (buffer, RC_LINEBUFFER, fp))) {
458     int lb = strlen (buffer) - 1;
459     if (buffer[lb] == '\n')
460     buffer[lb] = 0;
461 uberlord 2547
462 uberlord 2577 p = buffer;
463     if ((token = strsep (&p, "=")) == NULL || ! p)
464     continue;
465 uberlord 2547
466 uberlord 2577 if (strlen (p) == 0)
467     continue;
468 uberlord 2547
469 uberlord 2577 if (strcmp (token, "exec") == 0) {
470     if (exec)
471     free (exec);
472     exec = strdup (p);
473     } else if (strcmp (token, "name") == 0) {
474     if (name)
475     free (name);
476     name = strdup (p);
477     } else if (strcmp (token, "pidfile") == 0) {
478     if (pidfile)
479     free (pidfile);
480     pidfile = strdup (p);
481     }
482     }
483     fclose (fp);
484 uberlord 2547
485 uberlord 2577 pid = 0;
486     if (pidfile) {
487     if (! rc_exists (pidfile)) {
488     retval = true;
489     break;
490     }
491 uberlord 2547
492 uberlord 2577 if ((fp = fopen (pidfile, "r")) == NULL) {
493     eerror ("fopen `%s': %s", pidfile, strerror (errno));
494     retval = true;
495     break;
496     }
497 uberlord 2547
498 uberlord 2577 if (fscanf (fp, "%d", &pid) != 1) {
499     eerror ("no pid found in `%s'", pidfile);
500     fclose (fp);
501     retval = true;
502     break;
503     }
504 uberlord 2547
505 uberlord 2577 fclose (fp);
506     free (pidfile);
507     pidfile = NULL;
508     }
509 uberlord 2547
510 uberlord 2577 if ((pids = rc_find_pids (exec, name, 0, pid)) == NULL) {
511     retval = true;
512     break;
513     }
514     free (pids);
515 uberlord 2547
516 uberlord 2577 if (exec) {
517     free (exec);
518     exec = NULL;
519     }
520     if (name) {
521     free (name);
522     name = NULL;
523     }
524     }
525 uberlord 2547
526 uberlord 2577 if (exec) {
527     free (exec);
528     exec = NULL;
529     }
530     if (name) {
531     free (name);
532     name = NULL;
533     }
534 uberlord 2547
535 uberlord 2577 free (dirpath);
536     rc_strlist_free (files);
537 uberlord 2547
538 uberlord 2577 return (retval);
539 uberlord 2547 }
540 vapier 2597 librc_hidden_def(rc_service_daemons_crashed)

  ViewVC Help
Powered by ViewVC 1.1.20