ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD,
int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,        long i, void *p, void (*f)(void), int cmd_optional)        {	int num;	if((e == NULL) || (cmd_name == NULL))		{		ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,			ERR_R_PASSED_NULL_PARAMETER);		return 0;		}	if((e->ctrl == NULL) || ((num = ENGINE_ctrl(e,					ENGINE_CTRL_GET_CMD_FROM_NAME,					0, (void *)cmd_name, NULL)) <= 0))		{		/* If the command didn't *have* to be supported, we fake		 * success. This allows certain settings to be specified for		 * multiple ENGINEs and only require a change of ENGINE id		 * (without having to selectively apply settings). Eg. changing		 * from a hardware device back to the regular software ENGINE		 * without editing the config file, etc. */		if(cmd_optional)			{			ERR_clear_error();			return 1;			}		ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD,			ENGINE_R_INVALID_CMD_NAME);		return 0;		}	/* Force the result of the control command to 0 or 1, for the reasons	 * mentioned before. */        if (ENGINE_ctrl(e, num, i, p, f))                return 1;        return 0;        }