Beispiel #1
0
inline void run_cleanup()
{
    // only call this once, on exit
    // to make sure valgrind output is clean
    // http://xmlsoft.org/xmlmem.html
    xmlCleanupCharEncodingHandlers();
    xmlCleanupEncodingAliases();
    xmlCleanupGlobals();
    xmlCleanupParser();
    xmlCleanupThreads();
    xmlCleanupInputCallbacks();
    xmlCleanupOutputCallbacks();
    xmlCleanupMemory();

#if defined(HAVE_CAIRO)
    // http://cairographics.org/manual/cairo-Error-handling.html#cairo-debug-reset-static-data
    cairo_debug_reset_static_data();
#endif

    // http://icu-project.org/apiref/icu4c/uclean_8h.html#a93f27d0ddc7c196a1da864763f2d8920
    u_cleanup();

#ifdef MAPNIK_USE_PROJ4
    // http://trac.osgeo.org/proj/ticket/149
 #if PJ_VERSION >= 480
    pj_clear_initcache();
 #endif
    // https://trac.osgeo.org/proj/wiki/ProjAPI#EnvironmentFunctions
    pj_deallocate_grids();
#endif    
}
Beispiel #2
0
CX_OBJECT_FREE(cxEngine, cxObject)
{
    CX_RELEASE(this->bmpfonts);
    CX_RELEASE(this->actions);
    CX_RELEASE(this->lang);
    CX_RELEASE(this->datasets);
    CX_RELEASE(this->scripts);
    CX_RELEASE(this->dbenvs);
    CX_RELEASE(this->window);
    CX_EVENT_RELEASE(this->onExit);
    CX_SIGNAL_RELEASE(this->onRecvJson);
    CX_SIGNAL_RELEASE(this->onTouch);
    CX_SIGNAL_RELEASE(this->onUpdate);
    CX_SIGNAL_RELEASE(this->onPause);
    CX_SIGNAL_RELEASE(this->onResume);
    CX_SIGNAL_RELEASE(this->onMemory);
    CX_METHOD_RELEASE(this->MakeAction);
    CX_METHOD_RELEASE(this->MakeView);
    cxEventBaseDestroy();
    cxCurveDestroy();
    cxOpenGLDestroy();
    cxIconvDestroy();
    cxFreeTypeDestroy();
    cxPlayerDestroy();
    cxMessageDestroy();
    xmlCleanupGlobals();
    kmGLFreeAll();
    cxAutoPoolDestroy();
    lua_close(gL);
}
Beispiel #3
0
int main(int argc, char * argv[])
{
	xmlNodePtr sentence;
	gchar ** tokens;

	GString * linebuffer = g_string_new("");

	GIOChannel * in = g_io_channel_unix_new(fileno(stdin));

	//首先读取一行文字
	g_io_channel_read_line_string(in,linebuffer,NULL,NULL);

	//分割
	tokens = g_strsplit_set(linebuffer->str," ",1024);

	//为此行文字打标记
	init_yylex(tokens);

	//打好词性标记后开始解析语法结构
	xmlInitGlobals();
	xmlInitMemory();
	yyparse(&sentence);
	xmlCleanupGlobals();
	xmlCleanupMemory();

	xmlSaveCtxtPtr saver = 	xmlSaveToFd(2,"UTF-8",0);

	xmlSaveTree(saver,sentence);
	xmlSaveFlush(saver);
	xmlSaveClose(saver);
	write(2,"\n",1);

	//输出语法树, 以 XML 形式
	return 0;
}
Beispiel #4
0
PLIST_API void plist_cleanup(void)
{
    /* free memory from parser initialization */
    xmlCleanupCharEncodingHandlers();
    xmlDictCleanup();
    xmlResetLastError();
    xmlCleanupGlobals();
    xmlCleanupThreads();
    xmlCleanupMemory();
}
	CServer::~CServer()
	{
		lock();

		INTEGRA_TRACE_PROGRESS << "setting terminate flag";

		pthread_mutex_lock( &m_shutdown_mutex );

		unlock();

		/* delete all nodes */
		node_map copy_of_nodes = m_nodes;
		for( node_map::const_iterator i = copy_of_nodes.begin(); i != copy_of_nodes.end(); i++ )
		{
			process_command( IDeleteCommand::create( i->second->get_path() ), CCommandSource::SYSTEM );
		}
	
		delete m_audio_engine;

		delete m_dsp_engine;

		delete m_midi_engine;

		delete m_midi_input_dispatcher;

		delete m_module_manager;

		delete m_reentrance_checker;

		delete m_scratch_directory;

		delete m_lua_engine;

		delete m_player_handler;

		INTEGRA_TRACE_PROGRESS << "cleaning up XML parser";
		xmlCleanupParser();
		xmlCleanupGlobals();

		INTEGRA_TRACE_PROGRESS << "done!";

		pthread_mutex_unlock( &m_shutdown_mutex );

		pthread_mutex_destroy( &m_mutex );
		pthread_mutex_destroy( &m_shutdown_mutex );

		INTEGRA_TRACE_PROGRESS << "server destruction complete";
	}
