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