1pass.c
author Ryan C. Gordon <icculus@icculus.org>
Tue, 15 Apr 2014 12:10:14 -0400
changeset 29 769393898e93
parent 28 60136c984e3b
child 31 838492d40709
permissions -rw-r--r--
Forcibly lock keychain on timeout instead of checking timeout on next access.
icculus@28
     1
#include <linux/input.h>
icculus@28
     2
#include <fcntl.h>
icculus@0
     3
#include <stdio.h>
icculus@0
     4
#include <stdlib.h>
icculus@0
     5
#include <string.h>
icculus@0
     6
#include <assert.h>
icculus@28
     7
#include <errno.h>
icculus@28
     8
#include <unistd.h>
icculus@28
     9
icculus@0
    10
#include "lua.h"
icculus@0
    11
#include "lauxlib.h"
icculus@0
    12
#include "lualib.h"
icculus@0
    13
#include "pkcs5_pbkdf2.h"
icculus@0
    14
#include "aes.h"
icculus@0
    15
#include "base64.h"
icculus@0
    16
#include "md5.h"
icculus@17
    17
#include "keyhook.h"
icculus@11
    18
#include <gtk/gtk.h>
icculus@0
    19
icculus@0
    20
#define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) )
icculus@0
    21
icculus@28
    22
// plug in a Griffin Powermate, make sure you have access to it, and run with
icculus@28
    23
//  --powermate=/dev/input/eventX
icculus@28
    24
static int powermate_fd = -1;
icculus@28
    25
static int pumpPowermate(void)
icculus@28
    26
{
icculus@28
    27
    struct input_event buf[32];
icculus@28
    28
    int pressed = 0;
icculus@28
    29
    ssize_t br;
icculus@28
    30
icculus@28
    31
    if (powermate_fd == -1)
icculus@28
    32
        return 0;  // nothing to do.
icculus@28
    33
icculus@28
    34
    while ((br = read(powermate_fd, buf, sizeof (buf))) > 0)
icculus@28
    35
    {
icculus@28
    36
        ssize_t i;
icculus@28
    37
        br /= sizeof (buf[0]);
icculus@28
    38
        for (i = 0; i < br; i++)
icculus@28
    39
        {
icculus@28
    40
            struct input_event *ev = &buf[i];
icculus@28
    41
            if ((ev->type == EV_KEY) && (ev->code == BTN_0) && (ev->value))
icculus@28
    42
                pressed = 1;
icculus@28
    43
        } // for
icculus@28
    44
    } // while
icculus@28
    45
icculus@28
    46
    return pressed;
icculus@28
    47
}
icculus@28
    48
icculus@28
    49
static void setPowermateLED(const int enable)
icculus@28
    50
{
icculus@28
    51
    struct input_event ev;
icculus@28
    52
    const int brightness = enable ? 255 : 0;
icculus@28
    53
    const int pulse_speed = 255;
icculus@28
    54
    const int pulse_table = 0;
icculus@28
    55
    const int pulse_awake = enable ? 1 : 0;
icculus@28
    56
    const int pulse_asleep = 0;
icculus@28
    57
icculus@28
    58
    if (powermate_fd == -1)
icculus@28
    59
        return;
icculus@28
    60
icculus@28
    61
    memset(&ev, '\0', sizeof (ev));
icculus@28
    62
    ev.type = EV_MSC;
icculus@28
    63
    ev.code = MSC_PULSELED;
icculus@28
    64
    ev.value = brightness | (pulse_speed << 8) | (pulse_table << 17) | (pulse_asleep << 19) | (pulse_awake << 20);
icculus@28
    65
icculus@28
    66
    if (write(powermate_fd, &ev, sizeof (ev)) != sizeof (ev))
icculus@28
    67
        fprintf(stderr, "WARNING: tried to set Powermate LED and failed: %s\n", strerror(errno));
icculus@28
    68
} // setPowermateLED
icculus@28
    69
icculus@28
    70
icculus@28
    71
