rpm 5.3.12
rpmio/rpmtcl.c
Go to the documentation of this file.
00001 #include "system.h"
00002 
00003 #include <argv.h>
00004 
00005 #ifdef  WITH_TCL
00006 #include <tcl.h>
00007 #endif
00008 #define _RPMTCL_INTERNAL
00009 #include "rpmtcl.h"
00010 
00011 #include "debug.h"
00012 
00013 /*@unchecked@*/
00014 int _rpmtcl_debug = 0;
00015 
00016 /*@unchecked@*/ /*@relnull@*/
00017 rpmtcl _rpmtclI = NULL;
00018 
00019 static void rpmtclFini(void * _tcl)
00020         /*@globals fileSystem @*/
00021         /*@modifies *_tcl, fileSystem @*/
00022 {
00023     rpmtcl tcl = _tcl;
00024 
00025 #if defined(WITH_TCL)
00026     Tcl_DeleteInterp((Tcl_Interp *)tcl->I);
00027 #endif
00028     tcl->I = NULL;
00029     (void)rpmiobFree(tcl->iob);
00030     tcl->iob = NULL;
00031 }
00032 
00033 /*@unchecked@*/ /*@only@*/ /*@null@*/
00034 rpmioPool _rpmtclPool;
00035 
00036 static rpmtcl rpmtclGetPool(/*@null@*/ rpmioPool pool)
00037         /*@globals _rpmtclPool, fileSystem @*/
00038         /*@modifies pool, _rpmtclPool, fileSystem @*/
00039 {
00040     rpmtcl tcl;
00041 
00042     if (_rpmtclPool == NULL) {
00043         _rpmtclPool = rpmioNewPool("tcl", sizeof(*tcl), -1, _rpmtcl_debug,
00044                         NULL, NULL, rpmtclFini);
00045         pool = _rpmtclPool;
00046     }
00047     return (rpmtcl) rpmioGetPool(pool, sizeof(*tcl));
00048 }
00049 
00050 #if defined(WITH_TCL)
00051 static int rpmtclIOclose(ClientData CD, Tcl_Interp *I)
00052         /*@*/
00053 {
00054 if (_rpmtcl_debug)
00055 fprintf(stderr, "==> %s(%p, %p)\n", __FUNCTION__, CD, I);
00056     return 0;
00057 }
00058 
00059 static int rpmtclIOread(ClientData CD, char *b, int nb, int *errnop)
00060         /*@*/
00061 {
00062 if (_rpmtcl_debug)
00063 fprintf(stderr, "==> %s(%p, %p[%d], %p)\n", __FUNCTION__, CD, b, nb, errnop);
00064     *errnop = EINVAL;
00065     return -1;
00066 }
00067 
00068 static int rpmtclIOwrite(ClientData CD, const char *b, int nb, int *errnop)
00069         /*@*/
00070 {
00071     rpmtcl tcl = (rpmtcl) CD;
00072 if (_rpmtcl_debug)
00073 fprintf(stderr, "==> %s(%p, %p[%d], %p)\n", __FUNCTION__, CD, b, nb, errnop);
00074     if (nb > 0) {
00075         char * t = (char *)b;
00076         int c = t[nb];
00077         if (c) t[nb] = '\0';
00078         (void) rpmiobAppend(tcl->iob, b, 0);
00079         if (c) t[nb] = c;
00080     }
00081     return nb;
00082 }
00083 
00084 static int rpmtclIOseek(ClientData CD, long off, int mode, int *errnop)
00085         /*@*/
00086 {
00087 if (_rpmtcl_debug)
00088 fprintf(stderr, "==> %s(%p, %ld, %d, %p)\n", __FUNCTION__, CD, off, mode, errnop);
00089     *errnop = EINVAL;
00090     return -1;
00091 }
00092 
00093 static Tcl_ChannelType rpmtclIO = {
00094     "rpmtclIO",                 /* Type name */
00095     TCL_CHANNEL_VERSION_2,      /* Tcl_ChannelTypeVersion */
00096     rpmtclIOclose,              /* Tcl_DriverCloseProc */
00097     rpmtclIOread,               /* Tcl_DriverInputProc */
00098     rpmtclIOwrite,              /* Tcl_DriverOutputProc */
00099     rpmtclIOseek,               /* Tcl_DriverSeekProc */
00100     NULL,                       /* Tcl_DriverSetOptionProc */
00101     NULL,                       /* Tcl_DriverGetOptionProc */
00102     NULL,                       /* Tcl_DriverWatchProc */
00103     NULL,                       /* Tcl_DriverGetHandleProc */
00104     NULL,                       /* Tcl_DriverClose2Proc */
00105     NULL,                       /* Tcl_DriverBlockModeProc */
00106     NULL,                       /* Tcl_DriverFlushProc */
00107     NULL,                       /* Tcl_DriverHandlerProc */
00108     NULL,                       /* Tcl_DriverWideSeekProc */
00109     NULL,                       /* Tcl_DriverThreadActionProc */
00110 #if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 4
00111     NULL,                       /* Tcl_DriverTruncateProc */
00112 #endif
00113 };
00114 #endif
00115 
00116 static rpmtcl rpmtclI(void)
00117         /*@globals _rpmtclI @*/
00118         /*@modifies _rpmtclI @*/
00119 {
00120     if (_rpmtclI == NULL)
00121         _rpmtclI = rpmtclNew(NULL, 0);
00122     return _rpmtclI;
00123 }
00124 
00125 rpmtcl rpmtclNew(char ** av, uint32_t flags)
00126 {
00127     rpmtcl tcl =
00128 #ifdef  NOTYET
00129         (flags & 0x80000000) ? rpmtclI() :
00130 #endif
00131         rpmtclGetPool(_rpmtclPool);
00132 
00133 #if defined(WITH_TCL)
00134     static char * _av[] = { "rpmtcl", NULL };
00135     Tcl_Interp * tclI = Tcl_CreateInterp();
00136     char b[32];
00137     int ac;
00138 
00139     if (av == NULL) av = _av;
00140     ac = argvCount((ARGV_t)av);
00141 
00142     Tcl_SetVar(tclI, "argv", Tcl_Merge(ac-1, (const char *const *)av+1), TCL_GLOBAL_ONLY);
00143     (void)sprintf(b, "%d", ac-1);
00144     Tcl_SetVar(tclI, "argc", b, TCL_GLOBAL_ONLY);
00145     Tcl_SetVar(tclI, "argv0", av[0], TCL_GLOBAL_ONLY);
00146     Tcl_SetVar(tclI, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
00147 
00148     tcl->I = tclI;
00149     tcl->tclout = Tcl_GetStdChannel(TCL_STDOUT);
00150     Tcl_SetChannelOption(tclI, tcl->tclout, "-translation", "auto");
00151     Tcl_StackChannel(tclI, &rpmtclIO, tcl, TCL_WRITABLE, tcl->tclout);
00152 #endif
00153     tcl->iob = rpmiobNew(0);
00154 
00155     return rpmtclLink(tcl);
00156 }
00157 
00158 rpmRC rpmtclRunFile(rpmtcl tcl, const char * fn, const char ** resultp)
00159 {
00160     rpmRC rc = RPMRC_FAIL;
00161 
00162 if (_rpmtcl_debug)
00163 fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, tcl, fn);
00164 
00165     if (tcl == NULL) tcl = rpmtclI();
00166 
00167 #if defined(WITH_TCL)
00168     if (fn != NULL && Tcl_EvalFile((Tcl_Interp *)tcl->I, fn) == TCL_OK) {
00169         rc = RPMRC_OK;
00170         if (resultp)
00171             *resultp = rpmiobStr(tcl->iob);
00172     }
00173 #endif
00174     return rc;
00175 }
00176 
00177 rpmRC rpmtclRun(rpmtcl tcl, const char * str, const char ** resultp)
00178 {
00179     rpmRC rc = RPMRC_FAIL;
00180 
00181 if (_rpmtcl_debug)
00182 fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, tcl, str);
00183 
00184     if (tcl == NULL) tcl = rpmtclI();
00185 
00186 #if defined(WITH_TCL)
00187     if (str != NULL && Tcl_Eval((Tcl_Interp *)tcl->I, str) == TCL_OK) {
00188         rc = RPMRC_OK;
00189         if (resultp)
00190             *resultp = rpmiobStr(tcl->iob);
00191     }
00192 #endif
00193     return rc;
00194 }