Beispiel #6
0
/**
 *  Output document
 */
static void
edOutput(const char* filename, const XmlEdAction* ops, int ops_count,
    const edOptions* g_ops)
{
    xmlDocPtr doc;
    int save_options =
#if LIBXML_VERSION >= 20708
        (g_ops->noblanks? 0 : XML_SAVE_WSNONSIG) |
#endif
        (g_ops->preserveFormat? 0 : XML_SAVE_FORMAT) |
        (g_ops->omit_decl? XML_SAVE_NO_DECL : 0);
    int read_options =
        (g_ops->nonet? XML_PARSE_NONET : 0);
    xmlSaveCtxtPtr save;

    doc = xmlReadFile(filename, NULL, read_options);
    if (!doc)
    {
        cleanupNSArr(ns_arr);
        xmlCleanupParser();
        xmlCleanupGlobals();
        exit(EXIT_BAD_FILE);
    }

    edProcess(doc, ops, ops_count);

    /* avoid getting ASCII CRs in UTF-16/UCS-(2,4) text */
    if ((xmlStrcasestr(doc->encoding, BAD_CAST "UTF") == 0
            && xmlStrcasestr(doc->encoding, BAD_CAST "16") == 0)
        ||
        (xmlStrcasestr(doc->encoding, BAD_CAST "UCS") == 0
            && (xmlStrcasestr(doc->encoding, BAD_CAST "2") == 0
                ||
                xmlStrcasestr(doc->encoding, BAD_CAST "4") == 0)))
    {
        set_stdout_binary();
    }

    save = xmlSaveToFilename(g_ops->inplace? filename : "-", NULL, save_options);
    xmlSaveDoc(save, doc);
    xmlSaveClose(save);

    xmlFreeDoc(doc);
}
Beispiel #7
0
/**
 * Stop engine.
 *
 */
void
engine_stop(engine_type *engine)
{
    ods_orm_shutdown();
    ods_protobuf_shutdown();

    if (engine && engine->config) {
        if (engine->config->pid_filename) {
            (void)unlink(engine->config->pid_filename);
        }
        if (engine->config->clisock_filename) {
            (void)unlink(engine->config->clisock_filename);
        }
    }
    engine_cleanup(engine);
    engine = NULL;
    ods_log_close();
    xmlCleanupParser();
    xmlCleanupGlobals();
    xmlCleanupThreads();
}
/**
 * Start engine.
 *
 */