static void initPowermate(int *_argc, char **argv)
icculus@28
    72
{
icculus@28
    73
    const char *arg = "--powermate=";
icculus@28
    74
    const size_t arglen = strlen(arg);
icculus@28
    75
    int argc = *_argc;
icculus@28
    76
    int i;
icculus@28
    77
icculus@28
    78
    for (i = 1; i < argc; i++)
icculus@28
    79
    {
icculus@28
    80
        const char *thisarg = argv[i];
icculus@28
    81
        if (strncmp(thisarg, arg, arglen) != 0)
icculus@28
    82
            continue;
icculus@28
    83
icculus@28
    84
        thisarg += arglen;
icculus@28
    85
        powermate_fd = open(thisarg, O_RDWR);
icculus@28
    86
        if (powermate_fd == -1)
icculus@28
    87
            fprintf(stderr, "WARNING: couldn't open Powermate at %s: %s\n", thisarg, strerror(errno));
icculus@28
    88
        else
icculus@28
    89
        {
icculus@28
    90
            const int flags = fcntl(powermate_fd, F_GETFL, 0) | O_NONBLOCK;
icculus@28
    91
            fcntl(powermate_fd, F_SETFL, flags);
icculus@28
    92
        } // else
icculus@28
    93
icculus@28
    94
        // eliminate this command line.
icculus@28
    95
        memmove(&argv[i], &argv[i+1], (argc-i) * sizeof (char *));
icculus@28
    96
        argc--;
icculus@28
    97
    } // for
icculus@28
    98
icculus@28
    99
    *_argc = argc;
icculus@28
   100
} // initPowermate
icculus@28
   101
icculus@28
   102
icculus@0
   103
static lua_State *luaState = NULL;
icculus@0
   104
