tidying up RISC OS 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 <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     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 %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 static void
80 riscos_set_filetype_by_number(const char *filename, int type)
81 {
82     if (_swix(OS_File, _INR(0,2), 18, filename, type))
83         log_fatal("Can't set filetype for file %s!\n"
84                   "Is the file on a read-only file system?\n", filename);
85 }        
86
87 /* exported RISC OS functions */
88
89 void
90 riscos_global_defaults(void)
91 {
92     __riscosify_control = __RISCOSIFY_NO_PROCESS;
93     __feature_imagefs_is_file = 1;
94 }
95
96 void
97 riscos_set_filetype(const char *filename, const char *mimetype)
98 {
99     int result;
100
101     if (_swix(MimeMap_Translate, _INR(0,2) | _OUT(3),
102               MMM_TYPE_MIME, mimetype, MMM_TYPE_RISCOS, &result))
103         log_fatal("Can't translate MIME type %s!\n", mimetype);
104
105     riscos_set_filetype_by_number(filename, result);
106 }        
107
108 pid_t
109 riscos_getpid(void)
110 {
111     int state;
112
113     if (_swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 3, &state))
114         log_fatal("Wimp_ReadSysInfo failed: Can't get WimpState (R0=3)!\n");
115
116     if (state)
117         if (_swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 5, &state))
118             log_fatal("Wimp_ReadSysInfo failed: Can't get task handle (R0=5)!\n");
119
120     return (pid_t) state;
121 }
122
123 int
124 riscos_kill(pid_t pid, int sig)
125 {
126     int buf[4], iter = 0;
127
128     if (sig)
129         kill(pid, sig);
130
131     do {
132         if (_swix(TaskManager_EnumerateTasks, _INR(0,2) | _OUT(0),
133                   iter, buf, 16, &iter))
134             log_fatal("TaskManager_EnumerateTasks failed!\n");
135         if (buf[0] == pid)
136             return 0;
137     } while (iter >= 0);
138
139     return __set_errno(ESRCH);
140 }
141
142 int
143 riscos_access(const char *path, int amode)
144 {
145     /* Do additional check, i.e. whether path is on write-protected floppy */
146     if ((amode & W_OK) && is_read_only(path))
147         return 1;
148     return access(path, amode);
149 }
150
151 int
152 riscos_getchar(void)
153 {
154     int c, flags;
155
156     if (_swix(OS_ReadC, _OUT(0) | _OUT(_FLAGS), &c, &flags))
157         log_fatal("OS_ReadC failed: Couldn't read from keyboard!\n");
158     if (flags & _C)
159         log_fatal("OS_ReadC failed: Return Code = %i!\n", c);
160
161     return c;
162 }
163
164 #ifdef DEBUG
165 void
166 dump_fdlist(void)
167 {
168     struct fds_item *iter = fds_list;
169     printf("List of open file descriptors:\n");
170     while (iter) {
171         printf("  %i\n", iter->fd);
172         iter = iter->next;
173     }
174 }
175 #endif /* DEBUG */
176
177 int
178 fdopenfile(const char *filename, const int allow_write)
179 {
180     struct fds_item *h;
181     int fd;
182     if (allow_write)
183         fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
184     else
185         fd = open(filename, O_RDONLY);
186     if (fd == -1)
187         log_error("Can't open file %s: %i, %s!\n", filename, errno, strerror(errno));
188
189     if (!initialized) {
190         atexit (close_fds);
191         initialized = 1;
192     }
193
194     h = fds_list;
195     fds_list = (struct fds_item *) m_alloc(sizeof(struct fds_item));
196     fds_list->fd = fd;
197     fds_list->next = h;
198
199     return fd;
200 }
201
202 void
203 close_fds(void)
204 {
205     FILE *fp;
206     struct fds_item *h = fds_list;
207     while( fds_list ) {
208         h = fds_list->next;
209         fp = fdopen (fds_list->fd, "a");
210         if (fp)
211             fflush(fp);
212         close(fds_list->fd);
213         m_free(fds_list);
214         fds_list = h;
215     }
216 }
217
218 int
219 renamefile(const char *old, const char *new)
220 {
221     _kernel_oserror *e;
222
223     if (e = _swix(OS_FSControl, _INR(0,2), 25, old, new)) {
224         if (e->errnum == 214)
225             return __set_errno(ENOENT);
226         if (e->errnum == 176)
227             return __set_errno(EEXIST);
228         printf("Error during renaming: %i, %s!\n", e->errnum, e->errmess);
229         return __set_errno(EOPSYS);
230     }
231     return 0;
232 }
233
234 char *
235 gstrans(const char *old)
236 {
237     int size = 256, last;
238     char *buf, *tmp;
239
240     buf = (char *) m_alloc(size);
241     if (!buf)
242         log_fatal("Can't claim memory for OS_GSTrans buffer!\n");
243     while (_C & _swi(OS_GSTrans, _INR(0,2) | _OUT(2) | _RETURN(_FLAGS),
244                      old, buf, size, &last)) {
245         size += 256;
246         tmp = (char *) m_realloc(buf, size);
247         if (!tmp)
248              log_fatal("Can't claim memory for OS_GSTrans buffer!\n");
249         buf = tmp;
250     }
251
252     buf[last] = '\0';
253     tmp = (char *) m_realloc(buf, last + 1);
254     if (!tmp)
255         log_fatal("Can't realloc memory after OS_GSTrans!\n");
256
257     return tmp;
258 }
259
260 #ifdef DEBUG
261 void
262 list_openfiles(void)
263 {
264     char *name;
265     int i, len;
266     
267     for (i = 255; i >= 0; --i) {
268         if (_swix(OS_Args, _INR(0,2) | _IN(5) | _OUT(5), 7, i, 0, 0, &len))
269             continue;
270
271         name = (char *) m_alloc(1-len);
272         if (!name)
273             log_fatal("Can't claim memory for OS_Args buffer!\n");
274
275         if (_swix(OS_Args, _INR(0,2) | _IN(5), 7, i, name, 1-len)) {
276             m_free(name);
277             log_fatal("Error when calling OS_Args(7)!\n");
278         }
279         
280         if (_swix(OS_Args, _INR(0,1) | _OUT(0), 254, i, &len)) {
281             m_free(name);
282             log_fatal("Error when calling OS_Args(254)!\n");
283         }
284         
285         printf("%3i: %s (%c%c)\n", i, name,
286                                    (len & 0x40) ? 'R' : 0,
287                                    (len & 0x80) ? 'W' : 0);
288         m_free(name);
289     }
290 }
291 #endif
292
293 void
294 not_implemented(const char *feature)
295 {
296     log_info("%s is not implemented in the RISC OS version!\n", feature);
297 }
298
299 #endif /* !__RISCOS__C__ */