void
engine_start(const char* cfgfile, int cmdline_verbosity, int daemonize,
    int info, int single_run)
{
    engine_type* engine = NULL;
    int use_syslog = 0;
    ods_status zl_changed = ODS_STATUS_UNCHANGED;
    ods_status status = ODS_STATUS_OK;
    int close_hsm = 0;

    ods_log_assert(cfgfile);
    ods_log_init(NULL, use_syslog, cmdline_verbosity);
    ods_log_verbose("[%s] starting signer", engine_str);

    /* initialize */
    xmlInitGlobals();
    xmlInitParser();
    xmlInitThreads();
    engine = engine_create();
    if (!engine) {
        ods_fatal_exit("[%s] create failed", engine_str);
        return;
    }
    engine->daemonize = daemonize;

    /* config */
    engine->config = engine_config(engine->allocator, cfgfile,
        cmdline_verbosity);
    status = engine_config_check(engine->config);
    if (status != ODS_STATUS_OK) {
        ods_log_error("[%s] cfgfile %s has errors", engine_str, cfgfile);
        goto earlyexit;
    }
    if (info) {
        engine_config_print(stdout, engine->config); /* for debugging */
        goto earlyexit;
    }
    /* check pidfile */
    if (!util_check_pidfile(engine->config->pid_filename)) {
        exit(1);
    }
    /* open log */
    ods_log_init(engine->config->log_filename, engine->config->use_syslog,
       engine->config->verbosity);
    /* setup */
    tzset(); /* for portability */
    status = engine_setup(engine);
    if (status != ODS_STATUS_OK) {
        ods_log_error("[%s] setup failed: %s", engine_str,
            ods_status2str(status));
        engine->need_to_exit = 1;
        if (status != ODS_STATUS_WRITE_PIDFILE_ERR) {
            /* command handler had not yet been started */
            engine->cmdhandler_done = 1;
        }
    } else {
        /* setup ok, mark hsm open */
        close_hsm = 1;
    }

    /* run */
    while (engine->need_to_exit == 0) {
        /* update zone list */
        lock_basic_lock(&engine->zonelist->zl_lock);
        zl_changed = zonelist_update(engine->zonelist,
            engine->config->zonelist_filename);
        engine->zonelist->just_removed = 0;
        engine->zonelist->just_added = 0;
        engine->zonelist->just_updated = 0;
        lock_basic_unlock(&engine->zonelist->zl_lock);
        /* start/reload */
        if (engine->need_to_reload) {
            ods_log_info("[%s] signer reloading", engine_str);
            engine->need_to_reload = 0;
        } else {
            ods_log_info("[%s] signer started", engine_str);
            zl_changed = engine_recover(engine);
        }
        if (zl_changed == ODS_STATUS_OK ||
            zl_changed == ODS_STATUS_UNCHANGED) {
            engine_update_zones(engine, zl_changed);
        }
        engine_run(engine, single_run);
    }

    /* shutdown */
    ods_log_info("[%s] signer shutdown", engine_str);
    if (close_hsm) {
        ods_log_verbose("[%s] close hsm", engine_str);
        hsm_close();
    }
    if (!engine->cmdhandler_done) {
        engine_stop_xfrhandler(engine);
        engine_stop_dnshandler(engine);
        engine_stop_cmdhandler(engine);
    }

earlyexit:
    if (engine && engine->config) {
        if (engine->config->pid_filename) {
            (void)unlink(engine->config->pid_filename);
        }
        if (engine->config->clisock_filename) {
            (void)unlink(engine->config->clisock_filename);
        }
    }
    tsig_handler_cleanup();
    engine_cleanup(engine);
    engine = NULL;
    ods_log_close();
    xmlCleanupParser();
    xmlCleanupGlobals();
    xmlCleanupThreads();
    return;
}
/**
 * Set up engine.
 *
 */