static const uint8_t zero16[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
icculus@0
   105
static const char saltprefix[] = { 'S', 'a', 'l', 't', 'e', 'd', '_', '_' };
icculus@0
   106
icculus@0
   107
static inline int retvalStringBytes(lua_State *L, const uint8_t *str, size_t len)
icculus@0
   108
{
icculus@0
   109
    if (str != NULL)
icculus@0
   110
        lua_pushlstring(L, (const char *) str, len);
icculus@0
   111
    else
icculus@0
   112
        lua_pushnil(L);
icculus@0
   113
    return 1;
icculus@0
   114
} // retvalStringBytes
icculus@0
   115
icculus@12
   116
static inline int retvalString(lua_State *L, const char *str)
icculus@12
   117
{
icculus@15
   118
    return retvalStringBytes(L, (const uint8_t *) str, str ? strlen(str) : 0);
icculus@12
   119
} // retvalString
icculus@12
   120
icculus@11
   121
static inline int retvalPointer(lua_State *L, void *ptr)
icculus@11
   122
{
icculus@11
   123
    if (ptr != NULL)
icculus@11
   124
        lua_pushlightuserdata(L, ptr);
icculus@11
   125
    else
icculus@11
   126
        lua_pushnil(L);
icculus@11
   127
    return 1;
icculus@11
   128
} // retvalPointer
icculus@11
   129
icculus@0
   130
static inline void xorBlock(uint8_t *dst, const uint8_t *src)
icculus@0
   131
{
icculus@0
   132
    int i;
icculus@0
   133
    for (i = 0; i < 16; i++, dst++, src++)
icculus@0
   134
        *dst ^= *src;
icculus@0
   135
} // xorBlock
icculus@0
   136
icculus@0
   137
static int decryptUsingKeyAndIvec(uint8_t *data, size_t *datalen, const uint8_t *key, const uint8_t *iv)
icculus@0
   138
{
icculus@0
   139
    const size_t blocks = *datalen / 16;
icculus@0
   140
    uint8_t *block = data + ((blocks-1) * 16);   // start at final block, work backwards
icculus@0
   141
    const uint8_t *padding = &block[15];
icculus@0
   142
    uint8_t expkey[aesExpandedKeySize];
icculus@0
   143
    size_t i;
icculus@0
   144
icculus@0
   145
    if (blocks == 0)
icculus@0
   146
        return 1;  // nothing to do.
icculus@0
   147
icculus@0
   148
	aesExpandKey(key, expkey);
icculus@0
   149
icculus@0
   150
    for (i = 0; i < blocks-1; i++)
icculus@0
   151
    {
icculus@0
   152
        aesDecrypt(block, expkey, block);   // decrypt in place.
icculus@0
   153
        xorBlock(block, block-16);
icculus@0
   154
        block -= 16;
icculus@0
   155
    }
icculus@0
   156
    aesDecrypt(block, expkey, block);   // decrypt in place.
icculus@0
   157
    xorBlock(block, iv);   // xor against initial vector for final block.
icculus@0
   158
icculus@0
   159
    if (*padding > 16)
icculus@0
   160
        return 0;  // bad data?
icculus@0
   161
icculus@0
   162
    *datalen -= *padding;
icculus@0
   163
icculus@0
   164
    return 1;
icculus@0
   165
} // decryptBinaryUsingKeyAndIvec
icculus@0
   166
icculus@0
   167
icculus@0
   168
static inline int isSalted(const uint8_t *data, const size_t datalen)
icculus@0
   169
{
icculus@0
   170
    return ( (datalen > sizeof (saltprefix)) &&
icculus@0
   171
             (memcmp(data, saltprefix, sizeof (saltprefix)) == 0) );
icculus@0
   172
} // isSalted
icculus@0
   173
icculus@0
   174
icculus@0
   175
static int decryptUsingPBKDF2(lua_State *L)
icculus@0
   176
{
icculus@0
   177
    const char *base64 = luaL_checkstring(L, 1);
icculus@0
   178
    const char *password = luaL_checkstring(L, 2);
icculus@0
   179
    const int iterations = luaL_checkinteger(L, 3);
icculus@0
   180
    size_t datalen = strlen(base64);
icculus@0
   181
    uint8_t *dataptr = (uint8_t *) malloc(datalen);
icculus@0
   182
    uint8_t *data = dataptr;
icculus@0
   183
    base64_decodestate base64state;
icculus@0
   184
icculus@0
   185
    base64_init_decodestate(&base64state);
icculus@0
   186
    datalen = base64_decode_block(base64, (int) datalen, data, &base64state);
icculus@0
   187
icculus@0
   188
    const uint8_t *salt = zero16;
icculus@0
   189
    int saltlen = sizeof (zero16);
icculus@0
   190
    if (isSalted(data, datalen))
icculus@0
   191
    {
icculus@0
   192
        salt = data + 8;
icculus@0
   193
        saltlen = 8;
icculus@0
   194
        data += 16;
icculus@0
   195
        datalen -= 16;
icculus@0
   196
    } // if
icculus@0
   197
icculus@0
   198
    uint8_t output[32];
icculus@0
   199
    pkcs5_pbkdf2(password, strlen(password), salt, saltlen, output, sizeof (output), (unsigned int) iterations);
icculus@0
   200
icculus@0
   201
    const uint8_t *aeskey = &output[0];
icculus@0
   202
    const uint8_t *aesiv = &output[16];
icculus@0
   203
	if (decryptUsingKeyAndIvec(data, &datalen, aeskey, aesiv))
icculus@0
   204
        retvalStringBytes(L, data, datalen);
icculus@0
   205
    else
icculus@0
   206
        lua_pushnil(L);
icculus@0
   207
icculus@0
   208
    free(dataptr);
icculus@0
   209
    return 1;
icculus@0
   210
} // decryptUsingPBKDF2
icculus@0
   211
icculus@0
   212
icculus@0
   213
static int decryptBase64UsingKey(lua_State *L)
icculus@0
   214
{
icculus@0
   215
    size_t keylen = 0;
icculus@0
   216
    const char *base64 = luaL_checkstring(L, 1);
icculus@0
   217
    const uint8_t *key = (const uint8_t *) luaL_checklstring(L, 2, &keylen);
icculus@0
   218
    size_t datalen = strlen(base64);
icculus@0
   219
    uint8_t *dataptr = (uint8_t *) malloc(datalen);
icculus@0
   220
    uint8_t *data = dataptr;
icculus@0
   221
    base64_decodestate base64state;
icculus@0
   222
icculus@0
   223
    base64_init_decodestate(&base64state);
icculus@0
   224
    datalen = base64_decode_block(base64, (int) datalen, data, &base64state);
icculus@0
   225
icculus@0
   226
    uint8_t aeskey[16];
icculus@0
   227
    uint8_t aesiv[16];
icculus@0
   228
    MD5_CTX md5;
icculus@0
   229
icculus@0
   230
    if (isSalted(data, datalen))
icculus@0
   231
    {
icculus@0
   232
        const uint8_t *salt = data + 8;
icculus@0
   233
        const size_t saltlen = 8;
icculus@0
   234
        data += 16;
icculus@0
   235
        datalen -= 16;
icculus@0
   236
icculus@0
   237
        assert(aesNr == 10);  // AES-256 needs more rounds.
icculus@0
   238
        assert(aesNk == 4);   // hashing size is hardcoded later.
icculus@0
   239
        uint8_t hashing[32];
icculus@0
   240
icculus@0
   241
        MD5_init(&md5);
icculus@0
   242
        MD5_append(&md5, key, keylen);
icculus@0
   243
        MD5_append(&md5, salt, saltlen);
icculus@0
   244
        MD5_finish(&md5, hashing);
icculus@0
   245
icculus@0
   246
        MD5_init(&md5);
icculus@0
   247
        MD5_append(&md5, hashing, 16);
icculus@0
   248
        MD5_append(&md5, key, keylen);
icculus@0
   249
        MD5_append(&md5, salt, saltlen);
icculus@0
   250
        MD5_finish(&md5, &hashing[16]);
icculus@0
   251
icculus@0
   252
        memcpy(aeskey, hashing, 4 * aesNk);
icculus@0
   253
        memcpy(aesiv, &hashing[4 * aesNk], 16);
icculus@0
   254
    } // if
icculus@0
   255
    else
icculus@0
   256
    {
icculus@0
   257
        MD5_init(&md5);
icculus@0
   258
        MD5_append(&md5, key, keylen);
icculus@0
   259
        MD5_finish(&md5, aeskey);
icculus@0
   260
        memset(aesiv, '\0', sizeof (aesiv));
icculus@0
   261
    } // else
icculus@0
   262
icculus@0
   263
	if (decryptUsingKeyAndIvec(data, &datalen, aeskey, aesiv))
icculus@0
   264
        retvalStringBytes(L, data, datalen);
icculus@0
   265
    else
icculus@0
   266
        lua_pushnil(L);
icculus@0
   267
icculus@0
   268
    free(dataptr);
icculus@0
   269
    return 1;
icculus@0
   270
} // decryptBase64UsingKey
icculus@0
   271
icculus@0
   272
icculus@12
   273
static int runGuiPasswordPrompt(lua_State *L)
icculus@12
   274
{
icculus@12
   275
    const char *hintstr = lua_tostring(L, 1);
icculus@12
   276
    GtkWidget *dialog = gtk_dialog_new_with_buttons(
icculus@12
   277
                            "Master Password", NULL, GTK_DIALOG_MODAL,
icculus@12
   278
                            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
icculus@12
   279
                            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
icculus@12
   280
                            NULL);
icculus@12
   281
icculus@12
   282
    GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
icculus@12
   283
icculus@12
   284
    if (hintstr != NULL)
icculus@12
   285
    {
icculus@12
   286
        GtkWidget *label = gtk_label_new(hintstr);
icculus@12
   287
        gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
icculus@12
   288
        gtk_container_add(GTK_CONTAINER(content_area), label);
icculus@12
   289
    } // if
icculus@12
   290
icculus@12
   291
    GtkWidget *entry = gtk_entry_new();
icculus@12
   292
    gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
icculus@12
   293
    gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
icculus@12
   294
    gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
icculus@12
   295
    gtk_container_add(GTK_CONTAINER(content_area), entry);
icculus@12
   296
icculus@12
   297
    gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
icculus@12
   298
    gtk_widget_show_all(dialog);
icculus@26
   299
    gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
icculus@12
   300
    const int ok = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT);
icculus@12
   301
    retvalString(L, ok ? (const char *) gtk_entry_get_text(GTK_ENTRY(entry)) : NULL);
icculus@12
   302
    gtk_widget_destroy(dialog);
icculus@12
   303
icculus@12
   304
    return 1;
icculus@12
   305
} // runGuiPasswordPrompt
icculus@12
   306
