~vorlon/ubuntu/raring/upstart/lp.1199778

« back to all changes in this revision

Viewing changes to init/cfgfile.c

  • Committer: Scott James Remnant
  • Date: 2007-02-01 16:51:28 UTC
  • Revision ID: scott@netsplit.com-20070201165128-n5vcucr1wa4o9bey
* init/cfgfile.c (cfg_watch_dir): Port to the new NihWatch API and
use nih_dir_walk().  This also fixes the long-standing bug where we
wouldn't watch the configuration directory if inotify was disabled.
Drop both the parent and prefix members for now, until we clean this
up later.
(cfg_create_modify_handler): Wrap cfg_read_job after figuring out
the job name.
(cfg_job_name): Function to figure out the job name from a path.
(cfg_visitor): Visitor function to handle initial parsing, figuring
out the job name; otherwise identical to the standard handler.
* init/cfgfile.h: Update prototype for cfg_watch_dir.
* init/main.c (main): Update call to cfg_watch_dir.

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
#include <nih/string.h>
43
43
#include <nih/list.h>
44
44
#include <nih/timer.h>
45
 
#include <nih/file.h>
 
45
#include <nih/watch.h>
46
46
#include <nih/config.h>
47
47
#include <nih/logging.h>
48
48
#include <nih/error.h>
55
55
#include "errors.h"
56
56
 
57
57
 
58
 
/**
59
 
 * WatchInfo:
60
 
 * @parent: parent for jobs,
61
 
 * @prefix: prefix for job names.
62
 
 *
63
 
 * Data pointed passed to the config file watcher function.
64
 
 **/
65
 
typedef struct watch_info {
66
 
        const void *parent;
67
 
        char       *prefix;
68
 
} WatchInfo;
69
 
 
70
 
 
71
58
/* Prototypes for static functions */
72
 
static int  cfg_stanza_description (Job *job, NihConfigStanza *stanza,
73
 
                                    const char *file, size_t len,
74
 
                                    size_t *pos, size_t *lineno);
75
 
static int  cfg_stanza_author      (Job *job, NihConfigStanza *stanza,
76
 
                                    const char *file, size_t len,
77
 
                                    size_t *pos, size_t *lineno);
78
 
static int  cfg_stanza_version     (Job *job, NihConfigStanza *stanza,
79
 
                                    const char *file, size_t len,
80
 
                                    size_t *pos, size_t *lineno);
81
 
static int  cfg_stanza_emits       (Job *job, NihConfigStanza *stanza,
82
 
                                    const char *file, size_t len,
83
 
                                    size_t *pos, size_t *lineno);
84
 
static int  cfg_stanza_on          (Job *job, NihConfigStanza *stanza,
85
 
                                    const char *file, size_t len,
86
 
                                    size_t *pos, size_t *lineno);
87
 
static int  cfg_stanza_start       (Job *job, NihConfigStanza *stanza,
88
 
                                    const char *file, size_t len,
89
 
                                    size_t *pos, size_t *lineno);
90
 
static int  cfg_stanza_stop        (Job *job, NihConfigStanza *stanza,
91
 
                                    const char *file, size_t len,
92
 
                                    size_t *pos, size_t *lineno);
93
 
static int  cfg_stanza_exec        (Job *job, NihConfigStanza *stanza,
94
 
                                    const char *file, size_t len,
95
 
                                    size_t *pos, size_t *lineno);
96
 
static int  cfg_stanza_daemon      (Job *job, NihConfigStanza *stanza,
97
 
                                    const char *file, size_t len,
98
 
                                    size_t *pos, size_t *lineno);
99
 
static int  cfg_stanza_respawn     (Job *job, NihConfigStanza *stanza,
100
 
                                    const char *file, size_t len,
101
 
                                    size_t *pos, size_t *lineno);
102
 