static ods_status
engine_setup(engine_type* engine)
{
    ods_status status = ODS_STATUS_OK;
    struct sigaction action;
    int result = 0;
    int sockets[2] = {0,0};

    ods_log_debug("[%s] setup signer engine", engine_str);
    if (!engine || !engine->config) {
        return ODS_STATUS_ASSERT_ERR;
    }
    /* set edns */
    edns_init(&engine->edns, EDNS_MAX_MESSAGE_LEN);

    /* create command handler (before chowning socket file) */
    engine->cmdhandler = cmdhandler_create(engine->allocator,
        engine->config->clisock_filename);
    if (!engine->cmdhandler) {
        return ODS_STATUS_CMDHANDLER_ERR;
    }
    engine->dnshandler = dnshandler_create(engine->allocator,
        engine->config->interfaces);
    engine->xfrhandler = xfrhandler_create(engine->allocator);
    if (!engine->xfrhandler) {
        return ODS_STATUS_XFRHANDLER_ERR;
    }
    if (engine->dnshandler) {
        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == -1) {
            return ODS_STATUS_XFRHANDLER_ERR;
        }
        engine->xfrhandler->dnshandler.fd = sockets[0];
        engine->dnshandler->xfrhandler.fd = sockets[1];
        status = dnshandler_listen(engine->dnshandler);
        if (status != ODS_STATUS_OK) {
            ods_log_error("[%s] setup: unable to listen to sockets (%s)",
                engine_str, ods_status2str(status));
        }
    }
    /* privdrop */
    engine->uid = privuid(engine->config->username);
    engine->gid = privgid(engine->config->group);
    /* TODO: does piddir exists? */
    /* remove the chown stuff: piddir? */
    ods_chown(engine->config->pid_filename, engine->uid, engine->gid, 1);
    ods_chown(engine->config->clisock_filename, engine->uid, engine->gid, 0);
    ods_chown(engine->config->working_dir, engine->uid, engine->gid, 0);
    if (engine->config->log_filename && !engine->config->use_syslog) {
        ods_chown(engine->config->log_filename, engine->uid, engine->gid, 0);
    }
    if (engine->config->working_dir &&
        chdir(engine->config->working_dir) != 0) {
        ods_log_error("[%s] setup: unable to chdir to %s (%s)", engine_str,
            engine->config->working_dir, strerror(errno));
        return ODS_STATUS_CHDIR_ERR;
    }
    if (engine_privdrop(engine) != ODS_STATUS_OK) {
        return ODS_STATUS_PRIVDROP_ERR;
    }
    /* daemonize */
    if (engine->daemonize) {
        switch ((engine->pid = fork())) {
            case -1: /* error */
                ods_log_error("[%s] setup: unable to fork daemon (%s)",
                    engine_str, strerror(errno));
                return ODS_STATUS_FORK_ERR;
            case 0: /* child */
                break;
            default: /* parent */
                engine_cleanup(engine);
                engine = NULL;
                xmlCleanupParser();
                xmlCleanupGlobals();
                xmlCleanupThreads();
                exit(0);
        }
        if (setsid() == -1) {
            ods_log_error("[%s] setup: unable to setsid daemon (%s)",
                engine_str, strerror(errno));
            return ODS_STATUS_SETSID_ERR;
        }
    }
    engine->pid = getpid();
    ods_log_verbose("[%s] running as pid %lu", engine_str,
        (unsigned long) engine->pid);
    /* catch signals */
    signal_set_engine(engine);
    action.sa_handler = signal_handler;
    sigfillset(&action.sa_mask);
    action.sa_flags = 0;
    sigaction(SIGTERM, &action, NULL);
    sigaction(SIGHUP, &action, NULL);
    sigaction(SIGINT, &action, NULL);
    sigaction(SIGILL, &action, NULL);
    sigaction(SIGUSR1, &action, NULL);
    sigaction(SIGALRM, &action, NULL);
    sigaction(SIGCHLD, &action, NULL);
    action.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &action, NULL);
    /* set up hsm */ /* LEAK */
    result = lhsm_open(engine->config->cfg_filename);
    if (result != HSM_OK) {
        return ODS_STATUS_HSM_ERR;
    }
    /* create workers/drudgers */
    engine_create_workers(engine);
    engine_create_drudgers(engine);
    /* start cmd/dns/xfr handlers */
    engine_start_cmdhandler(engine);
    engine_start_dnshandler(engine);
    engine_start_xfrhandler(engine);
    tsig_handler_init(engine->allocator);
    /* write pidfile */
    if (util_write_pidfile(engine->config->pid_filename, engine->pid) == -1) {
        hsm_close();
        return ODS_STATUS_WRITE_PIDFILE_ERR;
    }
    /* setup done */
    return ODS_STATUS_OK;
}
Beispiel #10
0
int
main(int argc, char* argv[])
{
    ods_status status;
    engineconfig_type* cfg;
    int c;
    int options_index = 0;
    const char* cfgfile = ODS_SE_CFGFILE;
    static struct option long_options[] = {
        {"config", required_argument, 0, 'c'},
        {"help", no_argument, 0, 'h'},
        {"verbose", no_argument, 0, 'v'},
        { 0, 0, 0, 0}
    };

    argv0 = argv[0];

    /* parse the commandline */
    while ((c=getopt_long(argc, argv, "c:hv", long_options, &options_index)) != -1) {
        switch (c) {
            case 'c':
                cfgfile = optarg;
                break;
            case 'h':
                usage();
                exit(0);
            case 'v':
                ++verbosity;
                break;
            default:
                usage();
                exit(1);
        }
    }
    argc -= optind;
    argv += optind;
    if (argc != 0) {
        usage();
        exit(1);
    }

    ods_log_init("ods-migrate", 0, NULL, verbosity);

    xmlInitGlobals();
    xmlInitParser();
    xmlInitThreads();

    tzset(); /* for portability */

    /* Parse config file */
    cfg = engine_config(cfgfile, verbosity, NULL);
    cfg->verbosity = verbosity;
    /* does it make sense? */
    if (engine_config_check(cfg) != ODS_STATUS_OK) {
        abort(); /* TODO give some error, abort */
    }

    status = hsm_open2(parse_conf_repositories(cfgfile), hsm_prompt_pin);
    if (status != HSM_OK) {
        char* errorstr =  hsm_get_error(NULL);
        if (errorstr != NULL) {
            fprintf(stderr, "%s", errorstr);
            free(errorstr);
            abort(); /* FIXME */
        } else {
            fprintf(stderr,"error opening libhsm (errno %i)\n", status);
        }
        return 1;
    }
    dblayer_initialize();

    switch (cfg->db_type) {
        case ENFORCER_DATABASE_TYPE_SQLITE:
#ifdef HAVE_SQLITE3
            dblayer_sqlite3_open(cfg->datastore);
#else
            fprintf(stderr, "Database SQLite3 not available during compile-time.\n");
#endif
            break;
        case ENFORCER_DATABASE_TYPE_MYSQL:
#ifdef HAVE_MYSQL
            dblayer_mysql_open(cfg->db_host, cfg->db_username, cfg->db_password, cfg->datastore, cfg->db_port, NULL);
#else
    fprintf(stderr, "Database MySQL not available during compile-time.\n");
#endif
            break;
        case ENFORCER_DATABASE_TYPE_NONE:
        default:
            fprintf(stderr, "No database defined\n");
    }

    dblayer_foreach(listQueryStr, updateQueryStr, &compute);
    
    hsm_close();

    engine_config_cleanup(cfg);
    /* dblayer_foreach for each frees something dblayer_close uses
     * We better just let it leak. */
    /* dblayer_close(); */
    dblayer_finalize();
    ods_log_close();

    xmlCleanupParser();
    xmlCleanupGlobals();

    return 0;
}
Beispiel #11
0
/**
 * Set up engine and return the setup status.
 *
 */
