17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
54421e676Stn143363 * Common Development and Distribution License (the "License").
64421e676Stn143363 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*9444c26fSTom Whitten * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate * inetconv - convert inetd.conf entries into smf(5) service manifests,
287c478bd9Sstevel@tonic-gate * import them into smf(5) repository
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/param.h>
337c478bd9Sstevel@tonic-gate #include <sys/stat.h>
347c478bd9Sstevel@tonic-gate #include <sys/wait.h>
357c478bd9Sstevel@tonic-gate #include <stdio.h>
367c478bd9Sstevel@tonic-gate #include <stdlib.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <unistd.h>
397c478bd9Sstevel@tonic-gate #include <fcntl.h>
407c478bd9Sstevel@tonic-gate #include <pwd.h>
417c478bd9Sstevel@tonic-gate #include <grp.h>
427c478bd9Sstevel@tonic-gate #include <errno.h>
437c478bd9Sstevel@tonic-gate #include <limits.h>
447c478bd9Sstevel@tonic-gate #include <locale.h>
457c478bd9Sstevel@tonic-gate #include <libintl.h>
467c478bd9Sstevel@tonic-gate #include <libscf.h>
477c478bd9Sstevel@tonic-gate #include <inetsvc.h>
487c478bd9Sstevel@tonic-gate #include <rpc/nettype.h>
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate /* exit codes */
517c478bd9Sstevel@tonic-gate #define EXIT_SUCCESS 0 /* succeeded */
527c478bd9Sstevel@tonic-gate #define EXIT_USAGE 1 /* bad options */
537c478bd9Sstevel@tonic-gate #define EXIT_ERROR_CONV 2 /* error(s) coverting inetd.conf entries */
547c478bd9Sstevel@tonic-gate #define EXIT_ERROR_IMP 3 /* error(s) importing manifests */
557c478bd9Sstevel@tonic-gate #define EXIT_ERROR_SYS 4 /* system error */
567c478bd9Sstevel@tonic-gate #define EXIT_ERROR_ENBL 5 /* error(s) enabling services */
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN
597c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SUNW_OST_OSCMD"
607c478bd9Sstevel@tonic-gate #endif
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate #define MAIN_CONFIG "/etc/inet/inetd.conf"
637c478bd9Sstevel@tonic-gate #define ALT_CONFIG "/etc/inetd.conf"
647c478bd9Sstevel@tonic-gate
65*9444c26fSTom Whitten #define MANIFEST_DIR "/lib/svc/manifest/network"
66cdc89861Sdstaff #define MANIFEST_RPC_DIR MANIFEST_DIR "/rpc"
677c478bd9Sstevel@tonic-gate #define SVCCFG_PATH "/usr/sbin/svccfg"
687c478bd9Sstevel@tonic-gate
69cdc89861Sdstaff #define RPCBIND_FMRI "svc:/network/rpc/bind"
70cdc89861Sdstaff
717c478bd9Sstevel@tonic-gate /* maximum allowed length of an inetd.conf format line */
727c478bd9Sstevel@tonic-gate #define MAX_SRC_LINELEN 32768
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate /* Version of inetconv, used as a marker in services we generate */
757c478bd9Sstevel@tonic-gate #define INETCONV_VERSION 1
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate struct inetconfent {
787c478bd9Sstevel@tonic-gate /* fields as read from inetd.conf format line */
797c478bd9Sstevel@tonic-gate char *service;
807c478bd9Sstevel@tonic-gate char *endpoint;
817c478bd9Sstevel@tonic-gate char *protocol;
827c478bd9Sstevel@tonic-gate char *wait_status;
837c478bd9Sstevel@tonic-gate char *username;
847c478bd9Sstevel@tonic-gate char *server_program;
857c478bd9Sstevel@tonic-gate char *server_args;
867c478bd9Sstevel@tonic-gate /* information derived from above fields */
877c478bd9Sstevel@tonic-gate boolean_t wait;
887c478bd9Sstevel@tonic-gate boolean_t isrpc;
897c478bd9Sstevel@tonic-gate int rpc_low_version;
907c478bd9Sstevel@tonic-gate int rpc_high_version;
917c478bd9Sstevel@tonic-gate char *rpc_prog;
927c478bd9Sstevel@tonic-gate char *groupname;
937c478bd9Sstevel@tonic-gate char *exec;
947c478bd9Sstevel@tonic-gate char *arg0;
957c478bd9Sstevel@tonic-gate };
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate struct fileinfo {
987c478bd9Sstevel@tonic-gate FILE *fp;
997c478bd9Sstevel@tonic-gate char *filename;
1007c478bd9Sstevel@tonic-gate int lineno;
1017c478bd9Sstevel@tonic-gate int failcnt;
1027c478bd9Sstevel@tonic-gate };
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate static char *progname;
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate static boolean_t import = B_TRUE;
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /* start of manifest XML template strings */
1097c478bd9Sstevel@tonic-gate static const char xml_header[] =
1107c478bd9Sstevel@tonic-gate "<?xml version='1.0'?>\n"
1117c478bd9Sstevel@tonic-gate "<!DOCTYPE service_bundle SYSTEM "
1127c478bd9Sstevel@tonic-gate "'/usr/share/lib/xml/dtd/service_bundle.dtd.1'>\n";
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate static const char xml_comment[] =
1157c478bd9Sstevel@tonic-gate "<!--\n"
1167c478bd9Sstevel@tonic-gate " Service manifest for the %s service.\n"
1177c478bd9Sstevel@tonic-gate "\n"
1187c478bd9Sstevel@tonic-gate " Generated by inetconv(1M) from inetd.conf(4).\n"
1197c478bd9Sstevel@tonic-gate "-->\n\n";
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate static const char xml_service_bundle[] =
1227c478bd9Sstevel@tonic-gate "<service_bundle type='manifest' name='inetconv:%s'>\n\n";
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate static const char xml_service_name[] =
1257c478bd9Sstevel@tonic-gate "<service\n"
1267c478bd9Sstevel@tonic-gate " name='network/%s'\n"
1277c478bd9Sstevel@tonic-gate " type='service'\n"
1287c478bd9Sstevel@tonic-gate " version='1'>\n\n";
1297c478bd9Sstevel@tonic-gate
130cdc89861Sdstaff static const char xml_dependency[] =
131cdc89861Sdstaff " <dependency\n"
132cdc89861Sdstaff " name='%s'\n"
133cdc89861Sdstaff " grouping='require_all'\n"
134cdc89861Sdstaff " restart_on='restart'\n"
135cdc89861Sdstaff " type='service'>\n"
136cdc89861Sdstaff " <service_fmri value='%s' />\n"
137cdc89861Sdstaff " </dependency>\n\n";
138cdc89861Sdstaff
1397c478bd9Sstevel@tonic-gate static const char xml_instance[] =
1407c478bd9Sstevel@tonic-gate " <create_default_instance enabled='true'/>\n\n";
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate static const char xml_restarter[] =
1437c478bd9Sstevel@tonic-gate " <restarter>\n"
1447c478bd9Sstevel@tonic-gate " <service_fmri value='%s' />\n"
1457c478bd9Sstevel@tonic-gate " </restarter>\n\n";
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate static const char xml_exec_method_start[] =
1487c478bd9Sstevel@tonic-gate " <!--\n"
1497c478bd9Sstevel@tonic-gate " Set a timeout of 0 to signify to inetd that we don't want to\n"
1507c478bd9Sstevel@tonic-gate " timeout this service, since the forked process is the one that\n"
1517c478bd9Sstevel@tonic-gate " does the service's work. This is the case for most/all legacy\n"
1527c478bd9Sstevel@tonic-gate " inetd services; for services written to take advantage of SMF\n"
1537c478bd9Sstevel@tonic-gate " capabilities, the start method should fork off a process to\n"
1547c478bd9Sstevel@tonic-gate " handle the request and return a success code.\n"
1557c478bd9Sstevel@tonic-gate " -->\n"
1567c478bd9Sstevel@tonic-gate " <exec_method\n"
1577c478bd9Sstevel@tonic-gate " type='method'\n"
1587c478bd9Sstevel@tonic-gate " name='%s'\n"
1597c478bd9Sstevel@tonic-gate " %s='%s'\n"
1607c478bd9Sstevel@tonic-gate " timeout_seconds='0'>\n"
1617c478bd9Sstevel@tonic-gate " <method_context>\n"
1627c478bd9Sstevel@tonic-gate " <method_credential %s='%s' group='%s' />\n"
1637c478bd9Sstevel@tonic-gate " </method_context>\n";
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate static const char xml_arg0[] =
1667c478bd9Sstevel@tonic-gate " <propval name='%s' type='astring'\n"
1677c478bd9Sstevel@tonic-gate " value='%s' />\n";
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate static const char xml_exec_method_end[] =
1707c478bd9Sstevel@tonic-gate " </exec_method>\n\n";
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate static const char xml_exec_method_disable[] =
1737c478bd9Sstevel@tonic-gate " <!--\n"
1747c478bd9Sstevel@tonic-gate " Use inetd's built-in kill support to disable services.\n"
1757c478bd9Sstevel@tonic-gate " -->\n"
1767c478bd9Sstevel@tonic-gate " <exec_method\n"
1777c478bd9Sstevel@tonic-gate " type='method'\n"
1787c478bd9Sstevel@tonic-gate " name='%s'\n"
1797c478bd9Sstevel@tonic-gate " %s=':kill'\n"
1807c478bd9Sstevel@tonic-gate " timeout_seconds='0'>\n";
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate static const char xml_exec_method_offline[] =
1837c478bd9Sstevel@tonic-gate " <!--\n"
1847c478bd9Sstevel@tonic-gate " Use inetd's built-in process kill support to offline wait type\n"
1857c478bd9Sstevel@tonic-gate " services.\n"
1867c478bd9Sstevel@tonic-gate " -->\n"
1877c478bd9Sstevel@tonic-gate " <exec_method\n"
1887c478bd9Sstevel@tonic-gate " type='method'\n"
1897c478bd9Sstevel@tonic-gate " name='%s'\n"
1907c478bd9Sstevel@tonic-gate " %s=':kill_process'\n"
1917c478bd9Sstevel@tonic-gate " timeout_seconds='0'>\n";
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate static const char xml_inetconv_group_start[] =
1947c478bd9Sstevel@tonic-gate " <!--\n"
1957c478bd9Sstevel@tonic-gate " This property group is used to record information about\n"
1967c478bd9Sstevel@tonic-gate " how this manifest was created. It is an implementation\n"
1977c478bd9Sstevel@tonic-gate " detail which should not be modified or deleted.\n"
1987c478bd9Sstevel@tonic-gate " -->\n"
1997c478bd9Sstevel@tonic-gate " <property_group name='%s' type='framework'>\n"
2007c478bd9Sstevel@tonic-gate " <propval name='%s' type='boolean' value='%s' />\n"
2017c478bd9Sstevel@tonic-gate " <propval name='%s' type='integer' value='%d' />\n"
2027c478bd9Sstevel@tonic-gate " <propval name='%s' type='astring' value=\n"
2037c478bd9Sstevel@tonic-gate "'%s %s %s %s %s %s%s%s'\n"
2047c478bd9Sstevel@tonic-gate " />\n";
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate static const char xml_property_group_start[] =
2077c478bd9Sstevel@tonic-gate " <property_group name='%s' type='framework'>\n"
2087c478bd9Sstevel@tonic-gate " <propval name='%s' type='astring' value='%s' />\n"
2097c478bd9Sstevel@tonic-gate " <propval name='%s' type='astring' value='%s' />\n"
2107c478bd9Sstevel@tonic-gate " <propval name='%s' type='astring' value='%s' />\n"
2117c478bd9Sstevel@tonic-gate " <propval name='%s' type='boolean' value='%s' />\n"
2127c478bd9Sstevel@tonic-gate " <propval name='%s' type='boolean' value='%s' />\n";
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate static const char xml_property_group_rpc[] =
2157c478bd9Sstevel@tonic-gate " <propval name='%s' type='integer' value='%d' />\n"
2167c478bd9Sstevel@tonic-gate " <propval name='%s' type='integer' value='%d' />"
2177c478bd9Sstevel@tonic-gate "\n";
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate static const char xml_property_group_end[] =
2207c478bd9Sstevel@tonic-gate " </property_group>\n\n";
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate static const char xml_stability[] =
2237c478bd9Sstevel@tonic-gate " <stability value='External' />\n\n";
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate static const char xml_template[] =
2267c478bd9Sstevel@tonic-gate " <template>\n"
2277c478bd9Sstevel@tonic-gate " <common_name>\n"
2287c478bd9Sstevel@tonic-gate " <loctext xml:lang='C'>\n"
2297c478bd9Sstevel@tonic-gate "%s\n"
2307c478bd9Sstevel@tonic-gate " </loctext>\n"
2317c478bd9Sstevel@tonic-gate " </common_name>\n"
2327c478bd9Sstevel@tonic-gate " </template>\n";
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate static const char xml_footer[] =
2357c478bd9Sstevel@tonic-gate "</service>\n"
2367c478bd9Sstevel@tonic-gate "\n"
2377c478bd9Sstevel@tonic-gate "</service_bundle>\n";
2387c478bd9Sstevel@tonic-gate /* end of manifest XML template strings */
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate static void *
safe_malloc(size_t size)2417c478bd9Sstevel@tonic-gate safe_malloc(size_t size)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate void *cp;
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate if ((cp = malloc(size)) == NULL) {
2467c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: malloc failed: %s\n"),
2477c478bd9Sstevel@tonic-gate progname, strerror(errno));
2487c478bd9Sstevel@tonic-gate exit(EXIT_ERROR_SYS);
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate return (cp);
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate static char *
safe_strdup(char * s)2547c478bd9Sstevel@tonic-gate safe_strdup(char *s)
2557c478bd9Sstevel@tonic-gate {
2567c478bd9Sstevel@tonic-gate char *cp;
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate if ((cp = strdup(s)) == NULL) {
2597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: strdup failed: %s\n"),
2607c478bd9Sstevel@tonic-gate progname, strerror(errno));
2617c478bd9Sstevel@tonic-gate exit(EXIT_ERROR_SYS);
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate return (cp);
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate static char *
propertyname(char * name,char * prefix)2677c478bd9Sstevel@tonic-gate propertyname(char *name, char *prefix)
2687c478bd9Sstevel@tonic-gate {
2697c478bd9Sstevel@tonic-gate static char *buf;
2707c478bd9Sstevel@tonic-gate size_t len;
2717c478bd9Sstevel@tonic-gate int c;
2727c478bd9Sstevel@tonic-gate char *cp;
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate /* free any memory allocated by a previous call */
2757c478bd9Sstevel@tonic-gate free(buf);
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate len = strlen(name) + strlen(prefix) + 1;
2787c478bd9Sstevel@tonic-gate buf = safe_malloc(len);
2797c478bd9Sstevel@tonic-gate buf[0] = '\0';
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate * Property names must match the regular expression:
2837c478bd9Sstevel@tonic-gate * ([A-Za-z][_A-Za-z0-9.-]*,)?[A-Za-z][_A-Za-z0-9-]*
2847c478bd9Sstevel@tonic-gate */
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate /*
2877c478bd9Sstevel@tonic-gate * Make sure the first character is alphabetic, if not insert prefix.
2884421e676Stn143363 * Can't use isalpha() here as it's locale dependent but the property
2897c478bd9Sstevel@tonic-gate * name regular expression isn't.
2907c478bd9Sstevel@tonic-gate */
2917c478bd9Sstevel@tonic-gate c = name[0];
2927c478bd9Sstevel@tonic-gate if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) {
2937c478bd9Sstevel@tonic-gate (void) strlcat(buf, prefix, len);
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate (void) strlcat(buf, name, len);
2967c478bd9Sstevel@tonic-gate
2974421e676Stn143363 /* convert any disallowed characters into '_' */
2987c478bd9Sstevel@tonic-gate for (cp = buf; *cp != '\0'; cp++) {
2997c478bd9Sstevel@tonic-gate if ((*cp < 'A' || *cp > 'Z') && (*cp < 'a' || *cp > 'z') &&
3007c478bd9Sstevel@tonic-gate (*cp < '0' || *cp > '9') && (*cp != '.') && (*cp != '-'))
3017c478bd9Sstevel@tonic-gate *cp = '_';
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate return (buf);
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate static char *
servicename(struct inetconfent * iconf)3077c478bd9Sstevel@tonic-gate servicename(struct inetconfent *iconf)
3087c478bd9Sstevel@tonic-gate {
3097c478bd9Sstevel@tonic-gate static char *buf;
3107c478bd9Sstevel@tonic-gate size_t len;
3114421e676Stn143363 char *cp, *proto;
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate /* free any memory allocated by a previous call */
3147c478bd9Sstevel@tonic-gate free(buf);
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate len = strlen(iconf->service) + strlen(iconf->protocol) +
3177c478bd9Sstevel@tonic-gate sizeof ("rpc-/visible");
3187c478bd9Sstevel@tonic-gate buf = safe_malloc(len);
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate /*
3217c478bd9Sstevel@tonic-gate * Combine the service and protocol fields to produce a unique
3227c478bd9Sstevel@tonic-gate * manifest service name. The syntax of a service name is:
3237c478bd9Sstevel@tonic-gate * prop(/prop)*
3247c478bd9Sstevel@tonic-gate */
3257c478bd9Sstevel@tonic-gate (void) strlcpy(buf, propertyname(iconf->service,
3267c478bd9Sstevel@tonic-gate iconf->isrpc ? "rpc-": "s-"), len);
3277c478bd9Sstevel@tonic-gate (void) strlcat(buf, "/", len);
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate proto = iconf->protocol;
3307c478bd9Sstevel@tonic-gate if (iconf->isrpc && (strcmp(iconf->protocol, "rpc/*") == 0))
3317c478bd9Sstevel@tonic-gate proto = "rpc/visible";
3324421e676Stn143363
3334421e676Stn143363 /*
3344421e676Stn143363 * SMF service names may not contain '.', but IANA services do
3354421e676Stn143363 * allow its use, and property names can contain '.' as returned
3364421e676Stn143363 * by propertyname(). So if the resultant SMF service name
3374421e676Stn143363 * would contain a '.' we fix it here.
3384421e676Stn143363 */
3394421e676Stn143363 for (cp = buf; *cp != '\0'; cp++) {
3404421e676Stn143363 if (*cp == '.')
3414421e676Stn143363 *cp = '_';
3424421e676Stn143363 }
3437c478bd9Sstevel@tonic-gate (void) strlcat(buf, propertyname(proto, "p-"), len);
3447c478bd9Sstevel@tonic-gate return (buf);
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate static boolean_t
is_v6only(char * protocol)3487c478bd9Sstevel@tonic-gate is_v6only(char *protocol)
3497c478bd9Sstevel@tonic-gate {
3507c478bd9Sstevel@tonic-gate /* returns true if protocol is an IPv6 only protocol */
3517c478bd9Sstevel@tonic-gate if ((strcmp(protocol, SOCKET_PROTO_TCP6_ONLY) == 0) ||
3527c478bd9Sstevel@tonic-gate (strcmp(protocol, SOCKET_PROTO_UDP6_ONLY) == 0))
3537c478bd9Sstevel@tonic-gate return (B_TRUE);
3547c478bd9Sstevel@tonic-gate return (B_FALSE);
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate static char *
invalid_props(inetd_prop_t * p)3587c478bd9Sstevel@tonic-gate invalid_props(inetd_prop_t *p)
3597c478bd9Sstevel@tonic-gate {
3607c478bd9Sstevel@tonic-gate static char
3617c478bd9Sstevel@tonic-gate buf[sizeof (" service-name endpoint-type protocol wait-status")];
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate buf[0] = '\0';
3647c478bd9Sstevel@tonic-gate if ((p[PT_SVC_NAME_INDEX].ip_error == IVE_INVALID) ||
3657c478bd9Sstevel@tonic-gate (p[PT_SVC_NAME_INDEX].ip_error == IVE_UNSET) ||
3667c478bd9Sstevel@tonic-gate (p[PT_RPC_LW_VER_INDEX].ip_error == IVE_INVALID) ||
3677c478bd9Sstevel@tonic-gate (p[PT_RPC_HI_VER_INDEX].ip_error == IVE_INVALID))
3687c478bd9Sstevel@tonic-gate (void) strlcat(buf, " service-name", sizeof (buf));
3697c478bd9Sstevel@tonic-gate if ((p[PT_SOCK_TYPE_INDEX].ip_error == IVE_INVALID) ||
3707c478bd9Sstevel@tonic-gate (p[PT_SOCK_TYPE_INDEX].ip_error == IVE_UNSET))
3717c478bd9Sstevel@tonic-gate (void) strlcat(buf, " endpoint-type", sizeof (buf));
3727c478bd9Sstevel@tonic-gate if ((p[PT_PROTO_INDEX].ip_error == IVE_INVALID) ||
3737c478bd9Sstevel@tonic-gate (p[PT_PROTO_INDEX].ip_error == IVE_UNSET) ||
3747c478bd9Sstevel@tonic-gate (p[PT_ISRPC_INDEX].ip_error == IVE_INVALID))
3757c478bd9Sstevel@tonic-gate (void) strlcat(buf, " protocol", sizeof (buf));
3767c478bd9Sstevel@tonic-gate if (p[PT_ISWAIT_INDEX].ip_error == IVE_INVALID)
3777c478bd9Sstevel@tonic-gate (void) strlcat(buf, " wait-status", sizeof (buf));
3787c478bd9Sstevel@tonic-gate return (buf);
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate static boolean_t
valid_basic_properties(struct inetconfent * iconf,struct fileinfo * finfo)3827c478bd9Sstevel@tonic-gate valid_basic_properties(struct inetconfent *iconf, struct fileinfo *finfo)
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate size_t prop_size;
3857c478bd9Sstevel@tonic-gate inetd_prop_t *prop, *inetd_properties;
3867c478bd9Sstevel@tonic-gate boolean_t valid = B_TRUE;
3877c478bd9Sstevel@tonic-gate char *proto = iconf->protocol;
3887c478bd9Sstevel@tonic-gate char *svc_name = iconf->service;
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate inetd_properties = get_prop_table(&prop_size);
3917c478bd9Sstevel@tonic-gate prop = safe_malloc(prop_size * sizeof (inetd_prop_t));
3927c478bd9Sstevel@tonic-gate (void) memcpy(prop, inetd_properties,
3937c478bd9Sstevel@tonic-gate prop_size * sizeof (inetd_prop_t));
3947c478bd9Sstevel@tonic-gate
395ba1637f8Smh138676 put_prop_value_boolean(prop, PR_ISRPC_NAME, iconf->isrpc);
396ba1637f8Smh138676 put_prop_value_boolean(prop, PR_ISWAIT_NAME, iconf->wait);
3977c478bd9Sstevel@tonic-gate if (iconf->isrpc) {
398ba1637f8Smh138676 put_prop_value_int(prop, PR_RPC_LW_VER_NAME,
399ba1637f8Smh138676 iconf->rpc_low_version);
400ba1637f8Smh138676 put_prop_value_int(prop, PR_RPC_HI_VER_NAME,
401ba1637f8Smh138676 iconf->rpc_high_version);
4027c478bd9Sstevel@tonic-gate svc_name = iconf->rpc_prog;
4037c478bd9Sstevel@tonic-gate proto += 4; /* skip 'rpc/' */
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate
406ba1637f8Smh138676 if (!put_prop_value_string(prop, PR_SOCK_TYPE_NAME, iconf->endpoint) ||
407ba1637f8Smh138676 !put_prop_value_string(prop, PR_SVC_NAME_NAME, svc_name)) {
4087c478bd9Sstevel@tonic-gate valid = B_FALSE;
4097c478bd9Sstevel@tonic-gate
410ba1637f8Smh138676 if (errno == ENOMEM) {
411ba1637f8Smh138676 (void) fprintf(stderr,
412ba1637f8Smh138676 gettext("%s: failed to allocate memory: %s\n"),
413ba1637f8Smh138676 progname, strerror(errno));
414ba1637f8Smh138676 exit(EXIT_ERROR_SYS);
415ba1637f8Smh138676 }
416ba1637f8Smh138676 }
417ba1637f8Smh138676
418ba1637f8Smh138676 put_prop_value_string_list(prop, PR_PROTO_NAME, get_protos(proto));
419ba1637f8Smh138676
4207c478bd9Sstevel@tonic-gate if (!valid_props(prop, NULL, NULL, NULL, NULL) || !valid) {
4217c478bd9Sstevel@tonic-gate valid = B_FALSE;
4227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: Error %s line %d "
4237c478bd9Sstevel@tonic-gate "invalid or inconsistent fields:%s\n"), progname,
4247c478bd9Sstevel@tonic-gate finfo->filename, finfo->lineno,
4257c478bd9Sstevel@tonic-gate invalid_props(prop));
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate free_instance_props(prop);
4297c478bd9Sstevel@tonic-gate return (valid);
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate static boolean_t
valid_inetconfent(struct inetconfent * iconf,struct fileinfo * finfo)4337c478bd9Sstevel@tonic-gate valid_inetconfent(struct inetconfent *iconf, struct fileinfo *finfo)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate boolean_t valid = B_TRUE;
4367c478bd9Sstevel@tonic-gate size_t len;
4377c478bd9Sstevel@tonic-gate char *cp, *endp;
4387c478bd9Sstevel@tonic-gate struct passwd *pwd;
4397c478bd9Sstevel@tonic-gate struct group *grp;
4407c478bd9Sstevel@tonic-gate struct stat statb;
4417c478bd9Sstevel@tonic-gate char *proto = iconf->protocol;
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate iconf->isrpc = B_FALSE;
4447c478bd9Sstevel@tonic-gate if (strncmp(iconf->protocol, "rpc/", 4) == 0) {
4457c478bd9Sstevel@tonic-gate iconf->isrpc = B_TRUE;
4467c478bd9Sstevel@tonic-gate iconf->rpc_prog = safe_strdup(iconf->service);
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate /* set RPC version numbers */
4497c478bd9Sstevel@tonic-gate iconf->rpc_low_version = 1;
4507c478bd9Sstevel@tonic-gate iconf->rpc_high_version = 1;
4517c478bd9Sstevel@tonic-gate if ((cp = strrchr(iconf->rpc_prog, '/')) != NULL) {
4527c478bd9Sstevel@tonic-gate *cp = '\0';
4537c478bd9Sstevel@tonic-gate if (*++cp != '\0') {
4547c478bd9Sstevel@tonic-gate errno = 0;
4557c478bd9Sstevel@tonic-gate iconf->rpc_low_version = strtol(cp, &endp, 10);
4567c478bd9Sstevel@tonic-gate if (errno != 0)
4577c478bd9Sstevel@tonic-gate goto vererr;
4587c478bd9Sstevel@tonic-gate cp = endp;
4597c478bd9Sstevel@tonic-gate if (*cp == '-') {
4607c478bd9Sstevel@tonic-gate if (*++cp == '\0')
4617c478bd9Sstevel@tonic-gate goto vererr;
4627c478bd9Sstevel@tonic-gate errno = 0;
4637c478bd9Sstevel@tonic-gate iconf->rpc_high_version = strtol(cp,
4647c478bd9Sstevel@tonic-gate &endp, 10);
4657c478bd9Sstevel@tonic-gate if ((errno != 0) || (*endp != '\0'))
4667c478bd9Sstevel@tonic-gate goto vererr;
4677c478bd9Sstevel@tonic-gate } else if (*cp == '\0') {
4687c478bd9Sstevel@tonic-gate iconf->rpc_high_version =
4697c478bd9Sstevel@tonic-gate iconf->rpc_low_version;
4707c478bd9Sstevel@tonic-gate } else {
4717c478bd9Sstevel@tonic-gate vererr:
4727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
4737c478bd9Sstevel@tonic-gate "%s: Error %s line %d invalid RPC "
4747c478bd9Sstevel@tonic-gate "version in service: %s\n"),
4757c478bd9Sstevel@tonic-gate progname, finfo->filename,
4767c478bd9Sstevel@tonic-gate finfo->lineno, iconf->service);
4777c478bd9Sstevel@tonic-gate valid = B_FALSE;
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate proto += 4; /* skip 'rpc/' */
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate /* tcp6only and udp6only are not valid in inetd.conf */
4847c478bd9Sstevel@tonic-gate if (is_v6only(proto)) {
4857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: Error %s line %d "
4867c478bd9Sstevel@tonic-gate "invalid protocol: %s\n"), progname,
4877c478bd9Sstevel@tonic-gate finfo->filename, finfo->lineno, proto);
4887c478bd9Sstevel@tonic-gate valid = B_FALSE;
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate if (strcmp(iconf->wait_status, "wait") == 0) {
4927c478bd9Sstevel@tonic-gate iconf->wait = B_TRUE;
4937c478bd9Sstevel@tonic-gate } else if (strcmp(iconf->wait_status, "nowait") == 0) {
4947c478bd9Sstevel@tonic-gate iconf->wait = B_FALSE;
4957c478bd9Sstevel@tonic-gate } else {
4967c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
4977c478bd9Sstevel@tonic-gate gettext("%s: Error %s line %d invalid wait-status: %s\n"),
4987c478bd9Sstevel@tonic-gate progname, finfo->filename, finfo->lineno,
4997c478bd9Sstevel@tonic-gate iconf->wait_status);
5007c478bd9Sstevel@tonic-gate valid = B_FALSE;
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate /* look up the username to set the groupname */
5047c478bd9Sstevel@tonic-gate if ((pwd = getpwnam(iconf->username)) == NULL) {
5057c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
5067c478bd9Sstevel@tonic-gate gettext("%s: Error %s line %d unknown user: %s\n"),
5077c478bd9Sstevel@tonic-gate progname, finfo->filename, finfo->lineno,
5087c478bd9Sstevel@tonic-gate iconf->username);
5097c478bd9Sstevel@tonic-gate valid = B_FALSE;
5107c478bd9Sstevel@tonic-gate } else {
5117c478bd9Sstevel@tonic-gate if ((grp = getgrgid(pwd->pw_gid)) != NULL) {
5127c478bd9Sstevel@tonic-gate iconf->groupname = safe_strdup(grp->gr_name);
5137c478bd9Sstevel@tonic-gate } else {
5147c478bd9Sstevel@tonic-gate /* use the group ID if no groupname */
5157c478bd9Sstevel@tonic-gate char s[1];
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate len = snprintf(s, 1, "%d", pwd->pw_gid) + 1;
5187c478bd9Sstevel@tonic-gate iconf->groupname = safe_malloc(len);
5197c478bd9Sstevel@tonic-gate (void) snprintf(iconf->groupname, len, "%d",
5207c478bd9Sstevel@tonic-gate pwd->pw_gid);
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate /* check for internal services */
5257c478bd9Sstevel@tonic-gate if (strcmp(iconf->server_program, "internal") == 0) {
5267c478bd9Sstevel@tonic-gate valid = B_FALSE;
5277c478bd9Sstevel@tonic-gate if ((strcmp(iconf->service, "echo") == 0) ||
5287c478bd9Sstevel@tonic-gate (strcmp(iconf->service, "discard") == 0) ||
5297c478bd9Sstevel@tonic-gate (strcmp(iconf->service, "time") == 0) ||
5307c478bd9Sstevel@tonic-gate (strcmp(iconf->service, "daytime") == 0) ||
5317c478bd9Sstevel@tonic-gate (strcmp(iconf->service, "chargen") == 0)) {
5327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
5337c478bd9Sstevel@tonic-gate "%s: Error %s line %d the SUNWcnsr and SUNWcnsu"
5347c478bd9Sstevel@tonic-gate " packages contain the internal services\n"),
5357c478bd9Sstevel@tonic-gate progname, finfo->filename, finfo->lineno);
5367c478bd9Sstevel@tonic-gate } else {
5377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: Error %s line %d "
5387c478bd9Sstevel@tonic-gate "unknown internal service: %s\n"), progname,
5397c478bd9Sstevel@tonic-gate finfo->filename, finfo->lineno, iconf->service);
5407c478bd9Sstevel@tonic-gate }
5417c478bd9Sstevel@tonic-gate } else if ((stat(iconf->server_program, &statb) == -1) &&
5427c478bd9Sstevel@tonic-gate (errno == ENOENT)) {
5437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
5447c478bd9Sstevel@tonic-gate "%s: Error %s line %d server-program not found: %s\n"),
5457c478bd9Sstevel@tonic-gate progname, finfo->filename, finfo->lineno,
5467c478bd9Sstevel@tonic-gate iconf->server_program);
5477c478bd9Sstevel@tonic-gate valid = B_FALSE;
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate
5507c478bd9Sstevel@tonic-gate return (valid && valid_basic_properties(iconf, finfo));
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate static void
free_inetconfent(struct inetconfent * iconf)5547c478bd9Sstevel@tonic-gate free_inetconfent(struct inetconfent *iconf)
5557c478bd9Sstevel@tonic-gate {
5567c478bd9Sstevel@tonic-gate if (iconf == NULL)
5577c478bd9Sstevel@tonic-gate return;
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate free(iconf->service);
5607c478bd9Sstevel@tonic-gate free(iconf->endpoint);
5617c478bd9Sstevel@tonic-gate free(iconf->protocol);
5627c478bd9Sstevel@tonic-gate free(iconf->wait_status);
5637c478bd9Sstevel@tonic-gate free(iconf->username);
5647c478bd9Sstevel@tonic-gate free(iconf->server_program);
5657c478bd9Sstevel@tonic-gate free(iconf->server_args);
5667c478bd9Sstevel@tonic-gate free(iconf->rpc_prog);
5677c478bd9Sstevel@tonic-gate free(iconf->groupname);
5687c478bd9Sstevel@tonic-gate free(iconf->exec);
5697c478bd9Sstevel@tonic-gate free(iconf->arg0);
5707c478bd9Sstevel@tonic-gate
5717c478bd9Sstevel@tonic-gate free(iconf);
5727c478bd9Sstevel@tonic-gate }
5737c478bd9Sstevel@tonic-gate
5747c478bd9Sstevel@tonic-gate static struct inetconfent *
line_to_inetconfent(char * line)5757c478bd9Sstevel@tonic-gate line_to_inetconfent(char *line)
5767c478bd9Sstevel@tonic-gate {
5777c478bd9Sstevel@tonic-gate char *cp;
5787c478bd9Sstevel@tonic-gate struct inetconfent *iconf;
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate iconf = safe_malloc(sizeof (struct inetconfent));
5817c478bd9Sstevel@tonic-gate (void) memset(iconf, 0, sizeof (struct inetconfent));
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate if ((cp = strtok(line, " \t\n")) == NULL)
5847c478bd9Sstevel@tonic-gate goto fail;
5857c478bd9Sstevel@tonic-gate iconf->service = safe_strdup(cp);
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate if ((cp = strtok(NULL, " \t\n")) == NULL)
5887c478bd9Sstevel@tonic-gate goto fail;
5897c478bd9Sstevel@tonic-gate iconf->endpoint = safe_strdup(cp);
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate if ((cp = strtok(NULL, " \t\n")) == NULL)
5927c478bd9Sstevel@tonic-gate goto fail;
5937c478bd9Sstevel@tonic-gate iconf->protocol = safe_strdup(cp);
5947c478bd9Sstevel@tonic-gate
5957c478bd9Sstevel@tonic-gate if ((cp = strtok(NULL, " \t\n")) == NULL)
5967c478bd9Sstevel@tonic-gate goto fail;
5977c478bd9Sstevel@tonic-gate iconf->wait_status = safe_strdup(cp);
5987c478bd9Sstevel@tonic-gate
5997c478bd9Sstevel@tonic-gate if ((cp = strtok(NULL, " \t\n")) == NULL)
6007c478bd9Sstevel@tonic-gate goto fail;
6017c478bd9Sstevel@tonic-gate iconf->username = safe_strdup(cp);
6027c478bd9Sstevel@tonic-gate
6037c478bd9Sstevel@tonic-gate if ((cp = strtok(NULL, " \t\n")) == NULL)
6047c478bd9Sstevel@tonic-gate goto fail;
6057c478bd9Sstevel@tonic-gate iconf->server_program = safe_strdup(cp);
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate /* last field is optional */
6087c478bd9Sstevel@tonic-gate if ((cp = strtok(NULL, "\n")) != NULL)
6097c478bd9Sstevel@tonic-gate iconf->server_args = safe_strdup(cp);
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate /* Combine args and server name to construct exec and args fields */
6127c478bd9Sstevel@tonic-gate if (iconf->server_args == NULL) {
6137c478bd9Sstevel@tonic-gate iconf->exec = safe_strdup(iconf->server_program);
6147c478bd9Sstevel@tonic-gate } else {
6157c478bd9Sstevel@tonic-gate int len;
6167c478bd9Sstevel@tonic-gate char *args, *endp;
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate len = strlen(iconf->server_program) +
6197c478bd9Sstevel@tonic-gate strlen(iconf->server_args) + 1;
6207c478bd9Sstevel@tonic-gate iconf->exec = safe_malloc(len);
6217c478bd9Sstevel@tonic-gate (void) strlcpy(iconf->exec, iconf->server_program, len);
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate args = safe_strdup(iconf->server_args);
6247c478bd9Sstevel@tonic-gate if ((cp = strtok(args, " \t")) != NULL) {
6257c478bd9Sstevel@tonic-gate if ((endp = strrchr(iconf->exec, '/')) == NULL)
6267c478bd9Sstevel@tonic-gate endp = iconf->exec;
6277c478bd9Sstevel@tonic-gate else
6287c478bd9Sstevel@tonic-gate endp++;
6297c478bd9Sstevel@tonic-gate /* only set arg0 property value if needed */
6307c478bd9Sstevel@tonic-gate if (strcmp(endp, cp) != 0)
6317c478bd9Sstevel@tonic-gate iconf->arg0 = safe_strdup(cp);
6327c478bd9Sstevel@tonic-gate while ((cp = strtok(NULL, " \t")) != NULL) {
6337c478bd9Sstevel@tonic-gate (void) strlcat(iconf->exec, " ", len);
6347c478bd9Sstevel@tonic-gate (void) strlcat(iconf->exec, cp, len);
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate }
6377c478bd9Sstevel@tonic-gate free(args);
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate
6407c478bd9Sstevel@tonic-gate return (iconf);
6417c478bd9Sstevel@tonic-gate fail:
6427c478bd9Sstevel@tonic-gate free_inetconfent(iconf);
6437c478bd9Sstevel@tonic-gate return (NULL);
6447c478bd9Sstevel@tonic-gate }
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate static void
skipline(FILE * fp)6477c478bd9Sstevel@tonic-gate skipline(FILE *fp)
6487c478bd9Sstevel@tonic-gate {
6497c478bd9Sstevel@tonic-gate int c;
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate /* skip remainder of a line */
6527c478bd9Sstevel@tonic-gate while (((c = getc(fp)) != EOF) && (c != '\n'))
6537c478bd9Sstevel@tonic-gate ;
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate static struct inetconfent *
fgetinetconfent(struct fileinfo * finfo,boolean_t validate)6577c478bd9Sstevel@tonic-gate fgetinetconfent(struct fileinfo *finfo, boolean_t validate)
6587c478bd9Sstevel@tonic-gate {
6597c478bd9Sstevel@tonic-gate char *cp;
6607c478bd9Sstevel@tonic-gate struct inetconfent *iconf;
6617c478bd9Sstevel@tonic-gate char line[MAX_SRC_LINELEN];
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate while (fgets(line, sizeof (line), finfo->fp) != NULL) {
6647c478bd9Sstevel@tonic-gate finfo->lineno++;
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate /* skip empty or commented out lines */
6677c478bd9Sstevel@tonic-gate if (*line == '\n')
6687c478bd9Sstevel@tonic-gate continue;
6697c478bd9Sstevel@tonic-gate if (*line == '#') {
6707c478bd9Sstevel@tonic-gate if (line[strlen(line) - 1] != '\n')
6717c478bd9Sstevel@tonic-gate skipline(finfo->fp);
6727c478bd9Sstevel@tonic-gate continue;
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate /* check for lines which are too long */
6757c478bd9Sstevel@tonic-gate if (line[strlen(line) - 1] != '\n') {
6767c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
6777c478bd9Sstevel@tonic-gate gettext("%s: Error %s line %d too long, skipped\n"),
6787c478bd9Sstevel@tonic-gate progname, finfo->filename, finfo->lineno);
6797c478bd9Sstevel@tonic-gate skipline(finfo->fp);
6807c478bd9Sstevel@tonic-gate finfo->failcnt++;
6817c478bd9Sstevel@tonic-gate continue;
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate /* remove in line comments and newline character */
6847c478bd9Sstevel@tonic-gate if ((cp = strchr(line, '#')) == NULL)
6857c478bd9Sstevel@tonic-gate cp = strchr(line, '\n');
6867c478bd9Sstevel@tonic-gate if (cp)
6877c478bd9Sstevel@tonic-gate *cp = '\0';
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate if ((iconf = line_to_inetconfent(line)) == NULL) {
6907c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
6917c478bd9Sstevel@tonic-gate "%s: Error %s line %d too few fields, skipped\n"),
6927c478bd9Sstevel@tonic-gate progname, finfo->filename, finfo->lineno);
6937c478bd9Sstevel@tonic-gate finfo->failcnt++;
6947c478bd9Sstevel@tonic-gate continue;
6957c478bd9Sstevel@tonic-gate }
6967c478bd9Sstevel@tonic-gate
6977c478bd9Sstevel@tonic-gate if (!validate || valid_inetconfent(iconf, finfo))
6987c478bd9Sstevel@tonic-gate return (iconf);
6997c478bd9Sstevel@tonic-gate
7007c478bd9Sstevel@tonic-gate finfo->failcnt++;
7017c478bd9Sstevel@tonic-gate free_inetconfent(iconf);
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate return (NULL);
7047c478bd9Sstevel@tonic-gate }
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate static char *
boolstr(boolean_t val)7077c478bd9Sstevel@tonic-gate boolstr(boolean_t val)
7087c478bd9Sstevel@tonic-gate {
7097c478bd9Sstevel@tonic-gate if (val)
7107c478bd9Sstevel@tonic-gate return ("true");
7117c478bd9Sstevel@tonic-gate return ("false");
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate static int
print_manifest(FILE * f,char * filename,struct inetconfent * iconf)7157c478bd9Sstevel@tonic-gate print_manifest(FILE *f, char *filename, struct inetconfent *iconf)
7167c478bd9Sstevel@tonic-gate {
7177c478bd9Sstevel@tonic-gate if (fprintf(f, xml_header) < 0)
7187c478bd9Sstevel@tonic-gate goto print_err;
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate if (fprintf(f, xml_comment,
7217c478bd9Sstevel@tonic-gate iconf->isrpc ? iconf->rpc_prog : iconf->service) < 0)
7227c478bd9Sstevel@tonic-gate goto print_err;
7237c478bd9Sstevel@tonic-gate
7247c478bd9Sstevel@tonic-gate if (fprintf(f, xml_service_bundle, iconf->service) < 0)
7257c478bd9Sstevel@tonic-gate goto print_err;
7267c478bd9Sstevel@tonic-gate if (fprintf(f, xml_service_name, servicename(iconf)) < 0)
7277c478bd9Sstevel@tonic-gate goto print_err;
7287c478bd9Sstevel@tonic-gate if (fprintf(f, xml_instance) < 0)
7297c478bd9Sstevel@tonic-gate goto print_err;
7307c478bd9Sstevel@tonic-gate if (fprintf(f, xml_restarter, INETD_INSTANCE_FMRI) < 0)
7317c478bd9Sstevel@tonic-gate goto print_err;
732cdc89861Sdstaff if (iconf->isrpc) {
733cdc89861Sdstaff if (fprintf(f, xml_dependency, "rpcbind", RPCBIND_FMRI) < 0)
734cdc89861Sdstaff goto print_err;
735cdc89861Sdstaff }
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate if (fprintf(f, xml_exec_method_start, START_METHOD_NAME, PR_EXEC_NAME,
7387c478bd9Sstevel@tonic-gate iconf->exec, PR_USER_NAME, iconf->username, iconf->groupname) < 0)
7397c478bd9Sstevel@tonic-gate goto print_err;
7407c478bd9Sstevel@tonic-gate if (iconf->arg0 != NULL) {
7417c478bd9Sstevel@tonic-gate if (fprintf(f, xml_arg0, PR_ARG0_NAME, iconf->arg0) < 0)
7427c478bd9Sstevel@tonic-gate goto print_err;
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate if (fprintf(f, xml_exec_method_end) < 0)
7457c478bd9Sstevel@tonic-gate goto print_err;
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate if (fprintf(f, xml_exec_method_disable, DISABLE_METHOD_NAME,
7487c478bd9Sstevel@tonic-gate PR_EXEC_NAME) < 0)
7497c478bd9Sstevel@tonic-gate goto print_err;
7507c478bd9Sstevel@tonic-gate if (fprintf(f, xml_exec_method_end) < 0)
7517c478bd9Sstevel@tonic-gate goto print_err;
7527c478bd9Sstevel@tonic-gate
7537c478bd9Sstevel@tonic-gate if (iconf->wait) {
7547c478bd9Sstevel@tonic-gate if (fprintf(f, xml_exec_method_offline, OFFLINE_METHOD_NAME,
7557c478bd9Sstevel@tonic-gate PR_EXEC_NAME) < 0)
7567c478bd9Sstevel@tonic-gate goto print_err;
7577c478bd9Sstevel@tonic-gate if (fprintf(f, xml_exec_method_end) < 0)
7587c478bd9Sstevel@tonic-gate goto print_err;
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate if (fprintf(f, xml_inetconv_group_start, PG_NAME_INETCONV,
7627c478bd9Sstevel@tonic-gate PR_AUTO_CONVERTED_NAME, boolstr(B_TRUE),
7637c478bd9Sstevel@tonic-gate PR_VERSION_NAME, INETCONV_VERSION,
7647c478bd9Sstevel@tonic-gate PR_SOURCE_LINE_NAME, iconf->service,
7657c478bd9Sstevel@tonic-gate iconf->endpoint, iconf->protocol, iconf->wait_status,
7667c478bd9Sstevel@tonic-gate iconf->username, iconf->server_program,
7677c478bd9Sstevel@tonic-gate iconf->server_args == NULL ? "" : " ",
7687c478bd9Sstevel@tonic-gate iconf->server_args == NULL ? "" : iconf->server_args) < 0)
7697c478bd9Sstevel@tonic-gate goto print_err;
7707c478bd9Sstevel@tonic-gate if (fprintf(f, xml_property_group_end) < 0)
7717c478bd9Sstevel@tonic-gate goto print_err;
7727c478bd9Sstevel@tonic-gate
7737c478bd9Sstevel@tonic-gate if (fprintf(f, xml_property_group_start, PG_NAME_SERVICE_CONFIG,
7747c478bd9Sstevel@tonic-gate PR_SVC_NAME_NAME, iconf->isrpc ? iconf->rpc_prog : iconf->service,
7757c478bd9Sstevel@tonic-gate PR_SOCK_TYPE_NAME, iconf->endpoint,
7767c478bd9Sstevel@tonic-gate PR_PROTO_NAME, iconf->isrpc ? iconf->protocol + 4 :
7777c478bd9Sstevel@tonic-gate iconf->protocol,
7787c478bd9Sstevel@tonic-gate PR_ISWAIT_NAME, boolstr(iconf->wait),
7797c478bd9Sstevel@tonic-gate PR_ISRPC_NAME, boolstr(iconf->isrpc)) < 0)
7807c478bd9Sstevel@tonic-gate goto print_err;
7817c478bd9Sstevel@tonic-gate if (iconf->isrpc) {
7827c478bd9Sstevel@tonic-gate if (fprintf(f, xml_property_group_rpc,
7837c478bd9Sstevel@tonic-gate PR_RPC_LW_VER_NAME, iconf->rpc_low_version,
7847c478bd9Sstevel@tonic-gate PR_RPC_HI_VER_NAME, iconf->rpc_high_version) < 0)
7857c478bd9Sstevel@tonic-gate goto print_err;
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate if (fprintf(f, xml_property_group_end) < 0)
7887c478bd9Sstevel@tonic-gate goto print_err;
7897c478bd9Sstevel@tonic-gate
7907c478bd9Sstevel@tonic-gate if (fprintf(f, xml_stability) < 0)
7917c478bd9Sstevel@tonic-gate goto print_err;
7927c478bd9Sstevel@tonic-gate if (fprintf(f, xml_template,
7937c478bd9Sstevel@tonic-gate iconf->isrpc ? iconf->rpc_prog : iconf->service) < 0)
7947c478bd9Sstevel@tonic-gate goto print_err;
7957c478bd9Sstevel@tonic-gate if (fprintf(f, xml_footer) < 0)
7967c478bd9Sstevel@tonic-gate goto print_err;
7977c478bd9Sstevel@tonic-gate
7987c478bd9Sstevel@tonic-gate (void) printf("%s -> %s\n", iconf->service, filename);
7997c478bd9Sstevel@tonic-gate return (0);
8007c478bd9Sstevel@tonic-gate
8017c478bd9Sstevel@tonic-gate print_err:
8027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: Error writing manifest %s: %s\n"),
8037c478bd9Sstevel@tonic-gate progname, filename, strerror(errno));
8047c478bd9Sstevel@tonic-gate return (-1);
8057c478bd9Sstevel@tonic-gate }
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate static struct fileinfo *
open_srcfile(char * filename)8087c478bd9Sstevel@tonic-gate open_srcfile(char *filename)
8097c478bd9Sstevel@tonic-gate {
8107c478bd9Sstevel@tonic-gate struct fileinfo *finfo = NULL;
8117c478bd9Sstevel@tonic-gate FILE *fp;
8127c478bd9Sstevel@tonic-gate
8137c478bd9Sstevel@tonic-gate if (filename != NULL) {
8147c478bd9Sstevel@tonic-gate if ((fp = fopen(filename, "r")) == NULL) {
8157c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
8167c478bd9Sstevel@tonic-gate gettext("%s: Error opening %s: %s\n"),
8177c478bd9Sstevel@tonic-gate progname, filename, strerror(errno));
8187c478bd9Sstevel@tonic-gate }
8197c478bd9Sstevel@tonic-gate } else {
8207c478bd9Sstevel@tonic-gate /*
8217c478bd9Sstevel@tonic-gate * If no source file specified, do the same as inetd and first
8227c478bd9Sstevel@tonic-gate * try /etc/inet/inetd.conf, followed by /etc/inetd.conf.
8237c478bd9Sstevel@tonic-gate */
8247c478bd9Sstevel@tonic-gate filename = MAIN_CONFIG;
8257c478bd9Sstevel@tonic-gate if ((fp = fopen(filename, "r")) == NULL) {
8267c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
8277c478bd9Sstevel@tonic-gate gettext("%s: Error opening %s: %s\n"),
8287c478bd9Sstevel@tonic-gate progname, filename, strerror(errno));
8297c478bd9Sstevel@tonic-gate filename = ALT_CONFIG;
8307c478bd9Sstevel@tonic-gate if ((fp = fopen(filename, "r")) == NULL) {
8317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
8327c478bd9Sstevel@tonic-gate "%s: Error opening %s: %s\n"), progname,
8337c478bd9Sstevel@tonic-gate filename, strerror(errno));
8347c478bd9Sstevel@tonic-gate }
8357c478bd9Sstevel@tonic-gate }
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate if (fp != NULL) {
8387c478bd9Sstevel@tonic-gate finfo = safe_malloc(sizeof (struct fileinfo));
8397c478bd9Sstevel@tonic-gate finfo->fp = fp;
8407c478bd9Sstevel@tonic-gate finfo->filename = filename;
8417c478bd9Sstevel@tonic-gate finfo->lineno = 0;
8427c478bd9Sstevel@tonic-gate finfo->failcnt = 0;
8437c478bd9Sstevel@tonic-gate (void) fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
8447c478bd9Sstevel@tonic-gate }
8457c478bd9Sstevel@tonic-gate return (finfo);
8467c478bd9Sstevel@tonic-gate }
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate /*
8497c478bd9Sstevel@tonic-gate * Opens manifest output file. Returns 0 on success, -1 if the file
8507c478bd9Sstevel@tonic-gate * exists, -2 on other errors.
8517c478bd9Sstevel@tonic-gate */
8527c478bd9Sstevel@tonic-gate static int
open_dstfile(char * destdir,boolean_t overwrite,struct inetconfent * iconf,struct fileinfo ** finfo)8537c478bd9Sstevel@tonic-gate open_dstfile(
8547c478bd9Sstevel@tonic-gate char *destdir,
8557c478bd9Sstevel@tonic-gate boolean_t overwrite,
8567c478bd9Sstevel@tonic-gate struct inetconfent *iconf,
8577c478bd9Sstevel@tonic-gate struct fileinfo **finfo)
8587c478bd9Sstevel@tonic-gate {
8597c478bd9Sstevel@tonic-gate int fd;
8607c478bd9Sstevel@tonic-gate size_t len;
8617c478bd9Sstevel@tonic-gate char *dstfile, *cp, *proto;
8627c478bd9Sstevel@tonic-gate FILE *fp;
8637c478bd9Sstevel@tonic-gate
8647c478bd9Sstevel@tonic-gate /* if no destdir specified, use appropriate default */
8657c478bd9Sstevel@tonic-gate if (destdir == NULL) {
8667c478bd9Sstevel@tonic-gate if (iconf->isrpc)
8677c478bd9Sstevel@tonic-gate destdir = MANIFEST_RPC_DIR;
8687c478bd9Sstevel@tonic-gate else
8697c478bd9Sstevel@tonic-gate destdir = MANIFEST_DIR;
8707c478bd9Sstevel@tonic-gate }
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate len = strlen(destdir) + strlen(iconf->service) +
8737c478bd9Sstevel@tonic-gate strlen(iconf->protocol) + sizeof ("/-visible.xml");
8747c478bd9Sstevel@tonic-gate dstfile = safe_malloc(len);
8757c478bd9Sstevel@tonic-gate
8767c478bd9Sstevel@tonic-gate (void) strlcpy(dstfile, destdir, len);
8777c478bd9Sstevel@tonic-gate if (dstfile[strlen(dstfile) - 1] != '/')
8787c478bd9Sstevel@tonic-gate (void) strlcat(dstfile, "/", len);
8797c478bd9Sstevel@tonic-gate cp = dstfile + strlen(dstfile);
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate (void) strlcat(dstfile, iconf->service, len);
8827c478bd9Sstevel@tonic-gate (void) strlcat(dstfile, "-", len);
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate proto = iconf->protocol;
8857c478bd9Sstevel@tonic-gate if (iconf->isrpc && (strcmp(iconf->protocol, "rpc/*") == 0))
8867c478bd9Sstevel@tonic-gate proto = "rpc/visible";
8877c478bd9Sstevel@tonic-gate
8887c478bd9Sstevel@tonic-gate (void) strlcat(dstfile, proto, len);
8897c478bd9Sstevel@tonic-gate (void) strlcat(dstfile, ".xml", len);
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate /* convert any '/' chars in service or protocol to '_' chars */
8927c478bd9Sstevel@tonic-gate while ((cp = strchr(cp, '/')) != NULL)
8937c478bd9Sstevel@tonic-gate *cp = '_';
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate fd = open(dstfile, O_WRONLY|O_CREAT|(overwrite ? O_TRUNC : O_EXCL),
8967c478bd9Sstevel@tonic-gate 0644);
8977c478bd9Sstevel@tonic-gate if (fd == -1) {
8987c478bd9Sstevel@tonic-gate if (!overwrite && (errno == EEXIST)) {
8997c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
9007c478bd9Sstevel@tonic-gate gettext("%s: Notice: Service manifest for "
9017c478bd9Sstevel@tonic-gate "%s already generated as %s, skipped\n"),
9027c478bd9Sstevel@tonic-gate progname, iconf->service, dstfile);
9037c478bd9Sstevel@tonic-gate free(dstfile);
9047c478bd9Sstevel@tonic-gate return (-1);
9057c478bd9Sstevel@tonic-gate } else {
9067c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
9077c478bd9Sstevel@tonic-gate gettext("%s: Error opening %s: %s\n"),
9087c478bd9Sstevel@tonic-gate progname, dstfile, strerror(errno));
9097c478bd9Sstevel@tonic-gate free(dstfile);
9107c478bd9Sstevel@tonic-gate return (-2);
9117c478bd9Sstevel@tonic-gate }
9127c478bd9Sstevel@tonic-gate }
9137c478bd9Sstevel@tonic-gate /* Clear errno to catch the "no stdio streams" case */
9147c478bd9Sstevel@tonic-gate errno = 0;
9157c478bd9Sstevel@tonic-gate if ((fp = fdopen(fd, "w")) == NULL) {
9167c478bd9Sstevel@tonic-gate char *s = strerror(errno);
9177c478bd9Sstevel@tonic-gate if (errno == 0)
9187c478bd9Sstevel@tonic-gate s = gettext("No stdio streams available");
9197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: Error fdopen failed: %s\n"),
9207c478bd9Sstevel@tonic-gate progname, s);
9217c478bd9Sstevel@tonic-gate (void) close(fd);
9227c478bd9Sstevel@tonic-gate free(dstfile);
9237c478bd9Sstevel@tonic-gate return (-2);
9247c478bd9Sstevel@tonic-gate }
9257c478bd9Sstevel@tonic-gate *finfo = safe_malloc(sizeof (struct fileinfo));
9267c478bd9Sstevel@tonic-gate (*finfo)->fp = fp;
9277c478bd9Sstevel@tonic-gate (*finfo)->filename = dstfile;
9287c478bd9Sstevel@tonic-gate (*finfo)->lineno = 0;
9297c478bd9Sstevel@tonic-gate (*finfo)->failcnt = 0;
9307c478bd9Sstevel@tonic-gate return (0);
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate static int
import_manifest(char * filename)9347c478bd9Sstevel@tonic-gate import_manifest(char *filename)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate int status;
9377c478bd9Sstevel@tonic-gate pid_t pid, wpid;
9387c478bd9Sstevel@tonic-gate char *cp;
9397c478bd9Sstevel@tonic-gate
9407c478bd9Sstevel@tonic-gate if ((cp = strrchr(filename, '/')) == NULL)
9417c478bd9Sstevel@tonic-gate cp = filename;
9427c478bd9Sstevel@tonic-gate else
9437c478bd9Sstevel@tonic-gate cp++;
9447c478bd9Sstevel@tonic-gate (void) printf(gettext("Importing %s ..."), cp);
9457c478bd9Sstevel@tonic-gate
9467c478bd9Sstevel@tonic-gate if ((pid = fork()) == -1) {
9477c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
9487c478bd9Sstevel@tonic-gate gettext("\n%s: fork failed, %s not imported: %s\n"),
9497c478bd9Sstevel@tonic-gate progname, filename, strerror(errno));
9507c478bd9Sstevel@tonic-gate exit(EXIT_ERROR_SYS);
9517c478bd9Sstevel@tonic-gate }
9527c478bd9Sstevel@tonic-gate if (pid == 0) {
9537c478bd9Sstevel@tonic-gate /* child */
9547c478bd9Sstevel@tonic-gate (void) fclose(stdin);
9557c478bd9Sstevel@tonic-gate (void) setenv("SVCCFG_CHECKHASH", "1", 1);
9567c478bd9Sstevel@tonic-gate (void) execl(SVCCFG_PATH, "svccfg", "import", filename, NULL);
9577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("\n%s: exec of %s failed: %s"),
9587c478bd9Sstevel@tonic-gate progname, SVCCFG_PATH, strerror(errno));
9597c478bd9Sstevel@tonic-gate _exit(EXIT_ERROR_SYS);
9607c478bd9Sstevel@tonic-gate }
9617c478bd9Sstevel@tonic-gate /* parent */
9627c478bd9Sstevel@tonic-gate if ((wpid = waitpid(pid, &status, 0)) != pid) {
9637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
9647c478bd9Sstevel@tonic-gate "\n%s: unexpected wait (%d) from import of %s: %s\n"),
9657c478bd9Sstevel@tonic-gate progname, wpid, filename, strerror(errno));
9667c478bd9Sstevel@tonic-gate return (-1);
9677c478bd9Sstevel@tonic-gate }
9687c478bd9Sstevel@tonic-gate if (WIFEXITED(status) && (WEXITSTATUS(status) != 0)) {
9697c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
9707c478bd9Sstevel@tonic-gate gettext("\n%s: import failure (%d) for %s\n"),
9717c478bd9Sstevel@tonic-gate progname, WEXITSTATUS(status), filename);
9727c478bd9Sstevel@tonic-gate return (-1);
9737c478bd9Sstevel@tonic-gate }
9747c478bd9Sstevel@tonic-gate (void) printf(gettext("Done\n"));
9757c478bd9Sstevel@tonic-gate return (0);
9767c478bd9Sstevel@tonic-gate }
9777c478bd9Sstevel@tonic-gate
9787c478bd9Sstevel@tonic-gate static int
inetd_config_path(char ** path)9797c478bd9Sstevel@tonic-gate inetd_config_path(char **path)
9807c478bd9Sstevel@tonic-gate {
9817c478bd9Sstevel@tonic-gate int fd;
9827c478bd9Sstevel@tonic-gate char *arg1, *configfile, *configstr;
9837c478bd9Sstevel@tonic-gate scf_simple_prop_t *sp;
9847c478bd9Sstevel@tonic-gate char cpath[PATH_MAX];
9857c478bd9Sstevel@tonic-gate
9867c478bd9Sstevel@tonic-gate if ((sp = scf_simple_prop_get(NULL, INETD_INSTANCE_FMRI, "start",
9877c478bd9Sstevel@tonic-gate SCF_PROPERTY_EXEC)) == NULL)
9887c478bd9Sstevel@tonic-gate return (-1);
9897c478bd9Sstevel@tonic-gate if ((configstr = scf_simple_prop_next_astring(sp)) == NULL) {
9907c478bd9Sstevel@tonic-gate scf_simple_prop_free(sp);
9917c478bd9Sstevel@tonic-gate return (-1);
9927c478bd9Sstevel@tonic-gate }
9937c478bd9Sstevel@tonic-gate configstr = safe_strdup(configstr);
9947c478bd9Sstevel@tonic-gate scf_simple_prop_free(sp);
9957c478bd9Sstevel@tonic-gate
9967c478bd9Sstevel@tonic-gate /*
9977c478bd9Sstevel@tonic-gate * Look for the optional configuration file, the syntax is:
9987c478bd9Sstevel@tonic-gate * /usr/lib/inet/inetd [config-file] start|stop|refresh|disable|%m
9997c478bd9Sstevel@tonic-gate */
10007c478bd9Sstevel@tonic-gate if (strtok(configstr, " \t") == NULL) {
10017c478bd9Sstevel@tonic-gate free(configstr);
10027c478bd9Sstevel@tonic-gate return (-1);
10037c478bd9Sstevel@tonic-gate }
10047c478bd9Sstevel@tonic-gate if ((arg1 = strtok(NULL, " \t")) == NULL) {
10057c478bd9Sstevel@tonic-gate free(configstr);
10067c478bd9Sstevel@tonic-gate return (-1);
10077c478bd9Sstevel@tonic-gate }
10087c478bd9Sstevel@tonic-gate if (strtok(NULL, " \t") == NULL) {
10097c478bd9Sstevel@tonic-gate /*
10107c478bd9Sstevel@tonic-gate * No configuration file specified, do the same as inetd and
10117c478bd9Sstevel@tonic-gate * first try /etc/inet/inetd.conf, followed by /etc/inetd.conf.
10127c478bd9Sstevel@tonic-gate */
10137c478bd9Sstevel@tonic-gate configfile = MAIN_CONFIG;
10147c478bd9Sstevel@tonic-gate if ((fd = open(configfile, O_RDONLY)) >= 0)
10157c478bd9Sstevel@tonic-gate (void) close(fd);
10167c478bd9Sstevel@tonic-gate else
10177c478bd9Sstevel@tonic-gate configfile = ALT_CONFIG;
10187c478bd9Sstevel@tonic-gate
10197c478bd9Sstevel@tonic-gate } else {
10207c478bd9Sstevel@tonic-gate /* make sure there are no more arguments */
10217c478bd9Sstevel@tonic-gate if (strtok(NULL, " \t") != NULL) {
10227c478bd9Sstevel@tonic-gate free(configstr);
10237c478bd9Sstevel@tonic-gate return (-1);
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate configfile = arg1;
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate
10287c478bd9Sstevel@tonic-gate /* configuration file must be an absolute pathname */
10297c478bd9Sstevel@tonic-gate if (*configfile != '/') {
10307c478bd9Sstevel@tonic-gate free(configstr);
10317c478bd9Sstevel@tonic-gate return (-1);
10327c478bd9Sstevel@tonic-gate }
10337c478bd9Sstevel@tonic-gate
10347c478bd9Sstevel@tonic-gate if (realpath(configfile, cpath) == NULL)
10357c478bd9Sstevel@tonic-gate (void) strlcpy(cpath, configfile, sizeof (cpath));
10367c478bd9Sstevel@tonic-gate
10377c478bd9Sstevel@tonic-gate free(configstr);
10387c478bd9Sstevel@tonic-gate *path = safe_strdup(cpath);
10397c478bd9Sstevel@tonic-gate return (0);
10407c478bd9Sstevel@tonic-gate }
10417c478bd9Sstevel@tonic-gate
10427c478bd9Sstevel@tonic-gate static int
update_hash(char * srcfile)10437c478bd9Sstevel@tonic-gate update_hash(char *srcfile)
10447c478bd9Sstevel@tonic-gate {
10457c478bd9Sstevel@tonic-gate scf_error_t rval;
10467c478bd9Sstevel@tonic-gate char *inetd_cpath, *hashstr;
10477c478bd9Sstevel@tonic-gate char cpath[PATH_MAX];
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate /* determine the config file inetd is using */
10507c478bd9Sstevel@tonic-gate if (inetd_config_path(&inetd_cpath) == -1) {
10517c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
10527c478bd9Sstevel@tonic-gate gettext("%s: Error reading from repository\n"), progname);
10537c478bd9Sstevel@tonic-gate return (-1);
10547c478bd9Sstevel@tonic-gate }
10557c478bd9Sstevel@tonic-gate
10567c478bd9Sstevel@tonic-gate /* resolve inetconv input filename */
10577c478bd9Sstevel@tonic-gate if (realpath(srcfile, cpath) == NULL)
10587c478bd9Sstevel@tonic-gate (void) strlcpy(cpath, srcfile, sizeof (cpath));
10597c478bd9Sstevel@tonic-gate
10607c478bd9Sstevel@tonic-gate /* if inetconv and inetd are using the same config file, update hash */
10617c478bd9Sstevel@tonic-gate if (strcmp(cpath, inetd_cpath) != 0) {
10627c478bd9Sstevel@tonic-gate free(inetd_cpath);
10637c478bd9Sstevel@tonic-gate return (0);
10647c478bd9Sstevel@tonic-gate }
10657c478bd9Sstevel@tonic-gate free(inetd_cpath);
10667c478bd9Sstevel@tonic-gate
10677c478bd9Sstevel@tonic-gate /* generic error message as use of hash is not exposed to the user */
10687c478bd9Sstevel@tonic-gate if (calculate_hash(cpath, &hashstr) != 0) {
10697c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
10707c478bd9Sstevel@tonic-gate gettext("%s: Error unable to update repository\n"),
10717c478bd9Sstevel@tonic-gate progname);
10727c478bd9Sstevel@tonic-gate return (-1);
10737c478bd9Sstevel@tonic-gate }
10747c478bd9Sstevel@tonic-gate /* generic error message as use of hash is not exposed to the user */
10757c478bd9Sstevel@tonic-gate if ((rval = store_inetd_hash(hashstr)) != SCF_ERROR_NONE) {
10767c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
10777c478bd9Sstevel@tonic-gate gettext("%s: Error updating repository: %s\n"),
10787c478bd9Sstevel@tonic-gate progname, scf_strerror(rval));
10797c478bd9Sstevel@tonic-gate free(hashstr);
10807c478bd9Sstevel@tonic-gate return (-1);
10817c478bd9Sstevel@tonic-gate }
10827c478bd9Sstevel@tonic-gate free(hashstr);
10837c478bd9Sstevel@tonic-gate return (0);
10847c478bd9Sstevel@tonic-gate }
10857c478bd9Sstevel@tonic-gate
10867c478bd9Sstevel@tonic-gate static void
property_error(const char * fmri,const char * prop)10877c478bd9Sstevel@tonic-gate property_error(const char *fmri, const char *prop)
10887c478bd9Sstevel@tonic-gate {
10897c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
10907c478bd9Sstevel@tonic-gate gettext("Error: Instance %1$s is missing property '%2$s'.\n"),
10917c478bd9Sstevel@tonic-gate fmri, prop);
10927c478bd9Sstevel@tonic-gate }
10937c478bd9Sstevel@tonic-gate
10947c478bd9Sstevel@tonic-gate /*
10957c478bd9Sstevel@tonic-gate * modify_sprop takes a handle, an instance, a property group, a property,
10967c478bd9Sstevel@tonic-gate * and an astring value, and modifies the instance (or service's) specified
10977c478bd9Sstevel@tonic-gate * property in the repository to the submitted value.
10987c478bd9Sstevel@tonic-gate *
10997c478bd9Sstevel@tonic-gate * returns -1 on error, 1 on successful transaction completion.
11007c478bd9Sstevel@tonic-gate */
11017c478bd9Sstevel@tonic-gate
11027c478bd9Sstevel@tonic-gate static int
modify_sprop(scf_handle_t * h,const scf_instance_t * inst,const char * pg,const char * prop,const char * value)11037c478bd9Sstevel@tonic-gate modify_sprop(scf_handle_t *h, const scf_instance_t *inst,
11047c478bd9Sstevel@tonic-gate const char *pg, const char *prop, const char *value)
11057c478bd9Sstevel@tonic-gate {
11067c478bd9Sstevel@tonic-gate scf_transaction_t *tx = NULL;
11077c478bd9Sstevel@tonic-gate scf_transaction_entry_t *ent = NULL;
11087c478bd9Sstevel@tonic-gate scf_propertygroup_t *gpg = NULL;
11097c478bd9Sstevel@tonic-gate scf_property_t *eprop = NULL;
11107c478bd9Sstevel@tonic-gate scf_value_t *v = NULL;
11117c478bd9Sstevel@tonic-gate scf_service_t *svc = NULL;
11127c478bd9Sstevel@tonic-gate int ret = 0, create = 0;
11137c478bd9Sstevel@tonic-gate
11147c478bd9Sstevel@tonic-gate if ((gpg = scf_pg_create(h)) == NULL)
11157c478bd9Sstevel@tonic-gate return (-1);
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate /* Get the property group */
11187c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, pg, gpg) == -1) {
11197c478bd9Sstevel@tonic-gate /* Not a property of the instance, try the service instead */
11207c478bd9Sstevel@tonic-gate if ((svc = scf_service_create(h)) == NULL) {
11217c478bd9Sstevel@tonic-gate ret = -1;
11227c478bd9Sstevel@tonic-gate goto out;
11237c478bd9Sstevel@tonic-gate }
11247c478bd9Sstevel@tonic-gate if ((scf_instance_get_parent(inst, svc) == -1) ||
11257c478bd9Sstevel@tonic-gate (scf_service_get_pg(svc, pg, gpg) == -1)) {
11267c478bd9Sstevel@tonic-gate ret = -1;
11277c478bd9Sstevel@tonic-gate goto out;
11287c478bd9Sstevel@tonic-gate }
11297c478bd9Sstevel@tonic-gate }
11307c478bd9Sstevel@tonic-gate
11317c478bd9Sstevel@tonic-gate if ((eprop = scf_property_create(h)) == NULL) {
11327c478bd9Sstevel@tonic-gate ret = -1;
11337c478bd9Sstevel@tonic-gate goto out;
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate
11367c478bd9Sstevel@tonic-gate if (scf_pg_get_property(gpg, prop, eprop) == -1) {
11377c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) {
11387c478bd9Sstevel@tonic-gate ret = -1;
11397c478bd9Sstevel@tonic-gate goto out;
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate
11427c478bd9Sstevel@tonic-gate create = 1;
11437c478bd9Sstevel@tonic-gate }
11447c478bd9Sstevel@tonic-gate
11457c478bd9Sstevel@tonic-gate if ((tx = scf_transaction_create(h)) == NULL ||
11467c478bd9Sstevel@tonic-gate (ent = scf_entry_create(h)) == NULL) {
11477c478bd9Sstevel@tonic-gate ret = -1;
11487c478bd9Sstevel@tonic-gate goto out;
11497c478bd9Sstevel@tonic-gate }
11507c478bd9Sstevel@tonic-gate
11517c478bd9Sstevel@tonic-gate do {
11527c478bd9Sstevel@tonic-gate if (scf_transaction_start(tx, gpg) == -1) {
11537c478bd9Sstevel@tonic-gate ret = -1;
11547c478bd9Sstevel@tonic-gate goto out;
11557c478bd9Sstevel@tonic-gate }
11567c478bd9Sstevel@tonic-gate
11577c478bd9Sstevel@tonic-gate /* Modify the property */
11587c478bd9Sstevel@tonic-gate if (create)
11597c478bd9Sstevel@tonic-gate ret = scf_transaction_property_new(tx, ent, prop,
11607c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING);
11617c478bd9Sstevel@tonic-gate else
11627c478bd9Sstevel@tonic-gate ret = scf_transaction_property_change_type(tx, ent,
11637c478bd9Sstevel@tonic-gate prop, SCF_TYPE_ASTRING);
11647c478bd9Sstevel@tonic-gate
11657c478bd9Sstevel@tonic-gate if (ret == -1)
11667c478bd9Sstevel@tonic-gate goto out;
11677c478bd9Sstevel@tonic-gate
11687c478bd9Sstevel@tonic-gate if ((v = scf_value_create(h)) == NULL) {
11697c478bd9Sstevel@tonic-gate ret = -1;
11707c478bd9Sstevel@tonic-gate goto out;
11717c478bd9Sstevel@tonic-gate }
11727c478bd9Sstevel@tonic-gate
11737c478bd9Sstevel@tonic-gate if (scf_value_set_astring(v, value) == -1) {
11747c478bd9Sstevel@tonic-gate ret = -1;
11757c478bd9Sstevel@tonic-gate goto out;
11767c478bd9Sstevel@tonic-gate }
11777c478bd9Sstevel@tonic-gate
11787c478bd9Sstevel@tonic-gate if (scf_entry_add_value(ent, v) == -1) {
11797c478bd9Sstevel@tonic-gate ret = -1;
11807c478bd9Sstevel@tonic-gate goto out;
11817c478bd9Sstevel@tonic-gate }
11827c478bd9Sstevel@tonic-gate
11837c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(tx);
11847c478bd9Sstevel@tonic-gate
11857c478bd9Sstevel@tonic-gate if (ret == 0) {
11867c478bd9Sstevel@tonic-gate /* Property group was stale, retry */
11877c478bd9Sstevel@tonic-gate if (scf_pg_update(gpg) == -1) {
11887c478bd9Sstevel@tonic-gate ret = -1;
11897c478bd9Sstevel@tonic-gate goto out;
11907c478bd9Sstevel@tonic-gate }
11917c478bd9Sstevel@tonic-gate scf_transaction_reset(tx);
11927c478bd9Sstevel@tonic-gate }
11937c478bd9Sstevel@tonic-gate
11947c478bd9Sstevel@tonic-gate } while (ret == 0);
11957c478bd9Sstevel@tonic-gate out:
11967c478bd9Sstevel@tonic-gate scf_value_destroy(v);
11977c478bd9Sstevel@tonic-gate scf_entry_destroy(ent);
11987c478bd9Sstevel@tonic-gate scf_transaction_destroy(tx);
11997c478bd9Sstevel@tonic-gate scf_property_destroy(eprop);
12007c478bd9Sstevel@tonic-gate scf_service_destroy(svc);
12017c478bd9Sstevel@tonic-gate scf_pg_destroy(gpg);
12027c478bd9Sstevel@tonic-gate
12037c478bd9Sstevel@tonic-gate return (ret);
12047c478bd9Sstevel@tonic-gate }
12057c478bd9Sstevel@tonic-gate
12067c478bd9Sstevel@tonic-gate /*
12077c478bd9Sstevel@tonic-gate * list_callback is the callback function to be handed to simple_walk_instances
12087c478bd9Sstevel@tonic-gate * in main. It is called once on every instance on a machine. If that
12097c478bd9Sstevel@tonic-gate * instance is controlled by inetd, we test whether it's the same
12107c478bd9Sstevel@tonic-gate * service that we're looking at from the inetd.conf file, and enable it if
12117c478bd9Sstevel@tonic-gate * they are the same.
12127c478bd9Sstevel@tonic-gate */
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12157c478bd9Sstevel@tonic-gate static int
list_callback(scf_handle_t * h,scf_instance_t * inst,void * buf)12167c478bd9Sstevel@tonic-gate list_callback(scf_handle_t *h, scf_instance_t *inst, void *buf)
12177c478bd9Sstevel@tonic-gate {
12187c478bd9Sstevel@tonic-gate ssize_t max_name_length;
12197c478bd9Sstevel@tonic-gate char *svc_name;
12207c478bd9Sstevel@tonic-gate scf_simple_prop_t *prop = NULL;
12217c478bd9Sstevel@tonic-gate scf_simple_prop_t *sockprop = NULL;
12227c478bd9Sstevel@tonic-gate scf_simple_prop_t *rpcprop = NULL;
12237c478bd9Sstevel@tonic-gate scf_simple_prop_t *progprop = NULL;
12247c478bd9Sstevel@tonic-gate const char *name, *endpoint, *restart_str, *prog;
12257c478bd9Sstevel@tonic-gate struct inetconfent *iconf = (struct inetconfent *)buf;
12267c478bd9Sstevel@tonic-gate uint8_t *isrpc;
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate max_name_length = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
12297c478bd9Sstevel@tonic-gate if ((svc_name = malloc(max_name_length + 1)) == NULL) {
12307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error: Out of memory.\n"));
12317c478bd9Sstevel@tonic-gate return (SCF_FAILED);
12327c478bd9Sstevel@tonic-gate }
12337c478bd9Sstevel@tonic-gate
12347c478bd9Sstevel@tonic-gate /*
12357c478bd9Sstevel@tonic-gate * Get the FMRI of the instance, and check if its delegated restarter
12367c478bd9Sstevel@tonic-gate * is inetd. A missing or empty restarter property implies that
12377c478bd9Sstevel@tonic-gate * svc.startd is the restarter.
12387c478bd9Sstevel@tonic-gate */
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate if (scf_instance_to_fmri(inst, svc_name, max_name_length) < 0) {
12417c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
12427c478bd9Sstevel@tonic-gate gettext("Error: Unable to obtain FMRI for service %1$s."),
12437c478bd9Sstevel@tonic-gate svc_name);
12447c478bd9Sstevel@tonic-gate free(svc_name);
12457c478bd9Sstevel@tonic-gate return (SCF_FAILED);
12467c478bd9Sstevel@tonic-gate }
12477c478bd9Sstevel@tonic-gate
12487c478bd9Sstevel@tonic-gate if ((prop = scf_simple_prop_get(h, svc_name, SCF_PG_GENERAL,
12497c478bd9Sstevel@tonic-gate SCF_PROPERTY_RESTARTER)) == NULL)
12507c478bd9Sstevel@tonic-gate goto out;
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate if ((restart_str = scf_simple_prop_next_ustring(prop)) == NULL)
12537c478bd9Sstevel@tonic-gate goto out;
12547c478bd9Sstevel@tonic-gate
12557c478bd9Sstevel@tonic-gate if (strcmp(restart_str, INETD_INSTANCE_FMRI) != 0)
12567c478bd9Sstevel@tonic-gate goto out;
12577c478bd9Sstevel@tonic-gate
12587c478bd9Sstevel@tonic-gate /* Free restarter prop so it can be reused below */
12597c478bd9Sstevel@tonic-gate scf_simple_prop_free(prop);
12607c478bd9Sstevel@tonic-gate
12617c478bd9Sstevel@tonic-gate /*
12627c478bd9Sstevel@tonic-gate * We know that this instance is managed by inetd.
12637c478bd9Sstevel@tonic-gate * Now get the properties needed to decide if it matches this
12647c478bd9Sstevel@tonic-gate * line in the old config file.
12657c478bd9Sstevel@tonic-gate */
12667c478bd9Sstevel@tonic-gate
12677c478bd9Sstevel@tonic-gate if (((prop = scf_simple_prop_get(h, svc_name, PG_NAME_SERVICE_CONFIG,
12687c478bd9Sstevel@tonic-gate PR_SVC_NAME_NAME)) == NULL) ||
12697c478bd9Sstevel@tonic-gate ((name = scf_simple_prop_next_astring(prop)) == NULL)) {
12707c478bd9Sstevel@tonic-gate property_error(svc_name, PR_SVC_NAME_NAME);
12717c478bd9Sstevel@tonic-gate goto out;
12727c478bd9Sstevel@tonic-gate }
12737c478bd9Sstevel@tonic-gate
12747c478bd9Sstevel@tonic-gate if (((sockprop = scf_simple_prop_get(h, svc_name,
12757c478bd9Sstevel@tonic-gate PG_NAME_SERVICE_CONFIG, PR_SOCK_TYPE_NAME)) == NULL) ||
12767c478bd9Sstevel@tonic-gate ((endpoint = scf_simple_prop_next_astring(sockprop)) == NULL)) {
12777c478bd9Sstevel@tonic-gate property_error(svc_name, PR_SOCK_TYPE_NAME);
12787c478bd9Sstevel@tonic-gate goto out;
12797c478bd9Sstevel@tonic-gate }
12807c478bd9Sstevel@tonic-gate
12817c478bd9Sstevel@tonic-gate if (((rpcprop = scf_simple_prop_get(h, svc_name,
12827c478bd9Sstevel@tonic-gate PG_NAME_SERVICE_CONFIG, PR_ISRPC_NAME)) == NULL) ||
12837c478bd9Sstevel@tonic-gate ((isrpc = scf_simple_prop_next_boolean(rpcprop)) == NULL)) {
12847c478bd9Sstevel@tonic-gate property_error(svc_name, PR_ISRPC_NAME);
12857c478bd9Sstevel@tonic-gate goto out;
12867c478bd9Sstevel@tonic-gate }
12877c478bd9Sstevel@tonic-gate
12887c478bd9Sstevel@tonic-gate if (((progprop = scf_simple_prop_get(h, svc_name, START_METHOD_NAME,
12897c478bd9Sstevel@tonic-gate PR_EXEC_NAME)) == NULL) ||
12907c478bd9Sstevel@tonic-gate ((prog = scf_simple_prop_next_astring(progprop)) == NULL)) {
12917c478bd9Sstevel@tonic-gate property_error(svc_name, PR_EXEC_NAME);
12927c478bd9Sstevel@tonic-gate }
12937c478bd9Sstevel@tonic-gate
12947c478bd9Sstevel@tonic-gate
12957c478bd9Sstevel@tonic-gate /* If it's RPC, we truncate off the version portion for comparison */
12967c478bd9Sstevel@tonic-gate if (*isrpc) {
12977c478bd9Sstevel@tonic-gate char *cp;
12987c478bd9Sstevel@tonic-gate
12997c478bd9Sstevel@tonic-gate cp = strchr(iconf->service, '/');
13007c478bd9Sstevel@tonic-gate if (cp != NULL)
13017c478bd9Sstevel@tonic-gate *cp = '\0';
13027c478bd9Sstevel@tonic-gate }
13037c478bd9Sstevel@tonic-gate
13047c478bd9Sstevel@tonic-gate /*
13057c478bd9Sstevel@tonic-gate * If name of this service and endpoint are equal to values from
13067c478bd9Sstevel@tonic-gate * iconf fields, and they're either both RPC or both non-RPC,
13077c478bd9Sstevel@tonic-gate * then we have a match; update the exec and arg0 properties if
13087c478bd9Sstevel@tonic-gate * necessary, then enable it.
13097c478bd9Sstevel@tonic-gate * We don't return an error if either operation fails so that we
13107c478bd9Sstevel@tonic-gate * continue to try all the other services.
13117c478bd9Sstevel@tonic-gate */
13127c478bd9Sstevel@tonic-gate if (strcmp(name, iconf->service) == 0 &&
13137c478bd9Sstevel@tonic-gate strcmp(endpoint, iconf->endpoint) == 0 &&
13147c478bd9Sstevel@tonic-gate *isrpc == (strncmp(iconf->protocol, "rpc/", 4) == 0)) {
13157c478bd9Sstevel@tonic-gate /* Can't update exec on internal services */
13167c478bd9Sstevel@tonic-gate if ((strcmp(iconf->server_program, "internal") != 0) &&
13177c478bd9Sstevel@tonic-gate (strcmp(iconf->exec, prog) != 0)) {
13187c478bd9Sstevel@tonic-gate /* User had edited the command */
13197c478bd9Sstevel@tonic-gate if (!import) {
13207c478bd9Sstevel@tonic-gate /* Dry run only */
13217c478bd9Sstevel@tonic-gate (void) printf(
13227c478bd9Sstevel@tonic-gate gettext("Would update %s to %s %s"),
13237c478bd9Sstevel@tonic-gate svc_name, PR_EXEC_NAME, iconf->exec);
13247c478bd9Sstevel@tonic-gate if (iconf->arg0 != NULL) {
13257c478bd9Sstevel@tonic-gate (void) printf(
13267c478bd9Sstevel@tonic-gate gettext(" with %s of %s\n"),
13277c478bd9Sstevel@tonic-gate PR_ARG0_NAME, iconf->arg0);
13287c478bd9Sstevel@tonic-gate } else {
13297c478bd9Sstevel@tonic-gate (void) printf("\n");
13307c478bd9Sstevel@tonic-gate }
13317c478bd9Sstevel@tonic-gate } else {
13327c478bd9Sstevel@tonic-gate /* Update instance's exec property */
13337c478bd9Sstevel@tonic-gate if (modify_sprop(h, inst, START_METHOD_NAME,
13347c478bd9Sstevel@tonic-gate PR_EXEC_NAME, iconf->exec) != 1)
13357c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
13367c478bd9Sstevel@tonic-gate gettext("Error: Unable to update "
13377c478bd9Sstevel@tonic-gate "%s property of %s, %s\n"),
13387c478bd9Sstevel@tonic-gate PR_EXEC_NAME, svc_name,
13397c478bd9Sstevel@tonic-gate scf_strerror(scf_error()));
13407c478bd9Sstevel@tonic-gate else
13417c478bd9Sstevel@tonic-gate (void) printf("%s will %s %s\n",
13427c478bd9Sstevel@tonic-gate svc_name, PR_EXEC_NAME,
13437c478bd9Sstevel@tonic-gate iconf->exec);
13447c478bd9Sstevel@tonic-gate
13457c478bd9Sstevel@tonic-gate /* Update arg0 prop, if needed */
13467c478bd9Sstevel@tonic-gate if (iconf->arg0 != NULL) {
13477c478bd9Sstevel@tonic-gate if (modify_sprop(h, inst,
13487c478bd9Sstevel@tonic-gate START_METHOD_NAME, PR_ARG0_NAME,
13497c478bd9Sstevel@tonic-gate iconf->arg0) != 1) {
13507c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
13517c478bd9Sstevel@tonic-gate gettext("Error: Unable to "
13527c478bd9Sstevel@tonic-gate "update %s property of "
13537c478bd9Sstevel@tonic-gate "%s, %s\n"), PR_ARG0_NAME,
13547c478bd9Sstevel@tonic-gate svc_name,
13557c478bd9Sstevel@tonic-gate scf_strerror(scf_error()));
13567c478bd9Sstevel@tonic-gate } else {
13577c478bd9Sstevel@tonic-gate (void) printf("%s will have an "
13587c478bd9Sstevel@tonic-gate "%s of %s\n", svc_name,
13597c478bd9Sstevel@tonic-gate PR_ARG0_NAME, iconf->arg0);
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate }
13627c478bd9Sstevel@tonic-gate }
13637c478bd9Sstevel@tonic-gate }
13647c478bd9Sstevel@tonic-gate
13657c478bd9Sstevel@tonic-gate if (!import) {
13667c478bd9Sstevel@tonic-gate /* Dry-run only */
13677c478bd9Sstevel@tonic-gate (void) printf("Would enable %s\n", svc_name);
13687c478bd9Sstevel@tonic-gate } else {
13697c478bd9Sstevel@tonic-gate if (smf_enable_instance(svc_name, 0) != 0)
13707c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
13717c478bd9Sstevel@tonic-gate gettext("Error: Failed to enable %s\n"),
13727c478bd9Sstevel@tonic-gate svc_name);
13737c478bd9Sstevel@tonic-gate else
13747c478bd9Sstevel@tonic-gate (void) printf("%s enabled\n", svc_name);
13757c478bd9Sstevel@tonic-gate }
13767c478bd9Sstevel@tonic-gate }
13777c478bd9Sstevel@tonic-gate
13787c478bd9Sstevel@tonic-gate out:
13797c478bd9Sstevel@tonic-gate free(svc_name);
13807c478bd9Sstevel@tonic-gate scf_simple_prop_free(prop);
13817c478bd9Sstevel@tonic-gate scf_simple_prop_free(sockprop);
13827c478bd9Sstevel@tonic-gate scf_simple_prop_free(rpcprop);
13837c478bd9Sstevel@tonic-gate scf_simple_prop_free(progprop);
13847c478bd9Sstevel@tonic-gate return (SCF_SUCCESS);
13857c478bd9Sstevel@tonic-gate }
13867c478bd9Sstevel@tonic-gate
13877c478bd9Sstevel@tonic-gate static void
usage(void)13887c478bd9Sstevel@tonic-gate usage(void)
13897c478bd9Sstevel@tonic-gate {
13907c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
13917c478bd9Sstevel@tonic-gate "Usage: %s [-fn] [-i srcfile] [-o destdir]\n"
13927c478bd9Sstevel@tonic-gate " %1$s -e [-n] [-i srcfile]\n"
13937c478bd9Sstevel@tonic-gate "-? Display this usage message\n"
13947c478bd9Sstevel@tonic-gate "-e Enable smf services which are enabled in the input\n"
13957c478bd9Sstevel@tonic-gate " file\n"
13967c478bd9Sstevel@tonic-gate "-f Force overwrite of existing manifests\n"
13977c478bd9Sstevel@tonic-gate "-n Do not import converted manifests,\n"
13987c478bd9Sstevel@tonic-gate " or only display services which would be enabled\n"
13997c478bd9Sstevel@tonic-gate "-i srcfile Alternate input file\n"
14007c478bd9Sstevel@tonic-gate "-o destdir Alternate output directory for manifests\n"),
14017c478bd9Sstevel@tonic-gate progname);
14027c478bd9Sstevel@tonic-gate exit(EXIT_USAGE);
14037c478bd9Sstevel@tonic-gate }
14047c478bd9Sstevel@tonic-gate
14057c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])14067c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
14077c478bd9Sstevel@tonic-gate {
14087c478bd9Sstevel@tonic-gate int c, rval, convert_err, import_err = 0, enable_err = 0;
14097c478bd9Sstevel@tonic-gate boolean_t overwrite = B_FALSE;
14107c478bd9Sstevel@tonic-gate boolean_t enable = B_FALSE;
14117c478bd9Sstevel@tonic-gate char *srcfile = NULL;
14127c478bd9Sstevel@tonic-gate char *destdir = NULL;
14137c478bd9Sstevel@tonic-gate struct fileinfo *srcfinfo, *dstfinfo;
14147c478bd9Sstevel@tonic-gate struct inetconfent *iconf;
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate setbuf(stdout, NULL);
14177c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
14187c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
14197c478bd9Sstevel@tonic-gate
14207c478bd9Sstevel@tonic-gate if ((progname = strrchr(argv[0], '/')) == NULL)
14217c478bd9Sstevel@tonic-gate progname = argv[0];
14227c478bd9Sstevel@tonic-gate else
14237c478bd9Sstevel@tonic-gate progname++;
14247c478bd9Sstevel@tonic-gate
14257c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "?efni:o:")) != -1) {
14267c478bd9Sstevel@tonic-gate switch (c) {
14277c478bd9Sstevel@tonic-gate case 'e':
14287c478bd9Sstevel@tonic-gate /* enable services based on existing file config */
14297c478bd9Sstevel@tonic-gate enable = B_TRUE;
14307c478bd9Sstevel@tonic-gate break;
14317c478bd9Sstevel@tonic-gate
14327c478bd9Sstevel@tonic-gate case 'f':
14337c478bd9Sstevel@tonic-gate /* overwrite existing manifests */
14347c478bd9Sstevel@tonic-gate overwrite = B_TRUE;
14357c478bd9Sstevel@tonic-gate break;
14367c478bd9Sstevel@tonic-gate case 'n':
14377c478bd9Sstevel@tonic-gate /* don't import manifests, or dry-run enable */
14387c478bd9Sstevel@tonic-gate import = B_FALSE;
14397c478bd9Sstevel@tonic-gate break;
14407c478bd9Sstevel@tonic-gate case 'i':
14417c478bd9Sstevel@tonic-gate /* alternate input file */
14427c478bd9Sstevel@tonic-gate if (srcfile != NULL) {
14437c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
14447c478bd9Sstevel@tonic-gate gettext("%s: Error only one -%c allowed\n"),
14457c478bd9Sstevel@tonic-gate progname, optopt);
14467c478bd9Sstevel@tonic-gate usage();
14477c478bd9Sstevel@tonic-gate }
14487c478bd9Sstevel@tonic-gate srcfile = optarg;
14497c478bd9Sstevel@tonic-gate break;
14507c478bd9Sstevel@tonic-gate case 'o':
14517c478bd9Sstevel@tonic-gate /* alternate output directory */
14527c478bd9Sstevel@tonic-gate if (destdir != NULL) {
14537c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
14547c478bd9Sstevel@tonic-gate gettext("%s: Error only one -%c allowed\n"),
14557c478bd9Sstevel@tonic-gate progname, optopt);
14567c478bd9Sstevel@tonic-gate usage();
14577c478bd9Sstevel@tonic-gate }
14587c478bd9Sstevel@tonic-gate destdir = optarg;
14597c478bd9Sstevel@tonic-gate break;
14607c478bd9Sstevel@tonic-gate case '?': /*FALLTHROUGH*/
14617c478bd9Sstevel@tonic-gate default:
14627c478bd9Sstevel@tonic-gate usage();
14637c478bd9Sstevel@tonic-gate break;
14647c478bd9Sstevel@tonic-gate }
14657c478bd9Sstevel@tonic-gate }
14667c478bd9Sstevel@tonic-gate
14677c478bd9Sstevel@tonic-gate /*
14687c478bd9Sstevel@tonic-gate * Display usage if extraneous args supplied or enable specified in
14697c478bd9Sstevel@tonic-gate * combination with overwrite or destdir
14707c478bd9Sstevel@tonic-gate */
14717c478bd9Sstevel@tonic-gate if ((optind != argc) || (enable && (overwrite || destdir != NULL)))
14727c478bd9Sstevel@tonic-gate usage();
14737c478bd9Sstevel@tonic-gate
14747c478bd9Sstevel@tonic-gate if ((srcfinfo = open_srcfile(srcfile)) == NULL)
14757c478bd9Sstevel@tonic-gate return (EXIT_ERROR_CONV);
14767c478bd9Sstevel@tonic-gate
14777c478bd9Sstevel@tonic-gate while ((iconf = fgetinetconfent(srcfinfo, !enable)) != NULL) {
14787c478bd9Sstevel@tonic-gate /*
14797c478bd9Sstevel@tonic-gate * If we're enabling, then just walk all the services for each
14807c478bd9Sstevel@tonic-gate * line and enable those which match.
14817c478bd9Sstevel@tonic-gate */
14827c478bd9Sstevel@tonic-gate if (enable) {
14837c478bd9Sstevel@tonic-gate rval = scf_simple_walk_instances(SCF_STATE_ALL, iconf,
14847c478bd9Sstevel@tonic-gate list_callback);
14857c478bd9Sstevel@tonic-gate free_inetconfent(iconf);
14867c478bd9Sstevel@tonic-gate if (rval == SCF_FAILED) {
14877c478bd9Sstevel@tonic-gate /* Only print msg if framework error */
14887c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_CALLBACK_FAILED)
14897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
14907c478bd9Sstevel@tonic-gate "Error walking instances: %s.\n"),
14917c478bd9Sstevel@tonic-gate scf_strerror(scf_error()));
14927c478bd9Sstevel@tonic-gate enable_err++;
14937c478bd9Sstevel@tonic-gate break;
14947c478bd9Sstevel@tonic-gate }
14957c478bd9Sstevel@tonic-gate continue;
14967c478bd9Sstevel@tonic-gate }
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate /* Remainder of loop used for conversion & import */
14997c478bd9Sstevel@tonic-gate if ((rval = open_dstfile(destdir, overwrite, iconf, &dstfinfo))
15007c478bd9Sstevel@tonic-gate < 0) {
15017c478bd9Sstevel@tonic-gate /*
15027c478bd9Sstevel@tonic-gate * Only increment error counter if the failure was
15037c478bd9Sstevel@tonic-gate * other than the file already existing.
15047c478bd9Sstevel@tonic-gate */
15057c478bd9Sstevel@tonic-gate if (rval == -2)
15067c478bd9Sstevel@tonic-gate srcfinfo->failcnt++;
15077c478bd9Sstevel@tonic-gate free_inetconfent(iconf);
15087c478bd9Sstevel@tonic-gate continue;
15097c478bd9Sstevel@tonic-gate }
15107c478bd9Sstevel@tonic-gate rval = print_manifest(dstfinfo->fp, dstfinfo->filename, iconf);
15117c478bd9Sstevel@tonic-gate (void) fclose(dstfinfo->fp);
15127c478bd9Sstevel@tonic-gate if (rval == 0) {
15137c478bd9Sstevel@tonic-gate if (import &&
15147c478bd9Sstevel@tonic-gate (import_manifest(dstfinfo->filename) != 0))
15157c478bd9Sstevel@tonic-gate import_err++;
15167c478bd9Sstevel@tonic-gate } else {
15177c478bd9Sstevel@tonic-gate (void) unlink(dstfinfo->filename);
15187c478bd9Sstevel@tonic-gate srcfinfo->failcnt++;
15197c478bd9Sstevel@tonic-gate }
15207c478bd9Sstevel@tonic-gate free(dstfinfo->filename);
15217c478bd9Sstevel@tonic-gate free(dstfinfo);
15227c478bd9Sstevel@tonic-gate free_inetconfent(iconf);
15237c478bd9Sstevel@tonic-gate }
15247c478bd9Sstevel@tonic-gate (void) fclose(srcfinfo->fp);
15257c478bd9Sstevel@tonic-gate convert_err = srcfinfo->failcnt;
15267c478bd9Sstevel@tonic-gate
15277c478bd9Sstevel@tonic-gate /* Update hash only if not in enable mode, and only if importing */
15287c478bd9Sstevel@tonic-gate if (!enable && import && (update_hash(srcfinfo->filename) != 0))
15297c478bd9Sstevel@tonic-gate import_err++;
15307c478bd9Sstevel@tonic-gate
15317c478bd9Sstevel@tonic-gate free(srcfinfo);
15327c478bd9Sstevel@tonic-gate
15337c478bd9Sstevel@tonic-gate if (enable_err != 0)
15347c478bd9Sstevel@tonic-gate return (EXIT_ERROR_ENBL);
15357c478bd9Sstevel@tonic-gate if (import_err != 0)
15367c478bd9Sstevel@tonic-gate return (EXIT_ERROR_IMP);
15377c478bd9Sstevel@tonic-gate if (convert_err != 0)
15387c478bd9Sstevel@tonic-gate return (EXIT_ERROR_CONV);
15397c478bd9Sstevel@tonic-gate return (EXIT_SUCCESS);
15407c478bd9Sstevel@tonic-gate }
1541