static int  cfg_stanza_script      (Job *job, NihConfigStanza *stanza,
103
 
                                    const char *file, size_t len,
104
 
                                    size_t *pos, size_t *lineno);
105
 
static int  cfg_stanza_instance    (Job *job, NihConfigStanza *stanza,
106
 
                                    const char *file, size_t len,
107
 
                                    size_t *pos, size_t *lineno);
108
 
static int  cfg_stanza_pid         (Job *job, NihConfigStanza *stanza,
109
 
                                    const char *file, size_t len,
110
 
                                    size_t *pos, size_t *lineno);
111
 
static int  cfg_stanza_kill        (Job *job, NihConfigStanza *stanza,
112
 
                                    const char *file, size_t len,
113
 
                                    size_t *pos, size_t *lineno);
114
 
static int  cfg_stanza_normalexit  (Job *job, NihConfigStanza *stanza,
115
 
                                    const char *file, size_t len,
116
 
                                    size_t *pos, size_t *lineno);
117
 
static int  cfg_stanza_console     (Job *job, NihConfigStanza *stanza,
118
 
                                    const char *file, size_t len,
119
 
                                    size_t *pos, size_t *lineno);
120
 
static int  cfg_stanza_env         (Job *job, NihConfigStanza *stanza,
121
 
                                    const char *file, size_t len,
122
 
                                    size_t *pos, size_t *lineno);
123
 
static int  cfg_stanza_umask       (Job *job, NihConfigStanza *stanza,
124
 
                                    const char *file, size_t len,
125
 
                                    size_t *pos, size_t *lineno);
126
 
static int  cfg_stanza_nice        (Job *job, NihConfigStanza *stanza,
127
 
                                    const char *file, size_t len,
128
 
                                    size_t *pos, size_t *lineno);
129
 
static int  cfg_stanza_limit       (Job *job, NihConfigStanza *stanza,
130
 
                                    const char *file, size_t len,
131
 
                                    size_t *pos, size_t *lineno);
132
 
static int  cfg_stanza_chroot      (Job *job, NihConfigStanza *stanza,
133
 
                                    const char *file, size_t len,
134
 
                                    size_t *pos, size_t *lineno);
135
 
static int  cfg_stanza_chdir       (Job *job, NihConfigStanza *stanza,
136
 
                                    const char *file, size_t len,
137
 
                                    size_t *pos, size_t *lineno);
 
59
static int   cfg_stanza_description    (Job *job, NihConfigStanza *stanza,
 
60
                                        const char *file, size_t len,
 
61
                                        size_t *pos, size_t *lineno);
 
62
static int   cfg_stanza_author         (Job *job, NihConfigStanza *stanza,
 
63
                                        const char *file, size_t len,
 
64
                                        size_t *pos, size_t *lineno);
 
65
static int   cfg_stanza_version        (Job *job, NihConfigStanza *stanza,
 
66
                                        const char *file, size_t len,
 
67
                                        size_t *pos, size_t *lineno);
 
68
static int   cfg_stanza_emits          (Job *job, NihConfigStanza *stanza,
 
69
                                        const char *file, size_t len,
 
70
                                        size_t *pos, size_t *lineno);
 
71
static int   cfg_stanza_on             (Job *job, NihConfigStanza *stanza,
 
72
                                        const char *file, size_t len,
 
73
                                        size_t *pos, size_t *lineno);
 
74
static int   cfg_stanza_start          (Job *job, NihConfigStanza *stanza,
 
75
                                        const char *file, size_t len,
 
76
                                        size_t *pos, size_t *lineno);
 
77
static int   cfg_stanza_stop           (Job *job, NihConfigStanza *stanza,
 
78
                                        const char *file, size_t len,
 
79
                                        size_t *pos, size_t *lineno);
 
80
static int   cfg_stanza_exec           (Job *job, NihConfigStanza *stanza,
 
81
                                        const char *file, size_t len,
 
82
                                        size_t *pos, size_t *lineno);
 
