1pass.c
author Ryan C. Gordon <icculus@icculus.org>
Tue, 15 Apr 2014 10:06:56 -0400
changeset 28 60136c984e3b
parent 26 52d346bbaa51
child 29 769393898e93
permissions -rw-r--r--
Hooked up support for a Griffin Powermate.

If you have access to one and run the program with --powermate=/dev/whatever,
1pass will accept button presses on the Powermate as if you hit the magic
key combo. Also, it will toggle the light on the device to pulse when the
keychain is unlocked.
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@17
   393
static gboolean keyhookPumper(void *arg)
icculus@17
   394
{
icculus@17
   395
    if (pumpKeyHook())
icculus@17
   396
        keyhookPressed();
icculus@28
   397
    else if (pumpPowermate())
icculus@28
   398
        keyhookPressed();
icculus@28
   399
icculus@17
   400
    return TRUE;  // keep firing timer
icculus@17
   401
} // keyhookPumper
icculus@17
   402
icculus@17
   403
icculus@11
   404
static int giveControlToGui(lua_State *L)
icculus@11
   405
{
icculus@17
   406
    if (initKeyHook())
icculus@17
   407
    {
icculus@17
   408
        atexit(deinitKeyHook);
icculus@17
   409
        g_timeout_add(200, (GSourceFunc) keyhookPumper, (gpointer) NULL);
icculus@17
   410
    } // if
icculus@17
   411
icculus@11
   412
    gtk_main();
icculus@11
   413
    return 0;
icculus@11
   414
} // giveControlToGui
icculus@11
   415
icculus@7
   416
icculus@0
   417
static void *luaAlloc(void *ud, void *ptr, size_t osize, size_t nsize)
icculus@0
   418
{
icculus@0
   419
    if (nsize == 0)
icculus@0
   420
    {
icculus@0
   421
        free(ptr);
icculus@0
   422
        return NULL;
icculus@0
   423
    } // if
icculus@0
   424
    return realloc(ptr, nsize);
icculus@0
   425
} // luaAlloc
icculus@0
   426
icculus@0
   427
icculus@0
   428
static inline void luaSetCFunc(lua_State *L, lua_CFunction f, const char *sym)
icculus@0
   429
{
icculus@0
   430
    lua_pushcfunction(L, f);
icculus@0
   431
    lua_setglobal(luaState, sym);
icculus@0
   432
} // luaSetCFunc
icculus@0
   433
icculus@0
   434
icculus@0
   435
static int luaFatal(lua_State *L)
icculus@0
   436
{
icculus@0
   437
    const char *errstr = lua_tostring(L, -1);
icculus@0
   438
    fprintf(stderr, "Lua panic: %s\n", errstr ? errstr : "(?)");
icculus@0
   439
    fflush(stderr);
icculus@0
   440
    exit(1);
icculus@0
   441
} // luaFatal
icculus@0
   442
icculus@0
   443
icculus@11
   444
static void deinitLua(void)
icculus@11
   445
{
icculus@11
   446
    if (luaState != NULL)
icculus@11
   447
    {
icculus@11
   448
        lua_close(luaState);
icculus@11
   449
        luaState = NULL;
icculus@11
   450
    } // if
icculus@11
   451
} // deinitLua
icculus@11
   452
icculus@11
   453
icculus@7
   454
static int initLua(const int argc, char **argv)
icculus@0
   455
{
icculus@11
   456
    atexit(deinitLua);
icculus@11
   457
icculus@0
   458
    assert(luaState == NULL);
icculus@0
   459
    luaState = lua_newstate(luaAlloc, NULL);
icculus@0
   460
icculus@0
   461
    lua_atpanic(luaState, luaFatal);
icculus@0
   462
    assert(lua_checkstack(luaState, 20));  // Just in case.
icculus@2
   463
    luaL_openlibs(luaState);
icculus@0
   464
icculus@0
   465
    // Set up initial C functions, etc we want to expose to Lua code...
icculus@0
   466
    luaSetCFunc(luaState, decryptUsingPBKDF2, "decryptUsingPBKDF2");
icculus@0
   467
    luaSetCFunc(luaState, decryptBase64UsingKey, "decryptBase64UsingKey");
icculus@11
   468
    luaSetCFunc(luaState, makeGuiMenu, "makeGuiMenu");
icculus@11
   469
    luaSetCFunc(luaState, appendGuiMenuItem, "appendGuiMenuItem");
icculus@11
   470
    luaSetCFunc(luaState, setGuiMenuItemSubmenu, "setGuiMenuItemSubmenu");
icculus@11
   471
    luaSetCFunc(luaState, popupGuiMenu, "popupGuiMenu");
icculus@11
   472
    luaSetCFunc(luaState, giveControlToGui, "giveControlToGui");
icculus@12
   473
    luaSetCFunc(luaState, runGuiPasswordPrompt, "runGuiPasswordPrompt");
icculus@12
   474
    luaSetCFunc(luaState, copyToClipboard, "copyToClipboard");
icculus@28
   475
    luaSetCFunc(luaState, setPowermateLED_Lua, "setPowermateLED");
icculus@0
   476
icculus@7
   477
    // Set up argv table...
icculus@7
   478
    lua_newtable(luaState);
icculus@7
   479
    int i;
icculus@28
   480
    int luai = 1;
icculus@7
   481
    for (i = 0; i < argc; i++)
icculus@7
   482
    {
icculus@28
   483
        if (argv[i])
icculus@28
   484
        {
icculus@28
   485
            lua_pushinteger(luaState, luai);
icculus@28
   486
            lua_pushstring(luaState, argv[i]);
icculus@28
   487
            lua_settable(luaState, -3);
icculus@28
   488
            luai++;
icculus@28
   489
        } // if
icculus@7
   490
    } // for
icculus@7
   491
    lua_setglobal(luaState, "argv");
icculus@7
   492
icculus@3
   493
    // Transfer control to Lua...
icculus@0
   494
    if (luaL_dofile(luaState, "1pass.lua") != 0)
icculus@16
   495
        luaFatal(luaState);
icculus@0
   496
icculus@0
   497
    return 1;
icculus@0
   498
} // initLua
icculus@0
   499
icculus@0
   500
icculus@0
   501
int main(int argc, char **argv)
icculus@0
   502
{
icculus@28
   503
    initPowermate(&argc, argv);
icculus@11
   504
    gtk_init(&argc, &argv);
icculus@0
   505
icculus@7
   506
    if (!initLua(argc, argv))  // this will move control to 1pass.lua
icculus@0
   507
        return 1;
icculus@0
   508
icculus@0
   509
    return 0;
icculus@0
   510
} // main
icculus@0
   511
icculus@0
   512
// end of 1pass.c ...
icculus@0
   513