icculus@12
   307
icculus@12
   308
static int copyToClipboard(lua_State *L)
icculus@12
   309
{
icculus@12
   310
    const char *str = luaL_checkstring(L, 1);
icculus@12
   311
    gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), str, -1);
icculus@12
   312
    gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), str, -1);
icculus@12
   313
} // copyToClipboard
icculus@12
   314
icculus@12
   315
icculus@11
   316
static int makeGuiMenu(lua_State *L)
icculus@11
   317
{
icculus@11
   318
    return retvalPointer(L, gtk_menu_new());
icculus@11
   319
} // makeGuiMenu
icculus@11
   320
icculus@11
   321
icculus@11
   322
static void clickedMenuItem(void *arg)
icculus@11
   323
{
icculus@11
   324
    // This is the callback from GTK+; now call into our actual Lua callback!
icculus@11
   325
    const int callback = (int) ((size_t)arg);
icculus@11
   326
    lua_rawgeti(luaState, LUA_REGISTRYINDEX, callback);
icculus@11
   327
    lua_call(luaState, 0, 0);
icculus@11
   328
} // clickedMenuItem
icculus@11
   329
icculus@12
   330
#if 0  // !!! FIXME: figure out how to fire this.
icculus@12
   331
static void deletedMenuItem(void *arg)
icculus@12
   332
{
icculus@12
   333
    // Clean up the Lua function we referenced in the Registry.
icculus@12
   334
    const int callback = (int) ((size_t)arg);
icculus@12
   335
printf("unref callback %d\n", callback);
icculus@12
   336
    luaL_unref(luaState, LUA_REGISTRYINDEX, callback);
icculus@12
   337
} // deletedMenuItem
icculus@12
   338
