Print this page
2989 Eliminate use of LOGNAME_MAX in ON
1166 useradd have warning with name more 8 chars


   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) {