/* * int wait_register(pid_t, char *, int, int) * wait_register is called after we have called fork(2), and know which pid we * wish to monitor. However, since the child may have already exited by the * time we are called, we must handle the error cases from open(2) * appropriately. The am_parent flag is recorded to handle waitpid(2) * behaviour on removal; similarly, the direct flag is passed through to a * potential call to wait_remove() to govern its behaviour in different * contexts. * * Returns 0 if registration successful, 1 if child pid did not exist, and -1 * if a different error occurred. */ int wait_register(pid_t pid, const char *inst_fmri, int am_parent, int direct) { char *fname = uu_msprintf("/proc/%ld/psinfo", pid); int fd; wait_info_t *wi; assert(pid != 0); if (fname == NULL) return (-1); wi = startd_alloc(sizeof (wait_info_t)); uu_list_node_init(wi, &wi->wi_link, wait_info_pool); wi->wi_fd = -1; wi->wi_pid = pid; wi->wi_fmri = inst_fmri; wi->wi_parent = am_parent; wi->wi_ignore = 0; MUTEX_LOCK(&wait_info_lock); (void) uu_list_insert_before(wait_info_list, NULL, wi); MUTEX_UNLOCK(&wait_info_lock); if ((fd = open(fname, O_RDONLY)) == -1) { if (errno == ENOENT) { /* * Child has already exited. */ wait_remove(wi, direct); uu_free(fname); return (1); } else { log_error(LOG_WARNING, "open %s failed; not monitoring %s: %s\n", fname, inst_fmri, strerror(errno)); uu_free(fname); return (-1); } } uu_free(fname); wi->wi_fd = fd; if (port_associate(port_fd, PORT_SOURCE_FD, fd, 0, wi)) { log_error(LOG_WARNING, "initial port_association of %d / %s failed: %s\n", fd, inst_fmri, strerror(errno)); return (-1); } log_framework(LOG_DEBUG, "monitoring PID %ld on fd %d (%s)\n", pid, fd, inst_fmri); return (0); }
/* * init_env() * A clone of the work init.c does to provide as much compatibility * for startup scripts as possible. */ void init_env() { int i; char line[MAXCMDL]; FILE *fp; int inquotes, length, wslength; char *tokp, *cp1, *cp2; char **newp; glob_env_n = 16; glob_envp = startd_alloc(sizeof (*glob_envp) * glob_env_n); glob_envp[0] = startd_alloc((unsigned)(strlen(DEF_PATH)+2)); (void) strcpy(glob_envp[0], DEF_PATH); if ((fp = fopen(ENVFILE, "r")) == NULL) { uu_warn("Cannot open %s. Environment not initialized.\n", ENVFILE); glob_envp[1] = NULL; return; } i = 1; while (fgets(line, MAXCMDL - 1, fp) != NULL) { /* * Toss newline */ length = strlen(line); if (line[length - 1] == '\n') line[length - 1] = '\0'; /* * Ignore blank or comment lines. */ if (line[0] == '#' || line[0] == '\0' || (wslength = strspn(line, " \t\n")) == strlen(line) || strchr(line, '#') == line + wslength) continue; /* * First make a pass through the line and change * any non-quoted semi-colons to blanks so they * will be treated as token separators below. */ inquotes = 0; for (cp1 = line; *cp1 != '\0'; cp1++) { if (*cp1 == '"') { if (inquotes == 0) inquotes = 1; else inquotes = 0; } else if (*cp1 == ';') { if (inquotes == 0) *cp1 = ' '; } } /* * Tokens within the line are separated by blanks * and tabs. For each token in the line which * contains a '=' we strip out any quotes and then * stick the token in the environment array. */ if ((tokp = strtok(line, " \t")) == NULL) continue; do { cp1 = strchr(tokp, '='); if (cp1 == NULL || cp1 == tokp) continue; length = strlen(tokp); while ((cp1 = strpbrk(tokp, "\"\'")) != NULL) { for (cp2 = cp1; cp2 < &tokp[length]; cp2++) *cp2 = *(cp2 + 1); length--; } /* * init already started us with this umask, and we * handled it in startd.c, so just skip it. */ if (strncmp(tokp, "CMASK=", 6) == 0 || strncmp(tokp, "SMF_", 4) == 0) continue; glob_envp[i] = startd_alloc((unsigned)(length + 1)); (void) strcpy(glob_envp[i], tokp); /* * Double the environment size whenever it is * full. */ if (++i == glob_env_n) { glob_env_n *= 2; newp = startd_alloc(sizeof (*glob_envp) * glob_env_n); (void) memcpy(newp, glob_envp, sizeof (*glob_envp) * glob_env_n / 2); startd_free(glob_envp, sizeof (*glob_envp) * glob_env_n / 2); glob_envp = newp; } } while ((tokp = strtok(NULL, " \t")) != NULL); } startd_fclose(fp); /* Append a null pointer to the environment array to mark its end. */ glob_envp[i] = NULL; /* * Get the zonename once; it is used to set SMF_ZONENAME for methods. */ (void) getzonenamebyid(getzoneid(), zonename, sizeof (zonename)); }