#endif
icculus@11
   339
icculus@11
   340
static int appendGuiMenuItem(lua_State *L)
icculus@11
   341
{
icculus@11
   342
    const int argc = lua_gettop(L);
icculus@11
   343
    GtkWidget *menu = (GtkWidget *) lua_touserdata(L, 1);
icculus@11
   344
    const char *label = luaL_checkstring(L, 2);
icculus@11
   345
    GtkWidget *item = gtk_menu_item_new_with_label(label);
icculus@11
   346
icculus@11
   347
    if ((argc >= 3) && (!lua_isnil(L, 3)))
icculus@11
   348
    {
icculus@11
   349
        assert(lua_isfunction(L, 3));
icculus@11
   350
        lua_pushvalue(L, 3);  // copy the Lua callback (luaL_ref() pops it).
icculus@11
   351
        const int callback = luaL_ref(L, LUA_REGISTRYINDEX);
icculus@11
   352
        gtk_signal_connect_object(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(clickedMenuItem), (gpointer) ((size_t)callback));
icculus@11
   353
    } // if
icculus@11
   354
icculus@11
   355
    gtk_widget_show(item);
icculus@11
   356
    gtk_menu_append(menu, item);
icculus@11
   357
    return retvalPointer(L, item);
icculus@11
   358
} // appendGuiMenuItem
icculus@11
   359
icculus@11
   360
icculus@11
   361