83
static int   cfg_stanza_daemon         (Job *job, NihConfigStanza *stanza,
 
84
                                        const char *file, size_t len,
 
85
                                        size_t *pos, size_t *lineno);
 
86
static int   cfg_stanza_respawn        (Job *job, NihConfigStanza *stanza,
 
87
                                        const char *file, size_t len,
 
88
                                        size_t *pos, size_t *lineno);
 
89
static int   cfg_stanza_script         (Job *job, NihConfigStanza *stanza,
 
90
                                        const char *file, size_t len,
 
91
                                        size_t *pos, size_t *lineno);
 
92
static int   cfg_stanza_instance       (Job *job, NihConfigStanza *stanza,
 
93
                                        const char *file, size_t len,
 
94
                                        size_t *pos, size_t *lineno);
 
95
static int   cfg_stanza_pid            (Job *job, NihConfigStanza *stanza,
 
96
                                        const char *file, size_t len,
 
97
                                        size_t *pos, size_t *lineno);
 
98
static int   cfg_stanza_kill           (Job *job, NihConfigStanza *stanza,
 
99
                                        const char *file, size_t len,
 
100
                                        size_t *pos, size_t *lineno);
 
101
static int   cfg_stanza_normalexit     (Job *job, NihConfigStanza *stanza,
 
102
                                        const char *file, size_t len,
 
103
                                        size_t *pos, size_t *lineno);
 
104
static int   cfg_stanza_console        (Job *job, NihConfigStanza *stanza,
 
105
                                        const char *file, size_t len,
 
106
                                        size_t *pos, size_t *lineno);
 
107
static int   cfg_stanza_env            (Job *job, NihConfigStanza *stanza,
 
108
                                        const char *file, size_t len,
 
109
                                        size_t *pos, size_t *lineno);
 
110
static int   cfg_stanza_umask          (Job *job, NihConfigStanza *stanza,
 
111
                                        const char *file, size_t len,
 
112
                                        size_t *pos, size_t *lineno);
 
113
static int   cfg_stanza_nice           (Job *job, NihConfigStanza *stanza,
 
114
                                        const char *file, size_t len,
 
115
                                        size_t *pos, size_t *lineno);
 
116
static int   cfg_stanza_limit          (Job *job, NihConfigStanza *stanza,
 
117
                                        const char *file, size_t len,
 
118
                                        size_t *pos, size_t *lineno);
 
119
static int   cfg_stanza_chroot         (Job *job, NihConfigStanza *stanza,
 
120
                                        const char *file, size_t len,
 
121
                                        size_t *pos, size_t *lineno);
 
122
static int   cfg_stanza_chdir          (Job *job, NihConfigStanza *stanza,
 
123
                                        const char *file, size_t len,
 
124
                                        size_t *pos, size_t *lineno);
138
125
 
139
 
static void cfg_watcher            (WatchInfo *info, NihFileWatch *watch,
140
 
                                    uint32_t events, const char *name);
 
126
static char *cfg_job_name              (const void *parent,
 
127
                                        const char *dirname, const char *path);
 
128
static void  cfg_create_modify_handler (void *data, NihWatch *watch,
 
129
                                        const char *path);
 
130
static void  cfg_delete_handler        (void *data, NihWatch *watch,
 
131
                                        const char *path);
 
132
static int   cfg_visitor               (void *data, const char *path);
141
133
 
142
134
 
