Amend (aka the recovery command language) had a half-implemented scheme of limiting which commands OTA packages were allowed to execute. It's not clear what this was ever supposed to be good for. Remove it.
		
			
				
	
	
		
			230 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C) 2007 The Android Open Source Project
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include "symtab.h"
 | 
						|
#include "commands.h"
 | 
						|
 | 
						|
#if 1
 | 
						|
#define TRACE(...)  printf(__VA_ARGS__)
 | 
						|
#else
 | 
						|
#define TRACE(...)  /**/
 | 
						|
#endif
 | 
						|
 | 
						|
typedef enum {
 | 
						|
    CMD_TYPE_UNKNOWN = -1,
 | 
						|
    CMD_TYPE_COMMAND = 0,
 | 
						|
    CMD_TYPE_FUNCTION
 | 
						|
} CommandType;
 | 
						|
 | 
						|
typedef struct {
 | 
						|
    const char *name;
 | 
						|
    void *cookie;
 | 
						|
    CommandType type;
 | 
						|
    CommandArgumentType argType;
 | 
						|
    CommandHook hook;
 | 
						|
} CommandEntry;
 | 
						|
 | 
						|
static struct {
 | 
						|
    SymbolTable *symbolTable;
 | 
						|
    bool commandStateInitialized;
 | 
						|
} gCommandState;
 | 
						|
 | 
						|
int
 | 
						|