static int setGuiMenuItemSubmenu(lua_State *L)
icculus@11
   362
{
icculus@11
   363
    GtkMenuItem *item = (GtkMenuItem *) lua_touserdata(L, 1);
icculus@11
   364
    GtkWidget *submenu = (GtkWidget *) lua_touserdata(L, 2);
icculus@11
   365
    gtk_menu_item_set_submenu(item, submenu);
icculus@11
   366
    return 0;
icculus@11
   367
} // setGuiMenuItemSubmenu
icculus@11
   368
icculus@11
   369
icculus@11
   370
static int popupGuiMenu(lua_State *L)
icculus@11
   371
{
icculus@11
   372
    GtkMenu *menu = (GtkMenu *) lua_touserdata(L, 1);
icculus@11
   373
    gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
icculus@11
   374
    return 0;
icculus@11
   375
} // popupGuiMenu
icculus@11
   376
icculus@11
   377
icculus@28
   378
static int setPowermateLED_Lua(lua_State *L)
icculus@28
   379
{
icculus@28
   380
    const int enable = lua_toboolean(L, 1);
icculus@28
   381
    setPowermateLED(enable);
icculus@28
   382
    return 0;
icculus@28
   383
} // setPowermateLED_Lua
icculus@28
   384
icculus@28
   385
icculus@17
   386
static void keyhookPressed(void)
icculus@17
   387
{
icculus@17
   388
    lua_getglobal(luaState, "keyhookPressed");
icculus@17
   389
    lua_call(luaState, 0, 0);
icculus@17
   390
} // keyhookPressed
icculus@17
   391
icculus@17
   392
icculus@29
   393
static int pumpLua(void)
icculus@29
   394
{
icculus@29
   395
    lua_getglobal(luaState, "pumpLua");
icculus@29
   396
    lua_call(luaState, 0, 0);
icculus@29
   397
} // pumpLua
icculus@29
   398
icculus@29
   399
icculus@17
   400
static gboolean keyhookPumper(void *arg)
icculus@17
   401
{
icculus@29
   402
    pumpLua();
icculus@17
   403
    if (pumpKeyHook())
icculus@17
   404
        keyhookPressed();
icculus@28
   405
    else if (pumpPowermate())
icculus@28
   406
        keyhookPressed();
icculus@28
   407
icculus@17
   408
    return TRUE;  // keep firing timer
icculus@17
   409
} // keyhookPumper
icculus@17
   410
icculus@17
   411
icculus@11
   412
static int giveControlToGui(lua_State *L)
icculus@11
   413
{
icculus@17
   414
    if (initKeyHook())
icculus@17
   415
    {
icculus@17
   416
        atexit(deinitKeyHook);
icculus@17
   417
        g_timeout_add(200, (GSourceFunc) keyhookPumper, (gpointer) NULL);
icculus@17
   418
    } // if
icculus@17
   419
icculus@11
   420
    gtk_main();
icculus@11
   421
    return 0;
icculus@11
   422
} // giveControlToGui
icculus@11
   423
icculus@7
   424
icculus@0
   425
static void *luaAlloc(void *ud, void *ptr, size_t osize, size_t nsize)
icculus@0
   426
{
icculus@0
   427
    if (nsize == 0)
icculus@0
   428
    {
icculus@0
   429
        free(ptr);
icculus@0
   430
        return NULL;
icculus@0
   431
    } // if
icculus@0
   432
    return realloc(ptr, nsize);
icculus@0
   433
} // luaAlloc
icculus@0
   434
icculus@0
   435
icculus@0
   436
static inline void luaSetCFunc(lua_State *L, lua_CFunction f, const char *sym)
icculus@0
   437
{
icculus@0
   438
    lua_pushcfunction(L, f);
icculus@0
   439
    lua_setglobal(luaState, sym);
icculus@0
   440
} // luaSetCFunc
icculus@0
   441
icculus@0
   442
icculus@0
   443
static int luaFatal(lua_State *L)
icculus@0
   444
{
icculus@0
   445
    const char *errstr = lua_tostring(L, -1);
icculus@0
   446
    fprintf(stderr, "Lua panic: %s\n", errstr ? errstr : "(?)");
icculus@0
   447
    fflush(stderr);
icculus@0
   448
    exit(1);
icculus@0
   449
} // luaFatal
icculus@0
   450