static ods_status
engine_setup_and_return_status(engine_type* engine)
{
    struct sigaction action;
    int result = 0;
    int fd;

    ods_log_debug("[%s] enforcer setup", engine_str);
    if (!engine || !engine->config) {
        return ODS_STATUS_ASSERT_ERR;
    }

    /* create command handler (before chowning socket file) */
    engine->cmdhandler = cmdhandler_create(engine->allocator,
        engine->config->clisock_filename);
    if (!engine->cmdhandler) {
        ods_log_error("[%s] create command handler to %s failed",
            engine_str, engine->config->clisock_filename);
        return ODS_STATUS_CMDHANDLER_ERR;
    }

    /* privdrop */
    engine->uid = privuid(engine->config->username);
    engine->gid = privgid(engine->config->group);
    /* TODO: does piddir exists? */
    /* remove the chown stuff: piddir? */
    ods_chown(engine->config->pid_filename, engine->uid, engine->gid, 1);
    ods_chown(engine->config->clisock_filename, engine->uid, engine->gid, 0);
    ods_chown(engine->config->working_dir, engine->uid, engine->gid, 0);
    if (engine->config->log_filename && !engine->config->use_syslog) {
        ods_chown(engine->config->log_filename, engine->uid, engine->gid, 0);
    }
    if (engine->config->working_dir &&
        chdir(engine->config->working_dir) != 0) {
        ods_log_error("[%s] chdir to %s failed: %s", engine_str,
            engine->config->working_dir, strerror(errno));
        return ODS_STATUS_CHDIR_ERR;
    }
    if (engine_privdrop(engine) != ODS_STATUS_OK) {
        ods_log_error("[%s] unable to drop privileges", engine_str);
        return ODS_STATUS_PRIVDROP_ERR;
    }

    /* daemonize */
    if (engine->daemonize) {
        switch ((engine->pid = fork())) {
            case -1: /* error */
                ods_log_error("[%s] unable to fork daemon: %s",
                    engine_str, strerror(errno));
                return ODS_STATUS_FORK_ERR;
            case 0: /* child */
                if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
                    (void)dup2(fd, STDIN_FILENO);
                    (void)dup2(fd, STDOUT_FILENO);
                    (void)dup2(fd, STDERR_FILENO);
                    if (fd > 2) (void)close(fd);
                }
                break;
            default: /* parent */
                engine_cleanup(engine);
                engine = NULL;
                xmlCleanupParser();
                xmlCleanupGlobals();
                xmlCleanupThreads();
                exit(0);
        }
        if (setsid() == -1) {
            ods_log_error("[%s] unable to setsid daemon (%s)",
                engine_str, strerror(errno));
            return ODS_STATUS_SETSID_ERR;
        }
    }
    engine->pid = getpid();
    ods_log_verbose("[%s] running as pid %lu", engine_str,
        (unsigned long) engine->pid);

    /* catch signals */
    signal_set_engine(engine);
    action.sa_handler = signal_handler;
    sigfillset(&action.sa_mask);
    action.sa_flags = 0;
    sigaction(SIGHUP, &action, NULL);
    sigaction(SIGTERM, &action, NULL);

    /* set up hsm */ /* LEAK */
    result = hsm_open(engine->config->cfg_filename, hsm_prompt_pin, NULL);
    if (result != HSM_OK) {
        ods_log_error("[%s] error initializing libhsm (errno %i)",
            engine_str, result);
        return ODS_STATUS_HSM_ERR;
    }

    /* create workers */
    engine_create_workers(engine);
    engine_create_drudgers(engine);

    /* start command handler */
    engine_start_cmdhandler(engine);

    /* write pidfile */
    if (util_write_pidfile(engine->config->pid_filename, engine->pid) == -1) {
        hsm_close();
        ods_log_error("[%s] unable to write pid file", engine_str);
        return ODS_STATUS_WRITE_PIDFILE_ERR;
    }

    return ODS_STATUS_OK;
}
Beispiel #12
0
/**
 *  This is the main function for 'edit' option
 */
