/* ARISA - Perl Engine - UI Linkage * Copyright (C) 2004 Carl Ritson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #define NEED_PERL_H #include #include #include #include "arisa.h" #include "script-eng.h" #include "admin.h" #include "admin-interface.h" #include "engine.h" #include "linkage.h" #include "ui.h" // Structure Definitions typedef struct perl_ui_call_t { pthread_mutex_t lock; pthread_cond_t cond; void *id; acontext_t *context; char **args; int no_args; volatile int ret_val; volatile int valid; } perl_ui_call_t; // Global Variables acontext_t *perl_ui_valid_context = NULL; // Functions static perl_ui_call_t *alloc_call(void *id, acontext_t *context, char **args, int no_args) { perl_ui_call_t *c = xalloc(sizeof(perl_ui_call_t)); LOCK_INIT(&c->lock); pthread_cond_init(&c->cond,NULL); c->id = id; c->context = context; c->args = args; c->no_args = no_args; c->ret_val = 0; c->valid = 1; return c; } static void free_call(perl_ui_call_t *c) { LOCK_FREE(&c->lock); pthread_cond_destroy(&c->cond); xfree(c); } MENU_CMD_NS(perl_make_ui_call) { perl_ui_call_t *c = alloc_call(menu_cmd,ac,args,no_args); struct timespec timeout; struct timeval now; int ret, ran = 0; LOCK(c); se_ui_call(perl_engine_interpreter,c); gettimeofday(&now,NULL); timeout.tv_sec = now.tv_sec + 10; timeout.tv_nsec = now.tv_usec * 1000; if(pthread_cond_timedwait(&c->cond,&c->lock,&timeout) == 0) { ret = c->ret_val; ran = 1; } else { pqueue_push_back(ac->msgqueue,xstrdup("Call Failed")); ret = RET_EXE_ERR; } c->valid = 0; UNLOCK(c); if(ran) free_call(c); return ret; } static void make_perl_call(plocal_t *l, perl_ui_call_t *c) { dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSViv((IV)c->id))); XPUSHs(sv_2mortal(create_ptr_object("Arisa::UI::Context",c->context))); XPUSHs(sv_2mortal(newRV_noinc((SV*)strarr_to_av(c->args,c->no_args)))); PUTBACK; perl_call_pv("Arisa::UI::_call", G_EVAL | G_SCALAR); SPAGAIN; if(SvTRUE(ERRSV)) { char *error = SvPV(ERRSV, PL_na); if (error != NULL) LOGTP(L_ERR,"Perl Error: %s",error); c->ret_val = RET_EXE_ERR; } else { c->ret_val = POPi; } PUTBACK; FREETMPS; LEAVE; } void perl_handle_ui_call(plocal_t *l, se_msg_t *msg) { perl_ui_call_t *c = (perl_ui_call_t *)msg->ui.data; LOCK(c); if(c->valid == 0) { UNLOCK(c); free_call(c); return; } pthread_cond_signal(&c->cond); perl_ui_valid_context = c->context; make_perl_call(l,c); perl_ui_valid_context = NULL; UNLOCK(c); }