documenting and reorganizing MetaInit::Parse
[darcs-mirror-metainit.git] / lib / MetaInit / Parse.pm
1 package MetaInit::Parse;
2
3 =head1 NAME
4
5 MetaInit::Parse - Parses a MetaInit definition fild
6
7 =head1 SYNOPSIS
8
9     $data = MetaInit::Parse::parse($filename)
10
11 Opens and parses the specified file. The parsed data is handed back as a
12 hashref, containing an entry for each definition.
13
14 =head2 FILE FORMAT
15
16 The file to be parsed should be in a RFC822-like format (field names and values
17 are separated by a colon (C<:>). Lines starting with a blank are just appended
18 to their previous line's value. Lines that contain only a period (C<.>) in them
19 will become an empty line in the output.
20
21 Empty lines are ignored. 
22
23 Comments are allowed - All characters after a # sign until the end of the 
24 line are ignored. If you need to include the # sign, prepend it with a 
25 backslash (\#).
26
27 =head2 FIELDS
28
29 A MetaInit file has several defined fields, out of which only some (C<Name> and
30 C<Exec>) are mandatory:
31
32 =over 4
33
34 =item Name
35
36 The name of the daemon or facility for which to generate the init scripts for
37
38 =item Desc
39
40 A short (~60 character) description of the daemon. Merely informative.
41
42 =item Description
43
44 A longer description of the daemon, usually a couple of lines long. Merely
45 informative.
46
47 =item Exec
48
49 The command to execute to get the daemon to room. Please keep in mind this 
50 should start the daemon in the I<foreground>, not send it to the background.
51
52 =item Required-Start
53
54 The facilities that should be started before this one. This can include the
55 LSB facility names.
56
57 =item Required-Stop
58
59 B<CURRENTLY IGNORED - SHOULD CHECK LATER>
60
61 =item Should-Start
62
63 B<CURRENTLY IGNORED - SHOULD CHECK LATER>
64
65 =item Should-Stop
66
67 B<CURRENTLY IGNORED - SHOULD CHECK LATER>
68
69 =item Prestart-Hook
70
71 A shell snippet that should be included in the generated init script I<before>
72 the daemon is run
73
74 =item Poststop-hook
75
76 A shell snippet that should be included in the generated init script I<after>
77 the daemon finishes running
78
79 =back
80
81 Some fields (Required-Start, Should-Start, Required-Stop and Should-Stop) will
82 not return strings but arrayrefs - Elements will be separated by whitespace.
83
84 =head1 NOTES
85
86 Note that this module is written specifically for MetaInit, it will quite 
87 probably not be useful outside it.
88
89 =head1 SEE ALSO
90
91 The (as for now inexistent ;-) ) MetaInit documentation
92
93 LSB facility names, 
94 http://refspecs.freestandards.org/LSB_2.1.0/LSB-generic/LSB-generic/facilname.html
95
96 =head1 AUTHOR
97
98 =cut
99
100 my @splits = qw(Required-Start Should-Start Required-Stop Should-Stop);
101 my @mandatory = qw(Exec Name);
102
103 sub parse {
104     my $filename = shift;
105     open(FILE, "<", $filename) || die $!;
106
107     my %parsed;
108     my $lastkey;
109     while (<FILE>) {
110         chomp;
111         # Ignore comments; unescape escaped #s
112         s/[^\\]\#.*//;
113         s/\\\#/\#/g;
114         # Ignore empty lines; convert single dots in a line into empty lines
115         next if /^\s*$/;
116         s/^\s*\.\s*$//;
117
118         if (my ($key, $value) = m/^(\S.*)\s*:\s*(.*)/) {
119             $parsed{$key} = $value;
120             $lastkey = $key;
121         }
122         elsif ($lastkey) {
123             s/^\s+//;
124             s/^\.$//;
125             $parsed{$lastkey} .= "\n$_";
126         } else {
127             die "Cannot parse line: ``$_''";
128         }
129     }
130     close FILE;
131
132     if (not exists $parsed{Description}) {
133         $parsed{Description} = $parsed{Name}
134     }
135
136     {
137         no warnings qw(uninitialized);
138         ($parsed{Path}, $parsed{Args}) = split(/\s+/,$parsed{Exec});
139
140         for (@splits){
141                 $parsed{$_} = [ split m/\s+/, $parsed{$_} ];
142         }
143     }
144
145     my $error_msg = "";
146     for (@mandatory){
147             $error_msg .= "No '$_:' provided\n" unless $parsed{$_};
148     } 
149     die $error_msg if $error_msg;
150
151     $parsed{File} = $filename;
152
153     return \%parsed;
154 }
155
156
157 # Return a true value
158 1;