int
edMain(int argc, char **argv)
{
    int i, ops_count, max_ops_count = 8, n, start = 0;
    XmlEdAction* ops = xmlMalloc(sizeof(XmlEdAction) * max_ops_count);
    static edOptions g_ops;
    int nCount = 0;

    if (argc < 3) edUsage(argv[0], EXIT_BAD_ARGS);

    edInitOptions(&g_ops);
    start = edParseOptions(&g_ops, argc, argv);

    parseNSArr(ns_arr, &nCount, argc-start, argv+start);
        
    /*
     *  Parse command line and fill array of operations
     */
    ops_count = 0;
    i = start + nCount;

    while (i < argc)
    {
        const char *arg = nextArg(argv, &i);
        if (arg[0] == '-')
        {
            if (ops_count >= max_ops_count)
            {
                max_ops_count *= 2;
                ops = xmlRealloc(ops, sizeof(XmlEdAction) * max_ops_count);
            }
            ops[ops_count].type = XML_UNDEFINED;

            if (!strcmp(arg, "-d") || !strcmp(arg, "--delete"))
            {
                ops[ops_count].op = XML_ED_DELETE;
                ops[ops_count].arg1 = nextArg(argv, &i);
                ops[ops_count].arg2 = 0;
            }
            else if (!strcmp(arg, "--var"))
            {
                ops[ops_count].op = XML_ED_VAR;
                ops[ops_count].arg1 = nextArg(argv, &i);
                ops[ops_count].arg2 = nextArg(argv, &i);
            }
            else if (!strcmp(arg, "-m") || !strcmp(arg, "--move"))
            {
                ops[ops_count].op = XML_ED_MOVE;
                ops[ops_count].arg1 = nextArg(argv, &i);
                ops[ops_count].arg2 = nextArg(argv, &i);
            }
            else if (!strcmp(arg, "-u") || !strcmp(arg, "--update"))
            {
                ops[ops_count].op = XML_ED_UPDATE;
                ops[ops_count].arg1 = nextArg(argv, &i);
                ops[ops_count].type = parseNextArg(argv, &i, OPT_VAL_OR_EXP);
                ops[ops_count].arg2 = nextArg(argv, &i);
            }
            else if (!strcmp(arg, "-r") || !strcmp(arg, "--rename"))
            {
                ops[ops_count].op = XML_ED_RENAME;
                ops[ops_count].arg1 = nextArg(argv, &i);
                ops[ops_count].type = parseNextArg(argv, &i, OPT_JUST_VAL);
                ops[ops_count].arg2 = nextArg(argv, &i);
            }
            else if (!strcmp(arg, "-i") || !strcmp(arg, "--insert"))
            {
                parseInsertionArgs(XML_ED_INSERT, &ops[ops_count], argv, &i);
            }
            else if (!strcmp(arg, "-a") || !strcmp(arg, "--append"))
            {
                parseInsertionArgs(XML_ED_APPEND, &ops[ops_count], argv, &i);
            }
            else if (!strcmp(arg, "-s") || !strcmp(arg, "--subnode"))
            {
                parseInsertionArgs(XML_ED_SUBNODE, &ops[ops_count], argv, &i);
            }
            else
            {
                fprintf(stderr, "Warning: unrecognized option '%s'\n", arg);
            }
            ops_count++;
        }
        else
        {
            i--;                /* it was a filename, we didn't use it */
            break;
        }
    }

    xmlKeepBlanksDefault(0);

    if ((!g_ops.noblanks) || g_ops.preserveFormat) xmlKeepBlanksDefault(1);

    if (i >= argc)
    {
        edOutput("-", ops, ops_count, &g_ops);
    }
    
    for (n=i; n<argc; n++)
    {
        edOutput(argv[n], ops, ops_count, &g_ops);
    }

    xmlFree(ops);
    cleanupNSArr(ns_arr);
    xmlCleanupParser();
    xmlCleanupGlobals();
    return 0;
}