Upload Tizen:Base source
[framework/base/util-linux-ng.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  */