commandInit()
 | 
						|
{
 | 
						|
    if (gCommandState.commandStateInitialized) {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    gCommandState.symbolTable = createSymbolTable();
 | 
						|
    if (gCommandState.symbolTable == NULL) {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    gCommandState.commandStateInitialized = true;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
commandCleanup()
 | 
						|
{
 | 
						|
    if (gCommandState.commandStateInitialized) {
 | 
						|
        gCommandState.commandStateInitialized = false;
 | 
						|
        deleteSymbolTable(gCommandState.symbolTable);
 | 
						|
        gCommandState.symbolTable = NULL;
 | 
						|
//xxx need to free the entries and names in the symbol table
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
registerCommandInternal(const char *name, CommandType type,
 | 
						|
        CommandArgumentType argType, CommandHook hook, void *cookie)
 | 
						|
{
 | 
						|
    CommandEntry *entry;
 | 
						|
 | 
						|
    if (!gCommandState.commandStateInitialized) {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    if (name == NULL || hook == NULL) {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    if (type != CMD_TYPE_COMMAND && type != CMD_TYPE_FUNCTION) {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    if (argType != CMD_ARGS_BOOLEAN && argType != CMD_ARGS_WORDS) {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    entry = (CommandEntry *)malloc(sizeof(CommandEntry));
 | 
						|
    if (entry != NULL) {
 | 
						|
        entry->name = strdup(name);
 | 
						|
        if (entry->name != NULL) {
 | 
						|
            int ret;
 | 
						|
 | 
						|
            entry->cookie = cookie;
 | 
						|
            entry->type = type;
 | 
						|
            entry->argType = argType;
 | 
						|
            entry->hook = hook;
 | 
						|
            ret = addToSymbolTable(gCommandState.symbolTable,
 | 
						|
                        entry->name, entry->type, entry);
 | 
						|
            if (ret == 0) {
 | 
						|
                return 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        free(entry);
 | 
						|
    }
 | 
						|
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
registerCommand(const char *name,
 | 
						|
        CommandArgumentType argType, CommandHook hook, void *cookie)
 | 
						|
{
 | 
						|
    return registerCommandInternal(name,
 | 
						|
            CMD_TYPE_COMMAND, argType, hook, cookie);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
registerFunction(const char *name, FunctionHook hook, void *cookie)
 | 
						|
{
 | 
						|
    return registerCommandInternal(name,
 | 
						|
            CMD_TYPE_FUNCTION, CMD_ARGS_WORDS, (CommandHook)hook, cookie);
 | 
						|
}
 | 
						|
 | 
						|
Command *
 | 
						|
findCommand(const char *name)
 | 
						|
{
 | 
						|
    return (Command *)findInSymbolTable(gCommandState.symbolTable,
 | 
						|
            name, CMD_TYPE_COMMAND);
 | 
						|
}
 | 
						|
 | 
						|
Function *
 | 
						|
findFunction(const char *name)
 | 
						|
{
 | 
						|
    return (Function *)findInSymbolTable(gCommandState.symbolTable,
 | 
						|
            name, CMD_TYPE_FUNCTION);
 | 
						|
}
 | 
						|
 | 
						|
CommandArgumentType
 | 
						|
getCommandArgumentType(Command *cmd)
 | 
						|
{
 | 
						|
    CommandEntry *entry = (CommandEntry *)cmd;
 | 
						|
 | 
						|
    if (entry != NULL) {
 | 
						|
        return entry->argType;
 | 
						|
    }
 | 
						|
    return CMD_ARGS_UNKNOWN;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
callCommandInternal(CommandEntry *entry, int argc, const char *argv[])
 | 
						|
{
 | 
						|
    if (entry != NULL && entry->argType == CMD_ARGS_WORDS &&
 | 
						|
            (argc == 0 || (argc > 0 && argv != NULL)))
 | 
						|
    {
 | 
						|
        int i;
 | 
						|
        for (i = 0; i < argc; i++) {
 | 
						|
            if (argv[i] == NULL) {
 | 
						|
                goto bail;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        TRACE("calling command %s\n", entry->name);
 | 
						|
        return entry->hook(entry->name, entry->cookie, argc, argv);
 | 
						|
    }
 | 
						|
bail:
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
callBooleanCommandInternal(CommandEntry *entry, bool arg)
 | 
						|
{
 | 
						|
    if (entry != NULL && entry->argType == CMD_ARGS_BOOLEAN) {
 | 
						|
        TRACE("calling boolean command %s\n", entry->name);
 | 
						|
        return entry->hook(entry->name, entry->cookie, arg ? 1 : 0, NULL);
 | 
						|
    }
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
callCommand(Command *cmd, int argc, const char *argv[])
 | 
						|
{
 | 
						|
    return callCommandInternal((CommandEntry *)cmd, argc, argv);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
callBooleanCommand(Command *cmd, bool arg)
 | 
						|
{
 | 
						|
    return callBooleanCommandInternal((CommandEntry *)cmd, arg);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
callFunctionInternal(CommandEntry *entry, int argc, const char *argv[],
 | 
						|
        char **result, size_t *resultLen)
 | 
						|
{
 | 
						|
    if (entry != NULL && entry->argType == CMD_ARGS_WORDS &&
 | 
						|
            (argc == 0 || (argc > 0 && argv != NULL)))
 | 
						|
    {
 | 
						|
        if (result != NULL)
 | 
						|
        {
 | 
						|
            /* This is the actual invocation of the function,
 | 
						|
             * which means that none of the arguments are allowed
 | 
						|
             * to be NULL.
 | 
						|
             */
 | 
						|
            int i;
 | 
						|
            for (i = 0; i < argc; i++) {
 | 
						|
                if (argv[i] == NULL) {
 | 
						|
                    goto bail;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            TRACE("calling function %s\n", entry->name);
 | 
						|
            return ((FunctionHook)entry->hook)(entry->name, entry->cookie,
 | 
						|
                    argc, argv, result, resultLen);
 | 
						|
        }
 | 
						|
    }
 | 
						|
bail:
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
callFunction(Function *fn, int argc, const char *argv[],
 | 
						|
        char **result, size_t *resultLen)
 | 
						|
{
 | 
						|
    return callFunctionInternal((CommandEntry *)fn, argc, argv,
 | 
						|
            result, resultLen);
 | 
						|
}
 |