Update head to match stable 1.0
[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 <stdarg.h>
27 #include <sys/types.h>
28 #include <sys/stat.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 #define __UNIXLIB_INTERNALS
38 #include <unixlib/unix.h>
39 #undef __UNIXLIB_INTERNALS
40
41 /* RISC OS specific defines that are not yet in UnixLib */
42
43 #define MimeMap_Translate      0x50B00
44 #define MMM_TYPE_RISCOS        0
45 #define MMM_TYPE_RISCOS_STRING 1
46 #define MMM_TYPE_MIME          2
47 #define MMM_TYPE_DOT_EXTN      3
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 initialized = 0;
57
58
59 /* local RISC OS functions */
60
61 static int
62 is_read_only(const char *filename)
63 {
64     _kernel_swi_regs r;
65     
66     r.r[0] = 17;
67     r.r[1] = (int) filename;
68     
69     if (_kernel_swi(OS_File, &r, &r))
70         log_fatal("Can't get file attributes for %s!\n", filename);
71     
72     if (r.r[0] == 0)
73         log_fatal("Can't find file %s!\n", filename);
74
75     r.r[0] = 4;
76     if (_kernel_swi(OS_File, &r, &r))
77         return 1;
78
79     return 0;
80 }
81
82 static void
83 riscos_set_filetype_by_number(const char *filename, int type)
84 {
85     _kernel_swi_regs r;
86
87     r.r[0] = 18;
88     r.r[1] = (int) filename;
89     r.r[2] = type;
90     
91     if (_kernel_swi(OS_File, &r, &r))
92         log_fatal("Can't set filetype for file %s!\n"
93                   "Is the file on a read-only file system?\n", filename);
94 }        
95
96 /* exported RISC OS functions */
97
98 void
99 riscos_global_defaults()
100 {
101     __riscosify_control = __RISCOSIFY_NO_PROCESS;
102     __feature_imagefs_is_file = 1;
103 }
104
105 void
106 riscos_set_filetype(const char *filename, const char *mimetype)
107 {
108     _kernel_swi_regs r;
109
110     r.r[0] = MMM_TYPE_MIME;
111     r.r[1] = (int) mimetype;
112     r.r[2] = MMM_TYPE_RISCOS;
113     
114     if (_kernel_swi(MimeMap_Translate, &r, &r))
115         log_fatal("Can't translate MIME type %s!\n", mimetype);
116
117     riscos_set_filetype_by_number(filename, r.r[3]);
118 }        
119
120 pid_t
121 riscos_getpid(void)
122 {
123     _kernel_swi_regs r;
124
125     r.r[0] = 3;
126     if (_kernel_swi(Wimp_ReadSysInfo, &r, &r))
127         log_fatal("Wimp_ReadSysInfo failed: Can't get WimpState (R0=3)!\n");
128
129     if (!r.r[0])
130         return (pid_t) 0;
131
132     r.r[0] = 5;
133     if (_kernel_swi(Wimp_ReadSysInfo, &r, &r))
134         log_fatal("Wimp_ReadSysInfo failed: Can't get task handle (R0=5)!\n");
135
136     return (pid_t) r.r[0];
137 }
138
139 int
140 riscos_kill(pid_t pid, int sig)
141 {
142     _kernel_swi_regs r;
143     int buf[4];
144
145     if (sig)
146         kill(pid, sig);
147
148     r.r[0] = 0;
149     do {
150         r.r[1] = (int) buf;
151         r.r[2] = 16;
152         if (_kernel_swi(TaskManager_EnumerateTasks, &r, &r))
153             log_fatal("TaskManager_EnumerateTasks failed!\n");
154         if (buf[0] == pid)
155             return 0;
156     } while (r.r[0] >= 0);
157
158     return __set_errno(ESRCH);
159 }
160
161 int
162 riscos_access(const char *path, int amode)
163 {
164     /* Do additional check, i.e. whether path is on write-protected floppy */
165     if ((amode & W_OK) && is_read_only(path))
166         return 1;
167     return access(path, amode);
168 }
169
170 #ifdef DEBUG
171 void
172 dump_fdlist(void)
173 {
174     struct fds_item *iter = fds_list;
175     printf("List of open file descriptors:\n");
176     while (iter) {
177         printf("  %i\n", iter->fd);
178         iter = iter->next;
179     }
180 }
181 #endif /* DEBUG */
182
183 int
184 fdopenfile(const char *filename, const int allow_write)
185 {
186     struct fds_item *h;
187     int fd;
188     if (allow_write)
189         fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
190     else
191         fd = open(filename, O_RDONLY);
192     if (fd == -1)
193         log_error("Can't open file %s: %i, %s!\n", filename, errno, strerror(errno));
194
195     if (!initialized) {
196         atexit (close_fds);
197         initialized = 1;
198     }
199
200     h = fds_list;
201     fds_list = (struct fds_item *) m_alloc(sizeof(struct fds_item));
202     fds_list->fd = fd;
203     fds_list->next = h;
204
205     return fd;
206 }
207
208 void
209 close_fds(void)
210 {
211     FILE *fp;
212     struct fds_item *h = fds_list;
213     while( fds_list ) {
214         h = fds_list->next;
215         fp = fdopen (fds_list->fd, "a");
216         if (fp)
217             fflush(fp);
218         close(fds_list->fd);
219         m_free(fds_list);
220         fds_list = h;
221     }
222 }
223
224 int
225 renamefile(const char *old, const char *new)
226 {
227     _kernel_swi_regs r;
228     _kernel_oserror *e;
229
230     r.r[0] = 25;
231     r.r[1] = (int) old;
232     r.r[2] = (int) new;
233     if (e = _kernel_swi(OS_FSControl, &r, &r)) {
234         if (e->errnum == 214)
235             return __set_errno(ENOENT);
236         if (e->errnum == 176)
237             return __set_errno(EEXIST);
238         printf("Error during renaming: %i, %s!\n", e->errnum, e->errmess);
239         return __set_errno(EOPSYS);
240     }
241     return 0;
242 }
243
244 char *
245 gstrans(const char *old)
246 {
247     _kernel_swi_regs r;
248     int c = 0;
249     int size = 256;
250     char *buf, *tmp;
251
252     buf = (char *) m_alloc(size);
253     if (!buf)
254         log_fatal("Can't claim memory for OS_GSTrans buffer!\n");
255     do {
256         r.r[0] = (int) old;
257         r.r[1] = (int) buf;
258         r.r[2] = size;
259         _kernel_swi_c(OS_GSTrans, &r, &r, &c);
260         if (c) {
261             size += 256;
262             tmp = (char *) m_realloc(buf, size);
263             if (!tmp)
264                  log_fatal("Can't claim memory for OS_GSTrans buffer!\n");
265             buf = tmp;
266         }
267     } while (c);
268
269     buf[r.r[2]] = '\0';
270     tmp = (char *) m_realloc(buf, r.r[2] + 1);
271     if (!tmp)
272         log_fatal("Can't realloc memory after OS_GSTrans!\n");
273
274     return tmp;
275 }
276
277 #ifdef DEBUG
278 void
279 list_openfiles(void)
280 {
281     _kernel_swi_regs r;
282     char *name;
283     int i;
284     
285     for (i = 255; i >= 0; --i) {
286         r.r[0] = 7;
287         r.r[1] = i;
288         r.r[2] = 0;
289         r.r[5] = 0;
290         if (_kernel_swi(OS_Args, &r, &r))
291             continue;
292
293         name = (char *) m_alloc(1-r.r[5]);
294         if (!name)
295             log_fatal("Can't claim memory for OS_Args buffer!\n");
296
297         r.r[0] = 7;
298         r.r[1] = i;
299         r.r[2] = (int) name;
300         r.r[5] = 1-r.r[5];
301         if (_kernel_swi(OS_Args, &r, &r)) {
302             m_free(name);
303             log_fatal("Error when calling OS_Args(7)!\n");
304         }
305         
306         r.r[0] = 254;
307         r.r[1] = i;
308         if (_kernel_swi(OS_Args, &r, &r)) {
309             m_free(name);
310             log_fatal("Error when calling OS_Args(254)!\n");
311         }
312         
313         printf("%3i: %s (%c%c)\n", i, name,
314                                    (r.r[0] & 0x40) ? 'R' : 0,
315                                    (r.r[0] & 0x80) ? 'W' : 0);
316         m_free(name);
317     }
318 }
319 #endif
320
321 void
322 not_implemented(const char *feature)
323 {
324     log_info("%s is not implemented in the RISC OS version!\n", feature);
325 }
326
327 #endif /* !__RISCOS__C__ */