]> git.ipfire.org Git - thirdparty/util-linux.git/blob - login-utils/initctl.c
Imported from util-linux-2.10s tarball.
[thirdparty/util-linux.git] / login-utils / initctl.c
1 /* initctl.c
2
3 Source file for initctl (init(8) control tool).
4
5 Copyright (C) 2000 Richard Gooch
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 Richard Gooch may be reached by email at rgooch@atnf.csiro.au
22 The postal address is:
23 Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
24 */
25
26 /*
27 This tool will send control messages to init(8). For example, it may
28 request init(8) to start a service and will wait for that service to be
29 available. If the service is already available, init(8) will not start it
30 again.
31 This tool may also be used to inspect the list of currently available
32 services.
33
34
35 Written by Richard Gooch 28-FEB-2000
36
37 Updated by Richard Gooch 11-OCT-2000: Added provide support.
38
39 Last updated by Richard Gooch 6-NOV-2000: Renamed to initctl.c
40
41
42 */
43 #include <unistd.h>
44 #include <stdio.h>
45 #include <limits.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <fcntl.h>
49 #include <signal.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include "simpleinit.h"
53
54
55 static void signal_handler (int sig);
56
57
58 static int caught_signal = 0;
59
60
61 int main (int argc, char **argv)
62 {
63 int fd, nbytes;
64 struct sigaction sa;
65 sigset_t ss;
66 char *ptr;
67 long buffer[COMMAND_SIZE / sizeof (long) + 1];
68 struct command_struct *command = (struct command_struct *) buffer;
69
70 sigemptyset (&ss);
71 sigaddset (&ss, SIG_PRESENT);
72 sigaddset (&ss, SIG_NOT_PRESENT);
73 sigaddset (&ss, SIG_FAILED);
74 sigprocmask (SIG_BLOCK, &ss, NULL);
75 sigemptyset (&sa.sa_mask);
76 sa.sa_flags = 0;
77 sa.sa_handler = signal_handler;
78 sigaction (SIG_PRESENT, &sa, NULL);
79 sigaction (SIG_NOT_PRESENT, &sa, NULL);
80 sigaction (SIG_FAILED, &sa, NULL);
81 command->pid = getpid ();
82 command->ppid = getppid ();
83 if ( ( ptr = strrchr (argv[0], '/') ) == NULL ) ptr = argv[0];
84 else ++ptr;
85 /* First generate command number by looking at invocation name */
86 if (strcmp (ptr, "display-services") == 0)
87 command->command = COMMAND_DUMP_LIST;
88 else if (strcmp (ptr, "need") == 0) command->command = COMMAND_NEED;
89 else if (strcmp (ptr, "provide") == 0) command->command = COMMAND_PROVIDE;
90 else command->command = COMMAND_TEST;
91 /* Now check for switches */
92 if ( (argc > 1) && (argv[1][0] == '-') )
93 {
94 switch (argv[1][1])
95 {
96 case 'n':
97 command->command = COMMAND_NEED;
98 break;
99 case 'r':
100 command->command = COMMAND_ROLLBACK;
101 break;
102 case 'd':
103 command->command = COMMAND_DUMP_LIST;
104 break;
105 case 'p':
106 command->command = COMMAND_PROVIDE;
107 break;
108 default:
109 fprintf (stderr, "Illegal switch: \"%s\"\n", argv[1]);
110 exit (1);
111 /*break;*/
112 }
113 --argc;
114 ++argv;
115 }
116 switch (command->command)
117 {
118 case COMMAND_NEED:
119 case COMMAND_PROVIDE:
120 if (argc < 2)
121 {
122 fprintf (stderr, "Usage:\tneed|provide programme\n");
123 exit (1);
124 }
125 /* Fall through */
126 case COMMAND_ROLLBACK:
127 if (argc > 1) strcpy (command->name, argv[1]);
128 else command->name[0] = '\0';
129 break;
130 case COMMAND_DUMP_LIST:
131 if (tmpnam (command->name) == NULL)
132 {
133 fprintf (stderr, "Unable to create a unique filename\t%s\n",
134 ERRSTRING);
135 exit (1);
136 }
137 if (mkfifo (command->name, S_IRUSR) != 0)
138 {
139 fprintf (stderr, "Unable to create FIFO: \"%s\"\t%s\n",
140 command->name, ERRSTRING);
141 exit (1);
142 }
143 break;
144 }
145 if ( ( fd = open ("/dev/initctl", O_WRONLY, 0) ) < 0 )
146 {
147 fprintf (stderr, "Error opening\t%s\n", ERRSTRING);
148 exit (1);
149 }
150 if (write (fd, buffer, COMMAND_SIZE) < COMMAND_SIZE)
151 {
152 fprintf (stderr, "Error writing\t%s\n", ERRSTRING);
153 exit (1);
154 }
155 close (fd);
156 if (command->command != COMMAND_DUMP_LIST)
157 {
158 sigemptyset (&ss);
159 while (caught_signal == 0) sigsuspend (&ss);
160 switch (command->command)
161 {
162 case COMMAND_PROVIDE:
163 switch (caught_signal)
164 {
165 case SIG_PRESENT:
166 return 1;
167 case SIG_NOT_PRESENT:
168 return 0;
169 case SIG_NOT_CHILD:
170 fprintf (stderr, "Error\n");
171 return 2;
172 default:
173 return 3;
174 }
175 break;
176 default:
177 switch (caught_signal)
178 {
179 case SIG_PRESENT:
180 return 0;
181 case SIG_NOT_PRESENT:
182 return 2;
183 case SIG_FAILED:
184 return 1;
185 default:
186 return 3;
187 }
188 break;
189 }
190 return 3;
191 }
192 /* Read back the data and display it */
193 if ( ( fd = open (command->name, O_RDONLY, 0) ) < 0 )
194 {
195 fprintf (stderr, "Error opening:\"%s\"\t%s\n",
196 command->name, ERRSTRING);
197 exit (1);
198 }
199 unlink (command->name);
200 fflush (stdout);
201 while ( ( nbytes = read (fd, buffer, COMMAND_SIZE) ) > 0 )
202 write (1, buffer, nbytes);
203 close (fd);
204 return (0);
205 } /* End Function main */
206
207 static void signal_handler (int sig)
208 {
209 caught_signal = sig;
210 } /* End Function signal_handler */