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