3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 /*
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
32 * All Rights Reserved
33 *
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
36 * contributors.
37 */
38
39 /*
40 * init(1M) is the general process spawning program. Its primary job is to
41 * start and restart svc.startd for smf(5). For backwards-compatibility it also
42 * spawns and respawns processes according to /etc/inittab and the current
122 #include <string.h>
123 #include <strings.h>
124 #include <syslog.h>
125 #include <time.h>
126 #include <ulimit.h>
127 #include <unistd.h>
128 #include <utmpx.h>
129 #include <wait.h>
130 #include <zone.h>
131 #include <ucontext.h>
132
133 #undef sleep
134
135 #define fioctl(p, sptr, cmd) ioctl(fileno(p), sptr, cmd)
136 #define min(a, b) (((a) < (b)) ? (a) : (b))
137
138 #define TRUE 1
139 #define FALSE 0
140 #define FAILURE -1
141
142 #define UT_LINE_SZ 32 /* Size of a utmpx ut_line field */
143
144 /*
145 * SLEEPTIME The number of seconds "init" sleeps between wakeups if
146 * nothing else requires this "init" wakeup.
147 */
148 #define SLEEPTIME (5 * 60)
149
150 /*
151 * MAXCMDL The maximum length of a command string in inittab.
152 */
153 #define MAXCMDL 512
154
155 /*
156 * EXEC The length of the prefix string added to all comamnds
157 * found in inittab.
158 */
159 #define EXEC (sizeof ("exec ") - 1)
160
161 /*
1683 case ACTION :
1684 /*
1685 * Null terminate the string in shcmd buffer and
1686 * then try to match against legal actions. If
1687 * the field is of length 0, then the default of
1688 * "RESPAWN" is used if the id is numeric,
1689 * otherwise the default is "OFF".
1690 */
1691 if (ptr == shcmd) {
1692 if (isdigit(cmd->c_id[0]) &&
1693 (cmd->c_id[1] == '\0' ||
1694 isdigit(cmd->c_id[1])) &&
1695 (cmd->c_id[2] == '\0' ||
1696 isdigit(cmd->c_id[2])) &&
1697 (cmd->c_id[3] == '\0' ||
1698 isdigit(cmd->c_id[3])))
1699 cmd->c_action = M_RESPAWN;
1700 else
1701 cmd->c_action = M_OFF;
1702 } else {
1703 for (cmd->c_action = 0, i = 0, *ptr = '\0';
1704 i < sizeof (actions)/sizeof (char *);
1705 i++) {
1706 if (strcmp(shcmd, actions[i]) == 0) {
1707 if ((cmd->c_levels & MASKSU) &&
1708 !(act_masks[i] & su_acts))
1709 cmd->c_action = 0;
1710 else
1711 cmd->c_action = act_masks[i];
1712 break;
1713 }
1714 }
1715 }
1716
1717 /*
1718 * If the action didn't match any legal action,
1719 * set state to FAILURE.
1720 */
1721 if (cmd->c_action == 0) {
1722 state = FAILURE;
1723 } else {
1724 state = COMMAND;
1725 (void) strcpy(shcmd, "exec ");
1726 }
1727 ptr = shcmd + EXEC;
1728 break;
1729 }
1730 continue;
1731 }
2093 for (oprocess = process;
2094 (process = efork(M_OFF, oprocess,
2095 (NAMED|NOCLEANUP))) == NO_ROOM;
2096 /* CSTYLED */)
2097 ;
2098 (void) sigrelse(SIGCLD);
2099
2100 if (process == NULLPROC) {
2101 maxfiles = ulimit(UL_GDESLIM, 0);
2102
2103 for (i = 0; i < maxfiles; i++)
2104 (void) fcntl(i, F_SETFD,
2105 FD_CLOEXEC);
2106 (void) execle(SH, "INITSH", "-c",
2107 cmd.c_command,
2108 (char *)0, glob_envp);
2109 console(B_TRUE,
2110 "Command\n\"%s\"\n failed to execute. errno = %d (exec of shell failed)\n",
2111 cmd.c_command, errno);
2112 exit(1);
2113 } else while (waitproc(process) == FAILURE);
2114 process->p_flags = 0;
2115 st_write();
2116 }
2117 }
2118 }
2119
2120 /* Restore the path. */
2121 free(glob_envp[0]);
2122 glob_envp[0] = old_path;
2123
2124 /*
2125 * This will enable st_write() to complain about init_state_file.
2126 */
2127 booting = 0;
2128
2129 /*
2130 * If the /etc/ioctl.syscon didn't exist or had invalid contents write
2131 * out a correct version.
2132 */
2133 if (write_ioctl)
2791 * if they don't already exist.
2792 */
2793 updwtmpx(WTMPX, up);
2794
2795 break;
2796 }
2797 }
2798
2799 endutxent();
2800 (void) sigprocmask(SIG_SETMASK, &unblock, NULL);
2801 }
2802
2803 /*
2804 * prog_name() searches for the word or unix path name and
2805 * returns a pointer to the last element of the pathname.
2806 */
2807 static char *
2808 prog_name(char *string)
2809 {
2810 char *ptr, *ptr2;
2811 /* XXX - utmp - fix name length */
2812 static char word[_POSIX_LOGIN_NAME_MAX];
2813
2814 /*
2815 * Search for the first word skipping leading spaces and tabs.
2816 */
2817 while (*string == ' ' || *string == '\t')
2818 string++;
2819
2820 /*
2821 * If the first non-space non-tab character is not one allowed in
2822 * a word, return a pointer to a null string, otherwise parse the
2823 * pathname.
2824 */
2825 if (*string != '.' && *string != '/' && *string != '_' &&
2826 (*string < 'a' || *string > 'z') &&
2827 (*string < 'A' || * string > 'Z') &&
2828 (*string < '0' || *string > '9'))
2829 return ("");
2830
2831 /*
2832 * Parse the pathname looking forward for '/', ' ', '\t', '\n' or
2833 * '\0'. Each time a '/' is found, move "ptr" to one past the
2834 * '/', thus when a ' ', '\t', '\n', or '\0' is found, "ptr" will
2835 * point to the last element of the pathname.
2836 */
2837 for (ptr = string; *string != ' ' && *string != '\t' &&
2838 *string != '\n' && *string != '\0'; string++) {
2839 if (*string == '/')
2840 ptr = string+1;
2841 }
2842
2843 /*
2844 * Copy out up to the size of the "ut_user" array into "word",
2845 * null terminate it and return a pointer to it.
2846 */
2847 /* XXX - utmp - fix name length */
2848 for (ptr2 = &word[0]; ptr2 < &word[_POSIX_LOGIN_NAME_MAX - 1] &&
2849 ptr < string; /* CSTYLED */)
2850 *ptr2++ = *ptr++;
2851
2852 *ptr2 = '\0';
2853 return (&word[0]);
2854 }
2855
2856
2857 /*
2858 * realcon() returns a nonzero value if there is a character device
2859 * associated with SYSCON that has the same device number as CONSOLE.
2860 */
2861 static int
2862 realcon()
2863 {
2864 struct stat sconbuf, conbuf;
2865
2866 if (stat(SYSCON, &sconbuf) != -1 &&
2867 stat(CONSOLE, &conbuf) != -1 &&
2868 S_ISCHR(sconbuf.st_mode) &&
3790 increase_proc_table_size()
3791 {
3792 sigset_t block, unblock;
3793 void *ptr;
3794 size_t delta = num_proc * sizeof (struct PROC_TABLE);
3795
3796
3797 /*
3798 * Block signals for realloc.
3799 */
3800 (void) sigfillset(&block);
3801 (void) sigprocmask(SIG_BLOCK, &block, &unblock);
3802
3803
3804 /*
3805 * On failure we just return because callers of this function check
3806 * for failure.
3807 */
3808 do
3809 ptr = realloc(g_state, g_state_sz + delta);
3810 while (ptr == NULL && errno == EAGAIN);
3811
3812 if (ptr != NULL) {
3813 /* ensure that the new part is initialized to zero */
3814 bzero((caddr_t)ptr + g_state_sz, delta);
3815
3816 g_state = ptr;
3817 g_state_sz += delta;
3818 num_proc <<= 1;
3819 }
3820
3821
3822 /* unblock our signals before returning */
3823 (void) sigprocmask(SIG_SETMASK, &unblock, NULL);
3824 }
3825
3826
3827
3828 /*
3829 * Sanity check g_state.
3830 */
3897 * If we can exclusively create the file, then we're the
3898 * initial invocation of init(1M).
3899 */
3900 st_fd = open(init_state_file, O_RDWR | O_CREAT | O_EXCL,
3901 S_IRUSR | S_IWUSR);
3902 } while (st_fd == -1 && errno == EINTR);
3903 if (st_fd != -1)
3904 goto new_state;
3905
3906 booting = 0;
3907
3908 do {
3909 st_fd = open(init_state_file, O_RDWR, S_IRUSR | S_IWUSR);
3910 } while (st_fd == -1 && errno == EINTR);
3911 if (st_fd == -1)
3912 goto new_state;
3913
3914 /* Get the size of the file. */
3915 do
3916 ret = fstat(st_fd, &stb);
3917 while (ret == -1 && errno == EINTR);
3918 if (ret == -1)
3919 goto new_state;
3920
3921 do
3922 g_state = malloc(stb.st_size);
3923 while (g_state == NULL && errno == EAGAIN);
3924 if (g_state == NULL)
3925 goto new_state;
3926
3927 to_be_read = stb.st_size;
3928 ptr = (char *)g_state;
3929 while (to_be_read > 0) {
3930 ssize_t read_ret;
3931
3932 read_ret = read(st_fd, ptr, to_be_read);
3933 if (read_ret < 0) {
3934 if (errno == EINTR)
3935 continue;
3936
3937 goto new_state;
3938 }
3939
3940 to_be_read -= read_ret;
3941 ptr += read_ret;
3942 }
3943
3949 console(B_TRUE, "Restarting.\n");
3950 return;
3951 }
3952
3953 insane = 1;
3954
3955 new_state:
3956 if (st_fd >= 0)
3957 (void) close(st_fd);
3958 else
3959 (void) unlink(init_state_file);
3960
3961 if (g_state != NULL)
3962 free(g_state);
3963
3964 /* Something went wrong, so allocate new state. */
3965 g_state_sz = sizeof (struct init_state) +
3966 ((init_num_proc - 1) * sizeof (struct PROC_TABLE));
3967 do
3968 g_state = calloc(1, g_state_sz);
3969 while (g_state == NULL && errno == EAGAIN);
3970 if (g_state == NULL) {
3971 /* Fatal error! */
3972 exit(errno);
3973 }
3974
3975 g_state->ist_runlevel = -1;
3976 num_proc = init_num_proc;
3977
3978 if (!booting) {
3979 console(B_TRUE, "Restarting.\n");
3980
3981 /* Overwrite the bad state file. */
3982 st_write();
3983
3984 if (!insane) {
3985 console(B_TRUE,
3986 "Error accessing persistent state file `%s'. "
3987 "Ignored.\n", init_state_file);
3988 } else {
3989 console(B_TRUE,
4057 console(B_TRUE, "Couldn't move persistent state "
4058 "file `%s' to `%s'.\n", init_next_state_file,
4059 init_state_file);
4060 }
4061 }
4062
4063 /*
4064 * Create a contract with these parameters.
4065 */
4066 static int
4067 contract_make_template(uint_t info, uint_t critical, uint_t fatal,
4068 uint64_t cookie)
4069 {
4070 int fd, err;
4071
4072 char *ioctl_tset_emsg =
4073 "Couldn't set \"%s\" contract template parameter: %s.\n";
4074
4075 do
4076 fd = open64(CTFS_ROOT "/process/template", O_RDWR);
4077 while (fd < 0 && errno == EINTR);
4078 if (fd < 0) {
4079 console(B_TRUE, "Couldn't create process template: %s.\n",
4080 strerror(errno));
4081 return (-1);
4082 }
4083
4084 if (err = ct_pr_tmpl_set_param(fd, CT_PR_INHERIT | CT_PR_REGENT))
4085 console(B_TRUE, "Contract set template inherit, regent "
4086 "failed: %s.\n", strerror(err));
4087
4088 /*
4089 * These errors result in a misconfigured template, which is better
4090 * than no template at all, so warn but don't abort.
4091 */
4092 if (err = ct_tmpl_set_informative(fd, info))
4093 console(B_TRUE, ioctl_tset_emsg, "informative", strerror(err));
4094
4095 if (err = ct_tmpl_set_critical(fd, critical))
4096 console(B_TRUE, ioctl_tset_emsg, "critical", strerror(err));
4097
4154 } else {
4155 (void) close(startd_tmpl);
4156 startd_tmpl = 254;
4157 }
4158
4159 (void) fcntl(startd_tmpl, F_SETFD, FD_CLOEXEC);
4160
4161 if (legacy_tmpl < 0 && startd_tmpl < 0) {
4162 /* The creation errors have already been reported. */
4163 console(B_TRUE,
4164 "Ignoring contract events. Core smf(5) services will not "
4165 "be restarted.\n");
4166 return;
4167 }
4168
4169 /*
4170 * Open an event endpoint.
4171 */
4172 do
4173 fd = open64(CTFS_ROOT "/process/pbundle", O_RDONLY);
4174 while (fd < 0 && errno == EINTR);
4175 if (fd < 0) {
4176 console(B_TRUE,
4177 "Couldn't open process pbundle: %s. Core smf(5) services "
4178 "will not be restarted.\n", strerror(errno));
4179 return;
4180 }
4181
4182 if (dup2(fd, 253) == -1) {
4183 console(B_TRUE, "Could not duplicate process bundle: %s.\n",
4184 strerror(errno));
4185 } else {
4186 (void) close(fd);
4187 fd = 253;
4188 }
4189
4190 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
4191
4192 /* Reset in case we've been restarted. */
4193 (void) ct_event_reset(fd);
4194
4195 poll_fds[0].fd = fd;
4196 poll_fds[0].events = POLLIN;
4197 poll_nfds = 1;
4198 }
4199
4200 static int
4201 contract_getfile(ctid_t id, const char *name, int oflag)
4202 {
4203 int fd;
4204
4205 do
4206 fd = contract_open(id, "process", name, oflag);
4207 while (fd < 0 && errno == EINTR);
4208
4209 if (fd < 0)
4210 console(B_TRUE, "Couldn't open %s for contract %ld: %s.\n",
4211 name, id, strerror(errno));
4212
4213 return (fd);
4214 }
4215
4216 static int
4217 contract_cookie(ctid_t id, uint64_t *cp)
4218 {
4219 int fd, err;
4220 ct_stathdl_t sh;
4221
4222 fd = contract_getfile(id, "status", O_RDONLY);
4223 if (fd < 0)
4224 return (-1);
4225
4226 err = ct_status_read(fd, CTD_COMMON, &sh);
4227 if (err != 0) {
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2013 Gary Mills
24 *
25 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 /*
32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 * The Regents of the University of California
34 * All Rights Reserved
35 *
36 * University Acknowledgment- Portions of this document are derived from
37 * software developed by the University of California, Berkeley, and its
38 * contributors.
39 */
40
41 /*
42 * init(1M) is the general process spawning program. Its primary job is to
43 * start and restart svc.startd for smf(5). For backwards-compatibility it also
44 * spawns and respawns processes according to /etc/inittab and the current
124 #include <string.h>
125 #include <strings.h>
126 #include <syslog.h>
127 #include <time.h>
128 #include <ulimit.h>
129 #include <unistd.h>
130 #include <utmpx.h>
131 #include <wait.h>
132 #include <zone.h>
133 #include <ucontext.h>
134
135 #undef sleep
136
137 #define fioctl(p, sptr, cmd) ioctl(fileno(p), sptr, cmd)
138 #define min(a, b) (((a) < (b)) ? (a) : (b))
139
140 #define TRUE 1
141 #define FALSE 0
142 #define FAILURE -1
143
144 #define UT_USER_SZ 32 /* Size of a utmpx ut_user field */
145 #define UT_LINE_SZ 32 /* Size of a utmpx ut_line field */
146
147 /*
148 * SLEEPTIME The number of seconds "init" sleeps between wakeups if
149 * nothing else requires this "init" wakeup.
150 */
151 #define SLEEPTIME (5 * 60)
152
153 /*
154 * MAXCMDL The maximum length of a command string in inittab.
155 */
156 #define MAXCMDL 512
157
158 /*
159 * EXEC The length of the prefix string added to all comamnds
160 * found in inittab.
161 */
162 #define EXEC (sizeof ("exec ") - 1)
163
164 /*
1686 case ACTION :
1687 /*
1688 * Null terminate the string in shcmd buffer and
1689 * then try to match against legal actions. If
1690 * the field is of length 0, then the default of
1691 * "RESPAWN" is used if the id is numeric,
1692 * otherwise the default is "OFF".
1693 */
1694 if (ptr == shcmd) {
1695 if (isdigit(cmd->c_id[0]) &&
1696 (cmd->c_id[1] == '\0' ||
1697 isdigit(cmd->c_id[1])) &&
1698 (cmd->c_id[2] == '\0' ||
1699 isdigit(cmd->c_id[2])) &&
1700 (cmd->c_id[3] == '\0' ||
1701 isdigit(cmd->c_id[3])))
1702 cmd->c_action = M_RESPAWN;
1703 else
1704 cmd->c_action = M_OFF;
1705 } else {
1706 for (cmd->c_action = 0, i = 0,
1707 *ptr = '\0';
1708 i <
1709 sizeof (actions)/sizeof (char *);
1710 i++) {
1711 if (strcmp(shcmd, actions[i]) == 0) {
1712 if ((cmd->c_levels & MASKSU) &&
1713 !(act_masks[i] & su_acts))
1714 cmd->c_action = 0;
1715 else
1716 cmd->c_action =
1717 act_masks[i];
1718 break;
1719 }
1720 }
1721 }
1722
1723 /*
1724 * If the action didn't match any legal action,
1725 * set state to FAILURE.
1726 */
1727 if (cmd->c_action == 0) {
1728 state = FAILURE;
1729 } else {
1730 state = COMMAND;
1731 (void) strcpy(shcmd, "exec ");
1732 }
1733 ptr = shcmd + EXEC;
1734 break;
1735 }
1736 continue;
1737 }
2099 for (oprocess = process;
2100 (process = efork(M_OFF, oprocess,
2101 (NAMED|NOCLEANUP))) == NO_ROOM;
2102 /* CSTYLED */)
2103 ;
2104 (void) sigrelse(SIGCLD);
2105
2106 if (process == NULLPROC) {
2107 maxfiles = ulimit(UL_GDESLIM, 0);
2108
2109 for (i = 0; i < maxfiles; i++)
2110 (void) fcntl(i, F_SETFD,
2111 FD_CLOEXEC);
2112 (void) execle(SH, "INITSH", "-c",
2113 cmd.c_command,
2114 (char *)0, glob_envp);
2115 console(B_TRUE,
2116 "Command\n\"%s\"\n failed to execute. errno = %d (exec of shell failed)\n",
2117 cmd.c_command, errno);
2118 exit(1);
2119 } else
2120 while (waitproc(process) == FAILURE)
2121 ;
2122 process->p_flags = 0;
2123 st_write();
2124 }
2125 }
2126 }
2127
2128 /* Restore the path. */
2129 free(glob_envp[0]);
2130 glob_envp[0] = old_path;
2131
2132 /*
2133 * This will enable st_write() to complain about init_state_file.
2134 */
2135 booting = 0;
2136
2137 /*
2138 * If the /etc/ioctl.syscon didn't exist or had invalid contents write
2139 * out a correct version.
2140 */
2141 if (write_ioctl)
2799 * if they don't already exist.
2800 */
2801 updwtmpx(WTMPX, up);
2802
2803 break;
2804 }
2805 }
2806
2807 endutxent();
2808 (void) sigprocmask(SIG_SETMASK, &unblock, NULL);
2809 }
2810
2811 /*
2812 * prog_name() searches for the word or unix path name and
2813 * returns a pointer to the last element of the pathname.
2814 */
2815 static char *
2816 prog_name(char *string)
2817 {
2818 char *ptr, *ptr2;
2819 static char word[UT_USER_SZ + 1];
2820
2821 /*
2822 * Search for the first word skipping leading spaces and tabs.
2823 */
2824 while (*string == ' ' || *string == '\t')
2825 string++;
2826
2827 /*
2828 * If the first non-space non-tab character is not one allowed in
2829 * a word, return a pointer to a null string, otherwise parse the
2830 * pathname.
2831 */
2832 if (*string != '.' && *string != '/' && *string != '_' &&
2833 (*string < 'a' || *string > 'z') &&
2834 (*string < 'A' || * string > 'Z') &&
2835 (*string < '0' || *string > '9'))
2836 return ("");
2837
2838 /*
2839 * Parse the pathname looking forward for '/', ' ', '\t', '\n' or
2840 * '\0'. Each time a '/' is found, move "ptr" to one past the
2841 * '/', thus when a ' ', '\t', '\n', or '\0' is found, "ptr" will
2842 * point to the last element of the pathname.
2843 */
2844 for (ptr = string; *string != ' ' && *string != '\t' &&
2845 *string != '\n' && *string != '\0'; string++) {
2846 if (*string == '/')
2847 ptr = string+1;
2848 }
2849
2850 /*
2851 * Copy out up to the size of the "ut_user" array into "word",
2852 * null terminate it and return a pointer to it.
2853 */
2854 for (ptr2 = &word[0]; ptr2 < &word[UT_USER_SZ] &&
2855 ptr < string; /* CSTYLED */)
2856 *ptr2++ = *ptr++;
2857
2858 *ptr2 = '\0';
2859 return (&word[0]);
2860 }
2861
2862
2863 /*
2864 * realcon() returns a nonzero value if there is a character device
2865 * associated with SYSCON that has the same device number as CONSOLE.
2866 */
2867 static int
2868 realcon()
2869 {
2870 struct stat sconbuf, conbuf;
2871
2872 if (stat(SYSCON, &sconbuf) != -1 &&
2873 stat(CONSOLE, &conbuf) != -1 &&
2874 S_ISCHR(sconbuf.st_mode) &&
3796 increase_proc_table_size()
3797 {
3798 sigset_t block, unblock;
3799 void *ptr;
3800 size_t delta = num_proc * sizeof (struct PROC_TABLE);
3801
3802
3803 /*
3804 * Block signals for realloc.
3805 */
3806 (void) sigfillset(&block);
3807 (void) sigprocmask(SIG_BLOCK, &block, &unblock);
3808
3809
3810 /*
3811 * On failure we just return because callers of this function check
3812 * for failure.
3813 */
3814 do
3815 ptr = realloc(g_state, g_state_sz + delta);
3816 while (ptr == NULL && errno == EAGAIN)
3817 ;
3818
3819 if (ptr != NULL) {
3820 /* ensure that the new part is initialized to zero */
3821 bzero((caddr_t)ptr + g_state_sz, delta);
3822
3823 g_state = ptr;
3824 g_state_sz += delta;
3825 num_proc <<= 1;
3826 }
3827
3828
3829 /* unblock our signals before returning */
3830 (void) sigprocmask(SIG_SETMASK, &unblock, NULL);
3831 }
3832
3833
3834
3835 /*
3836 * Sanity check g_state.
3837 */
3904 * If we can exclusively create the file, then we're the
3905 * initial invocation of init(1M).
3906 */
3907 st_fd = open(init_state_file, O_RDWR | O_CREAT | O_EXCL,
3908 S_IRUSR | S_IWUSR);
3909 } while (st_fd == -1 && errno == EINTR);
3910 if (st_fd != -1)
3911 goto new_state;
3912
3913 booting = 0;
3914
3915 do {
3916 st_fd = open(init_state_file, O_RDWR, S_IRUSR | S_IWUSR);
3917 } while (st_fd == -1 && errno == EINTR);
3918 if (st_fd == -1)
3919 goto new_state;
3920
3921 /* Get the size of the file. */
3922 do
3923 ret = fstat(st_fd, &stb);
3924 while (ret == -1 && errno == EINTR)
3925 ;
3926 if (ret == -1)
3927 goto new_state;
3928
3929 do
3930 g_state = malloc(stb.st_size);
3931 while (g_state == NULL && errno == EAGAIN)
3932 ;
3933 if (g_state == NULL)
3934 goto new_state;
3935
3936 to_be_read = stb.st_size;
3937 ptr = (char *)g_state;
3938 while (to_be_read > 0) {
3939 ssize_t read_ret;
3940
3941 read_ret = read(st_fd, ptr, to_be_read);
3942 if (read_ret < 0) {
3943 if (errno == EINTR)
3944 continue;
3945
3946 goto new_state;
3947 }
3948
3949 to_be_read -= read_ret;
3950 ptr += read_ret;
3951 }
3952
3958 console(B_TRUE, "Restarting.\n");
3959 return;
3960 }
3961
3962 insane = 1;
3963
3964 new_state:
3965 if (st_fd >= 0)
3966 (void) close(st_fd);
3967 else
3968 (void) unlink(init_state_file);
3969
3970 if (g_state != NULL)
3971 free(g_state);
3972
3973 /* Something went wrong, so allocate new state. */
3974 g_state_sz = sizeof (struct init_state) +
3975 ((init_num_proc - 1) * sizeof (struct PROC_TABLE));
3976 do
3977 g_state = calloc(1, g_state_sz);
3978 while (g_state == NULL && errno == EAGAIN)
3979 ;
3980 if (g_state == NULL) {
3981 /* Fatal error! */
3982 exit(errno);
3983 }
3984
3985 g_state->ist_runlevel = -1;
3986 num_proc = init_num_proc;
3987
3988 if (!booting) {
3989 console(B_TRUE, "Restarting.\n");
3990
3991 /* Overwrite the bad state file. */
3992 st_write();
3993
3994 if (!insane) {
3995 console(B_TRUE,
3996 "Error accessing persistent state file `%s'. "
3997 "Ignored.\n", init_state_file);
3998 } else {
3999 console(B_TRUE,
4067 console(B_TRUE, "Couldn't move persistent state "
4068 "file `%s' to `%s'.\n", init_next_state_file,
4069 init_state_file);
4070 }
4071 }
4072
4073 /*
4074 * Create a contract with these parameters.
4075 */
4076 static int
4077 contract_make_template(uint_t info, uint_t critical, uint_t fatal,
4078 uint64_t cookie)
4079 {
4080 int fd, err;
4081
4082 char *ioctl_tset_emsg =
4083 "Couldn't set \"%s\" contract template parameter: %s.\n";
4084
4085 do
4086 fd = open64(CTFS_ROOT "/process/template", O_RDWR);
4087 while (fd < 0 && errno == EINTR)
4088 ;
4089 if (fd < 0) {
4090 console(B_TRUE, "Couldn't create process template: %s.\n",
4091 strerror(errno));
4092 return (-1);
4093 }
4094
4095 if (err = ct_pr_tmpl_set_param(fd, CT_PR_INHERIT | CT_PR_REGENT))
4096 console(B_TRUE, "Contract set template inherit, regent "
4097 "failed: %s.\n", strerror(err));
4098
4099 /*
4100 * These errors result in a misconfigured template, which is better
4101 * than no template at all, so warn but don't abort.
4102 */
4103 if (err = ct_tmpl_set_informative(fd, info))
4104 console(B_TRUE, ioctl_tset_emsg, "informative", strerror(err));
4105
4106 if (err = ct_tmpl_set_critical(fd, critical))
4107 console(B_TRUE, ioctl_tset_emsg, "critical", strerror(err));
4108
4165 } else {
4166 (void) close(startd_tmpl);
4167 startd_tmpl = 254;
4168 }
4169
4170 (void) fcntl(startd_tmpl, F_SETFD, FD_CLOEXEC);
4171
4172 if (legacy_tmpl < 0 && startd_tmpl < 0) {
4173 /* The creation errors have already been reported. */
4174 console(B_TRUE,
4175 "Ignoring contract events. Core smf(5) services will not "
4176 "be restarted.\n");
4177 return;
4178 }
4179
4180 /*
4181 * Open an event endpoint.
4182 */
4183 do
4184 fd = open64(CTFS_ROOT "/process/pbundle", O_RDONLY);
4185 while (fd < 0 && errno == EINTR)
4186 ;
4187 if (fd < 0) {
4188 console(B_TRUE,
4189 "Couldn't open process pbundle: %s. Core smf(5) services "
4190 "will not be restarted.\n", strerror(errno));
4191 return;
4192 }
4193
4194 if (dup2(fd, 253) == -1) {
4195 console(B_TRUE, "Could not duplicate process bundle: %s.\n",
4196 strerror(errno));
4197 } else {
4198 (void) close(fd);
4199 fd = 253;
4200 }
4201
4202 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
4203
4204 /* Reset in case we've been restarted. */
4205 (void) ct_event_reset(fd);
4206
4207 poll_fds[0].fd = fd;
4208 poll_fds[0].events = POLLIN;
4209 poll_nfds = 1;
4210 }
4211
4212 static int
4213 contract_getfile(ctid_t id, const char *name, int oflag)
4214 {
4215 int fd;
4216
4217 do
4218 fd = contract_open(id, "process", name, oflag);
4219 while (fd < 0 && errno == EINTR)
4220 ;
4221
4222 if (fd < 0)
4223 console(B_TRUE, "Couldn't open %s for contract %ld: %s.\n",
4224 name, id, strerror(errno));
4225
4226 return (fd);
4227 }
4228
4229 static int
4230 contract_cookie(ctid_t id, uint64_t *cp)
4231 {
4232 int fd, err;
4233 ct_stathdl_t sh;
4234
4235 fd = contract_getfile(id, "status", O_RDONLY);
4236 if (fd < 0)
4237 return (-1);
4238
4239 err = ct_status_read(fd, CTD_COMMON, &sh);
4240 if (err != 0) {
|