icculus@0
   451
icculus@11
   452
static void deinitLua(void)
icculus@11
   453
{
icculus@11
   454
    if (luaState != NULL)
icculus@11
   455
    {
icculus@11
   456
        lua_close(luaState);
icculus@11
   457
        luaState = NULL;
icculus@11
   458
    } // if
icculus@11
   459
} // deinitLua
icculus@11
   460
icculus@11
   461
icculus@7
   462
static int initLua(const int argc, char **argv)
icculus@0
   463
{
icculus@11
   464
    atexit(deinitLua);
icculus@11
   465
icculus@0
   466
    assert(luaState == NULL);
icculus@0
   467
    luaState = lua_newstate(luaAlloc, NULL);
icculus@0
   468
icculus@0
   469
    lua_atpanic(luaState, luaFatal);
icculus@0
   470
    assert(lua_checkstack(luaState, 20));  // Just in case.
icculus@2
   471
    luaL_openlibs(luaState);
icculus@0
   472
icculus@0
   473
    // Set up initial C functions, etc we want to expose to Lua code...
icculus@0
   474
    luaSetCFunc(luaState, decryptUsingPBKDF2, "decryptUsingPBKDF2");
icculus@0
   475
    luaSetCFunc(luaState, decryptBase64UsingKey, "decryptBase64UsingKey");
icculus@11
   476
    luaSetCFunc(luaState, makeGuiMenu, "makeGuiMenu");
icculus@11
   477
    luaSetCFunc(luaState, appendGuiMenuItem, "appendGuiMenuItem");
icculus@11
   478
    luaSetCFunc(luaState, setGuiMenuItemSubmenu, "setGuiMenuItemSubmenu");
icculus@11
   479
    luaSetCFunc(luaState, popupGuiMenu, "popupGuiMenu");
icculus@11
   480
    luaSetCFunc(luaState, giveControlToGui, "giveControlToGui");
icculus@12
   481
    luaSetCFunc(luaState, runGuiPasswordPrompt, "runGuiPasswordPrompt");
icculus@12
   482
    luaSetCFunc(luaState, copyToClipboard, "copyToClipboard");
icculus@28
   483
    luaSetCFunc(luaState, setPowermateLED_Lua, "setPowermateLED");
icculus@0
   484
icculus@7
   485
    // Set up argv table...
icculus@7
   486
    lua_newtable(luaState);
icculus@7
   487
    int i;
icculus@28
   488
    int luai = 1;
icculus@7
   489
    for (i = 0; i < argc; i++)
icculus@7
   490
    {
icculus@28
   491
        if (argv[i])
icculus@28
   492
        {
icculus@28
   493
            lua_pushinteger(luaState, luai);
icculus@28
   494
            lua_pushstring(luaState, argv[i]);
icculus@28
   495
            lua_settable(luaState, -3);
icculus@28
   496
            luai++;
icculus@28
   497
        } // if
icculus@7
   498
    } // for
icculus@7
   499
    lua_setglobal(luaState, "argv");
icculus@7
   500
icculus@3
   501
    // Transfer control to Lua...
icculus@0
   502
    if (luaL_dofile(luaState, "1pass.lua") != 0)
icculus@16
   503
        luaFatal(luaState);
icculus@0
   504
icculus@0
   505
    return 1;
icculus@0
   506
} // initLua
icculus@0
   507
icculus@0
   508
icculus@0
   509
int main(int argc, char **argv)
icculus@0
   510
{
icculus@28
   511
    initPowermate(&argc, argv);
icculus@11
   512
    gtk_init(&argc, &argv);
icculus@0
   513
icculus@7
   514
    if (!initLua(argc, argv))  // this will move control to 1pass.lua
icculus@0
   515
        return 1;
icculus@0
   516
icculus@0
   517
    return 0;
icculus@0
   518
} // main
icculus@0
   519
icculus@0
   520
// end of 1pass.c ...
icculus@0
   521