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