memptr func_true(memptr func_expr) {

    if (num_nodes(func_expr) != 2) {
#ifdef DEBUG
        printf("15\n");
#endif
        ERROR(ERROR_TRUE, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

#ifdef EXTENDED_SECURITY
    memptr local_security = safe_allocate_cons();
    cons_pool[local_security].carKind = NIL;
    cons_pool[local_security].cdrKind = NIL;
#endif
    memptr param = resolve_expr(cons_pool[cons_pool[func_expr].cdr].car);
#ifdef EXTENDED_SECURITY
    cons_pool[local_security].car = param;
    cons_pool[local_security].carKind = CONS;
#endif
    if (type(param) == TYPE_OBJECT) {
        memptr lu = object_lookup(param, cons_pool[func_expr].car);
        if (lu == NOT_FOUND) {
            param = object_lookup(param, core_symbol);
        } else {
            return resolve_func_expr(func_expr, param, lu, true);
        }
    }
    return ((param == t) ? t : nil);
}
Beispiel #2
0
void
attack(void)
{
	object_t *objp	= (object_t *)random();
	object_t obj	= (object_t)random();
	char *name	= (char *)random();
	void *msg	= (void *)random();
	size_t size	= (size_t)random();
	task_t self	= task_self();
	void *addr	= (void *)random();
	int attr	= random() & 7;
	thread_t t	= (thread_t)random();
	thread_t *tp	= (thread_t *)random();

	object_create(NULL, NULL);
	object_create(NULL, objp);
	object_create(name, NULL);
	object_create(name, objp);

	object_destroy(0);
	object_destroy(obj);

	object_lookup(NULL, objp);
	object_lookup(name, NULL);
	object_lookup(name, objp);

	msg_send(0, msg, size);
	msg_send(obj, NULL, size);
	msg_send(obj, msg, 0);
	msg_send(0, msg, 0);
	msg_send(0, NULL, size);
	msg_send(obj, msg, size);

	msg_receive(0, msg, size);
	msg_receive(obj, NULL, size);
	msg_receive(obj, msg, 0);
	msg_receive(0, msg, 0);
	msg_receive(0, NULL, size);
	msg_receive(obj, msg, size);

	msg_reply(0, msg, size);
	msg_reply(obj, NULL, size);
	msg_reply(obj, msg, 0);
	msg_reply(0, msg, 0);
	msg_reply(0, NULL, size);
	msg_reply(obj, msg, size);

	vm_allocate(self, addr, size, 1);
	vm_allocate(self, &addr, size, 1);

	vm_free(self, addr);
	vm_attribute(self, addr, attr);
	vm_map(self, addr, size, &addr);

	thread_create(self, tp);
	thread_suspend(t);
	thread_terminate(t);
}
memptr func_cdr(memptr func_expr) {

    if (num_nodes(func_expr) != 2) {
#ifdef DEBUG
        printf("12\n");
#endif
        ERROR(ERROR_CDR, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

    memptr local_security = safe_allocate_cons();
    cons_pool[local_security].carKind = NIL;
    cons_pool[local_security].cdrKind = NIL;
    memptr param = resolve_expr(cons_pool[cons_pool[func_expr].cdr].car);
    cons_pool[local_security].car = param;
    cons_pool[local_security].carKind = CONS;

    while (true) {
        Type param_type = type(param);
        if (param_type == TYPE_CONS) {
            return cons_pool[param].cdr;
        } else if (param_type == TYPE_STRING) {
            memptr result;
            if ((cons_pool[param].cdr < 0) || (string_length(param) == 1)) {
                result = nil;
            } else {
                result = allocate_cons();
                cons_pool[result].car = cons_pool[param].car;
                cons_pool[result].cdr = cons_pool[param].cdr + 1;
                cons_pool[result].carKind = STRING;
                cons_pool[result].cdrKind = INTEGER;
            }
            return result;
        } else if (param_type == TYPE_OBJECT) {
            memptr lu = object_lookup(param, cons_pool[func_expr].car);
            if (lu == NOT_FOUND) {
                param = object_lookup(param, core_symbol);
                continue;
            } else {
                return resolve_func_expr(func_expr, param, lu, true);
            }
        }
        break;
    }

#ifdef DEBUG
    printf("13\n");
#endif
    ERROR(ERROR_CDR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
    return NOT_FOUND;
}
static bool supps(memptr value, memptr symbol) {

    bool s = false;
    Type value_type = type(value);
    switch (value_type) {
    case TYPE_CONS:
        s = (SUPPORTS(4) || SUPPORTS(5) || SUPPORTS(6) || SUPPORTS(7)
             || SUPPORTS(8) || SUPPORTS(9) || SUPPORTS(10) || SUPPORTS(11)
             || SUPPORTS(18) || SUPPORTS(19));
        break;
    case TYPE_INTEGER:
        s =
            (SUPPORTS(0) || SUPPORTS(1) || SUPPORTS(2) || SUPPORTS(3)
             || SUPPORTS(4) || SUPPORTS(5) || SUPPORTS(6)
             || SUPPORTS(7) || SUPPORTS(10) || SUPPORTS(11)
             || SUPPORTS(18) || SUPPORTS(19));
        break;
    case TYPE_NATIVE_FUNCTION:
        s =
            (SUPPORTS(4) || SUPPORTS(5) || SUPPORTS(6) || SUPPORTS(7)
             || SUPPORTS(10) || SUPPORTS(11) || SUPPORTS(18)
             || SUPPORTS(19));
        break;
    case TYPE_NIL_TRUE:
        s = (SUPPORTS(4) || SUPPORTS(5) || SUPPORTS(6) || SUPPORTS(7)
             || SUPPORTS(10) || SUPPORTS(11) || SUPPORTS(15) || SUPPORTS(16)
             || SUPPORTS(17) || SUPPORTS(18) || SUPPORTS(19));
        break;
    case TYPE_STRING:
        s = (SUPPORTS(4) || SUPPORTS(5) || SUPPORTS(6) || SUPPORTS(7)
             || SUPPORTS(8) || SUPPORTS(9) || SUPPORTS(10) || SUPPORTS(11)
             || SUPPORTS(18) || SUPPORTS(19));
        break;
    case TYPE_USER_FUNCTION:
        s =
            (SUPPORTS(4) || SUPPORTS(5) || SUPPORTS(6) || SUPPORTS(7)
             || SUPPORTS(10) || SUPPORTS(11) || SUPPORTS(18)
             || SUPPORTS(19));
        break;
    case TYPE_OBJECT:
        s = (object_lookup(value, symbol) != NOT_FOUND)
            || supps(object_lookup(value, core_symbol), symbol);
        break;
    default:
        s = false;
        break;
    }
    return s;
}
Beispiel #5
0
int
main(int argc, char *argv[])
{
	int i = 0;
	int found = 0;

	if (argc < 2) {
		pmctrl_help(1, NULL);
		exit(1);
	}

	if (object_lookup("!pow", &powobj) != 0) {
		fprintf(stderr, "No power server found\n");
		exit(1);
	}

	while (cmdtab[i].cmd != NULL) {
		if (!strncmp(argv[1], cmdtab[i].cmd, LINE_MAX)) {
			(cmdtab[i].func)(argc, argv);
			found = 1;
			break;
		}
		i++;
	}
	if (!found)
		pmctrl_help(1, NULL);
	exit(1);
}
memptr func_list(memptr func_expr) {

    if (num_nodes(func_expr) == 1) {
        return nil;
    }

    memptr current_node, current_param, current_dup_node = safe_allocate_cons(),
                                        base = current_dup_node;
    cons_pool[current_dup_node].carKind = NIL;
    cons_pool[current_dup_node].cdrKind = NIL;

    current_node = cons_pool[func_expr].cdr;
    current_param = resolve_expr(cons_pool[current_node].car);
    if (current_param == NOT_FOUND) {
#ifdef DEBUG
        printf("29\n");
#endif
        ERROR(ERROR_LIST, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
        return NOT_FOUND;
    } else if (type(current_param) == TYPE_OBJECT) {
        memptr lu = object_lookup(current_param, cons_pool[func_expr].car);
        if (lu != NOT_FOUND) {
#ifdef EXTENDED_SECURITY
            memptr local_security = safe_allocate_cons();
            cons_pool[local_security].car = current_param;
            cons_pool[local_security].carKind = CONS;
            cons_pool[local_security].cdrKind = NIL;
#endif
            return resolve_func_expr(func_expr, current_param, lu, true);
        }
    }
    cons_pool[current_dup_node].car = current_param;
    cons_pool[current_dup_node].carKind = CONS;

    while (cons_pool[current_node].cdrKind == CONS) {

        current_node = cons_pool[current_node].cdr;
        cons_pool[current_dup_node].cdr = allocate_cons();
        cons_pool[current_dup_node].cdrKind = CONS;
        current_dup_node = cons_pool[current_dup_node].cdr;
        cons_pool[current_dup_node].carKind = NIL;
        cons_pool[current_dup_node].cdrKind = NIL;

        current_param = resolve_expr(cons_pool[current_node].car);
        if (current_param == NOT_FOUND) {
#ifdef DEBUG
            printf("30\n");
#endif
            ERROR(ERROR_LIST, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            return NOT_FOUND;
        }
        cons_pool[current_dup_node].car = current_param;
        cons_pool[current_dup_node].carKind = CONS;
    }

    cons_pool[current_dup_node].cdrKind = CONS;
    cons_pool[current_dup_node].cdr = nil;

    return base;
}
Beispiel #7
0
/*
 * Send thread
 */
static void
send_thread(void)
{
	struct my_msg msg;
	object_t o1, o2;
	int error;
	char string[] = "A lazy dog laying on the road!!";

	printf("Send thread is starting...\n");

	/*
	 * Find objects.
	 */
	error = object_lookup("test-A", &o1);
	error = object_lookup("test-B", &o2);

	/*
	 * Wait a sec.
	 */
	timer_sleep(1000, 0);

	/*
	 * Delete object A.
	 */
	printf("Delete object A\n");
	object_destroy(o1);

	/*
	 * Wait a sec.
	 */
	timer_sleep(1000, 0);

	/*
	 * Send message to object B.
	 */
	printf("Send message to object B.\n");
	strncpy(msg.data, string, sizeof(string));
	msg.hdr.code = 42;
	msg_send(o2, &msg, sizeof(msg));

	printf("Send completed.\n");
	for (;;) ;
}
Beispiel #8
0
void
__process_init(void)
{
	int error;

	/* Look up process server */
	error = object_lookup("!proc", &__proc_obj);
	if (error)
		__proc_obj = 0;
}
Beispiel #9
0
/*
 * Test invalid request
 */
static void
test_invalid(void)
{
	object_t fs_obj;
	struct msg m;

	object_lookup(OBJNAME_FS, &fs_obj);
	m.hdr.code = 0x300;
	msg_send(fs_obj, &m, sizeof(m), 0);
}
Beispiel #10
0
/*
 * This is called first when task is started
 */
void
__file_init(void)
{
	int error;

	/*
	 * Look up file system server
	 */
	error = object_lookup("!fs", &__fs_obj);
	if (error)
		__fs_obj = 0;
}
Beispiel #11
0
/*
 * Send thread
 */
static void
send_thread(void)
{
	struct msg msg;
	object_t o1, o2;
	int error;

	printf("Send thread is starting...\n");

	/*
	 * Find objects.
	 */
	error = object_lookup("test-A", &o1);
	error = object_lookup("test-B", &o2);

	/*
	 * Wait a sec.
	 */
	timer_sleep(1000, 0);

	/*
	 * Delete object A.
	 */
	printf("Delete object A\n");
	object_destroy(o1);

	/*
	 * Wait a sec.
	 */
	timer_sleep(1000, 0);

	/*
	 * Send message to object B.
	 */
	printf("Send message to object B.\n");
	msg_send(o2, &msg, sizeof(msg));

	printf("Send completed.\n");
	for (;;) ;
}
memptr func_cons(memptr func_expr) {

    if (num_nodes(func_expr) != 3) {
#ifdef DEBUG
        printf("9\n");
#endif
        ERROR(ERROR_CONS, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

    memptr res = safe_allocate_cons();
    cons_pool[res].carKind = NIL;
    cons_pool[res].cdrKind = NIL;

    memptr current_node, current_data;
    // first parameter
    current_node = cons_pool[func_expr].cdr;
    current_data = cons_pool[current_node].car;
    cons_pool[res].car = resolve_expr(current_data);
    cons_pool[res].carKind = CONS;
    if (type(cons_pool[res].car) == TYPE_OBJECT) {
        memptr lu = object_lookup(cons_pool[res].car, cons_pool[func_expr].car);
        if (lu == NOT_FOUND && OBJECT_OPERATE_CORE) {
            cons_pool[res].car = object_lookup(cons_pool[res].car, core_symbol);
        } else if (lu != NOT_FOUND) {
            return resolve_func_expr(func_expr, cons_pool[res].car, lu, true);
        }
    }

    // second parameter
    current_node = cons_pool[current_node].cdr;
    current_data = cons_pool[current_node].car;
    cons_pool[res].cdr = resolve_expr(current_data);
    cons_pool[res].cdrKind = CONS;
    if (type(cons_pool[res].cdr) == TYPE_OBJECT && OBJECT_OPERATE_CORE) {
        cons_pool[res].cdr = object_lookup(cons_pool[res].cdr, core_symbol);
    }

    return res;
}
Beispiel #13
0
static void
register_process(void)
{
    struct msg m;
    object_t obj;
    int error;

    error = object_lookup("!proc", &obj);
    if (error)
        sys_panic("pow: no proc found");

    m.hdr.code = PS_REGISTER;
    msg_send(obj, &m, sizeof(m));
}
Beispiel #14
0
static void
shutdown_server(const char *name)
{
    struct msg m;
    object_t obj;
    int error;

    DPRINTF(("pow: shutdown %s\n", name));
    error = object_lookup((char *)name, &obj);
    if (error != 0)
        return;

    m.hdr.code = STD_SHUTDOWN;
    error = msg_send(obj, &m, sizeof(m));
    if (error)
        sys_panic("pow: shutdown error");
}
Beispiel #15
0
int
main(int argc, char *argv[])
{
	object_t obj;
	struct msg m;

	if (argc != 2)
		usage();

	if (object_lookup(argv[1], &obj) != 0) {
		fprintf(stderr, "debug: can not find object %s\n", argv[1]);
		exit(1);
	}
	m.hdr.code = STD_DEBUG;
	msg_send(obj, &m, sizeof(m), 0);
	exit(0);
}
Beispiel #16
0
/**
 * Find the object under this object that matches the given name.
 *
 * object: Object to search under.
 * name: Regex to check names against.
 **/
object_t *
object_lookup(object_t *object, const char *name)
{
	size_t i;
	object_t *ret;

	if (! strcmp(object->name, name))
		return object;

	/* FIXME: use cursors, not recursion */
	for (i = 0; i < object->child_count; i++) {
		ret = object_lookup(object->children[i], name);

		if (ret)
			return ret;
	}

	return NULL;
}
memptr func_value(memptr func_expr) {

    if (num_nodes(func_expr) < 2) {
#ifdef DEBUG
        printf("31\n");
#endif
        ERROR(ERROR_VALUE, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

    memptr next_node = cons_pool[func_expr].cdr, current_node, current_value;
    bool first_param = true;
    do {
#ifdef EXTENDED_SECURITY
        memptr local_security = safe_allocate_cons();
        cons_pool[local_security].carKind = NIL;
        cons_pool[local_security].cdrKind = NIL;
#endif
        current_node = next_node;
        current_value = resolve_expr(cons_pool[current_node].car);
#ifdef EXTENDED_SECURITY
        cons_pool[local_security].car = current_value;
        cons_pool[local_security].carKind = CONS;
#endif
        if (current_value == NOT_FOUND) {
#ifdef DEBUG
            printf("32\n");
#endif
            ERROR(ERROR_VALUE, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            return NOT_FOUND;
        } else if (first_param && (type(current_value) == TYPE_OBJECT)) {
            memptr lu = object_lookup(current_value, cons_pool[func_expr].car);
            if (lu != NOT_FOUND) {
                return resolve_func_expr(func_expr, current_value, lu, true);
            }
        }
        next_node = cons_pool[current_node].cdr;
        first_param = false;
    } while (cons_pool[current_node].cdrKind == CONS);

    return current_value;
}
Beispiel #18
0
/*
 * Wait until specified server starts.
 */
static void
wait_server(const char *name, object_t *pobj)
{
    int i, error = 0;

    /* Give chance to run other servers. */
    thread_yield();

    /*
     * Wait for server loading. timeout is 1 sec.
     */
    for (i = 0; i < 100; i++) {
        error = object_lookup((char *)name, pobj);
        if (error == 0)
            break;

        /* Wait 10msec */
        timer_sleep(10, 0);
        thread_yield();
    }
    if (error)
        sys_panic("pow: server not found");
}
Beispiel #19
0
int
main(int argc, char *argv[])
{
    static const char stat[][2] = { "R", "Z", "S" };
    static const char pol[][5] = { "FIFO", "RR  " };
    static struct threadinfo ti;
    static struct procinfo pi;
    int ch, rc, ps_flag = 0;
    pid_t last_pid = -2;

    while ((ch = getopt(argc, argv, "lx")) != -1)
        switch(ch) {
        case 'x':
            ps_flag |= PSFX;
            break;
        case 'l':
            ps_flag |= PSFL;
            break;

        case '?':
        default:
            fprintf(stderr, "usage: ps [-lx]\n");
            exit(1);
        }
    argc -= optind;
    argv += optind;

    if (object_lookup("!proc", &procobj))
        exit(1);

    if (ps_flag & PSFL)
        printf("  PID  PPID PRI STAT POL      TIME WCHAN       CMD\n");
    else
        printf("  PID     TIME CMD\n");

    rc = 0;
    ti.cookie = 0;
    do {
        /*
         * Get thread info from kernel.
         */
        rc = sys_info(INFO_THREAD, &ti);
        if (!rc) {
            /*
             * Get process info from server.
             */
            if (pstat(ti.task, &pi) && !(ps_flag & PSFX))
                continue;

            if (ps_flag & PSFL) {
                if (pi.pid == -1)
                    printf("    -     -"); /* kernel */
                else
                    printf("%5d %5d", pi.pid, pi.ppid);

                printf(" %3d %s    %s %8d "
                       "%-11s %-11s\n",
                       ti.priority, stat[pi.stat-1],
                       pol[ti.policy],
                       ti.time, ti.slpevt, ti.taskname);
            } else {
                if (!(ps_flag & PSFX) && (pi.pid == last_pid))
                    continue;
                if (pi.pid == -1)
                    printf("    -"); /* kernel */
                else
                    printf("%5d", pi.pid);

                printf(" %8d %-11s\n", ti.time, ti.taskname);
                last_pid = pi.pid;
            }
        }
    } while (rc == 0);
    exit(0);
}
Beispiel #20
0
/*
 * Note:
 *
 * The state after exec() are as follows:
 * - Opened file descriptors remain open except FD_CLOEXEC flag is set.
 * - Opened directory streams are closed
 * - Signals set to the default action.
 * - Any asynchronous I/O operations are cancelled.
 */
int
execve(char *path, char *argv[], char *envp[])
{
	object_t exec_obj;
	struct exec_msg msg;
	int err, i, argc, envc;
	size_t bufsz;
	char *dest, *src;

	if ((err = object_lookup(OBJNAME_EXEC, &exec_obj)) != 0) {
		errno = ENOSYS;
		return -1;
	}

	if (path == NULL) {
		errno = EFAULT;
		return -1;
	}

/*
    if (strlen(path) >= PATH_MAX)
        return ENAMETOOLONG;
*/

	/* Get arg/env buffer size */
	bufsz = 0;

	argc = 0;
	if (argv) {
		while (argv[argc]) {
			bufsz += (strlen(argv[argc]) + 1);
			argc++;
		}
	}
	envc = 0;
	if (envp) {
		while (envp[envc]) {
			bufsz += (strlen(envp[envc]) + 1);
			envc++;
		}
	}
	if (bufsz >= ARG_MAX) {
		errno = E2BIG;
		return -1;
	}

	dest = msg.buf;
	for (i = 0; i < argc; i++) {
		src = argv[i];
		while ((*dest++ = *src++) != 0);
	}
	for (i = 0; i < envc; i++) {
		src = envp[i];
		while ((*dest++ = *src++) != 0);
	}

	/* Request to exec server */
	msg.hdr.code = EX_EXEC;
	msg.argc = argc;
	msg.envc = envc;
	msg.bufsz = bufsz;
	strlcpy(msg.path, path, PATH_MAX);

	do {
		err = msg_send(exec_obj, &msg, sizeof(msg), 0);
	} while (err == EINTR);

	/*
	 * If exec() request is done successfully, control never comes here.
	 */
	errno = 0;
	if (err)
		errno = EIO;
	else if (msg.hdr.status)
		errno = msg.hdr.status;

	return -1;
}
Beispiel #21
0
int main(int argc, char *argv[])
{
	int ret;
	time_t t;
	double jd;
	struct tm tm;
	const struct object *obj;

	/* Default options */
	double horizon = LN_SOLAR_STANDART_HORIZON; /* 50 Bogenminuten; no twilight, normal sunset/rise */
	int tz = INT_MAX;

	char *obj_str = basename(argv[0]);
	char *format = "%H:%M %d.%m.%Y";
	//char *format = "time: %Y-%m-%d %H:%M:%S (%Z) az: §a (§s) alt: §h";
	char tzid[32];
	char *query = NULL;

	bool horizon_set = false;
	bool next = false;
	bool local_tz = false;
	
	time(&t);
	localtime_r(&t, &tm);

	enum {
		MOMENT_NOW,
		MOMENT_RISE,
		MOMENT_SET,
		MOMENT_TRANSIT
	} moment = MOMENT_NOW;

	struct ln_lnlat_posn obs = { DBL_MAX, DBL_MAX };
	struct object_details result;

	/* set tzid as empty (without repointing the buffer) */
	strcpy(tzid, "");
	/* parse command line arguments */
	while (1) {
		int c = getopt_long(argc, argv, "+hvnult:d:f:a:o:q:z:p:m:H:", long_options, NULL);

		/* detect the end of the options. */
		if (c == -1)
			break;

		switch (c) {
			case 'H':
				if      (strcmp(optarg, "civil") == 0)
					horizon = LN_SOLAR_CIVIL_HORIZON;
				else if (strcmp(optarg, "nautic") == 0)
					horizon = LN_SOLAR_NAUTIC_HORIZON;
				else if (strcmp(optarg, "astronomical") == 0)
					horizon = LN_SOLAR_ASTRONOMICAL_HORIZON;
				else {
					char *endptr;
					horizon = strtod(optarg, &endptr);

					if (endptr == optarg)
						usage_error("invalid horizon / twilight parameter");
				}
				
				horizon_set = true;
				break;

			case 't':
				tm.tm_isdst = -1; /* update dst */
				if (strchr(optarg, '_')) {
					if (!strptime(optarg, "%Y-%m-%d_%H:%M:%S", &tm))
						usage_error("invalid time/date parameter");
				}
				else {
					if (!strptime(optarg, "%Y-%m-%d", &tm))
						usage_error("invalid time/date parameter");
				}
				break;

			case 'm':
				if      (strcmp(optarg, "rise") == 0)
					moment = MOMENT_RISE;
				else if (strcmp(optarg, "set") == 0)
					moment = MOMENT_SET;
				else if (strcmp(optarg, "transit") == 0)
					moment = MOMENT_TRANSIT;
				else
					usage_error("invalid moment");
				break;

			case 'n':
				next = true;
				break;

			case 'f':
				format = strdup(optarg);
				break;

			case 'a':
				obs.lat = strtod(optarg, NULL);
				break;

			case 'o':
				obs.lng = strtod(optarg, NULL);
				break;
#ifdef GEONAMES_SUPPORT
			case 'q':
				query = strdup(optarg);
				break;

			case 'l':
				local_tz = true;
				break;
#endif
			case 'p':
				obj_str = optarg;
				break;

			case 'z':
				strncpy(tzid, optarg, sizeof(tzid));
				break;

			case 'u':
				strncpy(tzid, "UTC", sizeof(tzid));
				break;

			case 'v':
				print_version();
				return 0;

			case 'h':
				print_usage();
				return 0;

			case '?':
			default:
				usage_error("unrecognized option");
		}
	}
	
	/* Parse planet/obj */
	obj = object_lookup(obj_str);
	if (!obj)
		usage_error("invalid or missing object, use --object");

#ifdef GEONAMES_SUPPORT
	/* Lookup place at http://geonames.org */
	if (query) {
		ret =  geonames_lookup_latlng(query, &obs, NULL, 0);
		if (ret)
			usage_error("failed to lookup location");
	}
	
	if (local_tz) {
		int gmt_offset;
		ret =  geonames_lookup_tz(obs, &gmt_offset, tzid, sizeof(tzid));
		if (ret)
			usage_error("failed to lookup location");
	}
#endif

	if(strlen(tzid) > 0)	/* set TZ variable only when we have a value - otherwise rely on /etc/localtime or whatever other system fallbacks */
		setenv("TZ", tzid, 1);
	tzset();

	/* Validate observer coordinates */
	if (fabs(obs.lat) > 90)
		usage_error("invalid latitude, use --lat");
	if (fabs(obs.lng) > 180)
		usage_error("invalid longitude, use --lon");
	
	if (horizon_set && strcmp(object_name(obj), "sun"))
		usage_error("the twilight parameter can only be used for the sun");

	/* Calculate julian date */
	t = mktime(&tm);
	jd = ln_get_julian_from_timet(&t);

	result.obs = obs;

#ifdef DEBUG
	printf("Debug: calculate for jd: %f\n", jd);
	printf("Debug: calculate for ts: %ld\n", t);
	printf("Debug: for position: N %f, E %f\n", obs.lat, obs.lng);
	printf("Debug: for object: %s\n", object_name(obj));
	printf("Debug: with horizon: %f\n", horizon);
	printf("Debug: with timezone: %s\n", tzid);
#endif

	/* calc rst date */
rst:	if (object_rst(obj, jd - .5, horizon, &result.obs, &result.rst) == 1)  {
		if (moment != MOMENT_NOW) {
			fprintf(stderr, "object is circumpolar\n");
			return 2;
		}
	}
	else {
		switch (moment) {
			case MOMENT_NOW:	result.jd = jd; break;
			case MOMENT_RISE:	result.jd = result.rst.rise; break;
			case MOMENT_SET:	result.jd = result.rst.set; break;
			case MOMENT_TRANSIT:	result.jd = result.rst.transit; break;
		}

		if (next && result.jd < jd) {
			jd++;
			next = false;
			goto rst;
		}
	}
	
	ln_get_timet_from_julian(result.jd, &t);
	localtime_r(&t, &result.tm);

	object_pos(obj, jd, &result);

	format_result(format, &result);

	return 0;
}
memptr do_join_operation(memptr func_expr, JoinOperation operation_type) {

    if (num_nodes(func_expr) != 3) {
#ifdef DEBUG
        printf("1\n");
#endif
        switch (operation_type) {
        case PLUS:
            ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case MINUS:
            ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case MULT:
            ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case DIV:
            ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case EQUAL:
            ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case SMALLER:
            ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case GREATER:
            ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case OR:
            ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case AND:
            ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case XOR:
            ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        default:
            break;
        }
        return NOT_FOUND;
    }

    memptr current_node = cons_pool[func_expr].cdr;
    memptr local_security = safe_allocate_cons();
    cons_pool[local_security].carKind = NIL;
    cons_pool[local_security].cdrKind = NIL;
    memptr first_param = resolve_expr(cons_pool[current_node].car);
    if (first_param == NOT_FOUND) {
#ifdef DEBUG
        printf("2\n");
#endif
        switch (operation_type) {
        case PLUS:
            ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case MINUS:
            ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case MULT:
            ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case DIV:
            ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case EQUAL:
            ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case SMALLER:
            ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case GREATER:
            ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case OR:
            ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case AND:
            ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case XOR:
            ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        default:
            break;
        }
        return NOT_FOUND;
    }
    cons_pool[local_security].car = first_param;
    cons_pool[local_security].carKind = CONS;
    Type first_param_type = type(first_param);
    if (first_param_type == TYPE_OBJECT) {
        memptr lu = object_lookup(first_param, cons_pool[func_expr].car);
        if (lu == NOT_FOUND) {
            first_param = object_lookup(first_param, core_symbol);
            first_param_type = type(first_param);
        } else {
            return resolve_func_expr(func_expr, first_param, lu, true);
        }
    }

    current_node = cons_pool[current_node].cdr;
    memptr second_param = resolve_expr(cons_pool[current_node].car);
    if (second_param == NOT_FOUND) {
#ifdef DEBUG
        printf("3\n");
#endif
        switch (operation_type) {
        case PLUS:
            ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case MINUS:
            ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case MULT:
            ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case DIV:
            ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case EQUAL:
            ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case SMALLER:
            ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case GREATER:
            ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case OR:
            ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case AND:
            ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case XOR:
            ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        default:
            break;
        }
        return NOT_FOUND;
    }
    cons_pool[local_security].cdr = second_param;
    cons_pool[local_security].cdrKind = CONS;
    Type second_param_type = type(second_param);
    if (second_param_type == TYPE_OBJECT) {
        second_param = object_lookup(second_param, core_symbol);
        second_param_type = type(second_param);
    }

    memptr result = NOT_FOUND;
    if (operation_type == PLUS || operation_type == MINUS
            || operation_type == MULT || operation_type == DIV) {
        if (first_param_type != TYPE_INTEGER
                || second_param_type != TYPE_INTEGER) {
#ifdef DEBUG
            printf("4\n");
#endif
            switch (operation_type) {
            case PLUS:
                ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MINUS:
                ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MULT:
                ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case DIV:
                ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case EQUAL:
                ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case SMALLER:
                ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case GREATER:
                ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case OR:
                ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case AND:
                ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case XOR:
                ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            default:
                break;
            }
            return NOT_FOUND;
        }
        int first_value = fix_integer(cons_pool[first_param].car);
        int second_value = fix_integer(cons_pool[second_param].car);
        result = allocate_cons();
        cons_pool[result].carKind = INTEGER;
        cons_pool[result].cdrKind = NIL;
        switch (operation_type) {
        case PLUS:
            cons_pool[result].car = first_value + second_value;
            break;
        case MINUS:
            cons_pool[result].car = first_value - second_value;
            break;
        case MULT:
            cons_pool[result].car = first_value * second_value;
            break;
        case DIV:
            if (second_value == 0) {
#ifdef DEBUG
                printf("5\n");
#endif
                return NOT_FOUND;
            }
            cons_pool[result].car = first_value / second_value;
            break;
        default:
            break;
        }
    } else if (operation_type == EQUAL || operation_type == SMALLER
               || operation_type == GREATER) {
        if (first_param_type != second_param_type) {
#ifdef DEBUG
            printf("6\n");
#endif
            switch (operation_type) {
            case PLUS:
                ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MINUS:
                ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MULT:
                ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case DIV:
                ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case EQUAL:
                ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case SMALLER:
                ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case GREATER:
                ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case OR:
                ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case AND:
                ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case XOR:
                ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            default:
                break;
            }
        }
        int first_value;
        int second_value;
        if (first_param_type == TYPE_NIL_TRUE) {
            first_value = ((first_param == nil) ? 0 : 1);
            second_value = ((second_param == nil) ? 0 : 1);
        } else if (first_param_type == TYPE_INTEGER) {
            first_value = fix_integer(cons_pool[first_param].car);
            second_value = fix_integer(cons_pool[second_param].car);
        } else {
            // addresses comparison
            first_value = first_param;
            second_value = second_param;
        }
        // strings logic
        if (first_param_type == TYPE_STRING) {
            bool full_equal = false;
            int len1 = string_length(first_param);
            int len2 = string_length(second_param);
            if ((len1 == 1) || (len2 == 1)) {
                first_value =
                    strings_pool[get_string(cons_pool[first_param].car,
                                            cons_pool[first_param].cdr)];
                second_value = strings_pool[get_string(
                                                cons_pool[second_param].car,
                                                cons_pool[second_param].cdr)];
                if (len1 != 1) {
                    if (first_value == second_value) {
                        first_value++;
                    }
                }
                if (len2 != 1) {
                    if (first_value == second_value) {
                        second_value++;
                    }
                }
            } else {
                int iter1 = get_string(cons_pool[first_param].car,
                                       cons_pool[first_param].cdr), iter2 = get_string(
                                                   cons_pool[second_param].car,
                                                   cons_pool[second_param].cdr);
                first_value = second_value = 0;
                while (first_value == second_value
                        && strings_pool[iter1] != '\0'
                        && strings_pool[iter2] != '\0') {
                    first_value = strings_pool[iter1++];
                    second_value = strings_pool[iter2++];
                }
                if ((strings_pool[iter1] != '\0')
                        && (strings_pool[iter2] == '\0')
                        && (first_value == second_value)) {
                    first_value++;
                } else if ((strings_pool[iter1] == '\0')
                           && (strings_pool[iter2] != '\0')
                           && (first_value == second_value)) {
                    second_value++;
                }
            }
        }
        switch (operation_type) {
        case EQUAL:
            result = ((first_value == second_value) ? t : nil);
            break;
        case SMALLER:
            result = ((first_value < second_value) ? t : nil);
            break;
        case GREATER:
            result = ((first_value > second_value) ? t : nil);
            break;
        default:
#ifdef DEBUG
            printf("7\n");
#endif
            return NOT_FOUND;
            break;
        }
    } else if (operation_type == XOR || operation_type == OR
               || operation_type == AND) {
        if (first_param_type != TYPE_NIL_TRUE
                || second_param_type != TYPE_NIL_TRUE) {
#ifdef DEBUG
            printf("7.5\n");
#endif
            switch (operation_type) {
            case PLUS:
                ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MINUS:
                ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MULT:
                ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case DIV:
                ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case EQUAL:
                ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case SMALLER:
                ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case GREATER:
                ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case OR:
                ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case AND:
                ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case XOR:
                ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            default:
                break;
            }
            return NOT_FOUND;
        }
        switch (operation_type) {
        case XOR:
            result = ((first_param != second_param) ? t : nil);
            break;
        case OR:
            result = ((first_param == t || second_param == t) ? t : nil);
            break;
        case AND:
            result = ((first_param == t && second_param == t) ? t : nil);
            break;
        default:
#ifdef DEBUG
            printf("8\n");
#endif
            return NOT_FOUND;
            break;
        }
    }

    return result;
}