usr/src/cmd/auto-install/auto_ddu_lib.c
changeset 869 424db5e50fb5
parent 867 cfbbedf29419
child 870 1cd031050724
equal deleted inserted replaced
868:ccab1050a371 869:424db5e50fb5
    37 
    37 
    38 /* Python DDU package module related definitions. */
    38 /* Python DDU package module related definitions. */
    39 #define	DDU_PACKAGE_MODULE	"DDU.ddu_package"
    39 #define	DDU_PACKAGE_MODULE	"DDU.ddu_package"
    40 #define	DDU_PACKAGE_OBJECT	"ddu_package_object"
    40 #define	DDU_PACKAGE_OBJECT	"ddu_package_object"
    41 
    41 
    42 /* Pkg commands. */
       
    43 #define	PKG_PUBLISHER		"/usr/bin/pkg publisher"
       
    44 
       
    45 /* DDU error log */
    42 /* DDU error log */
    46 #define	DDU_ERRLOG		"/tmp/ddu_err.log"
    43 #define	DDU_ERRLOG		"/tmp/ddu_err.log"
    47 
       
    48 /*  DDU error module related. */
       
    49 #define	DDU_ERROR_MODULE		"DDU.ddu_errors"
       
    50 #define	DDU_PACKAGE_NOT_FOUND_EXC	"PackageNoFound"
       
    51 
    44 
    52 /* ICT module related definitions. */
    45 /* ICT module related definitions. */
    53 #define	ICT_MODULE		"osol_install.ict"
    46 #define	ICT_MODULE		"osol_install.ict"
    54 #define	ICT_CLASS		"ICT"
    47 #define	ICT_CLASS		"ICT"
    55 #define	ICT_UPDATE_ARCHIVE	"update_boot_archive"
    48 #define	ICT_UPDATE_ARCHIVE	"update_boot_archive"
    56 
    49 
    57 /* AI Manifest (AIM) related path definitions. */
    50 /* AI Manifest (AIM) related path definitions. */
    58 #define	AIM_PREFACE		"auto_install/ai_instance/add_drivers/"
    51 #define	AIM_PREFACE		    "auto_install/ai_instance/add_drivers/"
    59 #define	PKGSPEC_NODEPATH	"software"
    52 #define	PKGSPEC_NODEPATH	"software"
    60 #define	ORIGIN_NODEPATH		"software/source/publisher/origin/name"
    53 #define	ORIGIN_NODEPATH		"software/source/publisher/origin/name"
    61 #define	TYPE_NODEPATH		"software[source/publisher/origin/" \
    54 #define	TYPE_NODEPATH \
    62 				    "name=\"%s\"]/software_data/type"
    55 	"software[source/publisher/origin/name=\"%s\"]/software_data/type"
    63 #define	NAME_NODEPATH		"software[source/publisher/origin/" \
    56 #define	NAME_NODEPATH \
    64 				    "name=\"%s\":software_data/" \
    57 	"software[source/publisher/origin/name=\"%s\":software_data/type=\"%s\"]/software_data/name"
    65 				    "type=\"%s\"]/software_data/name"
       
    66 #define	ACTION_NONAME_NODEPATH \
    58 #define	ACTION_NONAME_NODEPATH \
    67 				"software[source/publisher/origin/" \
    59 	"software[source/publisher/origin/name=\"%s\":software_data/type=\"%s\"]/software_data/action"
    68 				    "name=\"%s\":software_data/" \
       
    69 				    "type=\"%s\"]/software_data/action"
       
    70 #define	ACTION_YESNAME_NODEPATH \
    60 #define	ACTION_YESNAME_NODEPATH \
    71 				"software[source/publisher/origin/" \
    61 	"software[source/publisher/origin/name=\"%s\":software_data/type=\"%s\":software_data/name=\"%s\"]/software_data/action"
    72 				    "name=\"%s\":software_data/type=\"%s\":" \
       
    73 				    "software_data/name=\"%s\"]/" \
       
    74 				    "software_data/action"
       
    75 
    62 
    76 #define	SEARCH_NODEPATH		"search_all"
    63 #define	SEARCH_NODEPATH		"search_all"
    77 #define	SEARCH_ORIGIN_NODEPATH	"search_all/source/publisher/origin/name"
    64 #define	SEARCH_ORIGIN_NODEPATH	"search_all/source/publisher/origin/name"
    78 #define	SEARCH_PUBNAME_NODEPATH	"search_all/source/publisher/name"
    65 #define	SEARCH_PUBNAME_NODEPATH	"search_all/source/publisher/name"
    79 #define	SEARCH_ADDALL_NODEPATH	"search_all/addall"
    66 #define	SEARCH_ADDALL_NODEPATH	"search_all/addall"
    83 typedef struct {
    70 typedef struct {
    84 	PyThreadState *myThreadState;
    71 	PyThreadState *myThreadState;
    85 	PyThreadState *mainThreadState;
    72 	PyThreadState *mainThreadState;
    86 	PyObject *pFunctionModule;
    73 	PyObject *pFunctionModule;
    87 	PyObject *pPackageModule;
    74 	PyObject *pPackageModule;
    88 	PyObject *pErrorModule;
       
    89 	PyObject *pICTModule;
    75 	PyObject *pICTModule;
    90 } py_state_t;
    76 } py_state_t;
    91 
    77 
    92 typedef struct {
    78 typedef struct {
    93 	char path_str[MAX_NODEPATH_SIZE];
    79 	char path_str[MAX_NODEPATH_SIZE];
    95 	int post_prefix_len;
    81 	int post_prefix_len;
    96 } path_t;
    82 } path_t;
    97 
    83 
    98 static py_state_t *auto_ddu_lib_init();
    84 static py_state_t *auto_ddu_lib_init();
    99 static void auto_ddu_lib_fini(py_state_t *py_state_p);
    85 static void auto_ddu_lib_fini(py_state_t *py_state_p);
   100 static void ai_dump_python_exception();
       
   101 static PyObject *ai_call_ddu_devscan(py_state_t *py_state_p,
    86 static PyObject *ai_call_ddu_devscan(py_state_t *py_state_p,
   102     boolean_t get_only_missing_drivers, char *dev_type);
    87     boolean_t get_only_missing_drivers, char *dev_type);
   103 static int ai_call_ddu_package_lookup(py_state_t *py_state_p,
    88 static PyObject *ai_call_ddu_package_lookup(py_state_t *py_state_p,
   104     PyObject *pDevObj, PyObject *pRepoList, PyObject **pPackageObj_p);
    89     PyObject *pDevObj, PyObject *pRepoList);
   105 static int ai_call_ddu_install_package(py_state_t *py_state_p,
    90 static int ai_call_ddu_install_package(py_state_t *py_state_p,
   106     PyObject *ddu_package_obj, char *install_root, boolean_t third_party_ok);
    91     PyObject *ddu_package_obj, char *install_root, boolean_t third_party_ok);
   107 static PyObject *ai_new_ddu_package_object(py_state_t *py_state_p,
    92 static PyObject *ai_new_ddu_package_object(py_state_t *py_state_p,
   108     char *type, char *name, char *origin);
    93     char *type, char *name, char *origin);
   109 static int ai_get_ddu_package_object_values(PyObject *pDDUPackageObject,
    94 static int ai_get_ddu_package_object_values(PyObject *pDDUPackageObject,
   110     char **type, char **location, char **name, char **descr, char **inf_link,
    95     char **type, char **origin, char **name, char **descr, char **inf_link,
   111     boolean_t *third_party);
    96     boolean_t *third_party);
   112 static int ai_get_ddu_dev_data_values(PyObject *pDDUDevData,
    97 static int ai_get_ddu_dev_data_values(PyObject *pDDUDevData,
   113     char **dev_type_p, char **descr_p, char **vendor_ID_p, char **device_ID_p,
    98     char **dev_type, char **descr);
   114     char **class_p);
    99 static void ai_du_process_manual_pkg(py_state_t *py_state_p,
   115 static int ai_du_process_manual_pkg(py_state_t *py_state_p,
       
   116     PyObject *pPackageList, char *origin, char *type, char *name,
   100     PyObject *pPackageList, char *origin, char *type, char *name,
   117     char *noinstall);
   101     char *noinstall);
   118 static int ai_du_process_manual_pkg_names(py_state_t *py_state_p,
   102 static void ai_du_process_manual_pkg_names(py_state_t *py_state_p,
   119     path_t *path_p, PyObject *pPackageList, char *origin, char *type,
   103     PyObject *pPackageList, path_t *path_p, char *origin, char *type,
   120     char *name);
   104     char *name);
   121 static int ai_du_process_manual_pkg_types(py_state_t *py_state_p,
   105 static void ai_du_process_manual_pkg_types(py_state_t *py_state_p,
   122     PyObject *pPackageList, path_t *path_p, char *origin, char *type);
   106     PyObject *pPackageList, path_t *path_p, char *origin, char *type);
   123 static int ai_du_get_manual_pkg_list(py_state_t *py_state_p, path_t *path_p,
   107 static PyObject *ai_du_get_manual_pkg_list(py_state_t *py_state_p,
   124     PyObject **pPackageList_p);
   108     path_t *path_p);
   125 static int ai_du_get_searched_pkg_list(py_state_t *py_state_p, path_t *path_p,
   109 static PyObject *ai_du_get_searched_pkg_list(py_state_t *py_state_p,
   126     char *install_root, PyObject **pPackageList_p);
   110     path_t *path_p);
   127 static int ai_du_install_packages(py_state_t *py_state_p,
   111 static int ai_du_install_packages(py_state_t *py_state_p,
   128     PyObject *pPkgTupleList, char *install_root, boolean_t honor_noinstall,
   112     PyObject *pPkgTupleList, char *install_root, boolean_t honor_noinstall,
   129     int *num_installed_pkgs_p);
   113     int *num_installed_pkgs_p);
   130 static char **ai_uniq_manifest_values(char **in, int *len_p);
   114 static char **ai_uniq_manifest_values(char **in, int *len_p);
   131 static int ai_du_call_update_archive_ict(py_state_t *py_state_p,
   115 static int ai_du_call_update_archive_ict(py_state_t *py_state_p,
   156  * function, to undo the effects of this function.
   140  * function, to undo the effects of this function.
   157  */
   141  */
   158 static py_state_t *
   142 static py_state_t *
   159 auto_ddu_lib_init()
   143 auto_ddu_lib_init()
   160 {
   144 {
       
   145 	PyObject *pName;
   161 	py_state_t *py_state_p = malloc(sizeof (py_state_t));
   146 	py_state_t *py_state_p = malloc(sizeof (py_state_t));
   162 
   147 
   163 	static PyObject *pFunctionModule = NULL;
   148 	py_state_p->pFunctionModule = NULL;
   164 	static PyObject *pPackageModule = NULL;
   149 	py_state_p->pPackageModule = NULL;
   165 	static PyObject *pErrorModule = NULL;
       
   166 	static PyObject *pICTModule = NULL;
       
   167 
       
   168 	if (py_state_p == NULL) {
       
   169 		auto_debug_print(AUTO_DBGLVL_ERR, "auto_ddu_lib_init: "
       
   170 		    "No memory.\n");
       
   171 		return (NULL);
       
   172 	}
       
   173 
       
   174 	/* If one of the above is NULL, all will be NULL. */
       
   175 	if (pFunctionModule == NULL) {
       
   176 		PyObject *pName;
       
   177 
       
   178 		/* Get names of modules for use by python/C interfaces. */
       
   179 		if ((pName = PyString_FromString(DDU_FUNCTION_MODULE)) !=
       
   180 		    NULL) {
       
   181 			pFunctionModule = PyImport_Import(pName);
       
   182 			Py_DECREF(pName);
       
   183 		}
       
   184 		if ((pName = PyString_FromString(DDU_PACKAGE_MODULE)) != NULL) {
       
   185 			pPackageModule = PyImport_Import(pName);
       
   186 			Py_DECREF(pName);
       
   187 		}
       
   188 		if ((pName = PyString_FromString(DDU_ERROR_MODULE)) != NULL) {
       
   189 			pErrorModule = PyImport_Import(pName);
       
   190 			Py_DECREF(pName);
       
   191 		}
       
   192 		if ((pName = PyString_FromString(ICT_MODULE)) != NULL) {
       
   193 			pICTModule = PyImport_Import(pName);
       
   194 			Py_DECREF(pName);
       
   195 		}
       
   196 
       
   197 		/* Cleanup and return NULL on error. */
       
   198 		if ((pFunctionModule == NULL) || (pPackageModule == NULL) ||
       
   199 		    (pErrorModule == NULL) || (pICTModule == NULL)) {
       
   200 			auto_debug_print(AUTO_DBGLVL_ERR, "auto_ddu_lib_init: "
       
   201 			    "error accessing DDU library or ICT modules.\n");
       
   202 			PyErr_Print();
       
   203 			Py_XDECREF(pFunctionModule);
       
   204 			Py_XDECREF(pPackageModule);
       
   205 			Py_XDECREF(pErrorModule);
       
   206 			Py_XDECREF(pICTModule);
       
   207 			pFunctionModule = pPackageModule = NULL;
       
   208 			pErrorModule = pICTModule = NULL;
       
   209 			free(py_state_p);
       
   210 			return (NULL);
       
   211 		}
       
   212 	}
       
   213 
   150 
   214 	/* Set up python interpreter state. */
   151 	/* Set up python interpreter state. */
   215 	PyEval_InitThreads();
   152 	PyEval_InitThreads();
   216 	py_state_p->mainThreadState = PyThreadState_Get();
   153 	py_state_p->mainThreadState = PyThreadState_Get();
   217 	py_state_p->myThreadState =
   154 	py_state_p->myThreadState =
   218 	    PyThreadState_New(py_state_p->mainThreadState->interp);
   155 	    PyThreadState_New(py_state_p->mainThreadState->interp);
   219 	(void) PyThreadState_Swap(py_state_p->myThreadState);
   156 	PyThreadState_Swap(py_state_p->myThreadState);
   220 
   157 
   221 	py_state_p->pFunctionModule = pFunctionModule;
   158 	/* Get names of modules for use by python/C interfaces. */
   222 	py_state_p->pPackageModule = pPackageModule;
   159 	if ((pName = PyString_FromString(DDU_FUNCTION_MODULE)) != NULL) {
   223 	py_state_p->pErrorModule = pErrorModule;
   160 		py_state_p->pFunctionModule = PyImport_Import(pName);
   224 	py_state_p->pICTModule = pICTModule;
   161 		Py_DECREF(pName);
       
   162 	}
       
   163 	if ((pName = PyString_FromString(DDU_PACKAGE_MODULE)) != NULL) {
       
   164 		py_state_p->pPackageModule = PyImport_Import(pName);
       
   165 		Py_DECREF(pName);
       
   166 	}
       
   167 	if ((pName = PyString_FromString(ICT_MODULE)) != NULL) {
       
   168 		py_state_p->pICTModule = PyImport_Import(pName);
       
   169 		Py_DECREF(pName);
       
   170 	}
       
   171 
       
   172 	/* Cleanup and return NULL on error. */
       
   173 	if ((py_state_p->pFunctionModule == NULL) ||
       
   174 	    (py_state_p->pPackageModule == NULL) ||
       
   175 	    (py_state_p->pICTModule == NULL)) {
       
   176 		auto_debug_print(AUTO_DBGLVL_ERR, "auto_ddu_lib_init: "
       
   177 		    "error accessing DDU library or ICT modules.\n");
       
   178 		PyErr_Print();
       
   179 		auto_ddu_lib_fini(py_state_p);
       
   180 		py_state_p = NULL;
       
   181 	}
   225 
   182 
   226 	return (py_state_p);
   183 	return (py_state_p);
   227 }
   184 }
   228 
   185 
   229 /*
   186 /*
   239 auto_ddu_lib_fini(py_state_t *py_state_p)
   196 auto_ddu_lib_fini(py_state_t *py_state_p)
   240 {
   197 {
   241 	if (py_state_p == NULL) {
   198 	if (py_state_p == NULL) {
   242 		return;
   199 		return;
   243 	}
   200 	}
   244 	(void) PyThreadState_Swap(py_state_p->mainThreadState);
   201 	Py_XDECREF(py_state_p->pFunctionModule);
       
   202 	Py_XDECREF(py_state_p->pPackageModule);
       
   203 	Py_XDECREF(py_state_p->pICTModule);
       
   204 	PyThreadState_Swap(py_state_p->mainThreadState);
   245 	PyThreadState_Clear(py_state_p->myThreadState);
   205 	PyThreadState_Clear(py_state_p->myThreadState);
   246 	PyThreadState_Delete(py_state_p->myThreadState);
   206 	PyThreadState_Delete(py_state_p->myThreadState);
   247 	free(py_state_p);
   207 	free(py_state_p);
   248 }
       
   249 
       
   250 /*
       
   251  * ai_dump_python_exception:
       
   252  * Dump the class and message of a python exception.  Traceback not dumped.
       
   253  *
       
   254  * Caveat: An exception must be ready to be dumped, as indicated by
       
   255  * PyErr_Occurred() * returning Non-NULL.
       
   256  *
       
   257  * Arguments: None
       
   258  *
       
   259  * Returns: N/A
       
   260  */
       
   261 static void
       
   262 ai_dump_python_exception()
       
   263 {
       
   264 	PyObject *pType, *pValue, *pTraceback;
       
   265 	PyObject *pTypeString, *pValueString;
       
   266 
       
   267 	if (PyErr_Occurred() == NULL) {
       
   268 		return;
       
   269 	}
       
   270 
       
   271 	PyErr_Fetch(&pType, &pValue, &pTraceback);
       
   272 	pTypeString = PyObject_Str(pType);
       
   273 	pValueString = PyObject_Str(pValue);
       
   274 	auto_debug_print(AUTO_DBGLVL_ERR,
       
   275 	    "%s\n", PyString_AsString(pTypeString));
       
   276 	auto_debug_print(AUTO_DBGLVL_ERR,
       
   277 	    "%s\n", PyString_AsString(pValueString));
       
   278 	Py_DECREF(pType);
       
   279 	Py_DECREF(pValue);
       
   280 	Py_DECREF(pTraceback);
       
   281 	Py_DECREF(pTypeString);
       
   282 	Py_DECREF(pValueString);
       
   283 	PyErr_Clear();
       
   284 }
   208 }
   285 
   209 
   286 /*
   210 /*
   287  * ai_call_ddu_build_repo_list:
   211  * ai_call_ddu_build_repo_list:
   288  * Call the DDU library ddu_build_repo_list function.  This sets up the
   212  * Call the DDU library ddu_build_repo_list function.  This sets up the
   318 		 * can decrement the refcount when pArgs is DECREFed.
   242 		 * can decrement the refcount when pArgs is DECREFed.
   319 		 */
   243 		 */
   320 		Py_INCREF(pRepoTupleList);
   244 		Py_INCREF(pRepoTupleList);
   321 
   245 
   322 		/* Set up args to python function and call it. */
   246 		/* Set up args to python function and call it. */
   323 		(void) PyTuple_SetItem(pArgs, 0, pRepoTupleList);
   247 		PyTuple_SetItem(pArgs, 0, pRepoTupleList);
   324 		pRet = PyObject_CallObject(pFunc, pArgs);
   248 		pRet = PyObject_CallObject(pFunc, pArgs);
   325 		Py_DECREF(pArgs);
   249 		Py_DECREF(pArgs);
   326 
   250 
   327 		if ((PyErr_Occurred() != NULL) || (pRet == NULL) ||
   251 		if ((PyErr_Occurred()) || (pRet == NULL) || (pRet == Py_None)) {
   328 		    (pRet == Py_None)) {
       
   329 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
   252 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
   330 			auto_debug_print(AUTO_DBGLVL_ERR,
   253 			auto_debug_print(AUTO_DBGLVL_ERR,
   331 			    "%s returned an error.\n", DDU_BUILD_REPO_LIST);
   254 			    "%s returned an error.\n", DDU_BUILD_REPO_LIST);
   332 			ai_dump_python_exception();
   255 			if (PyErr_Occurred()) {
       
   256 				PyErr_Print();
       
   257 			}
   333 			Py_XDECREF(pRet);
   258 			Py_XDECREF(pRet);
   334 			pRet = NULL;
   259 			pRet = NULL;
   335 		}
   260 		}
   336 	}
   261 	}
   337 
   262 
   352  *	function for the list of device types.  "all" is an acceptable device
   277  *	function for the list of device types.  "all" is an acceptable device
   353  *	type.
   278  *	type.
   354  *
   279  *
   355  * Returns:
   280  * Returns:
   356  *   Success:
   281  *   Success:
   357  *	A python object representing a list of unique ddu_dev_data objects is
   282  *	A python object representing a list of ddu_dev_data objects is returned.
   358  *	returned.
       
   359  *	- NOTE: if no devices are missing drivers and get_only_missing_drivers
   283  *	- NOTE: if no devices are missing drivers and get_only_missing_drivers
   360  *	  is true, then an empty list is returned.
   284  *	  is true, then an empty list is returned.
   361  *	- A ddu_dev_data object represents a found device.
   285  *	- A ddu_dev_data object represents a found device.
   362  *   Failure:
   286  *   Failure:
   363  *	NULL
   287  *	NULL
   365 static PyObject *
   289 static PyObject *
   366 ai_call_ddu_devscan(py_state_t *py_state_p,
   290 ai_call_ddu_devscan(py_state_t *py_state_p,
   367     boolean_t get_only_missing_drivers, char *dev_type)
   291     boolean_t get_only_missing_drivers, char *dev_type)
   368 {
   292 {
   369 	PyObject *pRet = NULL;
   293 	PyObject *pRet = NULL;
   370 	PyObject *pList = NULL;
       
   371 	Py_ssize_t orig_listlen;
       
   372 	char **vids, **dids, **classes;
       
   373 	Py_ssize_t new_listused = 0;
       
   374 	Py_ssize_t i, j;
       
   375 
   294 
   376 	/* Find the function */
   295 	/* Find the function */
   377 	PyObject *pFunc = PyObject_GetAttrString(py_state_p->pFunctionModule,
   296 	PyObject *pFunc = PyObject_GetAttrString(py_state_p->pFunctionModule,
   378 	    DDU_DEVSCAN);
   297 	    DDU_DEVSCAN);
   379 
   298 
   380 	if ((pFunc == NULL) || (!PyCallable_Check(pFunc))) {
   299 	if ((pFunc == NULL) || (!PyCallable_Check(pFunc))) {
   381 		auto_debug_print(AUTO_DBGLVL_ERR,
   300 		auto_debug_print(AUTO_DBGLVL_ERR,
   382 		    "Function not callable: %s\n", DDU_DEVSCAN);
   301 		    "Function not callable: %s\n", DDU_DEVSCAN);
   383 		Py_XDECREF(pFunc);
       
   384 		return (NULL);
       
   385 	} else {
   302 	} else {
   386 		/* Set up args to python function and call it. */
   303 		/* Set up args to python function and call it. */
   387 		PyObject *pArgs = PyTuple_New(2);
   304 		PyObject *pArgs = PyTuple_New(2);
   388 		(void) PyTuple_SetItem(pArgs, 0,
   305 		PyTuple_SetItem(pArgs, 0,
   389 		    PyBool_FromLong((long)get_only_missing_drivers));
   306 		    PyBool_FromLong((long)get_only_missing_drivers));
   390 		(void) PyTuple_SetItem(pArgs, 1, PyString_FromString(dev_type));
   307 		PyTuple_SetItem(pArgs, 1, PyString_FromString(dev_type));
   391 		pList = PyObject_CallObject(pFunc, pArgs);
   308 		pRet = PyObject_CallObject(pFunc, pArgs);
   392 
   309 
   393 		Py_DECREF(pArgs);
   310 		Py_DECREF(pArgs);
   394 		if ((PyErr_Occurred() != NULL) || (pList == NULL) ||
   311 		if ((PyErr_Occurred()) || (pRet == NULL) || (pRet == Py_None)) {
   395 		    (pList == Py_None)) {
       
   396 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
   312 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
   397 			auto_debug_print(AUTO_DBGLVL_ERR,
   313 			auto_debug_print(AUTO_DBGLVL_ERR,
   398 			    "%s returned an error.\n", DDU_DEVSCAN);
   314 			    "%s returned an error.\n", DDU_DEVSCAN);
   399 			ai_dump_python_exception();
   315 			if (PyErr_Occurred()) {
   400 			Py_XDECREF(pList);
   316 				PyErr_Print();
   401 			Py_XDECREF(pFunc);
   317 			}
   402 			return (NULL);
   318 			Py_XDECREF(pRet);
       
   319 			pRet = NULL;
   403 		}
   320 		}
   404 	}
   321 	}
   405 
   322 
   406 	Py_XDECREF(pFunc);
   323 	Py_XDECREF(pFunc);
   407 
       
   408 	orig_listlen = PyList_Size(pList);
       
   409 	if (orig_listlen < 2) {
       
   410 		return (pList);
       
   411 	}
       
   412 
       
   413 	/* Check for duplicates. */
       
   414 	vids = (char **)malloc(sizeof (char *) * orig_listlen);
       
   415 	dids = (char **)malloc(sizeof (char *) * orig_listlen);
       
   416 	classes = (char **)malloc(sizeof (char *) * orig_listlen);
       
   417 	if ((vids == NULL) || (dids == NULL) || (classes == NULL)) {
       
   418 		auto_debug_print(AUTO_DBGLVL_ERR,
       
   419 		    "ai_call_ddu_devscan: No memory.\n");
       
   420 		return (NULL);
       
   421 	}
       
   422 
       
   423 	/* Build a list of unique values to be returned. */
       
   424 	pRet = PyList_New(0);
       
   425 
       
   426 	/* Loop through the list. */
       
   427 	for (i = 0; i < orig_listlen; i++) {
       
   428 		PyObject *pDDUDevData = PyList_GetItem(pList, i);
       
   429 		char *vendor_ID, *device_ID, *class;
       
   430 		boolean_t dup;
       
   431 
       
   432 		if (ai_get_ddu_dev_data_values(pDDUDevData, NULL, NULL,
       
   433 		    &vendor_ID, &device_ID, &class) != AUTO_INSTALL_SUCCESS) {
       
   434 			/* If can't compare, just allow it. */
       
   435 			continue;
       
   436 		}
       
   437 
       
   438 		/* Check for matching vendor, device, class. */
       
   439 		for (j = 0, dup = B_FALSE; j < new_listused; j++) {
       
   440 			if ((strcmp(class, classes[j]) == 0) &&
       
   441 			    (strcmp(device_ID, dids[j]) == 0) &&
       
   442 			    (strcmp(vendor_ID, vids[j]) == 0)) {
       
   443 				dup = B_TRUE;
       
   444 				break;
       
   445 			}
       
   446 		}
       
   447 
       
   448 		if (!dup) {
       
   449 			(void) PyList_Append(pRet, pDDUDevData);
       
   450 			vids[new_listused] = vendor_ID;
       
   451 			dids[new_listused] = device_ID;
       
   452 			classes[new_listused++] = class;
       
   453 		}
       
   454 	}
       
   455 
       
   456 	free(vids);
       
   457 	free(dids);
       
   458 	free(classes);
       
   459 
       
   460 	Py_XDECREF(pList);
       
   461 	return (pRet);
   324 	return (pRet);
   462 }
   325 }
   463 
   326 
   464 /*
   327 /*
   465  * ai_call_ddu_package_lookup:
   328  * ai_call_ddu_package_lookup:
   470  * Arguments:
   333  * Arguments:
   471  *   py_state_p: Initialized py_state_t object.
   334  *   py_state_p: Initialized py_state_t object.
   472  *   pDevObj: A python ddu_dev_data object representing a device.
   335  *   pDevObj: A python ddu_dev_data object representing a device.
   473  *   pRepoList: A python list of ddu_repo_object objects.  This represents the
   336  *   pRepoList: A python list of ddu_repo_object objects.  This represents the
   474  *	list of repositories to search through for a driver package.
   337  *	list of repositories to search through for a driver package.
   475  *   pPackageObj_p: Pointer to the returned ddu_package_object.
       
   476  *
   338  *
   477  * Returns:
   339  * Returns:
   478  *   AUTO_INSTALL_SUCCESS: pPackageObj_p points to an object representing a
   340  *   Success: A python ddu_package_object representing a package to install for
   479  *	package to install for the given device.
   341  *	the given device.
   480  *   AUTO_INSTALL_PKG_NOT_FOUND: No package was found to install for the given
   342  *   Failure: NULL
   481  *	device.  pPackageObj_p set to NULL.
   343  */
   482  *   AUTO_INSTALL_FAILURE: Corresponds to an error other than not finding the
   344 static PyObject *
   483  *	package to install for the given device.  pPackageObj_p set to NULL.
       
   484  */
       
   485 static int
       
   486 ai_call_ddu_package_lookup(py_state_t *py_state_p,
   345 ai_call_ddu_package_lookup(py_state_t *py_state_p,
   487     PyObject *pDevObj, PyObject *pRepoList, PyObject **pPackageObj_p)
   346     PyObject *pDevObj, PyObject *pRepoList)
   488 {
   347 {
   489 	int err = AUTO_INSTALL_SUCCESS;
   348 	PyObject *pRet = NULL;
   490 
   349 
   491 	/* Find the function */
   350 	/* Find the function */
   492 	PyObject *pFunc = PyObject_GetAttrString(py_state_p->pFunctionModule,
   351 	PyObject *pFunc = PyObject_GetAttrString(py_state_p->pFunctionModule,
   493 	    DDU_PACKAGE_LOOKUP);
   352 	    DDU_PACKAGE_LOOKUP);
   494 
       
   495 	*pPackageObj_p = NULL;
       
   496 
   353 
   497 	if ((pFunc == NULL) || (!PyCallable_Check(pFunc))) {
   354 	if ((pFunc == NULL) || (!PyCallable_Check(pFunc))) {
   498 		auto_debug_print(AUTO_DBGLVL_ERR,
   355 		auto_debug_print(AUTO_DBGLVL_ERR,
   499 		    "Function not callable: %s\n", DDU_PACKAGE_LOOKUP);
   356 		    "Function not callable: %s\n", DDU_PACKAGE_LOOKUP);
   500 	} else {
   357 	} else {
   501 		/* Set up args to python function. */
   358 		/* Set up args to python function. */
   502 		PyObject *pArgs = PyTuple_New(2);
   359 		PyObject *pArgs = PyTuple_New(2);
   503 		Py_INCREF(pDevObj);	/* PyTuple_SetItem steals reference. */
   360 		Py_INCREF(pDevObj);	/* PyTuple_SetItem steals reference. */
   504 		Py_INCREF(pRepoList);	/* PyTuple_SetItem steals reference. */
   361 		Py_INCREF(pRepoList);	/* PyTuple_SetItem steals reference. */
   505 		(void) PyTuple_SetItem(pArgs, 0, pDevObj);
   362 		PyTuple_SetItem(pArgs, 0, pDevObj);
   506 		(void) PyTuple_SetItem(pArgs, 1, pRepoList);
   363 		PyTuple_SetItem(pArgs, 1, pRepoList);
   507 
   364 
   508 		/* Call ddu_package_lookup() */
   365 		/* Call ddu_package_lookup() */
   509 		*pPackageObj_p = PyObject_CallObject(pFunc, pArgs);
   366 		pRet = PyObject_CallObject(pFunc, pArgs);
   510 		Py_DECREF(pArgs);
   367 		Py_DECREF(pArgs);
   511 		if ((PyErr_Occurred() != NULL) || (*pPackageObj_p == NULL) ||
   368 		if ((PyErr_Occurred()) || (pRet == NULL) || (pRet == Py_None)) {
   512 		    (*pPackageObj_p == Py_None)) {
       
   513 			err = AUTO_INSTALL_FAILURE;
       
   514 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
   369 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
   515 			auto_debug_print(AUTO_DBGLVL_ERR,
   370 			auto_debug_print(AUTO_DBGLVL_ERR,
   516 			    "%s returned an error.\n", DDU_PACKAGE_LOOKUP);
   371 			    "%s returned an error.\n", DDU_PACKAGE_LOOKUP);
   517 			if (PyErr_Occurred() != NULL) {
   372 			if (PyErr_Occurred()) {
   518 				PyObject *pType, *pValue, *pTraceback;
   373 				PyErr_Print();
   519 				PyObject *pPkgNotFndExcObj =
       
   520 				    PyObject_GetAttrString(
       
   521 				    py_state_p->pErrorModule,
       
   522 				    DDU_PACKAGE_NOT_FOUND_EXC);
       
   523 				PyErr_Fetch(&pType, &pValue, &pTraceback);
       
   524 
       
   525 				if (PyObject_IsSubclass(pType,
       
   526 				    pPkgNotFndExcObj) == 1) {	/* 1 = match */
       
   527 					err = AUTO_INSTALL_PKG_NOT_FND;
       
   528 				}
       
   529 				Py_DECREF(pType);
       
   530 				Py_DECREF(pValue);
       
   531 				Py_DECREF(pTraceback);
       
   532 				Py_DECREF(pPkgNotFndExcObj);
       
   533 				PyErr_Clear();
       
   534 			}
   374 			}
   535 			Py_XDECREF(*pPackageObj_p);
   375 			Py_XDECREF(pRet);
   536 			*pPackageObj_p = NULL;
   376 			pRet = NULL;
   537 
       
   538 		} else {
       
   539 			/*
       
   540 			 * DDU can return a pPackageObj_p that has type unknown,
       
   541 			 * no location and no inf_link.  Treat these as
       
   542 			 * "package not found" as well.
       
   543 			 */
       
   544 			char *ttype = empty_string;
       
   545 			char *tlocn = empty_string;
       
   546 			char *tinf_link = empty_string;
       
   547 			(void) ai_get_ddu_package_object_values(*pPackageObj_p,
       
   548 			    &ttype, &tlocn, NULL, NULL, &tinf_link, NULL);
       
   549 			if ((tlocn[0] == '\0') && (tinf_link[0] == '\0') &&
       
   550 			    (strcmp(ttype, "UNK") == 0)) {
       
   551 				err = AUTO_INSTALL_PKG_NOT_FND;
       
   552 				Py_XDECREF(*pPackageObj_p);
       
   553 				*pPackageObj_p = NULL;
       
   554 			}
       
   555 		}
   377 		}
   556 	}
   378 	}
   557 
   379 
   558 	Py_XDECREF(pFunc);
   380 	Py_XDECREF(pFunc);
   559 	return (err);
   381 	return (pRet);
   560 }
   382 }
   561 
   383 
   562 /*
   384 /*
   563  * ai_call_ddu_install_package:
   385  * ai_call_ddu_install_package:
   564  * Call the DDU library ddu_install_package function.  Install the package
   386  * Call the DDU library ddu_install_package function.  Install the package
   599 	} else {
   421 	} else {
   600 
   422 
   601 		/* Set up args to python function. */
   423 		/* Set up args to python function. */
   602 		PyObject *pArgs = PyTuple_New(3);
   424 		PyObject *pArgs = PyTuple_New(3);
   603 		Py_INCREF(pDDUPackageObj);	/* PyTuple_SetItem steals ref */
   425 		Py_INCREF(pDDUPackageObj);	/* PyTuple_SetItem steals ref */
   604 		(void) PyTuple_SetItem(pArgs, 0, pDDUPackageObj);
   426 		PyTuple_SetItem(pArgs, 0, pDDUPackageObj);
   605 		(void) PyTuple_SetItem(pArgs, 1,
   427 		PyTuple_SetItem(pArgs, 1, PyString_FromString(install_root));
   606 		    PyString_FromString(install_root));
   428 		PyTuple_SetItem(pArgs, 2,
   607 		(void) PyTuple_SetItem(pArgs, 2,
       
   608 		    PyBool_FromLong((long)third_party_ok));
   429 		    PyBool_FromLong((long)third_party_ok));
   609 
   430 
   610 		/* Call ddu_install_packages() */
   431 		/* Call ddu_install_packages() */
   611 		(void) PyObject_CallObject(pFunc, pArgs);
   432 		PyObject_CallObject(pFunc, pArgs);
   612 		Py_DECREF(pArgs);
   433 		Py_DECREF(pArgs);
   613 
   434 
   614 		if (PyErr_Occurred() != NULL) {
   435 		if (PyErr_Occurred()) {
   615 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
   436 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
   616 			auto_debug_print(AUTO_DBGLVL_ERR,
   437 			auto_debug_print(AUTO_DBGLVL_ERR,
   617 			    "%s returned an error\n", DDU_INSTALL_PACKAGE);
   438 			    "%s returned an error\n", DDU_INSTALL_PACKAGE);
   618 			ai_dump_python_exception();
   439 			PyErr_Print();
   619 			rval = AUTO_INSTALL_FAILURE;
   440 			rval = AUTO_INSTALL_FAILURE;
   620 		}
   441 		}
   621 	}
   442 	}
   622 
   443 
   623 	Py_XDECREF(pFunc);
   444 	Py_XDECREF(pFunc);
   624 	return (rval);
   445 	return (rval);
   625 }
   446 }
   626 
   447 
   627 /*
   448 /*
   628  * ai_new_ddu_package_object:
   449  * ai_new_ddu_package_object:
   629  * Create a new ddu_package_object of given type, name and location.
   450  * Create a new ddu_package_object of given type, name and origin.
   630  *
   451  *
   631  * Arguments:
   452  * Arguments:
   632  *   py_state_p: Initialized py_state_t object.
   453  *   py_state_p: Initialized py_state_t object.
   633  *   type: type of package.
   454  *   type: type of package.
   634  *   name: name of package. (Not used by all types of packages.)
   455  *   name: name of package. (Not used by all types of packages.)
   635  *   origin: directory of where package is located.
   456  *   origin: directory of where package is located.
   636  *
   457  *
   637  * Returns:
   458  * Returns:
   638  *   Success: A new python ddu_package_object object of the given
   459  *   Success: A new python ddu_package_object object of the given
   639  *	type/name/location.
   460  *	type/name/origin.
   640  *   Failure: NULL
   461  *   Failure: NULL
   641  */
   462  */
   642 static PyObject *
   463 static PyObject *
   643 ai_new_ddu_package_object(py_state_t *py_state_p,
   464 ai_new_ddu_package_object(py_state_t *py_state_p,
   644     char *type, char *name, char *origin)
   465     char *type, char *name, char *origin)
   660 		auto_debug_print(AUTO_DBGLVL_ERR,
   481 		auto_debug_print(AUTO_DBGLVL_ERR,
   661 		    "ddu_package_object constructor not callable\n");
   482 		    "ddu_package_object constructor not callable\n");
   662 	} else {
   483 	} else {
   663 		/* Set up args to python function. */
   484 		/* Set up args to python function. */
   664 		PyObject *pArgs = PyTuple_New(3);
   485 		PyObject *pArgs = PyTuple_New(3);
   665 		(void) PyTuple_SetItem(pArgs, 0, PyString_FromString(type));
   486 		PyTuple_SetItem(pArgs, 0, PyString_FromString(type));
   666 		(void) PyTuple_SetItem(pArgs, 1, PyString_FromString(name));
   487 		PyTuple_SetItem(pArgs, 1, PyString_FromString(name));
   667 		(void) PyTuple_SetItem(pArgs, 2, PyString_FromString(origin));
   488 		PyTuple_SetItem(pArgs, 2, PyString_FromString(origin));
   668 
   489 
   669 		/* Call ddu_package_object constructor. */
   490 		/* Call ddu_package_object constructor. */
   670 		pRet = PyObject_CallObject(pFunc, pArgs);
   491 		pRet = PyObject_CallObject(pFunc, pArgs);
   671 		Py_DECREF(pArgs);
   492 		Py_DECREF(pArgs);
   672 		if ((PyErr_Occurred() != NULL) || (pRet == NULL) ||
   493 		if ((PyErr_Occurred()) || (pRet == NULL) || (pRet == Py_None)) {
   673 		    (pRet == Py_None)) {
       
   674 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
   494 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
   675 			auto_debug_print(AUTO_DBGLVL_ERR,
   495 			auto_debug_print(AUTO_DBGLVL_ERR,
   676 			    "ddu_package_object constructor failed\n");
   496 			    "ddu_package_object constructor failed\n");
   677 			ai_dump_python_exception();
   497 			if (PyErr_Occurred()) {
       
   498 				PyErr_Print();
       
   499 			}
   678 			Py_XDECREF(pRet);
   500 			Py_XDECREF(pRet);
   679 			pRet = NULL;
   501 			pRet = NULL;
   680 		}
   502 		}
   681 	}
   503 	}
   682 
   504 
   696  * Arguments:
   518  * Arguments:
   697  *   pDDUPackageObject: Object to extract values from.  Assumed to be a
   519  *   pDDUPackageObject: Object to extract values from.  Assumed to be a
   698  *	ddu_package_object;  not verified.
   520  *	ddu_package_object;  not verified.
   699  *   type: char string pointer returned filled in with "pkg_type" field.
   521  *   type: char string pointer returned filled in with "pkg_type" field.
   700  *	Not processed if NULL.
   522  *	Not processed if NULL.
   701  *   location: char string pointer returned filled in with "pkg_location" field.
   523  *   origin: char string pointer returned filled in with "pkg_location" field.
   702  *	Not processed if NULL.
   524  *	Not processed if NULL.
   703  *   name: char string pointer returned filled in with "pkg_name" field.
   525  *   name: char string pointer returned filled in with "pkg_name" field.
   704  *	Not processed if NULL.
   526  *	Not processed if NULL.
   705  *   descr: char string pointer returned filled in with "device_descriptor"
   527  *   descr: char string pointer returned filled in with "device_descriptor"
   706  *	field.  Not processed if NULL.
   528  *	field.  Not processed if NULL.
   714  *   AUTO_INSTALL_FAILURE: when one or more fields could not be found or
   536  *   AUTO_INSTALL_FAILURE: when one or more fields could not be found or
   715  *	extracted.
   537  *	extracted.
   716  */
   538  */
   717 static int
   539 static int
   718 ai_get_ddu_package_object_values(PyObject *pDDUPackageObject,
   540 ai_get_ddu_package_object_values(PyObject *pDDUPackageObject,
   719     char **type, char **location, char **name, char **descr, char **inf_link,
   541     char **type, char **origin, char **name, char **descr, char **inf_link,
   720     boolean_t *third_party)
   542     boolean_t *third_party)
   721 {
   543 {
   722 	PyObject *pValue;
   544 	PyObject *pValue;
   723 
   545 
   724 	if (type != NULL) {
   546 	if (type != NULL) {
   730 			return (AUTO_INSTALL_FAILURE);
   552 			return (AUTO_INSTALL_FAILURE);
   731 		}
   553 		}
   732 		*type = PyString_AsString(pValue);
   554 		*type = PyString_AsString(pValue);
   733 	}
   555 	}
   734 
   556 
   735 	if (location != NULL) {
   557 	if (origin != NULL) {
   736 		pValue = PyObject_GetAttrString(pDDUPackageObject,
   558 		pValue = PyObject_GetAttrString(pDDUPackageObject,
   737 		    "pkg_location");
   559 		    "pkg_location");
   738 		if (pValue == NULL) {
   560 		if (pValue == NULL) {
   739 			auto_debug_print(AUTO_DBGLVL_ERR,
   561 			auto_debug_print(AUTO_DBGLVL_ERR,
   740 			    "ai_get_ddu_package_object_values: "
   562 			    "ai_get_ddu_package_object_values: "
   741 			    "no ddu_package_object pkg_location field.\n");
   563 			    "no ddu_package_object pkg_location field.\n");
   742 			return (AUTO_INSTALL_FAILURE);
   564 			return (AUTO_INSTALL_FAILURE);
   743 		}
   565 		}
   744 		*location = PyString_AsString(pValue);
   566 		*origin = PyString_AsString(pValue);
   745 	}
   567 	}
   746 
   568 
   747 	if (name != NULL) {
   569 	if (name != NULL) {
   748 		pValue = PyObject_GetAttrString(pDDUPackageObject, "pkg_name");
   570 		pValue = PyObject_GetAttrString(pDDUPackageObject, "pkg_name");
   749 		if (pValue == NULL) {
   571 		if (pValue == NULL) {
   804  * Note: implementation is tied to the fields of the python object.
   626  * Note: implementation is tied to the fields of the python object.
   805  *
   627  *
   806  * Arguments:
   628  * Arguments:
   807  *   pDDUDevData: Object to extract values from.  Assumed to be a
   629  *   pDDUDevData: Object to extract values from.  Assumed to be a
   808  *	ddu_dev_data object;  not verified.
   630  *	ddu_dev_data object;  not verified.
   809  *   dev_type_p: char string pointer returned filled in with "device_type"
   631  *   dev_type: char string pointer returned filled in with "device_type" field.
   810  *	field.  Not processed if NULL.
       
   811  *   descr_p: char string pointer returned filled in with "description" field.
       
   812  *	Not processed if NULL.
   632  *	Not processed if NULL.
   813  *   vendor_ID_p: char string pointer returned filled in with "vendor ID" field.
   633  *   descr: char string pointer returned filled in with "description" field.
   814  *	Not processed if NULL.
       
   815  *   device_ID_p: char string pointer returned filled in with "device ID" field.
       
   816  *	Not processed if NULL.
       
   817  *   class_p: char string pointer returned filled in with PCI "class" field.
       
   818  *	Not processed if NULL.
   634  *	Not processed if NULL.
   819  *
   635  *
   820  * Returns:
   636  * Returns:
   821  *   AUTO_INSTALL_SUCCESS: when all requested fields are found and extracted.
   637  *   AUTO_INSTALL_SUCCESS: when all requested fields are found and extracted.
   822  *   AUTO_INSTALL_FAILURE: when one or more fields could not be found or
   638  *   AUTO_INSTALL_FAILURE: when one or more fields could not be found or
   823  *	extracted.
   639  *	extracted.
   824  */
   640  */
   825 static int
   641 static int
   826 ai_get_ddu_dev_data_values(PyObject *pDDUDevData, char **dev_type_p,
   642 ai_get_ddu_dev_data_values(PyObject *pDDUDevData, char **dev_type, char **descr)
   827     char **descr_p, char **vendor_ID_p, char **device_ID_p, char **class_p)
       
   828 {
   643 {
   829 	PyObject *pValue;
   644 	PyObject *pValue;
   830 
   645 
   831 	if (dev_type_p != NULL) {
   646 	if (dev_type != NULL) {
   832 		pValue = PyObject_GetAttrString(pDDUDevData, "device_type");
   647 		pValue = PyObject_GetAttrString(pDDUDevData, "device_type");
   833 		if (pValue == NULL) {
   648 		if (pValue == NULL) {
   834 			auto_debug_print(AUTO_DBGLVL_ERR,
   649 			auto_debug_print(AUTO_DBGLVL_ERR,
   835 			    "ai_get_ddu_dev_data_values: "
   650 			    "ai_get_ddu_dev_data_values: "
   836 			    "no ddu_dev_data device_type field.\n");
   651 			    "no ddu_dev_data device_type field.\n");
   837 			return (AUTO_INSTALL_FAILURE);
   652 			return (AUTO_INSTALL_FAILURE);
   838 		}
   653 		}
   839 		*dev_type_p = PyString_AsString(pValue);
   654 		*dev_type = PyString_AsString(pValue);
   840 	}
   655 	}
   841 
   656 
   842 	if (descr_p != NULL) {
   657 	if (descr != NULL) {
   843 		pValue = PyObject_GetAttrString(pDDUDevData, "description");
   658 		pValue = PyObject_GetAttrString(pDDUDevData, "description");
   844 		if (pValue == NULL) {
   659 		if (pValue == NULL) {
   845 			auto_debug_print(AUTO_DBGLVL_ERR,
   660 			auto_debug_print(AUTO_DBGLVL_ERR,
   846 			    "ai_get_ddu_dev_data_values: "
   661 			    "ai_get_ddu_dev_data_values: "
   847 			    "no ddu_dev_data description field.\n");
   662 			    "no ddu_dev_data description field.\n");
   848 			return (AUTO_INSTALL_FAILURE);
   663 			return (AUTO_INSTALL_FAILURE);
   849 		}
   664 		}
   850 		*descr_p = PyString_AsString(pValue);
   665 		*descr = PyString_AsString(pValue);
   851 	}
       
   852 
       
   853 	if (vendor_ID_p != NULL) {
       
   854 		pValue = PyObject_GetAttrString(pDDUDevData, "vendor_id");
       
   855 		if (pValue == NULL) {
       
   856 			auto_debug_print(AUTO_DBGLVL_ERR,
       
   857 			    "ai_get_ddu_dev_data_values: "
       
   858 			    "no ddu_dev_data vendor_id field.\n");
       
   859 			return (AUTO_INSTALL_FAILURE);
       
   860 		}
       
   861 		*vendor_ID_p = PyString_AsString(pValue);
       
   862 	}
       
   863 
       
   864 	if (device_ID_p != NULL) {
       
   865 		pValue = PyObject_GetAttrString(pDDUDevData, "device_id");
       
   866 		if (pValue == NULL) {
       
   867 			auto_debug_print(AUTO_DBGLVL_ERR,
       
   868 			    "ai_get_ddu_dev_data_values: "
       
   869 			    "no ddu_dev_data device_id field.\n");
       
   870 			return (AUTO_INSTALL_FAILURE);
       
   871 		}
       
   872 		*device_ID_p = PyString_AsString(pValue);
       
   873 	}
       
   874 
       
   875 	if (class_p != NULL) {
       
   876 		pValue = PyObject_GetAttrString(pDDUDevData, "class_code");
       
   877 		if (pValue == NULL) {
       
   878 			auto_debug_print(AUTO_DBGLVL_ERR,
       
   879 			    "ai_get_ddu_dev_data_values: "
       
   880 			    "no ddu_dev_data class_code field.\n");
       
   881 			return (AUTO_INSTALL_FAILURE);
       
   882 		}
       
   883 		*class_p = PyString_AsString(pValue);
       
   884 	}
   666 	}
   885 
   667 
   886 	return (AUTO_INSTALL_SUCCESS);
   668 	return (AUTO_INSTALL_SUCCESS);
   887 }
   669 }
   888 
   670 
   891  * Create a ddu_package_object from parameters, and add it to the pPackageList.
   673  * Create a ddu_package_object from parameters, and add it to the pPackageList.
   892  *
   674  *
   893  * Arguments:
   675  * Arguments:
   894  *   py_state_p: Initialized py_state_t object.
   676  *   py_state_p: Initialized py_state_t object.
   895  *   pPackageList: List of packages to append the new ddu_package_object to.
   677  *   pPackageList: List of packages to append the new ddu_package_object to.
   896  *   origin: directory of where package or package directive is located.
   678  *   origin: directory of where package is located.
   897  *   type: type of package.
   679  *   type: type of package.
   898  *   name: name of package.
   680  *   name: name of package.
   899  *   noinstall: boolean whether package is to be installed only to booted
   681  *   noinstall: boolean whether package is to be installed only to booted
   900  *	environment, not to target.
   682  *	environment, not to target.
   901  *
   683  *
   902  * Returns:
   684  * Returns: None
   903  *   AUTO_INSTALL_SUCCESS: A new package object was successfully appended to
   685  *   Note 1: the pPackageList will be modified.
   904  *	pPackageList.
   686  *   Note 2: Appropriate error messages are logged/displayed.
   905  *   AUTO_INSTALL_FAILURE: An error occurred when trying to create a new
   687  */
   906  *	package object or append it to the pPackageList.
   688 static void
   907  *
       
   908  *   Note: The list object referenced by pPackageList will be modified.
       
   909  */
       
   910 static int
       
   911 ai_du_process_manual_pkg(py_state_t *py_state_p, PyObject *pPackageList,
   689 ai_du_process_manual_pkg(py_state_t *py_state_p, PyObject *pPackageList,
   912     char *origin, char *type, char *name, char *noinstall)
   690     char *origin, char *type, char *name, char *noinstall)
   913 {
   691 {
   914 	PyObject *pDDUPackageObject;
   692 	PyObject *pDDUPackageObject;
   915 	PyObject *pTuple;
   693 	PyObject *pTuple;
   916 
   694 
   917 	auto_log_print(gettext(
   695 	auto_log_print(gettext("Found manifest entry for package:\n"));
   918 	    "Add Drivers: Found manifest entry for package:\n"));
       
   919 	if (name != empty_string) {
   696 	if (name != empty_string) {
   920 		auto_log_print(gettext("  type:%s, origin:%s, name:%s\n"),
   697 		auto_log_print(gettext("  type:%s, origin:%s, name:%s\n"),
   921 		    type, origin, name);
   698 		    type, origin, name);
   922 	} else {
   699 	} else {
   923 		auto_log_print(gettext("  type:%s, origin:%s\n"),
   700 		auto_log_print(gettext("  type:%s, origin:%s\n"),
   935 	pDDUPackageObject = ai_new_ddu_package_object(py_state_p,
   712 	pDDUPackageObject = ai_new_ddu_package_object(py_state_p,
   936 	    type, name, origin);
   713 	    type, name, origin);
   937 
   714 
   938 	if (pDDUPackageObject == NULL) {
   715 	if (pDDUPackageObject == NULL) {
   939 		auto_debug_print(AUTO_DBGLVL_ERR,
   716 		auto_debug_print(AUTO_DBGLVL_ERR,
   940 		    "ai_du_process_manual_pkg: <add_drivers> error:\n"
   717 		    "ai_du_get_pkg_list: <add_drivers> error:\n"
   941 		    "Error creating new package object for "
   718 		    "Error creating new package object for "
   942 		    "origin %s %s\n", origin, name);
   719 		    "origin %s %s\n", origin, name);
   943 		return (AUTO_INSTALL_FAILURE);
   720 		return;
   944 	}
   721 	}
   945 
   722 
   946 	pTuple = PyTuple_New(3);
   723 	pTuple = PyTuple_New(3);
   947 	(void) PyTuple_SetItem(pTuple, 0, pDDUPackageObject);
   724 	PyTuple_SetItem(pTuple, 0, pDDUPackageObject);
   948 	(void) PyTuple_SetItem(pTuple, 1, Py_True);	/* third party OK */
   725 	PyTuple_SetItem(pTuple, 1, Py_True);	/* third party OK */
   949 	(void) PyTuple_SetItem(pTuple, 2,
   726 	PyTuple_SetItem(pTuple, 2,
   950 	    (strcmp(noinstall, "true") == 0) ? Py_True : Py_False);
   727 	    (strcmp(noinstall, "true") == 0) ? Py_True : Py_False);
   951 
   728 
   952 	/*
   729 	/*
   953 	 * NOTE: Don't decref pTuple here as PyList_Append doesn't
   730 	 * NOTE: Don't decref pTuple here as PyList_Append doesn't
   954 	 * steal a reference to it.
   731 	 * steal a reference to it.
   955 	 */
   732 	 */
   956 	(void) PyList_Append(pPackageList, pTuple);
   733 	PyList_Append(pPackageList, pTuple);
   957 	return (AUTO_INSTALL_SUCCESS);
       
   958 }
   734 }
   959 
   735 
   960 /*
   736 /*
   961  * ai_du_process_manual_pkg_names:
   737  * ai_du_process_manual_pkg_names:
   962  * Do any processing of packages for which unique origin (location), type and
   738  * Do any processing of packages for which unique origin, type and name are
   963  *	name are known.
   739  *	known.
   964  *
   740  *
   965  * Arguments:
   741  * Arguments:
   966  *   py_state_p: Initialized py_state_t object.
   742  *   py_state_p: Initialized py_state_t object.
   967  *   path_p: Used to build nodepath strings for manifest checking.
       
   968  *   pPackageList: List of packages to append the new ddu_package_object to.
   743  *   pPackageList: List of packages to append the new ddu_package_object to.
   969  *   origin: directory of where package is located.
   744  *   origin: directory of where package is located.
   970  *   type: type of package.
   745  *   type: type of package.
   971  *   name: name of package.
   746  *   name: name of package.
   972  *
   747  *
   973  * Returns:
   748  * Returns: None
   974  *   AUTO_INSTALL_SUCCESS: Package processed successfully and appended to
   749  *   Note 1: the pPackageList will be modified.
   975  *	pPackageList.
   750  *   Note 2: Appropriate error messages are logged/displayed.
   976  *   AUTO_INSTALL_FAILURE: An error occurred.  No package appended to
   751  */
   977  *	pPackageList.
   752 static void
   978  *
   753 ai_du_process_manual_pkg_names(py_state_t *py_state_p, PyObject *pPackageList,
   979  *   Note 1: the object pointed to by pPackageList will be modified.
   754     path_t *path_p, char *origin, char *type, char *name)
   980  */
       
   981 static int
       
   982 ai_du_process_manual_pkg_names(py_state_t *py_state_p, path_t *path_p,
       
   983     PyObject *pPackageList, char *origin, char *type, char *name)
       
   984 {
   755 {
   985 	char **actions;
   756 	char **actions;
   986 	int actions_len;
   757 	int actions_len;
   987 	char *nodespec;
   758 	char *nodespec;
   988 	int rval;
       
   989 
   759 
   990 	/* Get the action attribute. */
   760 	/* Get the action attribute. */
   991 
   761 
   992 	/* Search is different depending on whether a name is specified. */
   762 	/* Search is different depending on whether a name is specified. */
   993 	if (name == empty_string) {
   763 	if (name == empty_string) {
   996 		nodespec = ACTION_YESNAME_NODEPATH;
   766 		nodespec = ACTION_YESNAME_NODEPATH;
   997 	}
   767 	}
   998 
   768 
   999 	if (snprintf(path_p->post_prefix_start, path_p->post_prefix_len,
   769 	if (snprintf(path_p->post_prefix_start, path_p->post_prefix_len,
  1000 	    nodespec, origin, type, name) >= path_p->post_prefix_len) {
   770 	    nodespec, origin, type, name) >= path_p->post_prefix_len) {
  1001 		auto_debug_print(AUTO_DBGLVL_ERR,
   771 		auto_debug_print(AUTO_DBGLVL_ERR, "ai_du_get_pkg_list: "
  1002 		    "ai_du_process_manual_pkg_names: "
       
  1003 		    "<add_drivers> manifest error:\n"
   772 		    "<add_drivers> manifest error:\n"
  1004 		    "action path buffer overflow for origin \"%s\", "
   773 		    "action path buffer overflow for origin \"%s\", "
  1005 		    "type \"%s\", name \"%s\"\n", origin, type, name);
   774 		    "type \"%s\", name \"%s\"\n", origin, type, name);
  1006 		return (AUTO_INSTALL_FAILURE);
   775 		return;
  1007 	}
   776 	}
  1008 
   777 
  1009 	actions = ai_get_manifest_values(path_p->path_str, &actions_len);
   778 	actions = ai_get_manifest_values(path_p->path_str, &actions_len);
  1010 
   779 
  1011 	/*
   780 	/*
  1012 	 * Note: action must be present and must be
   781 	 * Note: action must be present and must be either "install"
  1013 	 * either "install" or "noinstall".
   782 	 * or "noinstall".
  1014 	 */
   783 	 */
  1015 	if (actions_len <= 0) {
   784 	if (actions_len <= 0) {
  1016 		auto_log_print(gettext("Add Drivers: "
   785 		auto_log_print(gettext("ai_du_get_pkg_list: "
  1017 		    "<add_drivers> manifest error:\n"
   786 		    "<add_drivers> manifest error:\n"
  1018 		    "no action value for origin \"%s\", "
   787 		    "no action value for origin \"%s\", "
  1019 		    "type \"%s\", name \"%s\"\n"), origin, type, name);
   788 		    "type \"%s\", name \"%s\"\n"), origin, type, name);
  1020 		rval = AUTO_INSTALL_FAILURE;
   789 		return;
  1021 
   790 
  1022 	} else if (actions_len > 1) {
   791 	} else if (actions_len > 1) {
  1023 		auto_log_print(gettext("Add Drivers: "
   792 		auto_log_print(gettext("ai_du_get_pkg_list: "
  1024 		    "<add_drivers> manifest error:\n"
   793 		    "<add_drivers> manifest error:\n"
  1025 		    "multiple action values for origin \"%s\", "
   794 		    "multiple action values for origin \"%s\", "
  1026 		    "type \"%s\", name \"%s\"\n"), origin, type, name);
   795 		    "type \"%s\", name \"%s\"\n"), origin, type, name);
  1027 		rval = AUTO_INSTALL_FAILURE;
   796 		return;
  1028 
   797 
  1029 	} else if (strcmp(actions[0], "install") == 0) {
   798 	} else if (strcmp(actions[0], "install") == 0) {
  1030 		/*
   799 		/*
  1031 		 * If action="install" then call ai_du_process_manual_pkg with
   800 		 * If action="install" then call ai_du_process_manual_pkg with
  1032 		 * noinstall param set to empty_string, which means pkg will be
   801 		 * noinstall param set to empty_string, which means pkg will be
  1033 		 * installed in both boot env and target.
   802 		 * installed in both boot env and target.
  1034 		 */
   803 		 */
  1035 
   804 
  1036 		/* Obj pointed to by pPackageList will be modified. */
   805 		/* Obj pointed to by pPackageList will be modified. */
  1037 		rval = ai_du_process_manual_pkg(py_state_p, pPackageList,
   806 		ai_du_process_manual_pkg(py_state_p, pPackageList, origin,
  1038 		    origin, type, name, empty_string);
   807 		    type, name, empty_string);
  1039 	} else if (strcmp(actions[0], "noinstall") == 0) {
   808 	} else if (strcmp(actions[0], "noinstall") == 0) {
  1040 		/*
   809 		/*
  1041 		 * If action="noinstall" then call ai_du_process_manual_pkg with
   810 		 * If action="noinstall" then call ai_du_process_manual_pkg with
  1042 		 * noinstall param set to "true", which means pkg will only be
   811 		 * noinstall param set to "true", which means pkg will only be
  1043 		 * installed in both boot env and not in target.
   812 		 * installed in both boot env and not in target.
  1044 		 */
   813 		 */
  1045 		/* Obj pointed to by pPackageList will be modified. */
   814 		/* Obj pointed to by pPackageList will be modified. */
  1046 		rval = ai_du_process_manual_pkg(py_state_p, pPackageList,
   815 		ai_du_process_manual_pkg(py_state_p, pPackageList, origin,
  1047 		    origin, type, name, "true");
   816 		    type, name, "true");
  1048 	} else {
   817 	} else {
  1049 		auto_log_print(gettext("Add Drivers: "
   818 		auto_log_print(gettext("ai_du_get_pkg_list: "
  1050 		    "<add_drivers> manifest error:\n"
   819 		    "<add_drivers> manifest error:\n"
  1051 		    "action must be install or noinstall for origin \"%s\", "
   820 		    "action must be install or noinstall for origin \"%s\", "
  1052 		    "type \"%s\", name \"%s\"\n"), origin, type, name);
   821 		    "type \"%s\", name \"%s\"\n"), origin, type, name);
  1053 		rval = AUTO_INSTALL_FAILURE;
   822 		return;
       
   823 
  1054 	}
   824 	}
  1055 	ai_free_manifest_values(actions);
   825 	ai_free_manifest_values(actions);
  1056 	return (rval);
       
  1057 }
   826 }
  1058 
   827 
  1059 /*
   828 /*
  1060  * ai_du_process_manual_pkg_types:
   829  * ai_du_process_manual_pkg_types:
  1061  * Do any processing of packages for which unique location and type are known.
   830  * Do any processing of packages for which unique origin and type are known.
  1062  *
   831  *
  1063  * Arguments:
   832  * Arguments:
  1064  *   py_state_p: Initialized py_state_t object.
   833  *   py_state_p: Initialized py_state_t object.
  1065  *   pPackageList: List of packages to append the new ddu_package_object to.
   834  *   pPackageList: List of packages to append the new ddu_package_object to.
  1066  *   origin: directory of where package is located.
   835  *   origin: directory of where package is located.
  1067  *   type: type of package.
   836  *   type: type of package.
  1068  *
   837  *
  1069  * Returns:
   838  * Returns: None
  1070  *   AUTO_INSTALL_SUCCESS: Package processed successfully and appended to
       
  1071  *	pPackageList.
       
  1072  *   AUTO_INSTALL_FAILURE: An error occurred.  No package appended to
       
  1073  *	pPackageList.
       
  1074  *
       
  1075  *   Note 1: the pPackageList will be modified.
   839  *   Note 1: the pPackageList will be modified.
  1076  *   Note 2: Appropriate error messages are logged/displayed.
   840  *   Note 2: Appropriate error messages are logged/displayed.
  1077  */
   841  */
  1078 static int
   842 static void
  1079 ai_du_process_manual_pkg_types(py_state_t *py_state_p, PyObject *pPackageList,
   843 ai_du_process_manual_pkg_types(py_state_t *py_state_p, PyObject *pPackageList,
  1080     path_t *path_p, char *origin, char *type)
   844     path_t *path_p, char *origin, char *type)
  1081 {
   845 {
  1082 	char **names;
   846 	char **names;
  1083 	char **uniq_names;
   847 	char **uniq_names;
  1084 	int namelen;
   848 	int namelen;
  1085 	int k;
   849 	int k;
  1086 	int rval = AUTO_INSTALL_SUCCESS;
       
  1087 
   850 
  1088 	if ((strcmp(type, "P5I") != 0) &&
   851 	if ((strcmp(type, "P5I") != 0) &&
  1089 	    (strcmp(type, "SVR4") != 0) &&
   852 	    (strcmp(type, "SVR4") != 0) &&
  1090 	    (strcmp(type, "DU") != 0)) {
   853 	    (strcmp(type, "DU") != 0)) {
  1091 		auto_log_print(gettext("Add Drivers: "
   854 		auto_log_print(gettext("ai_du_get_pkg_list: "
  1092 		    "<add_drivers> manifest error:\n"
   855 		    "<add_drivers> manifest error:\n"
  1093 		    "invalid type %s given for origin %s\n"), type, origin);
   856 		    "invalid type %s given for origin %s\n"),
  1094 		return (AUTO_INSTALL_FAILURE);
   857 		    type, origin);
       
   858 		return;
  1095 	}
   859 	}
  1096 
   860 
  1097 	/* Get all names assocated with type and origin. */
   861 	/* Get all names assocated with type and origin. */
  1098 
   862 
  1099 	if (snprintf(path_p->post_prefix_start, path_p->post_prefix_len,
   863 	if (snprintf(path_p->post_prefix_start, path_p->post_prefix_len,
  1100 	    NAME_NODEPATH, origin, type) >= path_p->post_prefix_len) {
   864 	    NAME_NODEPATH, origin, type) >= path_p->post_prefix_len) {
  1101 		auto_debug_print(AUTO_DBGLVL_ERR,
   865 		auto_debug_print(AUTO_DBGLVL_ERR, "ai_du_get_pkg_list: "
  1102 		    "ai_du_process_manual_pkg_types: "
       
  1103 		    "<add_drivers> manifest error:\n"
   866 		    "<add_drivers> manifest error:\n"
  1104 		    "name path buffer overflow for origin "
   867 		    "name path buffer overflow for origin "
  1105 		    "%s, type %s\n", origin, type);
   868 		    "%s, type %s\n", origin, type);
  1106 		return (AUTO_INSTALL_FAILURE);
   869 		return;
  1107 	}
   870 	}
  1108 
   871 
  1109 	names = ai_get_manifest_values(path_p->path_str, &namelen);
   872 	names = ai_get_manifest_values(path_p->path_str, &namelen);
  1110 	uniq_names = ai_uniq_manifest_values(names, &namelen);
   873 	uniq_names = ai_uniq_manifest_values(names, &namelen);
  1111 	ai_free_manifest_values(names);
   874 	ai_free_manifest_values(names);
  1113 
   876 
  1114 	/* P5I and DU type entries don't have a "name" entry. */
   877 	/* P5I and DU type entries don't have a "name" entry. */
  1115 	if (strcmp(type, "SVR4") != 0) {
   878 	if (strcmp(type, "SVR4") != 0) {
  1116 		if (namelen > 0) {
   879 		if (namelen > 0) {
  1117 			auto_log_print(gettext(
   880 			auto_log_print(gettext(
  1118 			    "Add Drivers: <add_drivers> "
   881 			    "ai_du_get_pkg_list: <add_drivers> "
  1119 			    "manifest error:\n"
   882 			    "manifest error:\n"
  1120 			    "name given to P5I or DU package specification at "
   883 			    "name given to P5I or DU pkg spec at "
  1121 			    "origin %s\n"), origin);
   884 			    "origin %s\n"), origin);
  1122 			rval = AUTO_INSTALL_FAILURE;
   885 			return;
  1123 		} else {
   886 		} else {
  1124 			/* Obj pointed to by pPackageList will be modified. */
   887 			/* Obj pointed to by pPackageList will be modified. */
  1125 			rval = ai_du_process_manual_pkg_names(py_state_p,
   888 			ai_du_process_manual_pkg_names(py_state_p, pPackageList,
  1126 			    path_p, pPackageList, origin, type, empty_string);
   889 			    path_p, origin, type, empty_string);
  1127 		}
   890 		}
  1128 
   891 
  1129 	/* There must be at least one "name" entry per pkgspec for SVR4 type. */
   892 	/*
       
   893 	 * There must be at least one "name" entry per pkg spec
       
   894 	 * for SVR4 type.
       
   895 	 */
  1130 	} else if (namelen <= 0) {
   896 	} else if (namelen <= 0) {
  1131 		auto_log_print(gettext("Add Drivers: "
   897 		auto_log_print(gettext("ai_du_get_pkg_list: "
  1132 		    "<add_drivers> manifest error:\n"
   898 		    "<add_drivers> manifest error:\n"
  1133 		    "  no name given for SVR4 package specification\n"
   899 		    "no name given for SVR4 pkg spec at origin %s, type %s\n"),
  1134 		    "  at origin %s, type %s\n"), origin, type);
   900 		    origin, type);
  1135 		rval = AUTO_INSTALL_FAILURE;
   901 		return;
  1136 
   902 
  1137 	} else {
   903 	} else {
  1138 		/* Process each origin/type/name entry. */
   904 		/* Process each origin/type/name entry. */
  1139 		for (k = 0; k < namelen; k++) {
   905 		for (k = 0; k < namelen; k++) {
  1140 
   906 
  1141 			/* Obj pointed to by pPackageList will be modified. */
   907 			/* Obj pointed to by pPackageList will be modified. */
  1142 			int status = ai_du_process_manual_pkg_names(py_state_p,
   908 			ai_du_process_manual_pkg_names(py_state_p, pPackageList,
  1143 			    path_p, pPackageList, origin, type, names[k]);
   909 			    path_p, origin, type, names[k]);
  1144 			if (status == AUTO_INSTALL_FAILURE) {
   910 		}
  1145 				rval = AUTO_INSTALL_FAILURE;
   911 
  1146 			}
       
  1147 		}
       
  1148 	}
   912 	}
  1149 	ai_free_manifest_values(names);
   913 	ai_free_manifest_values(names);
  1150 	return (rval);
       
  1151 }
   914 }
  1152 
   915 
  1153 /*
   916 /*
  1154  * ai_du_get_manual_pkg_list:
   917  * ai_du_get_manual_pkg_list:
  1155  * Read the AI ai.xml Manifest file and process the <software> tags under the
   918  * Read the AI ai.xml Manifest file and process the <software> under the
  1156  * <add_drivers> section.  <software> represents a manual specification of a
   919  * <add_drivers> section.  A <software> is a manual specification of a package
  1157  * package to install.  Do error checking of the manifest as necessary, as this
   920  * to install.  Do error checking of the manifest as necessary, as this function
  1158  * function reads the manifest before it is validated against a schema.
   921  * reads the manifest before it is validated against a schema.
  1159  *
   922  *
  1160  * Validates syntax and processes the following from the manifest:
   923  * Validates syntax and processes the following from the manifest:
  1161  *	<add_drivers>
   924  *	<add_drivers>
  1162  *		<software>
   925  *		<software>
  1163  *			<source>
   926  *			<source>
  1164  *				<publisher>
   927  *				<publisher>
  1165  *					<origin name="location"/>
   928  *					<origin name="origin"/>
  1166  *				</publisher>
   929  *				</publisher>
  1167  *			</source>
   930  *			</source>
  1168  *			<software_data type="type" action="noinstall">
   931  *			<software_data type="type" action="noinstall">
  1169  *				<name>"name"</name>
   932  *				<name>"name"</name>
  1170  *			</software_data>
   933  *			</software_data>
  1172  *	</add_drivers>
   935  *	</add_drivers>
  1173  *
   936  *
  1174  *	type can be "SVR4", "P5I" or "DU".
   937  *	type can be "SVR4", "P5I" or "DU".
  1175  *	name not allowed if type is "P5I" or "DU"
   938  *	name not allowed if type is "P5I" or "DU"
  1176  *
   939  *
  1177  * Always return a list.  An empty list can be returned if the manifest shows
       
  1178  * there are no packages to install for Driver Update, or on some errors.
       
  1179  *
       
  1180  * Arguments:
   940  * Arguments:
  1181  *   py_state_p: Initialized py_state_t object.
   941  *   py_state_p: Initialized py_state_t object.
  1182  *   path_p: Used to build nodepath strings for manifest checking.
   942  *   path_p: Used to build nodepath strings for manifest checking.
  1183  *
   943  *
  1184  * Returns:
   944  * Returns:
  1185  *   AUTO_INSTALL_SUCCESS: A complete python list of (ddu_package_object,
   945  *   Success: A python list of (ddu_package_object, third_party_ok, noinstall)
  1186  *	third_party_ok, noinstall) tuples suitable for input to
   946  *	tuples suitable for input to ai_du_install_packages().
  1187  *	ai_du_install_packages() has been created.
   947  *	NOTE: if the manifest shows no packages to install for Driver Update,
  1188  *   AUTO_INSTALL_FAILURE: A python list of tuples suitable for input to
   948  *	this function will return an empty list.
  1189  *	ai_du_install_packages() has been created, but is missing one or more
   949  *   Failure: NULL
  1190  *	requested packages due to errors.  These errors could be manifest
       
  1191  *	parsing errors or errors in setting up the packages.
       
  1192  *
   950  *
  1193  * NOTE: check installer logfile for details of the failure.
   951  * NOTE: check installer logfile for details of the failure.
  1194  */
   952  */
  1195 static int
   953 static PyObject *
  1196 ai_du_get_manual_pkg_list(py_state_t *py_state_p, path_t *path_p,
   954 ai_du_get_manual_pkg_list(py_state_t *py_state_p, path_t *path_p)
  1197     PyObject **pPackageList_p)
       
  1198 {
   955 {
       
   956 	PyObject *pPackageList = NULL;
  1199 	char **uniq_origins = NULL;
   957 	char **uniq_origins = NULL;
  1200 	char **types = NULL;
   958 	char **types = NULL;
  1201 	int origin_len, typelen;
   959 	int origin_len, typelen;
  1202 	char **origins;
   960 	char **origins;
  1203 	char **uniq_types;
   961 	char **uniq_types;
  1204 	int num_pkgspecs;
   962 	int num_pkg_specs;
  1205 	int i, j;
   963 	int i, j;
  1206 	int rval = AUTO_INSTALL_SUCCESS;
       
  1207 
       
  1208 	/*
       
  1209 	 * Initialize a zero-length list.
       
  1210 	 * This will be returned empty if nothing to install has been found
       
  1211 	 * or if an error is found early on.
       
  1212 	 */
       
  1213 	*pPackageList_p = PyList_New(0);
       
  1214 
   964 
  1215 	/* Read manifest for specific package requests. */
   965 	/* Read manifest for specific package requests. */
  1216 
   966 
  1217 	/* Get the number of <software> package spec entries. */
   967 	/* Get the number of pkg spec entries. */
  1218 	if (strlcpy(path_p->post_prefix_start, PKGSPEC_NODEPATH,
   968 	if (strlcpy(path_p->post_prefix_start, PKGSPEC_NODEPATH,
  1219 	    path_p->post_prefix_len) > path_p->post_prefix_len) {
   969 	    path_p->post_prefix_len) > path_p->post_prefix_len) {
  1220 		auto_debug_print(AUTO_DBGLVL_ERR, "ai_du_get_manual_pkg_list: "
   970 		auto_debug_print(AUTO_DBGLVL_ERR,
  1221 		    "<software> path buffer overflow\n");
   971 		    "ai_du_get_pkg_list: pkg spec path buffer overflow\n");
  1222 		return (AUTO_INSTALL_FAILURE);
   972 		return (NULL);
  1223 	}
   973 	}
  1224 
   974 
  1225 	/* Use "origins" like a dummy here.  Interest only in num_pkgspecs. */
   975 	/* Use "origins" like a dummy here.  Interest only in num_pkg_specs. */
  1226 	origins = ai_get_manifest_values(path_p->path_str, &num_pkgspecs);
   976 	origins = ai_get_manifest_values(path_p->path_str, &num_pkg_specs);
  1227 	ai_free_manifest_values(origins);
   977 	ai_free_manifest_values(origins);
  1228 
   978 
  1229 	/* No package specs.  Return an empty list. */
   979 	/* No pkg specs.  Return an empty list. */
  1230 	if (num_pkgspecs <= 0) {
   980 	if (num_pkg_specs <= 0) {
  1231 		return (AUTO_INSTALL_SUCCESS);
   981 		return (PyList_New(0));
  1232 	}
   982 	}
  1233 
   983 
  1234 	/* Retrieve a list of all specific package request origins. */
   984 	/* Retrieve a list of all specific package request origins. */
  1235 	if (strlcpy(path_p->post_prefix_start, ORIGIN_NODEPATH,
   985 	if (strlcpy(path_p->post_prefix_start, ORIGIN_NODEPATH,
  1236 	    path_p->post_prefix_len) > path_p->post_prefix_len) {
   986 	    path_p->post_prefix_len) > path_p->post_prefix_len) {
  1237 		auto_debug_print(AUTO_DBGLVL_ERR,
   987 		auto_debug_print(AUTO_DBGLVL_ERR,
  1238 		    "ai_du_get_manual_pkg_list: origin path buffer overflow\n");
   988 		    "ai_du_get_pkg_list: origin path buffer overflow\n");
  1239 		return (AUTO_INSTALL_FAILURE);
   989 		return (NULL);
  1240 	}
   990 	}
  1241 
   991 
  1242 	/* Get real origins list here for use below. */
   992 	/* Get real origins list here for use below. */
  1243 	origins = ai_get_manifest_values(path_p->path_str, &origin_len);
   993 	origins = ai_get_manifest_values(path_p->path_str, &origin_len);
  1244 
   994 
  1245 	/*
   995 	/*
  1246 	 * Not a perfect test to validate package specs vs origins in
   996 	 * Not a perfect test to validate pkg specs and origins in manifest,
  1247 	 * manifest, but it will do...
   997 	 * but it will do...
  1248 	 */
   998 	 */
  1249 	if (origin_len != num_pkgspecs) {
   999 	if (origin_len != num_pkg_specs) {
  1250 		auto_debug_print(AUTO_DBGLVL_ERR,
  1000 		auto_debug_print(AUTO_DBGLVL_ERR,
  1251 		    "ai_du_get_manual_pkg_list: <add_drivers> manifest error:\n"
  1001 		    "ai_du_get_pkg_list: <add_drivers> manifest error:\n"
  1252 		    "There is not a 1-1 <origin> - <software> mapping.\n");
  1002 		    "There is not a 1-1 origin to pkg spec mapping.\n");
  1253 		ai_free_manifest_values(origins);
  1003 		return (NULL);
  1254 		return (AUTO_INSTALL_FAILURE);
       
  1255 	}
  1004 	}
  1256 
  1005 
  1257 	uniq_origins = ai_uniq_manifest_values(origins, &origin_len);
  1006 	uniq_origins = ai_uniq_manifest_values(origins, &origin_len);
  1258 	ai_free_manifest_values(origins);
  1007 	ai_free_manifest_values(origins);
  1259 	origins = uniq_origins;
  1008 	origins = uniq_origins;
  1260 
  1009 
  1261 	/*
  1010 	/*
  1262 	 * For each origin (location), get types.  Note it is possible for
  1011 	 * Initialize a zero-length list.
  1263 	 * there to be more than one type at an origin.  There can also be more
  1012 	 * This will be returned empty if nothing to install has been found.
  1264 	 * than one item of a given type at an origin.
  1013 	 */
       
  1014 	pPackageList = PyList_New(0);
       
  1015 
       
  1016 	/*
       
  1017 	 * For each origin, get types.  Note it is possible for there to be
       
  1018 	 * more than one type at a origin.  There can also be more than one
       
  1019 	 * item of a given type at a origin.
  1265 	 */
  1020 	 */
  1266 	for (i = 0; i < origin_len; i++) {
  1021 	for (i = 0; i < origin_len; i++) {
  1267 
  1022 
  1268 		/* Process "type" entries. */
  1023 		/* Process "type" entries. */
  1269 
  1024 
  1270 		if (snprintf(path_p->post_prefix_start, path_p->post_prefix_len,
  1025 		if (snprintf(path_p->post_prefix_start, path_p->post_prefix_len,
  1271 		    TYPE_NODEPATH, origins[i]) >= path_p->post_prefix_len) {
  1026 		    TYPE_NODEPATH, origins[i]) >= path_p->post_prefix_len) {
  1272 			auto_debug_print(AUTO_DBGLVL_ERR,
  1027 			auto_debug_print(AUTO_DBGLVL_ERR,
  1273 			    "ai_du_get_manual_pkg_list: "
  1028 			    "ai_du_get_pkg_list: "
  1274 			    "<add_drivers> manifest error:\n"
  1029 			    "<add_drivers> manifest error:\n"
  1275 			    "type path buffer overflow for origin %s\n",
  1030 			    "type path buffer overflow for origin %s\n",
  1276 			    origins[i]);
  1031 			    origins[i]);
  1277 			rval = AUTO_INSTALL_FAILURE;
       
  1278 			continue;
  1032 			continue;
  1279 		}
  1033 		}
  1280 
  1034 
  1281 		types = ai_get_manifest_values(path_p->path_str, &typelen);
  1035 		types = ai_get_manifest_values(path_p->path_str, &typelen);
  1282 		if (typelen <= 0) {
  1036 		if (typelen <= 0) {
  1283 			auto_log_print(gettext("Add Drivers: "
  1037 			auto_log_print(gettext("ai_du_get_pkg_list: "
  1284 			    "<add_drivers> manifest error:\n"
  1038 			    "<add_drivers> manifest error:\n"
  1285 			    "no type given for origin %s\n"), origins[i]);
  1039 			    "no type given for origin %s\n"), origins[i]);
  1286 			rval = AUTO_INSTALL_FAILURE;
       
  1287 			continue;
  1040 			continue;
  1288 		}
  1041 		}
  1289 
  1042 
  1290 		uniq_types = ai_uniq_manifest_values(types, &typelen);
  1043 		uniq_types = ai_uniq_manifest_values(types, &typelen);
  1291 		ai_free_manifest_values(types);
  1044 		ai_free_manifest_values(types);
  1292 		types = uniq_types;
  1045 		types = uniq_types;
  1293 
  1046 
  1294 		/* Loop for all types found at this origin... */
  1047 		/* Loop for all types found at this origin... */
  1295 		for (j = 0; j < typelen; j++) {
  1048 		for (j = 0; j < typelen; j++) {
  1296 
  1049 
  1297 			/* Obj *pPackageList_p points to will be modified.  */
  1050 			/* Obj pointed to by pPackageList will be modified. */
  1298 			int status = ai_du_process_manual_pkg_types(py_state_p,
  1051 			ai_du_process_manual_pkg_types(py_state_p, pPackageList,
  1299 			    *pPackageList_p, path_p, origins[i], types[j]);
  1052 			    path_p, origins[i], types[j]);
  1300 			if (status == AUTO_INSTALL_FAILURE) {
  1053 		}
  1301 				rval = AUTO_INSTALL_FAILURE;
  1054 	}
  1302 			}
       
  1303 		}
       
  1304 	}
       
  1305 
       
  1306 	ai_free_manifest_values(origins);
  1055 	ai_free_manifest_values(origins);
  1307 	ai_free_manifest_values(types);
  1056 	ai_free_manifest_values(types);
  1308 	return (rval);
  1057 	return (pPackageList);
  1309 }
  1058 }
  1310 
  1059 
  1311 /*
  1060 /*
  1312  * ai_du_get_searched_pkg_list:
  1061  * ai_du_get_searched_pkg_list:
  1313  * Read the AI ai.xml Manifest file and process the <search_all> tag under the
  1062  * Read the AI ai.xml Manifest file and process the <search_all> tag under the
  1314  * <add_drivers> section.  Do the needful to scan for missing devices and to
  1063  * <add_drivers> section.  Do the needful to scan for missing devices and to
  1315  * perform package searches and installs for missing drivers.  Do error
  1064  * perform package searches and installs for missing drivers.  Do error
  1316  * checking of the manifest as necessary, as this function reads the manifest
  1065  * checking of the manifest as necessary, as this function reads the manifest
  1317  * before it is validated against a schema.
  1066  * before it is validated against a schema.
  1318  *
  1067  *
  1319  * Always return a list.  An empty list can be returned if a search determines
       
  1320  * there are no packages to install for Driver Update (i.e. the system is
       
  1321  * missing no drivers), or on some errors.
       
  1322  *
       
  1323  * Validates syntax and processes the following from the manifest:
  1068  * Validates syntax and processes the following from the manifest:
  1324  *	<add_drivers>
  1069  *	<add_drivers>
  1325  *		<search_all addall="false">
  1070  *		<search_all addall="false">
  1326  *			<source>
  1071  *			<source>
  1327  *				<publisher name="publisher">
  1072  *				<publisher name="publisher">
  1328  *					<origin name="location"/>
  1073  *					<origin name="origin"/>
  1329  *				</publisher>
  1074  *				</publisher>
  1330  *			</source>
  1075  *			</source>
  1331  *		</search_all>
  1076  *		</search_all>
  1332  *	</add_drivers>
  1077  *	</add_drivers>
  1333  *
  1078  *
  1334  *	publisher and origin are both optional, but if one is specified then
  1079  *  publisher and origin are both optional, but if one is specified then the
  1335  *		the other must also be specified.
  1080  *  other must also be specified.
  1336  *
  1081  *	addall is optional.  Defaults to "false" if not specified.
  1337  *	addall is optional.  When true, it allows search_all to install third
       
  1338  *	party drivers (found via the database in the given pkg(5) repository,
       
  1339  *	but installed from somewhere else).  Defaults to "false" if not
       
  1340  *	specified.
       
  1341  *
  1082  *
  1342  * Arguments:
  1083  * Arguments:
  1343  *   py_state_p: Initialized py_state_t object.
  1084  *   py_state_p: Initialized py_state_t object.
  1344  *   path_p: Used to build nodepath strings for manifest checking.
  1085  *   path_p: Used to build nodepath strings for manifest checking.
  1345  *   install_root: Root used for determining pkg publisher.
       
  1346  *   pPackageList_p: A python list of (ddu_package_object, third_party_ok,
       
  1347  *	noinstall) tuples suitable for input to ai_du_install_packages().
       
  1348  *
  1086  *
  1349  * Returns:
  1087  * Returns:
  1350  *   AUTO_INSTALL_SUCCESS: No errors were encountered in retrieving package
  1088  *   Success: A python list of (ddu_package_object, third_party_ok, noinstall)
  1351  *	information.  It is also possible that the system is missing no drivers,
  1089  *	tuples suitable for input to ai_du_install_packages().
  1352  *	and an empty list is returned.
  1090  *	NOTE: if the system is missing no drivers, this function will return
  1353  *   AUTO_INSTALL_PKG_NOT_FND: Packages for one or more missing drivers are not
  1091  *	an empty list.
  1354  *	available.
  1092  *   Failure: NULL
  1355  *   AUTO_INSTALL_FAILURE: One or more errors (other than packages which were
       
  1356  *	not available) were encountered in retrieving package information.
       
  1357  *
  1093  *
  1358  * NOTE: check installer logfile for details of the failure.
  1094  * NOTE: check installer logfile for details of the failure.
  1359  */
  1095  */
  1360 static int
  1096 static PyObject *
  1361 ai_du_get_searched_pkg_list(py_state_t *py_state_p, path_t *path_p,
  1097 ai_du_get_searched_pkg_list(py_state_t *py_state_p, path_t *path_p)
  1362     char *install_root, PyObject **pPackageList_p)
       
  1363 {
  1098 {
       
  1099 	PyObject *pPackageList = NULL;
  1364 	PyObject *pDeviceList = NULL;
  1100 	PyObject *pDeviceList = NULL;
  1365 	PyObject *pTuple;
  1101 	PyObject *pTuple;
  1366 	PyObject *pRepoTupleList;
  1102 	PyObject *pRepoTupleList;
  1367 	int len, sublen;
  1103 	int len, sublen;
  1368 	PyObject *pSearchRepoList = NULL;
  1104 	PyObject *pSearchRepoList = NULL;
  1371 	char **searches = NULL;
  1107 	char **searches = NULL;
  1372 	char **search_origins = NULL;
  1108 	char **search_origins = NULL;
  1373 	char **search_pubs = NULL;
  1109 	char **search_pubs = NULL;
  1374 	char **search_addalls = NULL;
  1110 	char **search_addalls = NULL;
  1375 	Py_ssize_t i, listlen;
  1111 	Py_ssize_t i, listlen;
  1376 	int rval = AUTO_INSTALL_FAILURE;
  1112 	PyObject *pRval = NULL;
  1377 
  1113 
  1378 	*pPackageList_p = PyList_New(0); /* Initialize a zero-length list. */
  1114 	pPackageList = PyList_New(0); /* Initialize a zero-length list. */
  1379 
  1115 
  1380 	/* Read manifest for search requests. */
  1116 	/* Read manifest for search requests. */
  1381 
  1117 
  1382 	if (strlcpy(path_p->post_prefix_start, SEARCH_NODEPATH,
  1118 	if (strlcpy(path_p->post_prefix_start, SEARCH_NODEPATH,
  1383 	    path_p->post_prefix_len) > path_p->post_prefix_len) {
  1119 	    path_p->post_prefix_len) > path_p->post_prefix_len) {
  1384 		auto_debug_print(AUTO_DBGLVL_ERR,
  1120 		auto_debug_print(AUTO_DBGLVL_ERR,
  1385 		    "ai_du_get_searched_pkg_list: "
  1121 		    "ai_du_get_searched_pkg_list: "
  1386 		    "search pathname buffer overflow.\n");
  1122 		    "search pathname buffer overflow.\n");
  1387 		return (AUTO_INSTALL_FAILURE);
  1123 		return (NULL);
  1388 	}
  1124 	}
  1389 
  1125 
  1390 	searches = ai_get_manifest_values(path_p->path_str, &len);
  1126 	searches = ai_get_manifest_values(path_p->path_str, &len);
  1391 	ai_free_manifest_values(searches);
  1127 	ai_free_manifest_values(searches);
  1392 	if (len > 1) {
  1128 	if (len > 1) {
  1393 		auto_log_print(gettext("Add Drivers: "
  1129 		auto_log_print(gettext("ai_du_get_searched_pkg_list: "
  1394 		    "Only one <search_all> entry allowed in manifest\n"));
  1130 		    "too many <search_all> entries in manifest\n"));
  1395 		return (AUTO_INSTALL_FAILURE);
  1131 		return (NULL);
  1396 	}
  1132 
  1397 
  1133 	} else if (len <= 0) {
  1398 	if (len <= 0) {
  1134 		return (pPackageList);
  1399 		return (AUTO_INSTALL_SUCCESS);
  1135 	}
  1400 	}
  1136 
  1401 
  1137 	auto_log_print(gettext("ai_du_get_searched_pkg_list: Doing a device "
  1402 	auto_log_print(gettext("Add Drivers: Doing a device "
       
  1403 	    "scan for devices which are missing drivers...\n"));
  1138 	    "scan for devices which are missing drivers...\n"));
  1404 
  1139 
  1405 	/*
  1140 	/*
  1406 	 * Call ddu_devscan() to do search if requested.
  1141 	 * Call ddu_devscan() to do search if requested.
  1407 	 * The boolean value is to scan only for missing drivers.
  1142 	 * The boolean value is to scan only for missing drivers.
  1408 	 */
  1143 	 */
  1409 	pDeviceList = ai_call_ddu_devscan(py_state_p, B_TRUE, "all");
  1144 	pDeviceList = ai_call_ddu_devscan(py_state_p, B_TRUE, "all");
  1410 	if (pDeviceList == NULL) {
  1145 	if (pDeviceList == NULL) {
  1411 		auto_debug_print(AUTO_DBGLVL_ERR,
  1146 		auto_debug_print(AUTO_DBGLVL_ERR,
  1412 		    "ai_du_get_searched_pkg_list: "
  1147 		    "ai_du_get_searched_pkg_list: "
  1413 		    "Error scanning for missing drivers.\n");
  1148 		    "Error scanning for missing devices.\n");
  1414 		return (AUTO_INSTALL_FAILURE);
  1149 		return (NULL);
  1415 
  1150 
  1416 	/* An empty list is perfectly acceptable here.  No missing drivers. */
  1151 	/* An empty list is perfectly acceptable here.  No missing drivers. */
  1417 	} else if (PyList_Size(pDeviceList) == 0) {
  1152 	} else if (PyList_Size(pDeviceList) == 0) {
  1418 		auto_debug_print(AUTO_DBGLVL_ERR,
  1153 		return (pPackageList);
  1419 		    "ai_du_get_searched_pkg_list: No missing drivers found.\n");
  1154 	}
  1420 		return (AUTO_INSTALL_SUCCESS);
  1155 
  1421 	}
  1156 	/* Get repo origin, if specified. */
  1422 
       
  1423 	/* Get repo location, if specified. */
       
  1424 
  1157 
  1425 	if (strlcpy(path_p->post_prefix_start, SEARCH_ORIGIN_NODEPATH,
  1158 	if (strlcpy(path_p->post_prefix_start, SEARCH_ORIGIN_NODEPATH,
  1426 	    path_p->post_prefix_len) > path_p->post_prefix_len) {
  1159 	    path_p->post_prefix_len) > path_p->post_prefix_len) {
  1427 		auto_debug_print(AUTO_DBGLVL_ERR,
  1160 		auto_debug_print(AUTO_DBGLVL_ERR,
  1428 		    "ai_du_get_searched_pkg_list: search repo origin path "
  1161 		    "ai_du_get_searched_pkg_list: search repo origin path "
  1429 		    "buffer overflow.\n");
  1162 		    "buffer overflow.\n");
  1430 		return (AUTO_INSTALL_FAILURE);
  1163 		return (NULL);
  1431 	}
  1164 	}
  1432 
  1165 
  1433 	auto_log_print(gettext("Add Drivers: Querying manifest "
  1166 	auto_log_print(gettext("ai_du_get_searched_pkg_list: Querying manifest "
  1434 	    "for explicit repo for getting missing driver packages...\n"));
  1167 	    "for explicit repo for getting missing driver packages...\n"));
  1435 
  1168 
  1436 	search_origins = ai_get_manifest_values(path_p->path_str, &sublen);
  1169 	search_origins = ai_get_manifest_values(path_p->path_str, &sublen);
  1437 	if (sublen == 1) {
  1170 	if (sublen == 1) {
  1438 		search_origin = search_origins[0];
  1171 		search_origin = search_origins[0];
  1439 	} else if (sublen <= 0) {
  1172 	} else if (sublen <= 0) {
  1440 		search_origin = empty_string;
  1173 		search_origin = empty_string;
  1441 	} else {
  1174 	} else {
  1442 		auto_log_print(gettext("Add Drivers: "
  1175 		auto_log_print(gettext("ai_du_get_searched_pkg_list: "
  1443 		    "<add_drivers> manifest error:\n"
  1176 		    "<add_drivers> manifest error:\n"
  1444 		    "Only one origin allowed per <search_all> entry.\n"));
  1177 		    "Only one origin allowed per <search_all> entry.\n"));
  1445 		goto done;
  1178 		goto done;
  1446 	}
  1179 	}
  1447 
  1180 
  1459 	if (sublen == 1) {
  1192 	if (sublen == 1) {
  1460 		search_pub = search_pubs[0];
  1193 		search_pub = search_pubs[0];
  1461 	} else if (sublen <= 0) {
  1194 	} else if (sublen <= 0) {
  1462 		search_pub = empty_string;
  1195 		search_pub = empty_string;
  1463 	} else {
  1196 	} else {
  1464 		auto_log_print(gettext("Add Drivers: "
  1197 		auto_log_print(gettext("ai_du_get_searched_pkg_list: "
  1465 		    "<add_drivers> manifest error:\n"
  1198 		    "<add_drivers> manifest error:\n"
  1466 		    "Only one publisher allowed for a <search_all> entry\n"));
  1199 		    "Only one publisher allowed for a <search_all> entry\n"));
  1467 		goto done;
  1200 		goto done;
  1468 	}
  1201 	}
  1469 
  1202 
  1470 	/* Can't have one without the other. */
  1203 	/* Can't have one without the other. */
  1471 	if ((search_pub == empty_string) ^
  1204 	if ((search_pub == empty_string) ^
  1472 	    (search_origin == empty_string)) {
  1205 	    (search_origin == empty_string)) {
  1473 		auto_log_print(gettext("Add Drivers: "
  1206 		auto_log_print(gettext("ai_du_get_searched_pkg_list: "
  1474 		    "<add_drivers> manifest error:\n"
  1207 		    "<add_drivers> manifest error:\n"
  1475 		    "search repo origin and "
  1208 		    "search repo origin and "
  1476 		    "publisher must be specified together.\n"));
  1209 		    "publisher must be specified together.\n"));
  1477 		goto done;
  1210 		goto done;
  1478 	}
  1211 	}
  1481 	 * if publisher and origin provided, create tuple from them and
  1214 	 * if publisher and origin provided, create tuple from them and
  1482 	 * build a repo list from it.
  1215 	 * build a repo list from it.
  1483 	 */
  1216 	 */
  1484 	if (search_pub != empty_string) {
  1217 	if (search_pub != empty_string) {
  1485 
  1218 
  1486 		auto_log_print(gettext("Add Drivers: "
  1219 		auto_log_print(gettext("ai_du_get_searched_pkg_list: "
  1487 		    "Found repo in manifest: publisher:%s, origin:%s\n"),
  1220 		    "Found repo in manifest: publisher:%s, origin:%s\n"),
  1488 		    search_pub, search_origin);
  1221 		    search_pub, search_origin);
  1489 
  1222 
  1490 		pTuple = PyTuple_New(2);
  1223 		pTuple = PyTuple_New(2);
  1491 		(void) PyTuple_SetItem(pTuple, 0,
  1224 		PyTuple_SetItem(pTuple, 0, PyString_FromString(search_pub));
  1492 		    PyString_FromString(search_pub));
  1225 		PyTuple_SetItem(pTuple, 1, PyString_FromString(search_origin));
  1493 		(void) PyTuple_SetItem(pTuple, 1,
       
  1494 		    PyString_FromString(search_origin));
       
  1495 		pRepoTupleList = PyList_New(0);
  1226 		pRepoTupleList = PyList_New(0);
  1496 		(void) PyList_Append(pRepoTupleList, pTuple);
  1227 		PyList_Append(pRepoTupleList, pTuple);
  1497 		pSearchRepoList = ai_call_ddu_build_repo_list(py_state_p,
  1228 		pSearchRepoList = ai_call_ddu_build_repo_list(py_state_p,
  1498 		    pRepoTupleList);
  1229 		    pRepoTupleList);
  1499 		Py_DECREF(pTuple);
  1230 		Py_DECREF(pTuple);
  1500 		Py_DECREF(pRepoTupleList);
  1231 		Py_DECREF(pRepoTupleList);
  1501 
  1232 
  1503 			auto_debug_print(AUTO_DBGLVL_ERR,
  1234 			auto_debug_print(AUTO_DBGLVL_ERR,
  1504 			    "ai_du_get_searched_pkg_list:"
  1235 			    "ai_du_get_searched_pkg_list:"
  1505 			    "Error building search repo list.\n");
  1236 			    "Error building search repo list.\n");
  1506 			goto done;
  1237 			goto done;
  1507 		}
  1238 		}
  1508 
       
  1509 		auto_log_print(gettext("Add Drivers: "
       
  1510 		    "Searching for packages in %s repository at %s\n"),
       
  1511 		    search_pub, search_origin);
       
  1512 
       
  1513 	} else {
  1239 	} else {
  1514 		FILE *pub_info;
       
  1515 		char pub_buf[MAXPATHLEN];
       
  1516 		char cmd_buf[MAXPATHLEN];
       
  1517 
       
  1518 		/* No publisher/URL provided.  Return an empty repo list. */
  1240 		/* No publisher/URL provided.  Return an empty repo list. */
  1519 
  1241 
  1520 		auto_log_print(gettext("Add Drivers: "
  1242 		auto_debug_print(AUTO_DBGLVL_INFO,
  1521 		    "No explicit <search_all> repo specified in manifest\n"));
  1243 		    "ai_du_get_searched_pkg_list: "
  1522 		auto_log_print(gettext("... Searching for packages in "
  1244 		    "No <search_all> repo found in manifest\n");
  1523 		    "repositories already configured on the system\n"));
       
  1524 
       
  1525 		(void) snprintf(cmd_buf, MAXPATHLEN,
       
  1526 		    "/usr/bin/pkg -R %s publisher", install_root);
       
  1527 		if ((pub_info = popen(cmd_buf, "r")) != NULL) {
       
  1528 			while (fgets(pub_buf, MAXPATHLEN, pub_info) != NULL) {
       
  1529 				auto_log_print("%s\n", pub_buf);
       
  1530 			}
       
  1531 			(void) pclose(pub_info);
       
  1532 		}
       
  1533 
  1245 
  1534 		pSearchRepoList = PyList_New(0);
  1246 		pSearchRepoList = PyList_New(0);
  1535 	}
  1247 	}
  1536 
  1248 
  1537 	/* Find out if <addall> was specified. */
  1249 	/* Find out if <addall> was specified. */
  1548 	search_addalls = ai_get_manifest_values(path_p->path_str, &sublen);
  1260 	search_addalls = ai_get_manifest_values(path_p->path_str, &sublen);
  1549 	if ((sublen > 1) ||
  1261 	if ((sublen > 1) ||
  1550 	    ((sublen == 1) &&
  1262 	    ((sublen == 1) &&
  1551 	    ((strcmp(search_addalls[0], "true") != 0) &&
  1263 	    ((strcmp(search_addalls[0], "true") != 0) &&
  1552 	    (strcmp(search_addalls[0], "false") != 0)))) {
  1264 	    (strcmp(search_addalls[0], "false") != 0)))) {
  1553 		auto_log_print(gettext("Add Drivers: "
  1265 		auto_log_print(gettext("ai_du_get_searched_pkg_list: "
  1554 		    "<add_drivers> manifest error:\n"
  1266 		    "<add_drivers> manifest error:\n"
  1555 		    "invalid addall value for <search_all> entry\n"));
  1267 		    "invalid addall value for <search_all> entry\n"));
  1556 		goto done;
  1268 		goto done;
  1557 
  1269 
  1558 	/* Default to false if not provided. */
  1270 	/* Default to false if not provided. */
  1559 	} else if ((sublen <= 0) || (strcmp(search_addalls[0], "false") == 0)) {
  1271 	} else if ((sublen <= 0) || (strcmp(search_addalls[0], "false") == 0)) {
  1560 		Py_INCREF(Py_False);
  1272 		Py_INCREF(Py_False);
  1561 		py_search_addall = Py_False;
  1273 		py_search_addall = Py_False;
  1562 
  1274 
  1563 	} else {
  1275 	} else {
  1564 		auto_log_print(gettext("Add Drivers: Manifest "
  1276 		auto_log_print(gettext("ai_du_get_searched_pkg_list: Manifest "
  1565 		    "allows adding of third-party drivers\n"));
  1277 		    "allows adding of third-party drivers\n"));
  1566 		Py_INCREF(Py_True);
  1278 		Py_INCREF(Py_True);
  1567 		py_search_addall = Py_True;
  1279 		py_search_addall = Py_True;
  1568 	}
  1280 	}
  1569 
  1281 
  1570 	/*
  1282 	/*
  1571 	 * Append packages found for missing devices, to the list of packages
  1283 	 * Append packages found for missing devices, to the list of packages
  1572 	 * to install.
  1284 	 * to install.
  1573 	 */
  1285 	 */
  1574 	rval = AUTO_INSTALL_SUCCESS;
       
  1575 	listlen = PyList_Size(pDeviceList);
  1286 	listlen = PyList_Size(pDeviceList);
  1576 	for (i = 0; i < listlen; i++) {
  1287 	for (i = 0; i < listlen; i++) {
  1577 
  1288 
  1578 		PyObject *pDDUPackageObject;
  1289 		PyObject *pDDUPackageObject;
  1579 		PyObject *pDDUDevData;
  1290 		PyObject *pDDUDevData;
  1580 		char *dev_type;
  1291 		char *dev_type;
  1581 		char *descr;
  1292 		char *descr;
  1582 		int lookup_err;
       
  1583 		boolean_t third_party = B_FALSE;
  1293 		boolean_t third_party = B_FALSE;
  1584 
  1294 
  1585 		pDDUDevData = PyList_GetItem(pDeviceList, i);
  1295 		pDDUDevData = PyList_GetItem(pDeviceList, i);
  1586 
  1296 
  1587 		/* Find the package containing the driver for this device. */
  1297 		/* Find the package containing the driver for this device. */
  1588 		lookup_err = ai_call_ddu_package_lookup(py_state_p,
  1298 		pDDUPackageObject = ai_call_ddu_package_lookup(py_state_p,
  1589 		    pDDUDevData, pSearchRepoList, &pDDUPackageObject);
  1299 		    pDDUDevData, pSearchRepoList);
  1590 
  1300 
  1591 		/* Get info for display / logging purposes, and log it. */
  1301 		/* Get info for display / logging purposes, and log it. */
  1592 		if (ai_get_ddu_dev_data_values(pDDUDevData, &dev_type, &descr,
  1302 		if (ai_get_ddu_dev_data_values(pDDUDevData,
  1593 		    NULL, NULL, NULL) != AUTO_INSTALL_SUCCESS) {
  1303 		    &dev_type, &descr) != AUTO_INSTALL_SUCCESS) {
  1594 			auto_debug_print(AUTO_DBGLVL_ERR,
  1304 			auto_debug_print(AUTO_DBGLVL_ERR,
  1595 			    "ai_du_get_searched_pkg_list: Error retrieving "
  1305 			    "ai_du_get_searched_pkg_list: Error retrieving "
  1596 			    "device information for display\n");
  1306 			    "device information for display\n");
  1597 			dev_type = descr = empty_string;
  1307 			dev_type = descr = empty_string;
  1598 		}
  1308 		}
  1599 
  1309 
  1600 		/* Package not found is not considered an error. */
  1310 		if (pDDUPackageObject == NULL) {
  1601 		if (lookup_err == AUTO_INSTALL_PKG_NOT_FND) {
  1311 			auto_log_print(gettext("ai_du_get_searched_pkg_list: "
  1602 			auto_log_print(gettext("Add Drivers: "
       
  1603 			    "Warning: Search found no package for "
       
  1604 			    "\"%s\" type device \"%s\".\n"), dev_type, descr);
       
  1605 			/*
       
  1606 			 * Set marginal success status.
       
  1607 			 * Don't override failure status.
       
  1608 			 */
       
  1609 			if (rval == AUTO_INSTALL_SUCCESS) {
       
  1610 				rval = AUTO_INSTALL_PKG_NOT_FND;
       
  1611 			}
       
  1612 			continue;
       
  1613 		} else if (lookup_err != AUTO_INSTALL_SUCCESS) {
       
  1614 			auto_log_print(gettext("Add Drivers: "
       
  1615 			    "Error retrieving package for "
  1312 			    "Error retrieving package for "
  1616 			    "\"%s\" type device \"%s\".\n"), dev_type, descr);
  1313 			    "\"%s\" type device \"%s\".\n"), dev_type, descr);
  1617 			rval = AUTO_INSTALL_FAILURE;
       
  1618 			continue;
  1314 			continue;
  1619 		} else {
  1315 		} else {
  1620 			auto_log_print(gettext("Add Drivers: "
  1316 			auto_log_print(gettext("ai_du_get_searched_pkg_list: "
  1621 			    "DDU returned package info for "
  1317 			    "DDU returned package info for "
  1622 			    "\"%s\" type device \"%s\".\n"), dev_type, descr);
  1318 			    "\"%s\" type device \"%s\".\n"), dev_type, descr);
  1623 		}
  1319 		}
  1624 
  1320 
  1625 		(void) ai_get_ddu_package_object_values(pDDUPackageObject,
  1321 		(void) ai_get_ddu_package_object_values(pDDUPackageObject,
  1634 		/*
  1330 		/*
  1635 		 * NOTE: Don't decref pTuple here as PyList_Append doesn't
  1331 		 * NOTE: Don't decref pTuple here as PyList_Append doesn't
  1636 		 * steal a reference to it.
  1332 		 * steal a reference to it.
  1637 		 */
  1333 		 */
  1638 		pTuple = PyTuple_New(3);
  1334 		pTuple = PyTuple_New(3);
  1639 		(void) PyTuple_SetItem(pTuple, 0, pDDUPackageObject);
  1335 		PyTuple_SetItem(pTuple, 0, pDDUPackageObject);
  1640 		Py_INCREF(py_search_addall);	/* 3rd party OK */
  1336 		Py_INCREF(py_search_addall);
  1641 		(void) PyTuple_SetItem(pTuple, 1, py_search_addall);
  1337 		PyTuple_SetItem(pTuple, 1, py_search_addall); /* 3rd party OK */
  1642 		Py_INCREF(Py_False);		/* always install */
  1338 		Py_INCREF(Py_False);
  1643 		(void) PyTuple_SetItem(pTuple, 2, Py_False);
  1339 		PyTuple_SetItem(pTuple, 2, Py_False);	/* always install */
  1644 		(void) PyList_Append(*pPackageList_p, pTuple);
  1340 
  1645 	}
  1341 		PyList_Append(pPackageList, pTuple);
       
  1342 	}
       
  1343 
       
  1344 	/* Success.  Prepare to return the package list just prepared. */
       
  1345 	pRval = pPackageList;
       
  1346 
  1646 done:
  1347 done:
  1647 	/* Cleanup time, whether an error occured or not. */
  1348 	/* Cleanup time, whether an error occured or not. */
  1648 	ai_free_manifest_values(search_origins);
  1349 	ai_free_manifest_values(search_origins);
  1649 	ai_free_manifest_values(search_pubs);
  1350 	ai_free_manifest_values(search_pubs);
  1650 	Py_XDECREF(py_search_addall);
  1351 	Py_XDECREF(py_search_addall);
  1651 	Py_XDECREF(pSearchRepoList);
  1352 	Py_XDECREF(pSearchRepoList);
  1652 	Py_XDECREF(pDeviceList);
  1353 	Py_XDECREF(pDeviceList);
  1653 	return (rval);
  1354 	return (pRval);
  1654 }
  1355 }
  1655 
  1356 
  1656 /*
  1357 /*
  1657  * ai_du_install_packages:
  1358  * ai_du_install_packages:
  1658  * Install packages provided by the pPkgTupleList.  Install in the filesystem /
  1359  * Install packages provided by the pPkgTupleList.  Install in the filesystem /
  1659  * tree under install_root, skipping packages with noinstall flag set if
  1360  * tree under install_root, skipping packages with noinstall flag set if
  1660  * honor_noinstall is set.
  1361  * honor_noinstall is set.
  1661  *
       
  1662  * NOTE: it is assumed that the DDU library returns successful status when
       
  1663  * attempting to install a package which is already installed.
       
  1664  *
  1362  *
  1665  * Arguments:
  1363  * Arguments:
  1666  *   py_state_p: Initialized py_state_t object.
  1364  *   py_state_p: Initialized py_state_t object.
  1667  *   pPkgTupleList: Python list of (ddu_package_object, third_party_ok,
  1365  *   pPkgTupleList: Python list of (ddu_package_object, third_party_ok,
  1668  *	noinstall) tuples which define packages to add and their parameters for
  1366  *	noinstall) tuples which define packages to add and their parameters for
  1691 {
  1389 {
  1692 	Py_ssize_t len;
  1390 	Py_ssize_t len;
  1693 	Py_ssize_t i;
  1391 	Py_ssize_t i;
  1694 	int rval = AUTO_INSTALL_SUCCESS;
  1392 	int rval = AUTO_INSTALL_SUCCESS;
  1695 
  1393 
  1696 	auto_log_print(gettext("Add Drivers: "
  1394 	auto_log_print(gettext("ai_du_install_packages: "
  1697 	    "Installing packages to %s\n"), install_root);
  1395 	    "Installing packages to %s\n"), install_root);
  1698 
  1396 
  1699 	len = PyList_Size(pPkgTupleList);
  1397 	len = PyList_Size(pPkgTupleList);
  1700 	for (i = 0; i < len; i++) {
  1398 	for (i = 0; i < len; i++) {
  1701 
  1399 
  1703 
  1401 
  1704 		PyObject *pTuple = PyList_GetItem(pPkgTupleList, i);
  1402 		PyObject *pTuple = PyList_GetItem(pPkgTupleList, i);
  1705 		PyObject *pDDUPackageObject = PyTuple_GetItem(pTuple, 0);
  1403 		PyObject *pDDUPackageObject = PyTuple_GetItem(pTuple, 0);
  1706 		PyObject *pThirdPartyOK = PyTuple_GetItem(pTuple, 1);
  1404 		PyObject *pThirdPartyOK = PyTuple_GetItem(pTuple, 1);
  1707 		PyObject *pNoInstall = PyTuple_GetItem(pTuple, 2);
  1405 		PyObject *pNoInstall = PyTuple_GetItem(pTuple, 2);
  1708 		char *type, *location, *name, *descr, *inf_link;
  1406 		char *type = empty_string;
       
  1407 		char *origin = empty_string;
       
  1408 		char *name = empty_string;
       
  1409 		char *descr = empty_string;
       
  1410 		char *inf_link = empty_string;
  1709 		boolean_t third_party;
  1411 		boolean_t third_party;
  1710 
  1412 
  1711 		if (ai_get_ddu_package_object_values(pDDUPackageObject,
  1413 		if (ai_get_ddu_package_object_values(pDDUPackageObject,
  1712 		    &type, &location, &name, &descr, &inf_link, &third_party) !=
  1414 		    &type, &origin, &name, &descr, &inf_link, &third_party) !=
  1713 		    AUTO_INSTALL_SUCCESS) {
  1415 		    AUTO_INSTALL_SUCCESS) {
  1714 			auto_debug_print(AUTO_DBGLVL_ERR,
  1416 			auto_debug_print(AUTO_DBGLVL_ERR,
  1715 			    "ai_du_install_packages: Error extracting package "
  1417 			    "ai_du_install_packages: Error extracting package "
  1716 			    "information for ddu_package_object.\n");
  1418 			    "information for ddu_package_object.\n");
  1717 			type = location = name = descr = inf_link =
  1419 			type = origin = name = descr = inf_link =
  1718 			    empty_string;
  1420 			    empty_string;
  1719 			third_party = B_FALSE;
  1421 			third_party = B_FALSE;
  1720 		} else {
  1422 		} else {
  1721 			if (strcmp(name, empty_string) == 0) {
  1423 			if (strcmp(name, empty_string) == 0) {
  1722 				auto_log_print(gettext(
  1424 				auto_log_print(gettext(
  1723 				    "  %s package at origin:%s\n"),
  1425 				    "  %s package at origin:%s\n"),
  1724 				    type, location);
  1426 				    type, origin);
  1725 			} else {
  1427 			} else {
  1726 				auto_log_print(gettext(
  1428 				auto_log_print(gettext(
  1727 				    "  %s package at origin:%s, name:%s\n"),
  1429 				    "  %s package at origin:%s, name:%s\n"),
  1728 				    type, location, name);
  1430 				    type, origin, name);
  1729 			}
  1431 			}
  1730 		}
  1432 		}
  1731 
  1433 
  1732 		if (PyObject_IsTrue(pNoInstall) && honor_noinstall) {
  1434 		if (PyObject_IsTrue(pNoInstall) && honor_noinstall) {
  1733 			auto_log_print(gettext("Add Drivers: "
  1435 			auto_log_print(gettext("ai_du_install_packages: "
  1734 			    "    honoring noinstall: skipping package.\n"));
  1436 			    "    honoring noinstall: skipping package.\n"));
  1735 			continue;
  1437 			continue;
  1736 		}
  1438 		}
  1737 
  1439 
  1738 		/* Display any third-party package errors to console. */
  1440 		/* Display any third-party package errors to console. */
  1751 			rval = AUTO_INSTALL_FAILURE;
  1453 			rval = AUTO_INSTALL_FAILURE;
  1752 			continue;
  1454 			continue;
  1753 		}
  1455 		}
  1754 
  1456 
  1755 		/* Handle uninstallable package objects. */
  1457 		/* Handle uninstallable package objects. */
  1756 		if (strcmp(location, empty_string) == 0) {
  1458 		if (strcmp(origin, empty_string) == 0) {
  1757 			if (strcmp(inf_link, empty_string) == 0) {
  1459 			if (strcmp(inf_link, empty_string) == 0) {
  1758 				auto_log_print(gettext(
  1460 				auto_log_print(gettext(
  1759 				    "Add Drivers: Package not "
  1461 				    "ai_du_install_packages: Package not "
  1760 				    "found for device: \"%s\"\n"), descr);
  1462 				    "found for device: \"%s\"\n"), descr);
  1761 			} else {
  1463 			} else {
  1762 				auto_log_print(gettext(
  1464 				auto_log_print(gettext(
  1763 				    "Add Drivers: Package for device: \"%s\" "
  1465 				    "ai_du_install_packages: Package for "
  1764 				    "must be installed manually.\n"
  1466 				    "device: \"%s\" must be installed "
       
  1467 				    "manually.\n"
  1765 				    "For more information go to:\n %s\n"),
  1468 				    "For more information go to:\n %s\n"),
  1766 				    descr, inf_link);
  1469 				    descr, inf_link);
  1767 			}
  1470 			}
  1768 			rval = AUTO_INSTALL_FAILURE;
  1471 			rval = AUTO_INSTALL_FAILURE;
  1769 			continue;
  1472 			continue;
  1771 
  1474 
  1772 		/* All is well.  Install the package. */
  1475 		/* All is well.  Install the package. */
  1773 		if (ai_call_ddu_install_package(py_state_p, pDDUPackageObject,
  1476 		if (ai_call_ddu_install_package(py_state_p, pDDUPackageObject,
  1774 		    install_root, PyObject_IsTrue(pThirdPartyOK)) ==
  1477 		    install_root, PyObject_IsTrue(pThirdPartyOK)) ==
  1775 		    AUTO_INSTALL_FAILURE) {
  1478 		    AUTO_INSTALL_FAILURE) {
  1776 			auto_log_print(gettext("Add Drivers: "
  1479 			auto_log_print(gettext("ai_du_install_packages: "
  1777 			    "Error installing package to %s\n"), install_root);
  1480 			    "Error installing package to %s\n"), install_root);
  1778 			rval = AUTO_INSTALL_FAILURE;
  1481 			rval = AUTO_INSTALL_FAILURE;
  1779 		} else {
  1482 		} else {
  1780 			(*num_installed_pkgs_p)++;
  1483 			(*num_installed_pkgs_p)++;
  1781 		}
  1484 		}
  1821 			}
  1524 			}
  1822 		}
  1525 		}
  1823 	}
  1526 	}
  1824 
  1527 
  1825 	out = (char **)malloc((in_len - dup_count + 1) * sizeof (char *));
  1528 	out = (char **)malloc((in_len - dup_count + 1) * sizeof (char *));
  1826 	if (out == NULL) {
       
  1827 		return (NULL);
       
  1828 	}
       
  1829 	for (i = 0, j = 0; i < in_len; i++) {
  1529 	for (i = 0, j = 0; i < in_len; i++) {
  1830 		if (!is_dup[i]) {
  1530 		if (!is_dup[i]) {
  1831 			out[j++] = strdup(in[i]);
  1531 			out[j++] = strdup(in[i]);
  1832 		}
  1532 		}
  1833 	}
  1533 	}
  1864 		auto_debug_print(AUTO_DBGLVL_ERR,
  1564 		auto_debug_print(AUTO_DBGLVL_ERR,
  1865 		    "ICT constructor not callable\n");
  1565 		    "ICT constructor not callable\n");
  1866 	} else {
  1566 	} else {
  1867 		/* Set up args to python function. */
  1567 		/* Set up args to python function. */
  1868 		PyObject *pArgs = PyTuple_New(1);
  1568 		PyObject *pArgs = PyTuple_New(1);
  1869 		(void) PyTuple_SetItem(pArgs, 0,
  1569 		PyTuple_SetItem(pArgs, 0, PyString_FromString(install_root));
  1870 		    PyString_FromString(install_root));
       
  1871 
  1570 
  1872 		/* Call constructor. */
  1571 		/* Call constructor. */
  1873 		pICT_instance = PyObject_CallObject(pFunc, pArgs);
  1572 		pICT_instance = PyObject_CallObject(pFunc, pArgs);
  1874 		Py_XDECREF(pFunc);
  1573 		Py_XDECREF(pFunc);
  1875 		Py_DECREF(pArgs);
  1574 		Py_DECREF(pArgs);
  1876 		if ((PyErr_Occurred() != NULL) || (pICT_instance == NULL) ||
  1575 		if ((PyErr_Occurred()) || (pICT_instance == NULL) ||
  1877 		    (pICT_instance == Py_None)) {
  1576 		    (pICT_instance == Py_None)) {
  1878 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
  1577 			auto_debug_dump_file(AUTO_DBGLVL_ERR, DDU_ERRLOG);
  1879 			auto_debug_print(AUTO_DBGLVL_ERR,
  1578 			auto_debug_print(AUTO_DBGLVL_ERR,
  1880 			    "ICT constructor failed\n");
  1579 			    "ICT constructor failed\n");
  1881 			ai_dump_python_exception();
  1580 			if (PyErr_Occurred()) {
       
  1581 				PyErr_Print();
       
  1582 			}
  1882 			Py_CLEAR(pICT_instance);
  1583 			Py_CLEAR(pICT_instance);
  1883 		}
  1584 		}
  1884 	}
  1585 	}
  1885 
  1586 
  1886 	if (pICT_instance != NULL) {
  1587 	if (pICT_instance != NULL) {
  1915  *
  1616  *
  1916  * Install all explicitly-stated packages first.  Then do <search_all> last.
  1617  * Install all explicitly-stated packages first.  Then do <search_all> last.
  1917  * This is to handle any explicit requests for matching a special driver to a
  1618  * This is to handle any explicit requests for matching a special driver to a
  1918  * device, before <search_all> finds the first available one.
  1619  * device, before <search_all> finds the first available one.
  1919  *
  1620  *
  1920  * If search determines that a driver is missing and cannot find a package for
       
  1921  * it, this is not reported as an error.  A ddu_package_object is not created in
       
  1922  * this case, so no installation or package fetch is done for this driver.  Any
       
  1923  * other kind of problem which occurs around searched packages, during the
       
  1924  * search itself or during an installation of a package found during search, is
       
  1925  * reported as an error.
       
  1926  *
       
  1927  * Any issue found around explicitly specified packages (<software>s), whether
       
  1928  * it be that the package is not found or there was an issue during
       
  1929  * installation, is reported as an error.  ddu_package_objects are always
       
  1930  * created for these packages.
       
  1931  *
       
  1932  * Assumes ai_create_manifest_image() has set up the manifest data.
  1621  * Assumes ai_create_manifest_image() has set up the manifest data.
  1933  * Does not assume any data has been verified though.
  1622  * Does not assume any data has been verified though.
  1934  *
  1623  *
  1935  * Arguments:
  1624  * Arguments:
  1936  *   install_root: Top of the filesystem or tree where the packages are to be
  1625  *   install_root: Top of the filesystem or tree where the packages are to be
  1937  *	installed.
  1626  *	installed.
  1938  *   honor_noinstall: When true and the noinstall flag is set in a package
  1627  *   honor_noinstall: When true and the noinstall flag is set in a package
  1939  *	tuple, skip installing that package.
  1628  *	tuple, skip installing that package.
  1940  *   update_boot_archive: When true, run the ICT to update the boot archive.
  1629  *   update_boot_archive: When true, run the ICT to update the boot archive.
  1941  *   num_pkgs_installed_p: Returns the number of packages installed.
       
  1942  *
  1630  *
  1943  * Returns:
  1631  * Returns:
  1944  *   AUTO_INSTALL_SUCCESS: No errors found.
  1632  *   The number of packages successfully processed if all are successfully
  1945  *   AUTO_INSTALL_PKG_NOT_FND: At least one needed package found during search
  1633  *	processed.  NOTE: this can be zero if there are none to process.
  1946  *	could not be found.  No other errors encountered.
  1634  *   -1: One or more packages could not be successfully processed.
  1947  *   AUTO_INSTALL_FAILURE: An error was encountered and was different than
       
  1948  *	not being able to find a package for a missing driver.
       
  1949  *
       
  1950  *   Boot archive update status is not reflected in this return status.
  1635  *   Boot archive update status is not reflected in this return status.
  1951  *   NOTE: this routine will continue on most errors, in order to install as
  1636  *   NOTE: this routine will continue on most errors, in order to install as
  1952  *	many packages as possible.
  1637  *	many packages as possible.
  1953  *
  1638  *
  1954  * NOTE: return status and num_pkgs_installed together tell the caller the full
       
  1955  * story.  It is possible, for example, that no packages were installed because
       
  1956  * one package flagged during search could not be found.
       
  1957  *
       
  1958  * NOTE: check installer logfile for details of the failure.
  1639  * NOTE: check installer logfile for details of the failure.
  1959  *
  1640  *
  1960  * Side effects:
  1641  * Side effects:
  1961  *   module global py_pkg_list is set to point to list of packages to install.
  1642  *   module global py_pkg_list is set to point to list of packages to install.
  1962  */
  1643  */
  1963 int
  1644 int
  1964 ai_du_get_and_install(char *install_root, boolean_t honor_noinstall,
  1645 ai_du_get_and_install(char *install_root, boolean_t honor_noinstall,
  1965     boolean_t update_boot_archive, int *num_installed_pkgs_p)
  1646     boolean_t update_boot_archive)
  1966 {
  1647 {
  1967 	PyObject *manual_pkg_list;
  1648 	PyObject *manual_pkg_list;
  1968 	PyObject *searched_pkg_list;
  1649 	PyObject *searched_pkg_list;
  1969 	py_state_t *py_state_p;
  1650 	py_state_t *py_state_p;
  1970 	path_t path;
  1651 	path_t path;
  1971 	char **dummy_list;
  1652 	char **dummy_list;
  1972 	int num_entries;
  1653 	int num_entries;
  1973 	int len;
  1654 	int len;
  1974 	Py_ssize_t manual_size = 0;
  1655 	Py_ssize_t manual_size = 0;
  1975 	Py_ssize_t searched_size = 0;
  1656 	Py_ssize_t searched_size = 0;
  1976 	int rval = AUTO_INSTALL_SUCCESS;
  1657 	int rval = 0;
  1977 
  1658 	int num_pkgs_installed = 0;
  1978 	*num_installed_pkgs_p = 0;
       
  1979 
  1659 
  1980 	/* Initialize path, post_prefix_start and post_prefix_len for later. */
  1660 	/* Initialize path, post_prefix_start and post_prefix_len for later. */
  1981 	(void) strncpy(path.path_str, AIM_PREFACE, MAX_NODEPATH_SIZE);
  1661 	(void) strncpy(path.path_str, AIM_PREFACE, MAX_NODEPATH_SIZE);
  1982 	len = strlen(path.path_str);
  1662 	len = strlen(path.path_str);
  1983 	path.post_prefix_start = &path.path_str[len];
  1663 	path.post_prefix_start = &path.path_str[len];
  1992 	}
  1672 	}
  1993 
  1673 
  1994 	py_pkg_list = PyList_New(0);
  1674 	py_pkg_list = PyList_New(0);
  1995 
  1675 
  1996 	/*
  1676 	/*
  1997 	 * See if the manifest has at least one <software> or search_all entry.
  1677 	 * See if the manifest has at least one pkg spec or searchall entry.
  1998 	 * If not, just return success (e.g. no-op).
  1678 	 * If not, just return success (e.g. no-op).
  1999 	 */
  1679 	 */
  2000 
  1680 
  2001 	/* Get the number of <software> entries. */
  1681 	/* Get the number of pkg spec entries. */
  2002 	if (strlcpy(path.post_prefix_start, PKGSPEC_NODEPATH,
  1682 	if (strlcpy(path.post_prefix_start, PKGSPEC_NODEPATH,
  2003 	    path.post_prefix_len) > path.post_prefix_len) {
  1683 	    path.post_prefix_len) > path.post_prefix_len) {
  2004 		auto_debug_print(AUTO_DBGLVL_ERR,
  1684 		auto_debug_print(AUTO_DBGLVL_ERR,
  2005 		    "ai_du_get_and_install: <software> path buffer overflow\n");
  1685 		    "ai_du_get_and_install: pkg spec path buffer overflow\n");
  2006 		return (AUTO_INSTALL_FAILURE);
  1686 		return (-1);
  2007 	}
  1687 	}
  2008 
  1688 
  2009 	/* Get number of <software> entries in the manifest. */
  1689 	/* Get number of pkg spec entries in the manifest. */
  2010 	dummy_list = ai_get_manifest_values(path.path_str, &num_entries);
  1690 	dummy_list = ai_get_manifest_values(path.path_str, &num_entries);
  2011 	ai_free_manifest_values(dummy_list);
  1691 	ai_free_manifest_values(dummy_list);
  2012 
  1692 
  2013 	if (num_entries <= 0) {
  1693 	if (num_entries <= 0) {
  2014 		/* See if there is a search_all entry in the manifest. */
  1694 		/* See if there is a searchall entry in the manifest. */
  2015 		if (strlcpy(path.post_prefix_start, SEARCH_NODEPATH,
  1695 		if (strlcpy(path.post_prefix_start, SEARCH_NODEPATH,
  2016 		    path.post_prefix_len) > path.post_prefix_len) {
  1696 		    path.post_prefix_len) > path.post_prefix_len) {
  2017 			auto_debug_print(AUTO_DBGLVL_ERR,
  1697 			auto_debug_print(AUTO_DBGLVL_ERR,
  2018 			    "ai_du_get_and_install: "
  1698 			    "ai_du_get_and_install: "
  2019 			    "search path buffer overflow\n");
  1699 			    "search path buffer overflow\n");
  2020 			return (AUTO_INSTALL_FAILURE);
  1700 			return (-1);
  2021 		}
  1701 		}
  2022 
  1702 
  2023 		dummy_list = ai_get_manifest_values(path.path_str,
  1703 		dummy_list = ai_get_manifest_values(path.path_str,
  2024 		    &num_entries);
  1704 		    &num_entries);
  2025 		ai_free_manifest_values(dummy_list);
  1705 		ai_free_manifest_values(dummy_list);
  2026 		if (num_entries <= 0) {
  1706 		if (num_entries <= 0) {
  2027 			return (AUTO_INSTALL_SUCCESS);
  1707 			return (0);
  2028 		}
  1708 		}
  2029 	}
  1709 	}
  2030 
  1710 
  2031 	/*
  1711 	/*
  2032 	 * Install all explicitly specified packages first.
  1712 	 * Install all explicitly specified packages first.
  2038 
  1718 
  2039 	if ((py_state_p = auto_ddu_lib_init()) == NULL) {
  1719 	if ((py_state_p = auto_ddu_lib_init()) == NULL) {
  2040 		auto_debug_print(AUTO_DBGLVL_ERR,
  1720 		auto_debug_print(AUTO_DBGLVL_ERR,
  2041 		    "ai_du_get_and_install: "
  1721 		    "ai_du_get_and_install: "
  2042 		    "Error initializing auto_ddu_lib.\n");
  1722 		    "Error initializing auto_ddu_lib.\n");
  2043 		rval = AUTO_INSTALL_FAILURE;
  1723 		rval = -1;
  2044 		goto done;
  1724 		goto done;
  2045 	}
  1725 	}
  2046 
  1726 
  2047 	if (ai_du_get_manual_pkg_list(py_state_p, &path,
  1727 	manual_pkg_list = ai_du_get_manual_pkg_list(py_state_p, &path);
  2048 	    &manual_pkg_list) != AUTO_INSTALL_SUCCESS) {
  1728 	if (manual_pkg_list == NULL) {
  2049 		auto_debug_print(AUTO_DBGLVL_ERR,
  1729 		auto_debug_print(AUTO_DBGLVL_ERR,
  2050 		    "ai_du_get_and_install: "
  1730 		    "ai_du_get_and_install: "
  2051 		    "Error getting <software> package specification.\n");
  1731 		    "Error getting package specification.\n");
  2052 		rval = AUTO_INSTALL_FAILURE;
  1732 		rval = -1;
  2053 		/* Keep going.  Don't abort. */
  1733 		/* Keep going.  Don't abort. */
  2054 	}
  1734 	} else {
  2055 
  1735 		manual_size = PyList_Size(manual_pkg_list);
  2056 	manual_size = PyList_Size(manual_pkg_list);
  1736 		if (manual_size > 0) {
  2057 	if (manual_size > 0) {
  1737 			if (ai_du_install_packages(py_state_p, manual_pkg_list,
  2058 		if (ai_du_install_packages(py_state_p, manual_pkg_list,
  1738 			    install_root, honor_noinstall,
  2059 		    install_root, honor_noinstall, num_installed_pkgs_p) !=
  1739 			    &num_pkgs_installed) != AUTO_INSTALL_SUCCESS) {
  2060 		    AUTO_INSTALL_SUCCESS) {
  1740 				auto_debug_print(AUTO_DBGLVL_ERR,
  2061 			auto_debug_print(AUTO_DBGLVL_ERR,
  1741 				    "ai_du_get_and_install: Error installing "
  2062 			    "ai_du_get_and_install: Error installing at least "
  1742 				    "at least one package.\n");
  2063 			    "one <software> package specification.\n");
  1743 				rval = -1;
  2064 			rval = AUTO_INSTALL_FAILURE;
  1744 				/* Keep going.  Don't abort. */
  2065 			/* Keep going.  Don't abort. */
  1745 			}
  2066 		}
  1746 		}
  2067 	}
  1747 	}
  2068 
  1748 
  2069 	switch (ai_du_get_searched_pkg_list(py_state_p, &path, install_root,
  1749 	searched_pkg_list = ai_du_get_searched_pkg_list(py_state_p, &path);
  2070 	    &searched_pkg_list)) {
  1750 	if (searched_pkg_list == NULL) {
  2071 	case AUTO_INSTALL_FAILURE:
       
  2072 		rval = AUTO_INSTALL_FAILURE;
       
  2073 		auto_debug_print(AUTO_DBGLVL_ERR,
  1751 		auto_debug_print(AUTO_DBGLVL_ERR,
  2074 		    "ai_du_get_and_install: "
  1752 		    "ai_du_get_and_install: "
  2075 		    "Error searching for inoperable devices and "
  1753 		    "Error searching for inoperable devices and "
  2076 		    "missing driver packages.\n");
  1754 		    "missing driver packages.\n");
       
  1755 		rval = -1;
  2077 		/* Keep going.  Don't abort. */
  1756 		/* Keep going.  Don't abort. */
  2078 		break;
  1757 	} else {
  2079 	case AUTO_INSTALL_PKG_NOT_FND:
  1758 		searched_size = PyList_Size(searched_pkg_list);
  2080 		if (rval != AUTO_INSTALL_FAILURE) {
  1759 		if (searched_size > 0) {
  2081 			rval = AUTO_INSTALL_PKG_NOT_FND;
  1760 			if (ai_du_install_packages(py_state_p,
  2082 		}
  1761 			    searched_pkg_list, install_root, honor_noinstall,
  2083 		break;
  1762 			    &num_pkgs_installed) != AUTO_INSTALL_SUCCESS) {
  2084 	default:
  1763 				auto_debug_print(AUTO_DBGLVL_ERR,
  2085 		break;
  1764 				    "ai_du_get_and_install: Error installing "
  2086 	}
  1765 				    "at least one searched package "
  2087 
  1766 				    "for <search_all>.\n");
  2088 	searched_size = PyList_Size(searched_pkg_list);
  1767 				rval = -1;
  2089 	if (searched_size > 0) {
  1768 				/* Keep going.  Don't abort. */
  2090 		if (ai_du_install_packages(py_state_p, searched_pkg_list,
  1769 			}
  2091 		    install_root, honor_noinstall, num_installed_pkgs_p) !=
  1770 		}
  2092 		    AUTO_INSTALL_SUCCESS) {
  1771 	}
  2093 			auto_debug_print(AUTO_DBGLVL_ERR,
  1772 
  2094 			    "ai_du_get_and_install: Error installing at least "
  1773 	if ((update_boot_archive) && (num_pkgs_installed > 0)) {
  2095 			    "one searched package for <search_all>.\n");
       
  2096 			rval = AUTO_INSTALL_FAILURE;
       
  2097 			/* Keep going.  Don't abort. */
       
  2098 		}
       
  2099 	}
       
  2100 
       
  2101 	if (update_boot_archive && (*num_installed_pkgs_p > 0)) {
       
  2102 		if (ai_du_call_update_archive_ict(py_state_p, install_root) !=
  1774 		if (ai_du_call_update_archive_ict(py_state_p, install_root) !=
  2103 		    AUTO_INSTALL_SUCCESS) {
  1775 		    AUTO_INSTALL_SUCCESS) {
  2104 			auto_debug_print(AUTO_DBGLVL_ERR,
  1776 			auto_debug_print(AUTO_DBGLVL_ERR,
  2105 			    "ai_du_get_and_install: Warning: could not update "
  1777 			    "ai_du_get_and_install: Warning: could not update "
  2106 			    "boot archive for %s.\n", install_root);
  1778 			    "boot archive for %s.\n", install_root);
  2111 	 * Save the manual and searched package lists in py_pkg_list.
  1783 	 * Save the manual and searched package lists in py_pkg_list.
  2112 	 * The new list can be used in a later call to ai_du_install().
  1784 	 * The new list can be used in a later call to ai_du_install().
  2113 	 */
  1785 	 */
  2114 
  1786 
  2115 	if (manual_size > 0) {
  1787 	if (manual_size > 0) {
  2116 		(void) PyList_SetSlice(py_pkg_list, 0, manual_size - 1,
  1788 		PyList_SetSlice(py_pkg_list, 0, manual_size - 1,
  2117 		    manual_pkg_list);
  1789 		    manual_pkg_list);
  2118 	}
  1790 	}
  2119 	Py_DECREF(manual_pkg_list);
       
  2120 
  1791 
  2121 	if (searched_size > 0) {
  1792 	if (searched_size > 0) {
  2122 		(void) PyList_SetSlice(py_pkg_list, manual_size,
  1793 		PyList_SetSlice(py_pkg_list, manual_size,
  2123 		    manual_size + searched_size - 1, searched_pkg_list);
  1794 		    manual_size + searched_size - 1, searched_pkg_list);
  2124 	}
  1795 	}
  2125 	Py_DECREF(searched_pkg_list);
       
  2126 
       
  2127 done:
  1796 done:
  2128 	auto_ddu_lib_fini(py_state_p);
  1797 	auto_ddu_lib_fini(py_state_p);
  2129 
  1798 
       
  1799 	if (rval != -1) {
       
  1800 		rval = num_pkgs_installed;
       
  1801 	}
  2130 	return (rval);
  1802 	return (rval);
  2131 }
  1803 }
  2132 
  1804 
  2133 /*
  1805 /*
  2134  * ai_du_install:
  1806  * ai_du_install:
  2139  * honor_noinstall argument is set, skip adding that package.
  1811  * honor_noinstall argument is set, skip adding that package.
  2140  *
  1812  *
  2141  * This routine assumes the py_pkg_list was set up via a prior call to
  1813  * This routine assumes the py_pkg_list was set up via a prior call to
  2142  * ai_du_get_and_install_packages().
  1814  * ai_du_get_and_install_packages().
  2143  *
  1815  *
  2144  * The availability and origin (location) of all packages to be installed is
  1816  * The availability and origin of all packages to be installed is assumed the
  2145  * assumed the same as when the py_pkg_list was built (i.e. the most recent
  1817  * same as when the py_pkg_list was built (i.e. the most recent call to
  2146  * call to ai_du_get_and_install()).
  1818  * ai_du_get_and_install()).
  2147  *
  1819  *
  2148  * Arguments:
  1820  * Arguments:
  2149  *   install_root: Top of the filesystem or tree where the packages are to be
  1821  *   install_root: Top of the filesystem or tree where the packages are to be
  2150  *	installed.
  1822  *	installed.
  2151  *   honor_noinstall: When true and the noinstall flag is set in a package
  1823  *   honor_noinstall: When true and the noinstall flag is set in a package
  2152  *	tuple, skip installing that package.
  1824  *	tuple, skip installing that package.
  2153  *   update_boot_archive: When true, run the ICT to update the boot archive.
  1825  *   update_boot_archive: When true, run the ICT to update the boot archive.
  2154  *   num_installed_pkgs_p: Returns the number of packages successfully
       
  2155  *	installed.
       
  2156  *   NOTE: the modular global py_pkg_list specifies the packages to install.
  1826  *   NOTE: the modular global py_pkg_list specifies the packages to install.
  2157  *
  1827  *
  2158  * Returns:
  1828  * Returns:
  2159  *   AUTO_INSTALL_SUCCESS: No errors found and at least one package was
  1829  *   The number of packages successfully processed if all are successfully
  2160  *	installed.
  1830  *	processed.  NOTE: this can be zero if there are none to process.
  2161  *   AUTO_INSTALL_FAILURE: An error was encountered.  Some packages may have
  1831  *   -1: At least one package was not able to be installed.
  2162  *	been installed.
       
  2163  *
       
  2164  *   Boot archive update status is not reflected in this return status.
  1832  *   Boot archive update status is not reflected in this return status.
  2165  *   NOTE: this routine will continue on most errors, in order to install as
       
  2166  *	many packages as possible.
       
  2167  *
       
  2168  * NOTE: return status and num_pkgs_installed together tell the caller the full
       
  2169  * story.  It is possible, for example, that no packages were installed because
       
  2170  * one package flagged during search could not be found.
       
  2171  *
  1833  *
  2172  * NOTE: check installer logfile for details of the failure.
  1834  * NOTE: check installer logfile for details of the failure.
  2173  */
  1835  */
  2174 int
  1836 int
  2175 ai_du_install(char *install_root, boolean_t honor_noinstall,
  1837 ai_du_install(char *install_root, boolean_t honor_noinstall,
  2176     boolean_t update_boot_archive, int *num_installed_pkgs_p)
  1838     boolean_t update_boot_archive)
  2177 {
  1839 {
  2178 	int rval = AUTO_INSTALL_SUCCESS;
  1840 	int rval = 0;
       
  1841 	int num_pkgs_installed = 0;
  2179 
  1842 
  2180 	py_state_t *py_state_p;
  1843 	py_state_t *py_state_p;
  2181 
       
  2182 	*num_installed_pkgs_p = 0;
       
  2183 
  1844 
  2184 	if (py_pkg_list == NULL) {
  1845 	if (py_pkg_list == NULL) {
  2185 		auto_debug_print(AUTO_DBGLVL_ERR,
  1846 		auto_debug_print(AUTO_DBGLVL_ERR,
  2186 		    "ai_du_install: ai_du_get_and_install needs to be "
  1847 		    "ai_du_install: ai_du_get_and_install needs to be "
  2187 		    "called first.\n");
  1848 		    "called first.\n");
  2188 		return (AUTO_INSTALL_FAILURE);
  1849 		return (-1);
  2189 
  1850 
  2190 	} else if (PyList_Size(py_pkg_list) == 0) {
  1851 	} else if (PyList_Size(py_pkg_list) == 0) {
  2191 		return (AUTO_INSTALL_SUCCESS);
  1852 		return (num_pkgs_installed);
  2192 	}
  1853 	}
  2193 
  1854 
  2194 	if ((py_state_p = auto_ddu_lib_init()) == NULL) {
  1855 	if ((py_state_p = auto_ddu_lib_init()) == NULL) {
  2195 		auto_debug_print(AUTO_DBGLVL_ERR,
  1856 		auto_debug_print(AUTO_DBGLVL_ERR,
  2196 		    "ai_du_install: "
  1857 		    "ai_du_install: "
  2197 		    "Error initializing auto_ddu_lib.\n");
  1858 		    "Error initializing auto_ddu_lib.\n");
  2198 		return (AUTO_INSTALL_FAILURE);
  1859 		return (-1);
  2199 	}
  1860 	}
  2200 
  1861 
  2201 	if ((rval = ai_du_install_packages(py_state_p, py_pkg_list,
  1862 	if ((rval = ai_du_install_packages(py_state_p, py_pkg_list,
  2202 	    install_root, honor_noinstall, num_installed_pkgs_p)) !=
  1863 	    install_root, honor_noinstall, &num_pkgs_installed)) !=
  2203 	    AUTO_INSTALL_SUCCESS) {
  1864 	    AUTO_INSTALL_SUCCESS) {
  2204 		auto_debug_print(AUTO_DBGLVL_ERR,
  1865 		auto_debug_print(AUTO_DBGLVL_ERR,
  2205 		    "ai_du_install: Error installing packages.\n");
  1866 		    "ai_du_install: Error installing packages.\n");
  2206 		rval = AUTO_INSTALL_FAILURE;
  1867 		rval = -1;
  2207 	}
  1868 	}
  2208 
  1869 
  2209 	if (update_boot_archive && (*num_installed_pkgs_p > 0)) {
  1870 	if (update_boot_archive && (num_pkgs_installed > 0)) {
  2210 		if (ai_du_call_update_archive_ict(py_state_p,
  1871 		if (ai_du_call_update_archive_ict(py_state_p,
  2211 		    install_root) != AUTO_INSTALL_SUCCESS) {
  1872 		    install_root) != AUTO_INSTALL_SUCCESS) {
  2212 			auto_debug_print(AUTO_DBGLVL_ERR,
  1873 			auto_debug_print(AUTO_DBGLVL_ERR,
  2213 			    "ai_du_install: Warning: could not update boot "
  1874 			    "ai_du_install: Warning: could not update boot "
  2214 			    "archive for %s.\n", install_root);
  1875 			    "archive for %s.\n", install_root);
  2215 		}
  1876 		}
  2216 	}
  1877 	}
  2217 
  1878 
       
  1879 	if (rval != -1) {
       
  1880 		rval = num_pkgs_installed;
       
  1881 	}
       
  1882 
  2218 	auto_ddu_lib_fini(py_state_p);
  1883 	auto_ddu_lib_fini(py_state_p);
  2219 
  1884 
  2220 	return (rval);
  1885 	return (rval);
  2221 }
  1886 }