143
135
/**
230
222
                                   filename, lineno, err->message);
231
223
                        break;
232
224
                default:
233
 
                        nih_error (_("%s: unable to read: %s"), filename,
 
225
                        nih_error ("%s: %s: %s", filename, _("unable to read"),
234
226
                                   err->message);
235
227
                        break;
236
228
                }
1614
1606
 
1615
1607
/**
1616
1608
 * cfg_watch_dir:
1617
 
 * @parent: parent of jobs,
1618
 
 * @dirname: directory to watch,
1619
 
 * @prefix: prefix to append to job names.
 
1609
 * @dirname: directory to watch.
1620
1610
 *
1621
1611
 * Watch @dirname for creation or modification of configuration files or
1622
1612
 * sub-directories and parse them whenever they exist.  This also performs
1623
1613
 * the initial parsing of jobs in the directory.
1624
1614
 *
1625
 
 * Jobs are named by joining @prefix and the name of the file under @dir,
1626
 
 * @prefix may be NULL.
1627
 
 *
1628
 
 * If @parent is not NULL, it should be a pointer to another allocated
1629
 
 * block which will be used as the parent for this block.  When @parent
1630
 
 * is freed, the returned block will be freed too.  If you have clean-up
1631
 
 * that would need to be run, you can assign a destructor function using
1632
 
 * the nih_alloc_set_destructor() function.
1633
 
 *
1634
1615
 * Returns: zero on success, negative value on raised error.
1635
1616
 **/
1636
1617
int
1637
 
cfg_watch_dir (const void *parent,
1638
 
               const char *dirname,
1639
 
               const char *prefix)
 
1618
cfg_watch_dir (const char *dirname)
1640
1619
{
1641
 
        DIR           *dir;
1642
 
        struct dirent *ent;
1643
 
        WatchInfo     *info;
1644
 
        NihFileWatch  *watch;
 
1620
        NihWatch *watch;
1645
1621
 
1646
1622
        nih_assert (dirname != NULL);
1647
1623
 
1648
1624
        nih_info (_("Reading configuration from %s"), dirname);
1649
1625
 
1650
 
        NIH_MUST (info = nih_new (NULL, WatchInfo));
1651
 
        info->parent = parent;
1652
 
        info->prefix = prefix ? nih_strdup (info, prefix) : NULL;
1653
 
 
1654
 
        /* FIXME we don't handle move yet */
1655
 
 
1656
 
        /* Add a watch so we can keep up to date */
1657
 
        watch = nih_file_add_watch (NULL, dirname,
1658
 
                                    (IN_CREATE | IN_DELETE | IN_MODIFY),
1659
 
                                    (NihFileWatcher)cfg_watcher, info);
 
1626
        /* Use inotify to keep up to date about changes.  It's not critical
 
1627
         * for this to fail, but we do bitch about it.
 
1628
         */
 
1629
        watch = nih_watch_new (NULL, dirname, TRUE, (NihFileFilter)NULL,
 
1630
                               (NihCreateHandler)cfg_create_modify_handler,
 
1631
                               (NihModifyHandler)cfg_create_modify_handler,
 
1632
                               (NihDeleteHandler)cfg_delete_handler, NULL);
1660
1633
        if (! watch) {
1661
 
                nih_free (info);
1662
 
                return -1;
1663
 
        }
1664
 
 
1665
 
        /* Read through any files already in the directory */
1666
 
        dir = opendir (dirname);
1667
 
        if (! dir) {
1668
 
                nih_error_raise_system ();
1669
 
                nih_free (info);
1670
 
                return -1;
1671
 
        }
1672
 
 
1673
 
        /* Just call the watcher function */
1674
 
        while ((ent = readdir (dir)) != NULL)
1675
 
                cfg_watcher (info, watch, IN_CREATE, ent->d_name);
1676
 
 
1677
 
        closedir (dir);
1678
 
 
1679
 
        return 0;
1680
 
}
1681
 
 
1682
 
/**
1683
 
 * cfg_watcher:
1684
 
 * @info: watch information,
1685
 
 * @watch: watch that generated the event,
1686
 
 * @events: events that occurred,
1687
 
 * @name: name of file that changed.
1688
 
 *
1689
 
 * This function is called whenever a configuration file directory we are
1690
 
 * watching changes.  It arranges for the job to be parsed, or the new
1691
 
 * directory to be watched.
1692
 
 **/
1693
 
static void
1694
 
