8f840e10dc
MIME-info database contains multiple entries for *.png, namely image/png and image/x-apple-ios-png. The later one doesn't have associated handler program, but this one is selected by mimeopen tool. Not sure how this tool should behave in case of multiple matches (IOW is it a bug in File::MimeInfo perl module used by mimeopen). Instead of switching to different tool, which probably will break other files (check #423), add override for this particular file type.
166 lines
4.1 KiB
C
166 lines
4.1 KiB
C
#include <sys/stat.h>
|
|
#include <sys/wait.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <ioall.h>
|
|
#include "dvm2.h"
|
|
|
|
#define USER_HOME "/home/user"
|
|
#define MIMEINFO_DATABASES "/usr/share/mime:/usr/local/share:" USER_HOME "/.local/share:/usr/share/qubes/mime-override"
|
|
|
|
char *gettime()
|
|
{
|
|
static char retbuf[60];
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
snprintf(retbuf, sizeof(retbuf), "%lld.%lld",
|
|
(long long) tv.tv_sec, (long long) tv.tv_usec);
|
|
return retbuf;
|
|
}
|
|
|
|
char *get_filename()
|
|
{
|
|
char buf[DVM_FILENAME_SIZE];
|
|
static char retname[sizeof(buf) + sizeof("/tmp/")];
|
|
int i;
|
|
if (!read_all(0, buf, sizeof(buf)))
|
|
exit(1);
|
|
if (index(buf, '/')) {
|
|
fprintf(stderr, "filename contains /");
|
|
exit(1);
|
|
}
|
|
for (i=0; i < DVM_FILENAME_SIZE && buf[i]!=0; i++) {
|
|
// replace some characters with _ (eg mimeopen have problems with some of them)
|
|
if (index(" !?\"#$%^&*()[]<>;`~", buf[i]))
|
|
buf[i]='_';
|
|
}
|
|
snprintf(retname, sizeof(retname), "/tmp/%s", buf);
|
|
return retname;
|
|
}
|
|
|
|
void copy_file(char *filename)
|
|
{
|
|
int fd = open(filename, O_WRONLY | O_CREAT, 0600);
|
|
if (fd < 0) {
|
|
perror("open file");
|
|
exit(1);
|
|
}
|
|
if (!copy_fd_all(fd, 0))
|
|
exit(1);
|
|
close(fd);
|
|
}
|
|
|
|
void send_file_back(char * filename)
|
|
{
|
|
int fd = open(filename, O_RDONLY);
|
|
if (fd < 0) {
|
|
perror("open file");
|
|
exit(1);
|
|
}
|
|
if (!copy_fd_all(1, fd))
|
|
exit(1);
|
|
close(fd);
|
|
}
|
|
|
|
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(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
|
|
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);
|
|
return 0;
|
|
}
|