Annotation of embedaddon/lighttpd/src/mod_magnet.c, revision 1.1.1.2

1.1       misho       1: #include "base.h"
                      2: #include "log.h"
                      3: #include "buffer.h"
                      4: 
                      5: #include "plugin.h"
                      6: 
                      7: #include "mod_magnet_cache.h"
                      8: #include "response.h"
                      9: #include "stat_cache.h"
                     10: #include "status_counter.h"
                     11: #include "etag.h"
                     12: 
                     13: #include <ctype.h>
                     14: #include <stdlib.h>
                     15: #include <string.h>
                     16: #include <assert.h>
                     17: #include <setjmp.h>
                     18: 
                     19: #ifdef HAVE_LUA_H
                     20: #include <lua.h>
                     21: #include <lauxlib.h>
                     22: 
                     23: #define MAGNET_CONFIG_RAW_URL       "magnet.attract-raw-url-to"
                     24: #define MAGNET_CONFIG_PHYSICAL_PATH "magnet.attract-physical-path-to"
                     25: #define MAGNET_RESTART_REQUEST      99
                     26: 
                     27: /* plugin config for all request/connections */
                     28: 
                     29: static jmp_buf exceptionjmp;
                     30: 
                     31: typedef struct {
                     32:        array *url_raw;
                     33:        array *physical_path;
                     34: } plugin_config;
                     35: 
                     36: typedef struct {
                     37:        PLUGIN_DATA;
                     38: 
                     39:        script_cache *cache;
                     40: 
                     41:        buffer *encode_buf;
                     42: 
                     43:        plugin_config **config_storage;
                     44: 
                     45:        plugin_config conf;
                     46: } plugin_data;
                     47: 
                     48: /* init the plugin data */
                     49: INIT_FUNC(mod_magnet_init) {
                     50:        plugin_data *p;
                     51: 
                     52:        p = calloc(1, sizeof(*p));
                     53: 
                     54:        p->cache = script_cache_init();
                     55:        p->encode_buf = buffer_init();
                     56: 
                     57:        return p;
                     58: }
                     59: 
                     60: /* detroy the plugin data */
                     61: FREE_FUNC(mod_magnet_free) {
                     62:        plugin_data *p = p_d;
                     63: 
                     64:        UNUSED(srv);
                     65: 
                     66:        if (!p) return HANDLER_GO_ON;
                     67: 
                     68:        if (p->config_storage) {
                     69:                size_t i;
                     70: 
                     71:                for (i = 0; i < srv->config_context->used; i++) {
                     72:                        plugin_config *s = p->config_storage[i];
                     73: 
                     74:                        if (!s) continue;
                     75: 
                     76:                        array_free(s->url_raw);
                     77:                        array_free(s->physical_path);
                     78: 
                     79:                        free(s);
                     80:                }
                     81:                free(p->config_storage);
                     82:        }
                     83: 
                     84:        script_cache_free(p->cache);
                     85:        buffer_free(p->encode_buf);
                     86: 
                     87:        free(p);
                     88: 
                     89:        return HANDLER_GO_ON;
                     90: }
                     91: 
                     92: /* handle plugin config and check values */
                     93: 
                     94: SETDEFAULTS_FUNC(mod_magnet_set_defaults) {
                     95:        plugin_data *p = p_d;
                     96:        size_t i = 0;
                     97: 
                     98:        config_values_t cv[] = {
                     99:                { MAGNET_CONFIG_RAW_URL,       NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
                    100:                { MAGNET_CONFIG_PHYSICAL_PATH, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
                    101:                { NULL,                           NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
                    102:        };
                    103: 
                    104:        if (!p) return HANDLER_ERROR;
                    105: 
1.1.1.2 ! misho     106:        p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
1.1       misho     107: 
                    108:        for (i = 0; i < srv->config_context->used; i++) {
                    109:                plugin_config *s;
                    110: 
                    111:                s = calloc(1, sizeof(plugin_config));
                    112:                s->url_raw  = array_init();
                    113:                s->physical_path = array_init();
                    114: 
                    115:                cv[0].destination = s->url_raw;
                    116:                cv[1].destination = s->physical_path;
                    117: 
                    118:                p->config_storage[i] = s;
                    119: 
                    120:                if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
                    121:                        return HANDLER_ERROR;
                    122:                }
                    123:        }
                    124: 
                    125:        return HANDLER_GO_ON;
                    126: }
                    127: 
                    128: #define PATCH(x) \
                    129:        p->conf.x = s->x;
                    130: static int mod_magnet_patch_connection(server *srv, connection *con, plugin_data *p) {
                    131:        size_t i, j;
                    132:        plugin_config *s = p->config_storage[0];
                    133: 
                    134:        PATCH(url_raw);
                    135:        PATCH(physical_path);
                    136: 
                    137:        /* skip the first, the global context */
                    138:        for (i = 1; i < srv->config_context->used; i++) {
                    139:                data_config *dc = (data_config *)srv->config_context->data[i];
                    140:                s = p->config_storage[i];
                    141: 
                    142:                /* condition didn't match */
                    143:                if (!config_check_cond(srv, con, dc)) continue;
                    144: 
                    145:                /* merge config */
                    146:                for (j = 0; j < dc->value->used; j++) {
                    147:                        data_unset *du = dc->value->data[j];
                    148: 
                    149:                        if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_RAW_URL))) {
                    150:                                PATCH(url_raw);
                    151:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_PHYSICAL_PATH))) {
                    152:                                PATCH(physical_path);
                    153:                        }
                    154:                }
                    155:        }
                    156: 
                    157:        return 0;
                    158: }
                    159: #undef PATCH
                    160: 
                    161: /* See http://lua-users.org/wiki/GeneralizedPairsAndIpairs for implementation details. */
                    162: 
                    163: /* Override the default pairs() function to allow us to use a __pairs metakey */
                    164: static int magnet_pairs(lua_State *L) {
                    165:        luaL_checkany(L, 1);
                    166: 
                    167:        if (luaL_getmetafield(L, 1, "__pairs")) {
                    168:                lua_insert(L, 1);
                    169:                lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
                    170:                return lua_gettop(L);
                    171:        } else {
                    172:                lua_pushvalue(L, lua_upvalueindex(1));
                    173:                lua_insert(L, 1);
                    174:                lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
                    175:                return lua_gettop(L);
                    176:        }
                    177: }
                    178: 
                    179: /* Define a function that will iterate over an array* (in upval 1) using current position (upval 2) */
                    180: static int magnet_array_next(lua_State *L) {
                    181:        data_unset *du;
                    182:        data_string *ds;
                    183:        data_integer *di;
                    184: 
                    185:        size_t pos = lua_tointeger(L, lua_upvalueindex(1));
                    186:        array *a = lua_touserdata(L, lua_upvalueindex(2));
                    187: 
                    188:        lua_settop(L, 0);
                    189: 
                    190:        if (pos >= a->used) return 0;
                    191:        if (NULL != (du = a->data[pos])) {
                    192:                if (du->key->used) {
                    193:                        lua_pushlstring(L, du->key->ptr, du->key->used - 1);
                    194:                }
                    195:                else {
                    196:                        lua_pushlstring(L, "", 0);
                    197:                }
                    198:                switch (du->type) {
                    199:                        case TYPE_STRING:
                    200:                                ds = (data_string *)du;
                    201:                                if (ds->value && ds->value->used) {
                    202:                                        lua_pushlstring(L, ds->value->ptr, ds->value->used - 1);
                    203:                                } else {
                    204:                                        lua_pushnil(L);
                    205:                                }
                    206:                                break;
                    207:                        case TYPE_COUNT:
                    208:                        case TYPE_INTEGER:
                    209:                                di = (data_integer *)du;
                    210:                                lua_pushinteger(L, di->value);
                    211:                                break;
                    212:                        default:
                    213:                                lua_pushnil(L);
                    214:                                break;
                    215:                }
                    216: 
                    217:                /* Update our positional upval to reflect our new current position */
                    218:                pos++;
                    219:                lua_pushinteger(L, pos);
                    220:                lua_replace(L, lua_upvalueindex(1));
                    221: 
                    222:                /* Returning 2 items on the stack (key, value) */
                    223:                return 2;
                    224:        }
                    225:        return 0;
                    226: }
                    227: 
                    228: /* Create the closure necessary to iterate over the array *a with the above function */
                    229: static int magnet_array_pairs(lua_State *L, array *a) {
                    230:        lua_pushinteger(L, 0); /* Push our current pos (the start) into upval 1 */
                    231:        lua_pushlightuserdata(L, a); /* Push our array *a into upval 2 */
                    232:        lua_pushcclosure(L, magnet_array_next, 2); /* Push our new closure with 2 upvals */
                    233:        return 1;
                    234: }
                    235: 
                    236: static int magnet_print(lua_State *L) {
                    237:        const char *s = luaL_checkstring(L, 1);
                    238:        server *srv;
                    239: 
                    240:        lua_pushstring(L, "lighty.srv");
                    241:        lua_gettable(L, LUA_REGISTRYINDEX);
                    242:        srv = lua_touserdata(L, -1);
                    243:        lua_pop(L, 1);
                    244: 
                    245:        log_error_write(srv, __FILE__, __LINE__, "ss",
                    246:                        "(lua-print)", s);
                    247: 
                    248:        return 0;
                    249: }
                    250: 
                    251: static int magnet_stat(lua_State *L) {
                    252:        const char *s = luaL_checkstring(L, 1);
                    253:        server *srv;
                    254:        connection *con;
                    255:        buffer sb;
                    256:        stat_cache_entry *sce = NULL;
                    257: 
                    258:        lua_pushstring(L, "lighty.srv");
                    259:        lua_gettable(L, LUA_REGISTRYINDEX);
                    260:        srv = lua_touserdata(L, -1);
                    261:        lua_pop(L, 1);
                    262: 
                    263:        lua_pushstring(L, "lighty.con");
                    264:        lua_gettable(L, LUA_REGISTRYINDEX);
                    265:        con = lua_touserdata(L, -1);
                    266:        lua_pop(L, 1);
                    267: 
                    268:        sb.ptr = (char *)s;
                    269:        sb.used = sb.size = strlen(s) + 1;
                    270:        
                    271:        if (HANDLER_GO_ON != stat_cache_get_entry(srv, con, &sb, &sce)) {
                    272:                lua_pushnil(L);
                    273: 
                    274:                return 1;
                    275:        }
                    276: 
                    277:        lua_newtable(L);
                    278: 
                    279:        lua_pushboolean(L, S_ISREG(sce->st.st_mode));
                    280:        lua_setfield(L, -2, "is_file");
                    281:        
                    282:        lua_pushboolean(L, S_ISDIR(sce->st.st_mode));
                    283:        lua_setfield(L, -2, "is_dir");
                    284: 
                    285:        lua_pushboolean(L, S_ISCHR(sce->st.st_mode));
                    286:        lua_setfield(L, -2, "is_char");
                    287: 
                    288:        lua_pushboolean(L, S_ISBLK(sce->st.st_mode));
                    289:        lua_setfield(L, -2, "is_block");
                    290: 
                    291:        lua_pushboolean(L, S_ISSOCK(sce->st.st_mode));
                    292:        lua_setfield(L, -2, "is_socket");
                    293: 
                    294:        lua_pushboolean(L, S_ISLNK(sce->st.st_mode));
                    295:        lua_setfield(L, -2, "is_link");
                    296: 
                    297:        lua_pushboolean(L, S_ISFIFO(sce->st.st_mode));
                    298:        lua_setfield(L, -2, "is_fifo");
                    299: 
                    300:        lua_pushinteger(L, sce->st.st_mtime);
                    301:        lua_setfield(L, -2, "st_mtime");
                    302: 
                    303:        lua_pushinteger(L, sce->st.st_ctime);
                    304:        lua_setfield(L, -2, "st_ctime");
                    305: 
                    306:        lua_pushinteger(L, sce->st.st_atime);
                    307:        lua_setfield(L, -2, "st_atime");
                    308: 
                    309:        lua_pushinteger(L, sce->st.st_uid);
                    310:        lua_setfield(L, -2, "st_uid");
                    311: 
                    312:        lua_pushinteger(L, sce->st.st_gid);
                    313:        lua_setfield(L, -2, "st_gid");
                    314: 
                    315:        lua_pushinteger(L, sce->st.st_size);
                    316:        lua_setfield(L, -2, "st_size");
                    317: 
                    318:        lua_pushinteger(L, sce->st.st_ino);
                    319:        lua_setfield(L, -2, "st_ino");
                    320: 
                    321: 
                    322:        if (!buffer_is_empty(sce->etag)) {
                    323:                /* we have to mutate the etag */
                    324:                buffer *b = buffer_init();
                    325:                etag_mutate(b, sce->etag);
                    326: 
                    327:                lua_pushlstring(L, b->ptr, b->used - 1);
                    328:                buffer_free(b);
                    329:        } else {
                    330:                lua_pushnil(L);
                    331:        }
                    332:        lua_setfield(L, -2, "etag");
                    333: 
                    334:        if (!buffer_is_empty(sce->content_type)) {
                    335:                lua_pushlstring(L, sce->content_type->ptr, sce->content_type->used - 1);
                    336:        } else {
                    337:                lua_pushnil(L);
                    338:        }
                    339:        lua_setfield(L, -2, "content-type");
                    340: 
                    341:        return 1;
                    342: }
                    343: 
                    344: 
                    345: static int magnet_atpanic(lua_State *L) {
                    346:        const char *s = luaL_checkstring(L, 1);
                    347:        server *srv;
                    348: 
                    349:        lua_pushstring(L, "lighty.srv");
                    350:        lua_gettable(L, LUA_REGISTRYINDEX);
                    351:        srv = lua_touserdata(L, -1);
                    352:        lua_pop(L, 1);
                    353: 
                    354:        log_error_write(srv, __FILE__, __LINE__, "ss",
                    355:                        "(lua-atpanic)", s);
                    356: 
                    357:        longjmp(exceptionjmp, 1);
                    358: }
                    359: 
                    360: static int magnet_reqhdr_get(lua_State *L) {
                    361:        connection *con;
                    362:        data_string *ds;
                    363: 
                    364:        const char *key = luaL_checkstring(L, 2);
                    365: 
                    366:        lua_pushstring(L, "lighty.con");
                    367:        lua_gettable(L, LUA_REGISTRYINDEX);
                    368:        con = lua_touserdata(L, -1);
                    369:        lua_pop(L, 1);
                    370: 
                    371:        if (NULL != (ds = (data_string *)array_get_element(con->request.headers, key))) {
                    372:                if (ds->value->used) {
                    373:                        lua_pushlstring(L, ds->value->ptr, ds->value->used - 1);
                    374:                } else {
                    375:                        lua_pushnil(L);
                    376:                }
                    377:        } else {
                    378:                lua_pushnil(L);
                    379:        }
                    380:        return 1;
                    381: }
                    382: 
                    383: static int magnet_reqhdr_pairs(lua_State *L) {
                    384:        connection *con;
                    385: 
                    386:        lua_pushstring(L, "lighty.con");
                    387:        lua_gettable(L, LUA_REGISTRYINDEX);
                    388:        con = lua_touserdata(L, -1);
                    389:        lua_pop(L, 1);
                    390: 
                    391:        return magnet_array_pairs(L, con->request.headers);
                    392: }
                    393: 
                    394: static int magnet_status_get(lua_State *L) {
                    395:        data_integer *di;
                    396:        server *srv;
                    397:        size_t key_len = 0;
                    398: 
                    399:        const char *key = luaL_checklstring(L, 2, &key_len);
                    400: 
                    401:        lua_pushstring(L, "lighty.srv");
                    402:        lua_gettable(L, LUA_REGISTRYINDEX);
                    403:        srv = lua_touserdata(L, -1);
                    404:        lua_pop(L, 1);
                    405: 
                    406:        di = status_counter_get_counter(srv, key, key_len);
                    407: 
                    408:        lua_pushnumber(L, (double)di->value);
                    409: 
                    410:        return 1;
                    411: }
                    412: 
                    413: static int magnet_status_set(lua_State *L) {
                    414:        size_t key_len = 0;
                    415:        server *srv;
                    416: 
                    417:        const char *key = luaL_checklstring(L, 2, &key_len);
                    418:        int counter = luaL_checkint(L, 3);
                    419: 
                    420:        lua_pushstring(L, "lighty.srv");
                    421:        lua_gettable(L, LUA_REGISTRYINDEX);
                    422:        srv = lua_touserdata(L, -1);
                    423:        lua_pop(L, 1);
                    424: 
                    425:        status_counter_set(srv, key, key_len, counter);
                    426: 
                    427:        return 0;
                    428: }
                    429: 
                    430: static int magnet_status_pairs(lua_State *L) {
                    431:        server *srv;
                    432: 
                    433:        lua_pushstring(L, "lighty.srv");
                    434:        lua_gettable(L, LUA_REGISTRYINDEX);
                    435:        srv = lua_touserdata(L, -1);
                    436:        lua_pop(L, 1);
                    437: 
                    438:        return magnet_array_pairs(L, srv->status);
                    439: }
                    440: 
                    441: typedef struct {
                    442:        const char *name;
                    443:        enum {
                    444:                MAGNET_ENV_UNSET,
                    445: 
                    446:                MAGNET_ENV_PHYICAL_PATH,
                    447:                MAGNET_ENV_PHYICAL_REL_PATH,
                    448:                MAGNET_ENV_PHYICAL_DOC_ROOT,
1.1.1.2 ! misho     449:                MAGNET_ENV_PHYICAL_BASEDIR,
1.1       misho     450: 
                    451:                MAGNET_ENV_URI_PATH,
                    452:                MAGNET_ENV_URI_PATH_RAW,
                    453:                MAGNET_ENV_URI_SCHEME,
                    454:                MAGNET_ENV_URI_AUTHORITY,
                    455:                MAGNET_ENV_URI_QUERY,
                    456: 
                    457:                MAGNET_ENV_REQUEST_METHOD,
                    458:                MAGNET_ENV_REQUEST_URI,
                    459:                MAGNET_ENV_REQUEST_ORIG_URI,
                    460:                MAGNET_ENV_REQUEST_PATH_INFO,
                    461:                MAGNET_ENV_REQUEST_REMOTE_IP,
                    462:                MAGNET_ENV_REQUEST_PROTOCOL
                    463:        } type;
                    464: } magnet_env_t;
                    465: 
                    466: static const magnet_env_t magnet_env[] = {
                    467:        { "physical.path", MAGNET_ENV_PHYICAL_PATH },
                    468:        { "physical.rel-path", MAGNET_ENV_PHYICAL_REL_PATH },
                    469:        { "physical.doc-root", MAGNET_ENV_PHYICAL_DOC_ROOT },
1.1.1.2 ! misho     470:        { "physical.basedir", MAGNET_ENV_PHYICAL_BASEDIR },
1.1       misho     471: 
                    472:        { "uri.path", MAGNET_ENV_URI_PATH },
                    473:        { "uri.path-raw", MAGNET_ENV_URI_PATH_RAW },
                    474:        { "uri.scheme", MAGNET_ENV_URI_SCHEME },
                    475:        { "uri.authority", MAGNET_ENV_URI_AUTHORITY },
                    476:        { "uri.query", MAGNET_ENV_URI_QUERY },
                    477: 
                    478:        { "request.method", MAGNET_ENV_REQUEST_METHOD },
                    479:        { "request.uri", MAGNET_ENV_REQUEST_URI },
                    480:        { "request.orig-uri", MAGNET_ENV_REQUEST_ORIG_URI },
                    481:        { "request.path-info", MAGNET_ENV_REQUEST_PATH_INFO },
                    482:        { "request.remote-ip", MAGNET_ENV_REQUEST_REMOTE_IP },
                    483:        { "request.protocol", MAGNET_ENV_REQUEST_PROTOCOL },
                    484: 
                    485:        { NULL, MAGNET_ENV_UNSET }
                    486: };
                    487: 
                    488: static buffer *magnet_env_get_buffer_by_id(server *srv, connection *con, int id) {
                    489:        buffer *dest = NULL;
                    490: 
                    491:        UNUSED(srv);
                    492: 
                    493:        /**
                    494:         * map all internal variables to lua
                    495:         *
                    496:         */
                    497: 
                    498:        switch (id) {
                    499:        case MAGNET_ENV_PHYICAL_PATH: dest = con->physical.path; break;
                    500:        case MAGNET_ENV_PHYICAL_REL_PATH: dest = con->physical.rel_path; break;
                    501:        case MAGNET_ENV_PHYICAL_DOC_ROOT: dest = con->physical.doc_root; break;
1.1.1.2 ! misho     502:        case MAGNET_ENV_PHYICAL_BASEDIR: dest = con->physical.basedir; break;
1.1       misho     503: 
                    504:        case MAGNET_ENV_URI_PATH: dest = con->uri.path; break;
                    505:        case MAGNET_ENV_URI_PATH_RAW: dest = con->uri.path_raw; break;
                    506:        case MAGNET_ENV_URI_SCHEME: dest = con->uri.scheme; break;
                    507:        case MAGNET_ENV_URI_AUTHORITY: dest = con->uri.authority; break;
                    508:        case MAGNET_ENV_URI_QUERY: dest = con->uri.query; break;
                    509: 
                    510:        case MAGNET_ENV_REQUEST_METHOD:
                    511:                buffer_copy_string(srv->tmp_buf, get_http_method_name(con->request.http_method));
                    512:                dest = srv->tmp_buf;
                    513:                break;
                    514:        case MAGNET_ENV_REQUEST_URI:      dest = con->request.uri; break;
                    515:        case MAGNET_ENV_REQUEST_ORIG_URI: dest = con->request.orig_uri; break;
                    516:        case MAGNET_ENV_REQUEST_PATH_INFO: dest = con->request.pathinfo; break;
                    517:        case MAGNET_ENV_REQUEST_REMOTE_IP: dest = con->dst_addr_buf; break;
                    518:        case MAGNET_ENV_REQUEST_PROTOCOL:
                    519:                buffer_copy_string(srv->tmp_buf, get_http_version_name(con->request.http_version));
                    520:                dest = srv->tmp_buf;
                    521:                break;
                    522: 
                    523:        case MAGNET_ENV_UNSET: break;
                    524:        }
                    525: 
                    526:        return dest;
                    527: }
                    528: 
                    529: static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *key) {
                    530:        size_t i;
                    531: 
                    532:        for (i = 0; magnet_env[i].name; i++) {
                    533:                if (0 == strcmp(key, magnet_env[i].name)) break;
                    534:        }
                    535: 
                    536:        return magnet_env_get_buffer_by_id(srv, con, magnet_env[i].type);
                    537: }
                    538: 
                    539: static int magnet_env_get(lua_State *L) {
                    540:        server *srv;
                    541:        connection *con;
                    542: 
                    543:        const char *key = luaL_checkstring(L, 2);
                    544:        buffer *dest = NULL;
                    545: 
                    546:        lua_pushstring(L, "lighty.srv");
                    547:        lua_gettable(L, LUA_REGISTRYINDEX);
                    548:        srv = lua_touserdata(L, -1);
                    549:        lua_pop(L, 1);
                    550: 
                    551:        lua_pushstring(L, "lighty.con");
                    552:        lua_gettable(L, LUA_REGISTRYINDEX);
                    553:        con = lua_touserdata(L, -1);
                    554:        lua_pop(L, 1);
                    555: 
                    556:        dest = magnet_env_get_buffer(srv, con, key);
                    557: 
                    558:        if (dest && dest->used) {
                    559:                lua_pushlstring(L, dest->ptr, dest->used - 1);
                    560:        } else {
                    561:                lua_pushnil(L);
                    562:        }
                    563: 
                    564:        return 1;
                    565: }
                    566: 
                    567: static int magnet_env_set(lua_State *L) {
                    568:        server *srv;
                    569:        connection *con;
                    570: 
                    571:        const char *key = luaL_checkstring(L, 2);
                    572:        const char *val = luaL_checkstring(L, 3);
                    573:        buffer *dest = NULL;
                    574: 
                    575:        lua_pushstring(L, "lighty.srv");
                    576:        lua_gettable(L, LUA_REGISTRYINDEX);
                    577:        srv = lua_touserdata(L, -1);
                    578:        lua_pop(L, 1);
                    579: 
                    580:        lua_pushstring(L, "lighty.con");
                    581:        lua_gettable(L, LUA_REGISTRYINDEX);
                    582:        con = lua_touserdata(L, -1);
                    583:        lua_pop(L, 1);
                    584: 
                    585:        if (NULL != (dest = magnet_env_get_buffer(srv, con, key))) {
                    586:                buffer_copy_string(dest, val);
                    587:        } else {
                    588:                /* couldn't save */
                    589: 
                    590:                return luaL_error(L, "couldn't store '%s' in lighty.env[]", key);
                    591:        }
                    592: 
                    593:        return 0;
                    594: }
                    595: 
                    596: static int magnet_env_next(lua_State *L) {
                    597:        server *srv;
                    598:        connection *con;
                    599:        int pos = lua_tointeger(L, lua_upvalueindex(1));
                    600: 
                    601:        buffer *dest;
                    602: 
                    603:        lua_pushstring(L, "lighty.srv");
                    604:        lua_gettable(L, LUA_REGISTRYINDEX);
                    605:        srv = lua_touserdata(L, -1);
                    606:        lua_pop(L, 1);
                    607: 
                    608:        lua_pushstring(L, "lighty.con");
                    609:        lua_gettable(L, LUA_REGISTRYINDEX);
                    610:        con = lua_touserdata(L, -1);
                    611:        lua_pop(L, 1);
                    612: 
                    613:        lua_settop(L, 0);
                    614: 
                    615:        if (NULL == magnet_env[pos].name) return 0; /* end of list */
                    616: 
                    617:        lua_pushstring(L, magnet_env[pos].name);
                    618: 
                    619:        dest = magnet_env_get_buffer_by_id(srv, con, magnet_env[pos].type);
                    620:        if (dest && dest->used) {
                    621:                lua_pushlstring(L, dest->ptr, dest->used - 1);
                    622:        } else {
                    623:                lua_pushnil(L);
                    624:        }
                    625: 
                    626:        /* Update our positional upval to reflect our new current position */
                    627:        pos++;
                    628:        lua_pushinteger(L, pos);
                    629:        lua_replace(L, lua_upvalueindex(1));
                    630: 
                    631:        /* Returning 2 items on the stack (key, value) */
                    632:        return 2;
                    633: }
                    634: 
                    635: static int magnet_env_pairs(lua_State *L) {
                    636:        lua_pushinteger(L, 0); /* Push our current pos (the start) into upval 1 */
                    637:        lua_pushcclosure(L, magnet_env_next, 1); /* Push our new closure with 1 upvals */
                    638:        return 1;
                    639: }
                    640: 
                    641: static int magnet_cgi_get(lua_State *L) {
                    642:        connection *con;
                    643:        data_string *ds;
                    644: 
                    645:        const char *key = luaL_checkstring(L, 2);
                    646: 
                    647:        lua_pushstring(L, "lighty.con");
                    648:        lua_gettable(L, LUA_REGISTRYINDEX);
                    649:        con = lua_touserdata(L, -1);
                    650:        lua_pop(L, 1);
                    651: 
                    652:        if (NULL != (ds = (data_string *)array_get_element(con->environment, key)) && ds->value->used)
                    653:                lua_pushlstring(L, CONST_BUF_LEN(ds->value));
                    654:        else
                    655:                lua_pushnil(L);
                    656: 
                    657:        return 1;
                    658: }
                    659: 
                    660: static int magnet_cgi_set(lua_State *L) {
                    661:        connection *con;
                    662: 
                    663:        const char *key = luaL_checkstring(L, 2);
                    664:        const char *val = luaL_checkstring(L, 3);
                    665: 
                    666:        lua_pushstring(L, "lighty.con");
                    667:        lua_gettable(L, LUA_REGISTRYINDEX);
                    668:        con = lua_touserdata(L, -1);
                    669:        lua_pop(L, 1);
                    670: 
                    671:        array_set_key_value(con->environment, key, strlen(key), val, strlen(val));
                    672: 
                    673:        return 0;
                    674: }
                    675: 
                    676: static int magnet_cgi_pairs(lua_State *L) {
                    677:        connection *con;
                    678: 
                    679:        lua_pushstring(L, "lighty.con");
                    680:        lua_gettable(L, LUA_REGISTRYINDEX);
                    681:        con = lua_touserdata(L, -1);
                    682:        lua_pop(L, 1);
                    683: 
                    684:        return magnet_array_pairs(L, con->environment);
                    685: }
                    686: 
                    687: 
                    688: static int magnet_copy_response_header(server *srv, connection *con, plugin_data *p, lua_State *L) {
                    689:        UNUSED(p);
                    690:        /**
                    691:         * get the environment of the function
                    692:         */
                    693: 
                    694:        lua_getfenv(L, -1); /* -1 is the function */
                    695: 
                    696:        /* lighty.header */
                    697: 
                    698:        lua_getfield(L, -1, "lighty"); /* lighty.* from the env  */
1.1.1.2 ! misho     699:        force_assert(lua_istable(L, -1));
1.1       misho     700: 
                    701:        lua_getfield(L, -1, "header"); /* lighty.header */
                    702:        if (lua_istable(L, -1)) {
                    703:                /* header is found, and is a table */
                    704: 
                    705:                lua_pushnil(L);
                    706:                while (lua_next(L, -2) != 0) {
                    707:                        if (lua_isstring(L, -1) && lua_isstring(L, -2)) {
                    708:                                const char *key, *val;
                    709:                                size_t key_len, val_len;
                    710: 
                    711:                                key = lua_tolstring(L, -2, &key_len);
                    712:                                val = lua_tolstring(L, -1, &val_len);
                    713: 
                    714:                                response_header_overwrite(srv, con, key, key_len, val, val_len);
                    715:                        }
                    716: 
                    717:                        lua_pop(L, 1);
                    718:                }
                    719:        }
                    720: 
                    721:        lua_pop(L, 1); /* pop the header-table */
                    722:        lua_pop(L, 1); /* pop the lighty-env */
                    723:        lua_pop(L, 1); /* pop the function env */
                    724: 
                    725:        return 0;
                    726: }
                    727: 
                    728: /**
                    729:  * walk through the content array
                    730:  *
                    731:  * content = { "<pre>", { file = "/content" } , "</pre>" }
                    732:  *
                    733:  * header["Content-Type"] = "text/html"
                    734:  *
                    735:  * return 200
                    736:  */
                    737: static int magnet_attach_content(server *srv, connection *con, plugin_data *p, lua_State *L) {
                    738:        UNUSED(p);
                    739:        /**
                    740:         * get the environment of the function
                    741:         */
                    742: 
1.1.1.2 ! misho     743:        force_assert(lua_isfunction(L, -1));
1.1       misho     744:        lua_getfenv(L, -1); /* -1 is the function */
                    745: 
                    746:        lua_getfield(L, -1, "lighty"); /* lighty.* from the env  */
1.1.1.2 ! misho     747:        force_assert(lua_istable(L, -1));
1.1       misho     748: 
                    749:        lua_getfield(L, -1, "content"); /* lighty.content */
                    750:        if (lua_istable(L, -1)) {
                    751:                int i;
                    752:                /* header is found, and is a table */
                    753: 
                    754:                for (i = 1; ; i++) {
                    755:                        lua_rawgeti(L, -1, i);
                    756: 
                    757:                        /* -1 is the value and should be the value ... aka a table */
                    758:                        if (lua_isstring(L, -1)) {
                    759:                                size_t s_len = 0;
                    760:                                const char *s = lua_tolstring(L, -1, &s_len);
                    761: 
                    762:                                chunkqueue_append_mem(con->write_queue, s, s_len + 1);
                    763:                        } else if (lua_istable(L, -1)) {
                    764:                                lua_getfield(L, -1, "filename");
                    765:                                lua_getfield(L, -2, "length");
                    766:                                lua_getfield(L, -3, "offset");
                    767: 
                    768:                                if (lua_isstring(L, -3)) { /* filename has to be a string */
1.1.1.2 ! misho     769:                                        buffer *fn;
1.1       misho     770:                                        stat_cache_entry *sce;
1.1.1.2 ! misho     771:                                        const char *fn_str;
        !           772:                                        handler_t res;
1.1       misho     773: 
1.1.1.2 ! misho     774:                                        fn_str = lua_tostring(L, -3);
        !           775:                                        fn = buffer_init_string(fn_str);
1.1       misho     776: 
1.1.1.2 ! misho     777:                                        res = stat_cache_get_entry(srv, con, fn, &sce);
        !           778: 
        !           779:                                        if (HANDLER_GO_ON == res) {
1.1       misho     780:                                                off_t off = 0;
                    781:                                                off_t len = 0;
                    782: 
                    783:                                                if (lua_isnumber(L, -1)) {
                    784:                                                        off = lua_tonumber(L, -1);
                    785:                                                }
                    786: 
                    787:                                                if (lua_isnumber(L, -2)) {
                    788:                                                        len = lua_tonumber(L, -2);
                    789:                                                } else {
                    790:                                                        len = sce->st.st_size;
                    791:                                                }
                    792: 
                    793:                                                if (off < 0) {
1.1.1.2 ! misho     794:                                                        buffer_free(fn);
        !           795:                                                        return luaL_error(L, "offset for '%s' is negative", fn_str);
1.1       misho     796:                                                }
                    797: 
                    798:                                                if (len < off) {
1.1.1.2 ! misho     799:                                                        buffer_free(fn);
        !           800:                                                        return luaL_error(L, "offset > length for '%s'", fn_str);
1.1       misho     801:                                                }
                    802: 
                    803:                                                chunkqueue_append_file(con->write_queue, fn, off, len - off);
                    804:                                        }
                    805: 
                    806:                                        buffer_free(fn);
                    807:                                } else {
                    808:                                        lua_pop(L, 3 + 2); /* correct the stack */
                    809: 
                    810:                                        return luaL_error(L, "content[%d] is a table and requires the field \"filename\"", i);
                    811:                                }
                    812: 
                    813:                                lua_pop(L, 3);
                    814:                        } else if (lua_isnil(L, -1)) {
                    815:                                /* oops, end of list */
                    816: 
                    817:                                lua_pop(L, 1);
                    818: 
                    819:                                break;
                    820:                        } else {
                    821:                                lua_pop(L, 4);
                    822: 
                    823:                                return luaL_error(L, "content[%d] is neither a string nor a table: ", i);
                    824:                        }
                    825: 
                    826:                        lua_pop(L, 1); /* pop the content[...] table */
                    827:                }
                    828:        } else {
                    829:                return luaL_error(L, "lighty.content has to be a table");
                    830:        }
                    831:        lua_pop(L, 1); /* pop the header-table */
                    832:        lua_pop(L, 1); /* pop the lighty-table */
                    833:        lua_pop(L, 1); /* php the function env */
                    834: 
                    835:        return 0;
                    836: }
                    837: 
                    838: static int traceback (lua_State *L) {
                    839:        if (!lua_isstring(L, 1))  /* 'message' not a string? */
                    840:                return 1;  /* keep it intact */
                    841:        lua_getfield(L, LUA_GLOBALSINDEX, "debug");
                    842:        if (!lua_istable(L, -1)) {
                    843:                lua_pop(L, 1);
                    844:                return 1;
                    845:        }
                    846:        lua_getfield(L, -1, "traceback");
                    847:        if (!lua_isfunction(L, -1)) {
                    848:                lua_pop(L, 2);
                    849:                return 1;
                    850:        }
                    851:        lua_pushvalue(L, 1);  /* pass error message */
                    852:        lua_pushinteger(L, 2);  /* skip this function and traceback */
                    853:        lua_call(L, 2, 1);  /* call debug.traceback */
                    854:        return 1;
                    855: }
                    856: 
                    857: static int push_traceback(lua_State *L, int narg) {
                    858:        int base = lua_gettop(L) - narg;  /* function index */
                    859:        lua_pushcfunction(L, traceback);
                    860:        lua_insert(L, base);
                    861:        return base;
                    862: }
                    863: 
                    864: static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, buffer *name) {
                    865:        lua_State *L;
                    866:        int lua_return_value = -1;
                    867:        int errfunc;
                    868:        /* get the script-context */
                    869: 
                    870: 
                    871:        L = script_cache_get_script(srv, con, p->cache, name);
                    872: 
                    873:        if (lua_isstring(L, -1)) {
                    874:                log_error_write(srv, __FILE__, __LINE__,
                    875:                                "sbss",
                    876:                                "loading script",
                    877:                                name,
                    878:                                "failed:",
                    879:                                lua_tostring(L, -1));
                    880: 
                    881:                lua_pop(L, 1);
                    882: 
1.1.1.2 ! misho     883:                force_assert(lua_gettop(L) == 0); /* only the function should be on the stack */
1.1       misho     884: 
                    885:                con->http_status = 500;
                    886:                con->mode = DIRECT;
                    887: 
                    888:                return HANDLER_FINISHED;
                    889:        }
                    890: 
                    891:        lua_pushstring(L, "lighty.srv");
                    892:        lua_pushlightuserdata(L, srv);
                    893:        lua_settable(L, LUA_REGISTRYINDEX); /* registery[<id>] = srv */
                    894: 
                    895:        lua_pushstring(L, "lighty.con");
                    896:        lua_pushlightuserdata(L, con);
                    897:        lua_settable(L, LUA_REGISTRYINDEX); /* registery[<id>] = con */
                    898: 
                    899:        lua_atpanic(L, magnet_atpanic);
                    900: 
                    901:        /**
                    902:         * we want to create empty environment for our script
                    903:         *
                    904:         * setmetatable({}, {__index = _G})
                    905:         *
                    906:         * if a function, symbol is not defined in our env, __index will lookup
                    907:         * in the global env.
                    908:         *
                    909:         * all variables created in the script-env will be thrown
                    910:         * away at the end of the script run.
                    911:         */
                    912:        lua_newtable(L); /* my empty environment aka {}              (sp += 1) */
                    913: 
                    914:        /* we have to overwrite the print function */
                    915:        lua_pushcfunction(L, magnet_print);                       /* (sp += 1) */
                    916:        lua_setfield(L, -2, "print"); /* -1 is the env we want to set(sp -= 1) */
                    917: 
                    918:        /**
                    919:         * lighty.request[] has the HTTP-request headers
                    920:         * lighty.content[] is a table of string/file
                    921:         * lighty.header[] is a array to set response headers
                    922:         */
                    923: 
                    924:        lua_newtable(L); /* lighty.*                                 (sp += 1) */
                    925: 
                    926:        lua_newtable(L); /*  {}                                      (sp += 1) */
                    927:        lua_newtable(L); /* the meta-table for the request-table     (sp += 1) */
                    928:        lua_pushcfunction(L, magnet_reqhdr_get);                  /* (sp += 1) */
                    929:        lua_setfield(L, -2, "__index");                           /* (sp -= 1) */
                    930:        lua_pushcfunction(L, magnet_reqhdr_pairs);                /* (sp += 1) */
                    931:        lua_setfield(L, -2, "__pairs");                           /* (sp -= 1) */
                    932:        lua_setmetatable(L, -2); /* tie the metatable to request     (sp -= 1) */
                    933:        lua_setfield(L, -2, "request"); /* content = {}              (sp -= 1) */
                    934: 
                    935:        lua_newtable(L); /*  {}                                      (sp += 1) */
                    936:        lua_newtable(L); /* the meta-table for the request-table     (sp += 1) */
                    937:        lua_pushcfunction(L, magnet_env_get);                     /* (sp += 1) */
                    938:        lua_setfield(L, -2, "__index");                           /* (sp -= 1) */
                    939:        lua_pushcfunction(L, magnet_env_set);                     /* (sp += 1) */
                    940:        lua_setfield(L, -2, "__newindex");                        /* (sp -= 1) */
                    941:        lua_pushcfunction(L, magnet_env_pairs);                   /* (sp += 1) */
                    942:        lua_setfield(L, -2, "__pairs");                           /* (sp -= 1) */
                    943:        lua_setmetatable(L, -2); /* tie the metatable to request     (sp -= 1) */
                    944:        lua_setfield(L, -2, "env"); /* content = {}                  (sp -= 1) */
                    945: 
                    946:        lua_newtable(L); /*  {}                                      (sp += 1) */
                    947:        lua_newtable(L); /* the meta-table for the request-table     (sp += 1) */
                    948:        lua_pushcfunction(L, magnet_cgi_get);                     /* (sp += 1) */
                    949:        lua_setfield(L, -2, "__index");                           /* (sp -= 1) */
                    950:        lua_pushcfunction(L, magnet_cgi_set);                     /* (sp += 1) */
                    951:        lua_setfield(L, -2, "__newindex");                        /* (sp -= 1) */
                    952:        lua_pushcfunction(L, magnet_cgi_pairs);                   /* (sp += 1) */
                    953:        lua_setfield(L, -2, "__pairs");                           /* (sp -= 1) */
                    954:        lua_setmetatable(L, -2); /* tie the metatable to req_env     (sp -= 1) */
                    955:        lua_setfield(L, -2, "req_env"); /* content = {}              (sp -= 1) */
                    956: 
                    957:        lua_newtable(L); /*  {}                                      (sp += 1) */
                    958:        lua_newtable(L); /* the meta-table for the request-table     (sp += 1) */
                    959:        lua_pushcfunction(L, magnet_status_get);                  /* (sp += 1) */
                    960:        lua_setfield(L, -2, "__index");                           /* (sp -= 1) */
                    961:        lua_pushcfunction(L, magnet_status_set);                  /* (sp += 1) */
                    962:        lua_setfield(L, -2, "__newindex");                        /* (sp -= 1) */
                    963:        lua_pushcfunction(L, magnet_status_pairs);                /* (sp += 1) */
                    964:        lua_setfield(L, -2, "__pairs");                           /* (sp -= 1) */
                    965:        lua_setmetatable(L, -2); /* tie the metatable to request     (sp -= 1) */
                    966:        lua_setfield(L, -2, "status"); /* content = {}               (sp -= 1) */
                    967: 
                    968:        /* add empty 'content' and 'header' tables */
                    969:        lua_newtable(L); /*  {}                                      (sp += 1) */
                    970:        lua_setfield(L, -2, "content"); /* content = {}              (sp -= 1) */
                    971: 
                    972:        lua_newtable(L); /*  {}                                      (sp += 1) */
                    973:        lua_setfield(L, -2, "header"); /* header = {}                (sp -= 1) */
                    974: 
                    975:        lua_pushinteger(L, MAGNET_RESTART_REQUEST);
                    976:        lua_setfield(L, -2, "RESTART_REQUEST");
                    977: 
                    978:        lua_pushcfunction(L, magnet_stat);                        /* (sp += 1) */
                    979:        lua_setfield(L, -2, "stat"); /* -1 is the env we want to set (sp -= 1) */
                    980: 
                    981:        lua_setfield(L, -2, "lighty"); /* lighty.*                   (sp -= 1) */
                    982: 
                    983:        /* override the default pairs() function to our __pairs capable version */
                    984:        lua_getglobal(L, "pairs"); /* push original pairs()          (sp += 1) */
                    985:        lua_pushcclosure(L, magnet_pairs, 1);
                    986:        lua_setfield(L, -2, "pairs");                             /* (sp -= 1) */
                    987: 
                    988:        lua_newtable(L); /* the meta-table for the new env           (sp += 1) */
                    989:        lua_pushvalue(L, LUA_GLOBALSINDEX);                       /* (sp += 1) */
                    990:        lua_setfield(L, -2, "__index"); /* { __index = _G }          (sp -= 1) */
                    991:        lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) (sp -= 1) */
                    992: 
                    993: 
                    994:        lua_setfenv(L, -2); /* on the stack should be a modified env (sp -= 1) */
                    995: 
                    996:        errfunc = push_traceback(L, 0);
                    997:        if (lua_pcall(L, 0, 1, errfunc)) {
                    998:                lua_remove(L, errfunc);
                    999:                log_error_write(srv, __FILE__, __LINE__,
                   1000:                        "ss",
                   1001:                        "lua_pcall():",
                   1002:                        lua_tostring(L, -1));
                   1003:                lua_pop(L, 1); /* remove the error-msg and the function copy from the stack */
                   1004: 
1.1.1.2 ! misho    1005:                force_assert(lua_gettop(L) == 1); /* only the function should be on the stack */
1.1       misho    1006: 
                   1007:                con->http_status = 500;
                   1008:                con->mode = DIRECT;
                   1009: 
                   1010:                return HANDLER_FINISHED;
                   1011:        }
                   1012:        lua_remove(L, errfunc);
                   1013: 
                   1014:        /* we should have the function-copy and the return value on the stack */
