cleaned up RISC OS code and removed lots of unnecessary stuff
[gnupg.git] / util / riscos.c
1 /* riscos.c -  RISC OS stuff
2  *      Copyright (C) 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG for RISC OS.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #ifndef __RISCOS__C__
22 #define __RISCOS__C__
23
24 #include <config.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <signal.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <kernel.h>
32 #include <swis.h>
33 #include "util.h"
34 #include "memory.h"
35
36 #include <unixlib/local.h>     /* needed for RISCOSIFY_NO_PROCESS */
37 #define __UNIXLIB_INTERNALS
38 #include <unixlib/swiparams.h> /* needed for MMM_TYPE_* definitions */
39 #undef __UNIXLIB_INTERNALS
40
41
42 /* static symbols that trigger UnixLib behaviour */
43
44 int __riscosify_control = __RISCOSIFY_NO_PROCESS;
45 int __feature_imagefs_is_file = 1;
46
47
48 /* RISC OS file open descriptor control list */
49
50 struct fds_item {
51     int fd;
52     struct fds_item *next;
53 };
54 static struct fds_item *fds_list = NULL;
55 static int fdlist_initialized = 0;
56
57
58 /* local RISC OS functions */
59
60 static int
61 is_read_only(const char *filename)
62 {
63     int type, attr;
64     
65     if (_swix(OS_File, _INR(0,1) | _OUT(0) | _OUT(5),
66               17, filename, &type, &attr))
67         log_fatal("Can't get file attributes for file \"%s\"!\n", filename);
68     
69     if (type == 0)
70         log_fatal("Can't find file \"%s\"!\n", filename);
71
72     if (_swix(OS_File, _INR(0,1) | _IN(5), 4, filename, attr))
73         return 1;
74
75     return 0;
76 }
77
78 /* exported RISC OS functions */
79
80 int
81 riscos_load_module(const char *name, const char * const path[], int fatal)
82 {
83     int i;
84
85     /* Is module already loaded? */
86     if (!_swix(OS_Module, _INR(0,1), 18, name))
87         return 1;
88
89     /* Check all the places where the module could be located */
90     for (i=0; path[i]; ++i)
91         if (!_swix(OS_Module, _INR(0,1), 1, path[i]))
92             return 1;
93
94     /* Can't find module in the default locations */
95     if (fatal)
96         log_fatal("Operation cannot be performed without \"%s\" module!\n",
97                   name);
98     else
99         log_info("Can't load \"%s\" module, continuing anyway!\n", name);
100
101     return 0;
102 }
103
104 int
105 riscos_get_filetype_from_string(const char *string, int len)
106 {
107     int result = 0xfff;
108
109     if (strlen(string) < 5 || string[len - 4] != ',')
110         return -1;
111
112     sscanf(string+len-3, "%3x", &result);
113
114     return result;
115 }
116
117 int
118 riscos_get_filetype(const char *filename)
119 {
120     int result;
121
122     if (_swix(OS_File, _INR(0,1) | _OUT(2), 17, filename, &result))
123         log_fatal("Can't get filetype for file \"%s\"!\n", filename);
124
125     if ((result & 0xfff00000) == 0xfff00000)
126         return (result & 0xfff00) >> 8;
127     else
128         return 0;
129 }        
130
131 void
132 riscos_set_filetype_by_number(const char *filename, int type)
133 {
134     if (_swix(OS_File, _INR(0,2), 18, filename, type))
135         log_fatal("Can't set filetype for file \"%s\"!\n"
136                   "Is the file on a read-only file system?\n", filename);
137 }        
138
139 void
140 riscos_set_filetype_by_mimetype(const char *filename, const char *mimetype)
141 {
142     int result;
143
144     if (_swix(MimeMap_Translate, _INR(0,2) | _OUT(3),
145               MMM_TYPE_MIME, mimetype, MMM_TYPE_RISCOS, &result))
146         log_fatal("Can't translate MIME type \"%s\"!\n", mimetype);
147
148     riscos_set_filetype_by_number(filename, result);
149 }        
150
151 pid_t
152 riscos_getpid(void)
153 {
154     int state;
155
156     if (_swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 3, &state))
157         log_fatal("Wimp_ReadSysInfo failed: Can't get WimpState (R0=3)!\n");
158
159     if (state)
160         if (_swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 5, &state))
161             log_fatal("Wimp_ReadSysInfo failed: "
162                       "Can't get task handle (R0=5)!\n");
163
164     return (pid_t) state;
165 }
166
167 int
168 riscos_kill(pid_t pid, int sig)
169 {
170     int buf[4], iter = 0;
171
172     if (sig)
173         kill(pid, sig);
174
175     do {
176         if (_swix(TaskManager_EnumerateTasks, _INR(0,2) | _OUT(0),
177                   iter, buf, 16, &iter))
178             log_fatal("TaskManager_EnumerateTasks failed!\n");
179         if (buf[0] == pid)
180             return 0;
181     } while (iter >= 0);
182
183     return __set_errno(ESRCH);
184 }
185
186 int
187 riscos_access(const char *path, int amode)
188 {
189     /* Do additional check, i.e. whether path is on write-protected floppy */
190     if ((amode & W_OK) && is_read_only(path))
191         return 1;
192     return access(path, amode);
193 }
194
195 int
196 riscos_getchar(void)
197 {
198     int c, flags;
199
200     if (_swix(OS_ReadC, _OUT(0) | _OUT(_FLAGS), &c, &flags))
201         log_fatal("OS_ReadC failed: Couldn't read from keyboard!\n");
202     if (flags & _C)
203         log_fatal("OS_ReadC failed: Return Code = %i!\n", c);
204
205     return c;
206 }
207
208 #ifdef DEBUG
209 void
210 riscos_dump_fdlist(void)
211 {
212     struct fds_item *iter = fds_list;
213     printf("List of open file descriptors:\n");
214     while (iter) {
215         printf("  %i\n", iter->fd);
216         iter = iter->next;
217     }
218 }
219 #endif /* DEBUG */
220
221 int
222 riscos_fdopenfile(const char *filename, const int allow_write)
223 {
224     struct fds_item *h;
225     int fd;
226     if (allow_write)
227         fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
228     else
229         fd = open(filename, O_RDONLY);
230     if (fd == -1)
231         log_error("Can't open file \"%s\": %i, %s!\n",
232                   filename, errno, strerror(errno));
233
234     if (!fdlist_initialized) {
235         atexit (riscos_close_fds);
236         fdlist_initialized = 1;
237     }
238
239     h = fds_list;
240     fds_list = (struct fds_item *) m_alloc(sizeof(struct fds_item));
241     if (!fds_list)
242         log_fatal("Can't claim memory for fdopenfile() buffer!\n");
243     fds_list->fd = fd;
244     fds_list->next = h;
245
246     return fd;
247 }
248
249 void
250 riscos_close_fds(void)
251 {
252     FILE *fp;
253     struct fds_item *h = fds_list;
254     while( fds_list ) {
255         h = fds_list->next;
256         fp = fdopen (fds_list->fd, "a");
257         if (fp)
258             fflush(fp);
259         close(fds_list->fd);
260         m_free(fds_list);
261         fds_list = h;
262     }
263 }
264
265 int
266 riscos_renamefile(const char *old, const char *new)
267 {
268     _kernel_oserror *e;
269
270     if (e = _swix(OS_FSControl, _INR(0,2), 25, old, new)) {
271         if (e->errnum == 214)
272             return __set_errno(ENOENT);
273         if (e->errnum == 176)
274             return __set_errno(EEXIST);
275         printf("Error during renaming: %i, %s!\n", e->errnum, e->errmess);
276         return __set_errno(EOPSYS);
277     }
278     return 0;
279 }
280
281 char *
282 riscos_gstrans(const char *old)
283 {
284     int size = 256, last;
285     char *buf, *tmp;
286
287     buf = (char *) m_alloc(size);
288     if (!buf)
289         log_fatal("Can't claim memory for OS_GSTrans buffer!\n");
290     while (_C & _swi(OS_GSTrans, _INR(0,2) | _OUT(2) | _RETURN(_FLAGS),
291                      old, buf, size, &last)) {
292         size += 256;
293         tmp = (char *) m_realloc(buf, size);
294         if (!tmp)
295              log_fatal("Can't claim memory for OS_GSTrans buffer!\n");
296         buf = tmp;
297     }
298
299     buf[last] = '\0';
300     tmp = (char *) m_realloc(buf, last + 1);
301     if (!tmp)
302         log_fatal("Can't realloc memory after OS_GSTrans!\n");
303
304     return tmp;
305 }
306
307 /***************
308  * Extract from a given path the filename component.
309  * (cloned from util/fileutil.c and then heavily modified)
310  */
311 char *
312 riscos_make_basename(const char *filepath, const char *realfname)
313 {
314     char *result, *p;
315     int i, filetype;
316
317     if ( (p = strrchr(filepath, DIRSEP_C)) )
318         p++;
319     else if ( (p = strrchr(filepath, ':')) )
320         p++;
321     else
322         p = (char*) filepath;
323
324     i = strlen(p);
325     result = m_alloc(i + 5);
326     if (!result)
327         log_fatal("Can't claim memory for riscos_make_basename() buffer!\n");
328     strcpy(result, p);
329     
330     filetype = riscos_get_filetype( realfname );
331     result[i++] = ',';
332     result[i++] = "0123456789abcdef"[(filetype >> 8) & 0xf];
333     result[i++] = "0123456789abcdef"[(filetype >> 4) & 0xf];
334     result[i++] = "0123456789abcdef"[(filetype >> 0) & 0xf];
335     result[i]   = 0;
336
337     for(i=0; i<strlen(result); ++i)
338         if(result[i] == '/')
339             result[i] = '.';
340
341     return result;
342 }
343
344 #define RegEx_CompilePattern         0x52AC0
345 #define RegEx_Search                 0x52AC2
346 #define RegEx_Free                   0x52AC7
347 #define RegEx_CompileExtendedPattern 0x52AC9
348
349 static const char * const regex_path[] = {
350     "GnuPG:RegEx",
351     "System:310.Modules.RegEx",
352     "System:Modules.RegEx",
353     NULL
354 };
355
356 int
357 riscos_check_regexp(const char *exp, const char *string, int debug)
358 {
359     static int regex_initialized = 0;
360     int ret;
361     char *buf;
362   
363     if (!regex_initialized)
364         regex_initialized = riscos_load_module("RegEx", regex_path, 0);
365   
366     if (!regex_initialized) {
367         log_info("Regular expressions cannot be used!\n");
368         return 0;
369     }
370   
371     if (_swix(RegEx_CompileExtendedPattern, _INR(0,2) | _OUT(0) | _OUT(3),
372               0, exp, 1<<18,
373               &buf, &ret)) {
374         log_info("RegEx could not compile pattern \"%s\".\n", exp);
375         log_info("ErrorCode = %i\n", ret);
376         return 0;
377     }
378   
379     if (_swix(RegEx_Search, _INR(0,4) | _OUT(5),
380               buf, string, -1, 0, -1,
381               &ret)) {
382         log_info("RegEx error during execution of serach pattern \"%s\"\n",
383                  exp);
384         log_info("on string \"%s\"\n", string);
385         return 0;
386     }
387   
388     _swix(RegEx_Free, _IN(0), buf);
389   
390     if(debug)
391         log_debug("regexp \"%s\" on \"%s\": %s\n",exp,string,ret>=0?"YES":"NO");
392   
393     return (ret>=0);
394 }
395
396 #ifdef DEBUG
397 void
398 riscos_list_openfiles(void)
399 {
400     char *name;
401     int i, len;
402     
403     for (i = 255; i >= 0; --i) {
404         if (_swix(OS_Args, _INR(0,2) | _IN(5) | _OUT(5), 7, i, 0, 0, &len))
405             continue;
406
407         name = (char *) m_alloc(1-len);
408         if (!name)
409             log_fatal("Can't claim memory for OS_Args buffer!\n");
410
411         if (_swix(OS_Args, _INR(0,2) | _IN(5), 7, i, name, 1-len)) {
412             m_free(name);
413             log_fatal("Error when calling OS_Args(7)!\n");
414         }
415         
416         if (_swix(OS_Args, _INR(0,1) | _OUT(0), 254, i, &len)) {
417             m_free(name);
418             log_fatal("Error when calling OS_Args(254)!\n");
419         }
420         
421         printf("%3i: %s (%c%c)\n", i, name,
422                                    (len & 0x40) ? 'R' : 0,
423                                    (len & 0x80) ? 'W' : 0);
424         m_free(name);
425     }
426 }
427 #endif
428
429 void
430 riscos_not_implemented(const char *feature)
431 {
432     log_info("%s is not implemented in the RISC OS version!\n", feature);
433 }
434
435 #endif /* !__RISCOS__C__ */