Long time no see.
[pedecabra.git] / pedecabra.c
blob107b96bd40d0f30a4efeef792d18656ab2f425d2
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <errno.h>
4 #include <stdio.h>
5 #include <stdbool.h>
6 #include <string.h>
7 #include <libgen.h>
8 #include <assert.h>
9 #include <regex.h>
11 #include <magic.h>
13 /* Print Magic Error */
14 #define PME {
16 /* very stupid aproach, but very simple :) */
17 struct association_s {
18 const char *filetype; /* filetype of the file */
19 const char *viewapp; /* path to the view program */
20 const char *editapp; /* path to the edit program */
23 #include "config.h"
25 int entry_count = sizeof(associations)/sizeof(struct association_s);
27 /* determine <file> filetype
29 * if successfull <filetype> must be freed later by the user
30 * returns true if successfull, false otherwise
33 bool getfiletype(char *file, char **filetype)
35 assert (file != NULL);
37 magic_t mc; //magic_cookie
38 char *magictype;
39 int magictypelen;
40 int stat;
42 stat = access(file, F_OK);
43 if (stat == -1) {
44 perror("AH");
45 return false;
48 mc = magic_open(MAGIC_NONE);
49 if (mc == NULL) {
50 perror("AH");
51 return false;
54 stat = magic_load(mc, NULL);
55 if (stat == -1) {
56 fprintf(stderr, "AH: %s", magic_error(mc));
57 return false;
60 magictype = magic_file(mc, file);
61 if (magictype == NULL) {
62 fprintf(stderr, "AH: %s", magic_error(mc));
63 return false;
65 //printf("Magic says: %s\n\n", magictype);
67 /* "convert" (or copy) magic result to something local to close magic */
68 magictypelen = strlen(magictype);
69 (*filetype) = (char *)malloc(magictypelen+1);
70 if (*filetype == NULL) {
71 perror("AH");
72 return false;
74 strncpy(*filetype, magictype, magictypelen+1);
76 /* no more magic */
77 magic_close(mc);
79 return true;
82 /* match <filetype> against local database
84 * <index> gets the index of the found entry, if successfull
85 * returns true if entry was found, false otherwise
87 bool match(char *filetype, int *index)
89 assert(filetype != NULL);
90 assert(index != NULL);
92 bool found;
93 int r;
94 regex_t preg;
96 /* this is a nasty piece of code. need to beautify!!! */
97 for(r=0, found=false; (r < entry_count) && (found == false); ++r) {
98 if (regcomp(&preg, associations[r].filetype, REG_EXTENDED | REG_NOSUB) != 0) {
99 fprintf(stderr, "Unable to compile regex %s.\n", associations[r].filetype);
100 return false;
102 /* true on substring match. to match whole string prepend with '^' and append '$'. */
103 if (regexec(&preg, filetype, 0, 0, 0) == 0) {
104 found = true;
107 --r;
108 regfree(&preg);
110 *index = r;
111 return found;
114 void main (int argc, char *argv[])
116 bool stat;
117 char *file;
118 char *filetype;
119 int index;
120 char *newargv[3];
122 if (argc != 3) {
123 fprintf(stderr, "%s: Incorrect arguments.\n", argv[0]);
124 fprintf(stdout, "Usage: %s v|e <file>\n", argv[0]);
125 fprintf(stdout, "\t v: opens file with application registered to view\n");
126 fprintf(stdout, "\t e: opens file with application registered to edit\n");
127 exit(EXIT_FAILURE);
130 file = argv[2];
132 stat = getfiletype(file, &filetype);
133 if (stat == false) {
134 fprintf(stderr, "Could not determine %s type.\n", file);
135 exit(EXIT_FAILURE);
138 stat = match(filetype, &index);
139 if (stat == false) {
140 fprintf(stderr, "Type '%s' not configured.\nAdd it to associations "\
141 "array in config.h and recompile.\n", filetype);
142 exit(EXIT_FAILURE);
145 free(filetype);
147 switch (*argv[1]) {
148 case 'e':
149 newargv[0] = associations[index].editapp;
150 newargv[1] = file;
151 newargv[2] = (char *)NULL;
152 stat = execv(associations[index].editapp, newargv);
153 perror("AH");
154 break;
155 case 'v':
156 newargv[0] = associations[index].viewapp;
157 newargv[1] = file;
158 newargv[2] = (char *)NULL;
159 stat = execv(associations[index].viewapp, newargv);
160 perror("AH");
161 break;
162 default:
163 fprintf(stderr, "No application associated with the action %s for\
164 file %s.\n", argv[1], file);
165 break;
168 exit(EXIT_FAILURE);