1.1.1.2 ! misho    1015:        force_assert(lua_gettop(L) == 2);
1.1       misho    1016: 
                   1017:        if (lua_isnumber(L, -1)) {
                   1018:                /* if the ret-value is a number, take it */
                   1019:                lua_return_value = (int)lua_tonumber(L, -1);
                   1020:        }
                   1021:        lua_pop(L, 1); /* pop the ret-value */
                   1022: 
                   1023:        magnet_copy_response_header(srv, con, p, L);
                   1024: 
                   1025:        if (lua_return_value > 99) {
                   1026:                con->http_status = lua_return_value;
                   1027:                con->file_finished = 1;
                   1028: 
                   1029:                /* try { ...*/
                   1030:                if (0 == setjmp(exceptionjmp)) {
                   1031:                        magnet_attach_content(srv, con, p, L);
                   1032:                        if (!chunkqueue_is_empty(con->write_queue)) {
                   1033:                                con->mode = p->id;
                   1034:                        }
                   1035:                } else {
                   1036:                        /* } catch () { */
                   1037:                        con->http_status = 500;
                   1038:                        con->mode = DIRECT;
                   1039:                }
                   1040: 
1.1.1.2 ! misho    1041:                force_assert(lua_gettop(L) == 1); /* only the function should be on the stack */
1.1       misho    1042: 
                   1043:                /* we are finished */
                   1044:                return HANDLER_FINISHED;
                   1045:        } else if (MAGNET_RESTART_REQUEST == lua_return_value) {
1.1.1.2 ! misho    1046:                force_assert(lua_gettop(L) == 1); /* only the function should be on the stack */
1.1       misho    1047: 
                   1048:                return HANDLER_COMEBACK;
                   1049:        } else {
1.1.1.2 ! misho    1050:                force_assert(lua_gettop(L) == 1); /* only the function should be on the stack */
1.1       misho    1051: 
                   1052:                return HANDLER_GO_ON;
                   1053:        }
                   1054: }
                   1055: 
                   1056: static handler_t magnet_attract_array(server *srv, connection *con, plugin_data *p, array *files) {
                   1057:        size_t i;
                   1058: 
                   1059:        /* no filename set */
                   1060:        if (files->used == 0) return HANDLER_GO_ON;
                   1061: 
                   1062:        /**
                   1063:         * execute all files and jump out on the first !HANDLER_GO_ON
                   1064:         */
                   1065:        for (i = 0; i < files->used; i++) {
                   1066:                data_string *ds = (data_string *)files->data[i];
                   1067:                handler_t ret;
                   1068: 
                   1069:                if (buffer_is_empty(ds->value)) continue;
                   1070: 
                   1071:                ret = magnet_attract(srv, con, p, ds->value);
                   1072: 
                   1073:                if (ret != HANDLER_GO_ON) return ret;
                   1074:        }
                   1075: 
                   1076:        return HANDLER_GO_ON;
                   1077: }
                   1078: 
                   1079: URIHANDLER_FUNC(mod_magnet_uri_handler) {
                   1080:        plugin_data *p = p_d;
                   1081: 
                   1082:        mod_magnet_patch_connection(srv, con, p);
                   1083: 
                   1084:        return magnet_attract_array(srv, con, p, p->conf.url_raw);
                   1085: }
                   1086: 
                   1087: URIHANDLER_FUNC(mod_magnet_physical) {
                   1088:        plugin_data *p = p_d;
                   1089: 
                   1090:        mod_magnet_patch_connection(srv, con, p);
                   1091: 
                   1092:        return magnet_attract_array(srv, con, p, p->conf.physical_path);
                   1093: }
                   1094: 
                   1095: 
                   1096: /* this function is called at dlopen() time and inits the callbacks */
                   1097: 
                   1098: int mod_magnet_plugin_init(plugin *p);
                   1099: int mod_magnet_plugin_init(plugin *p) {
                   1100:        p->version     = LIGHTTPD_VERSION_ID;
                   1101:        p->name        = buffer_init_string("magnet");
                   1102: 
                   1103:        p->init        = mod_magnet_init;
                   1104:        p->handle_uri_clean  = mod_magnet_uri_handler;
                   1105:        p->handle_physical   = mod_magnet_physical;
                   1106:        p->set_defaults  = mod_magnet_set_defaults;
                   1107:        p->cleanup     = mod_magnet_free;
                   1108: 
                   1109:        p->data        = NULL;
                   1110: 
                   1111:        return 0;
                   1112: }
                   1113: 
                   1114: #else
                   1115: int mod_magnet_plugin_init(plugin *p);
                   1116: int mod_magnet_plugin_init(plugin *p) {
                   1117:        UNUSED(p);
                   1118:        return -1;
                   1119: }
                   1120: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>