cfg_watcher (WatchInfo    *info,
1695
 
             NihFileWatch *watch,
1696
 
             uint32_t      events,
1697
 
             const char   *name)
1698
 
{
1699
 
        struct stat  statbuf;
1700
 
        char        *filename, *jobname;
1701
 
 
1702
 
        nih_assert (watch != NULL);
1703
 
 
1704
 
        /* If this watch is now being ignored, free the info and watch */
1705
 
        if (events & IN_IGNORED) {
1706
 
                nih_debug ("Ceasing watching %s", watch->path);
1707
 
 
1708
 
                nih_list_free (&watch->entry);
1709
 
                nih_free (info);
1710
 
                return;
1711
 
        }
1712
 
 
1713
 
        /* Otherwise name should be set and shouldn't begin . */
1714
 
        if (! name)
1715
 
                return;
1716
 
 
1717
 
        if ((name[0] == '\0') || strchr (name, '.') || strchr (name, '~')) {
1718
 
                nih_debug ("Ignored %s/%s", watch->path, name);
1719
 
                return;
1720
 
        }
1721
 
 
1722
 
        /* FIXME better name checking required */
1723
 
 
1724
 
        /* FIXME we don't handle DELETE yet ... that should probably mark
1725
 
         * the running job as an instance or delete a stopped one
 
1634
                NihError *err;
 
1635
 
 
1636
                err = nih_error_get ();
 
1637
                nih_error ("%s: %s: %s", dirname,
 
1638
                           _("Unable to watch configuration directory"),
 
1639
                           err->message);
 
1640
                nih_free (err);
 
1641
        }
 
1642
 
 
1643
        /* Parse all files that we find right now.  If this fails, on the
 
1644
         * other hand, it is a problem (though we may have parsed something).
1726
1645
         */
1727
 
        if (events & IN_DELETE) {
1728
 
                nih_debug ("Delete of %s/%s (ignored)", watch->path, name);
1729
 
                return;
1730
 
        }
1731
 
 
1732
 
        /* Construct filename and job name (also new prefix) */
1733
 
        NIH_MUST (filename = nih_sprintf (NULL, "%s/%s", watch->path, name));
1734
 
        if (info->prefix) {
1735
 
                NIH_MUST (jobname = nih_sprintf (NULL, "%s/%s",
1736
 
                                                 info->prefix, name));
1737
 
        } else {
1738
 
                NIH_MUST (jobname = nih_strdup (NULL, name));
1739
 
        }
1740
 
 
1741
 
        /* Check we can stat it */
1742
 
        if (stat (filename, &statbuf) < 0) {
1743
 
                /* Bah, ignore the error */
1744
 
 
1745
 
        } else if (S_ISDIR (statbuf.st_mode)) {
1746
 
                /* It's a directory, watch it */
1747
 
                cfg_watch_dir (info->parent, filename, jobname);
1748
 
 
1749
 
        } else if (S_ISREG (statbuf.st_mode)) {
1750
 
                /* It's a file, we parse it */
1751
 
                cfg_read_job (info->parent, filename, jobname);
1752
 
 
1753
 
        }
1754
 
 
1755
 
        /* Free up */
1756
 
        nih_free (jobname);
1757
 
        nih_free (filename);
 
1646
        if (nih_dir_walk (dirname, S_IFREG, (NihFileFilter)NULL,
 
1647
                          (NihFileVisitor)cfg_visitor, NULL) < 0)
 
1648
                return -1;
 
1649
 
 
1650
        return 0;
 
1651
}
 
