int
main()
{
	struct stat stat_pre, stat_post, session_stat;
	char *filename = get_filename();
	int child, status, log_fd, null_fd;
	char var[1024], val[4096];
	FILE *env_file;
	FILE *waiter_pidfile;

	copy_file_by_name(filename);
	if (stat(filename, &stat_pre)) {
		perror("stat pre");
		exit(1);
	}
	fprintf(stderr, "time=%s, waiting for qubes-session\n", gettime());
	// wait for X server to starts (especially in DispVM)
	if (stat("/tmp/qubes-session-env", &session_stat)) {
		switch (child = fork()) {
			case -1:
				perror("fork");
				exit(1);
			case 0:
				waiter_pidfile = fopen("/tmp/qubes-session-waiter", "a");
				if (waiter_pidfile == NULL) {
					perror("fopen waiter_pidfile");
					exit(1);
				}
				fprintf(waiter_pidfile, "%d\n", getpid());
				fclose(waiter_pidfile);
				// check the second time, to prevent race
				if (stat("/tmp/qubes-session-env", &session_stat)) {
					// wait for qubes-session notify
					pause();
				}
				exit(0);
			default:
				waitpid(child, &status, 0);
				if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
					//propagate exit code from child
					exit(WEXITSTATUS(status));
				}
		}
	}
	fprintf(stderr, "time=%s, starting editor\n", gettime());
	switch (child = fork()) {
		case -1:
			perror("fork");
			exit(1);
		case 0:
			null_fd = open("/dev/null", O_RDONLY);
			dup2(null_fd, 0);
			close(null_fd);		

			env_file = fopen("/tmp/qubes-session-env", "r");
			while(fscanf(env_file, "%1024[^=]=%4096[^\n]\n", var, val) == 2) {
				setenv(var, val, 1);
			}
			fclose(env_file);

			log_fd = open("/tmp/mimeopen.log", O_CREAT | O_APPEND, 0666);
			if (log_fd == -1) {
				perror("open /tmp/mimeopen.log");
				exit(1);
			}
			dup2(log_fd, 1);
			close(log_fd);

			setenv("HOME", USER_HOME, 1);
			setenv("DISPLAY", ":0", 1);
			execl("/usr/bin/mimeopen", "mimeopen", "-n",
					"--database", MIMEINFO_DATABASES, filename, (char*)NULL);
			perror("execl");
			exit(1);
		default:
			waitpid(child, &status, 0);
			if (status != 0) {
				char cmd[512];
#ifdef USE_KDIALOG
				snprintf(cmd, sizeof(cmd),
						"HOME=/home/user DISPLAY=:0 /usr/bin/kdialog --sorry 'Unable to handle mimetype of the requested file (exit status: %d)!' > /tmp/kdialog.log 2>&1 </dev/null", status);
					("HOME=/home/user DISPLAY=:0 /usr/bin/kdialog --sorry 'Unable to handle mimetype of the requested file (exit status: %d)!' > /tmp/kdialog.log 2>&1 </dev/null", status);
#else
				snprintf(cmd, sizeof(cmd),
						"HOME=/home/user DISPLAY=:0 /usr/bin/zenity --error --text 'Unable to handle mimetype of the requested file (exit status: %d)!' > /tmp/kdialog.log 2>&1 </dev/null", status);
#endif
				status = system(cmd);
			}
	}

	if (stat(filename, &stat_post)) {
		perror("stat post");
		exit(1);
	}
	if (stat_pre.st_mtime != stat_post.st_mtime)
		send_file_back(filename);
	free(filename);
	return 0;
}
int
main()
{
    struct stat stat_pre, stat_post, session_stat;
    int view_only = 0;
    char *filename = get_filename(&view_only);
    int child, status, log_fd, null_fd;
    FILE *waiter_pidfile;

    copy_file_by_name(filename);
    if (view_only) {
        // mark file as read-only so applications will signal it to the user
        chmod(filename, 0400);
    }
    if (stat(filename, &stat_pre)) {
        perror("stat pre");
        exit(1);
    }
#ifdef DEBUG
    fprintf(stderr, "time=%s, waiting for qubes-session\n", gettime());
#endif
    // wait for X server to starts (especially in DispVM)
    if (stat("/tmp/qubes-session-env", &session_stat)) {
        switch (child = fork()) {
            case -1:
                perror("fork");
                exit(1);
            case 0:
                waiter_pidfile = fopen("/tmp/qubes-session-waiter", "a");
                if (waiter_pidfile == NULL) {
                    perror("fopen waiter_pidfile");
                    exit(1);
                }
                fprintf(waiter_pidfile, "%d\n", getpid());
                fclose(waiter_pidfile);
                // check the second time, to prevent race
                if (stat("/tmp/qubes-session-env", &session_stat)) {
                    // wait for qubes-session notify
                    pause();
                }
                exit(0);
            default:
                waitpid(child, &status, 0);
                if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
                    //propagate exit code from child
                    exit(WEXITSTATUS(status));
                }
        }
    }
#ifdef DEBUG
    fprintf(stderr, "time=%s, starting editor\n", gettime());
#endif
    switch (child = fork()) {
        case -1:
            perror("fork");
            exit(1);
        case 0:
            null_fd = open("/dev/null", O_RDONLY);
            dup2(null_fd, 0);
            close(null_fd);

            log_fd = open("/tmp/mimeopen.log", O_CREAT | O_APPEND, 0666);
            if (log_fd == -1) {
                perror("open /tmp/mimeopen.log");
                exit(1);
            }
            dup2(log_fd, 1);
            close(log_fd);

            setenv("HOME", USER_HOME, 1);
            setenv("DISPLAY", ":0", 1);
            execl("/usr/bin/qubes-open", "qubes-open", filename, (char*)NULL);
            perror("execl");
            exit(1);
        default:
            waitpid(child, &status, 0);
            if (status != 0) {
                char cmd[512];
#ifdef USE_KDIALOG
                snprintf(cmd, sizeof(cmd),
                        "HOME=/home/user DISPLAY=:0 /usr/bin/kdialog --sorry 'Unable to handle mimetype of the requested file (exit status: %d)!' > /tmp/kdialog.log 2>&1 </dev/null", status);
                    ("HOME=/home/user DISPLAY=:0 /usr/bin/kdialog --sorry 'Unable to handle mimetype of the requested file (exit status: %d)!' > /tmp/kdialog.log 2>&1 </dev/null", status);
#else
                snprintf(cmd, sizeof(cmd),
                        "HOME=/home/user DISPLAY=:0 /usr/bin/zenity --error --text 'Unable to handle mimetype of the requested file (exit status: %d)!' > /tmp/kdialog.log 2>&1 </dev/null", status);
#endif
                status = system(cmd);
            }
    }

    if (stat(filename, &stat_post)) {
        perror("stat post");
        exit(1);
    }
    if (stat_pre.st_mtime != stat_post.st_mtime)
        send_file_back(filename);
    free(filename);
    return 0;
}