1652
 
 
1653
 
 
1654
/**
 
1655
 * cfg_job_name:
 
1656
 * @parent: parent for new string,
 
1657
 * @dirname: top-level directory being watched,
 
1658
 * @path: full path to file.
 
1659
 *
 
1660
 * Constructs a job name for a given file by removing @dirname from the
 
1661
 * front.
 
1662
 *
 
1663
 * If @parent is not NULL, it should be a pointer to another allocated
 
1664
 * block which will be used as the parent for this block.  When @parent
 
1665
 * is freed, the returned block will be freed too.  If you have clean-up
 
1666
 * that would need to be run, you can assign a destructor function using
 
1667
 * the nih_alloc_set_destructor() function.
 
1668
 *
 
1669
 * Returns: newly allocated job name or NULL if insufficient memory.
 
1670
 **/
 
1671
static char *
 
1672
cfg_job_name (const void *parent,
 
1673
              const char *dirname,
 
1674
              const char *path)
 
1675
{
 
1676
        nih_assert (dirname != NULL);
 
1677
        nih_assert (path != NULL);
 
1678
 
 
1679
        /* Remove dirname from the front */
 
1680
        if (! strncmp (path, dirname, strlen (dirname)))
 
1681
                path += strlen (dirname);
 
1682
 
 
1683
        /* Remove slashes */
 
1684
        while (*path == '/')
 
1685
                path++;
 
1686
 
 
1687
        /* Construct job name */
 
1688
        return nih_strdup (parent, path);
 
1689
}
 
1690
 
 
1691
/**
 
1692
 * cfg_create_modify_handler:
 
1693
 * @data: not used,
 
1694
 * @watch: NihWatch for directory tree,
 
1695
 * @path: full path to file.
 
1696
 *
 
1697
 * This function is called whenever a new job file is created in a directory
 
1698
 * we're watching, or modified.  We attempt to parse the file as a valid job;
 
1699
 * though it's pretty common for these to fail since it's probably empty or
 
1700
 * only partially written.
 
1701
 **/
 
1702
static void
 
1703
cfg_create_modify_handler (void       *data,
 
1704
                           NihWatch   *watch,
 
1705
                           const char *path)
 
1706
{
 
1707
        char *name;
 
1708
 
 
1709
        nih_assert (watch != NULL);
 
1710
        nih_assert (path != NULL);
 
1711
 
 
1712
        NIH_MUST (name = cfg_job_name (NULL, watch->path, path));
 
1713
 
 
1714
        cfg_read_job (NULL, path, name);
 
1715
 
 
1716
        nih_free (name);
 
1717
}
 
1718
 
 
1719
/**
 
1720
 * cfg_delete_handler:
 
1721
 * @data: not used,
 
1722
 * @watch: NihWatch for directory tree,
 
1723
 * @path: full path to file.
 
1724
 *
 
1725
 * This function is called whenever a job file is deleted from a directory
 
1726
 * we're watching.
 
1727
 **/
 
1728
static void
 
1729
cfg_delete_handler (void       *data,
 
1730
                    NihWatch   *watch,
 
1731
                    const char *path)
 
1732
{
 
1733
        nih_assert (watch != NULL);
 
1734
        nih_assert (path != NULL);
 
1735
 
 
1736
        nih_debug ("Delete of %s (ignored)", path);
 
1737
}
 
1738
 
 
1739
/**
 
1740
 * cfg_visitor:
 
1741
 * @data: not used,
 
1742
 * @path: full path to file.
 
1743
 *
 
1744
 * This function is called for each file under a configuration directory
 
1745
 * whether or not we're watching it for changes; we parse the file to get
 
1746
 * the initial set of jobs.
 
1747
 *
 
1748
 * Returns: always zero.
 
1749
 **/
 
1750
static int
 
1751
cfg_visitor (void       *data,
 
1752
             const char *path)
 
1753
{
 
1754
        char *name;
 
1755
 
 
1756
        nih_assert (path != NULL);
 
1757
 
 
1758
        NIH_MUST (name = cfg_job_name (NULL, path, path));
 
1759
 
 
1760
        cfg_read_job (NULL, path, name);
 
1761
 
 
1762
        nih_free (name);
 
1763
 
 
1764
        return 0;
1758
1765
}