tidied RISC OS filetype support
[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 #include <unixlib/swiparams.h>
40 #undef __UNIXLIB_INTERNALS
41
42
43 /* RISC OS file open descriptor control list */
44
45 struct fds_item {
46     int fd;
47     struct fds_item *next;
48 };
49 static struct fds_item *fds_list = NULL;
50 static int initialized = 0;
51
52
53 /* local RISC OS functions */
54
55 static int
56 is_read_only(const char *filename)
57 {
58     int type, attr;
59     
60     if (_swix(OS_File, _INR(0,1) | _OUT(0) | _OUT(5),
61               17, filename, &type, &attr))
62         log_fatal("Can't get file attributes for %s!\n", filename);
63     
64     if (type == 0)
65         log_fatal("Can't find file %s!\n", filename);
66
67     if (_swix(OS_File, _INR(0,1) | _IN(5), 4, filename, attr))
68         return 1;
69
70     return 0;
71 }
72
73 /* exported RISC OS functions */
74
75 void
76 riscos_global_defaults(void)
77 {
78     __riscosify_control = __RISCOSIFY_NO_PROCESS;
79     __feature_imagefs_is_file = 1;
80 }
81
82 int
83 riscos_get_filetype_from_string(const char *string, int len)
84 {
85     int result = 0xfff;
86
87     if (strlen(string) < 5 || string[len - 4] != ',')
88         return -1;
89
90     sscanf(string+len-3, "%3x", &result);
91
92     return result;
93 }
94
95 int
96 riscos_get_filetype(const char *filename)
97 {
98     int result;
99
100     if (_swix(OS_File, _INR(0,1) | _OUT(6), 23, filename, &result))
101         log_fatal("Can't get filetype for file %s!\n", filename);
102
103     return result;
104 }        
105
106 void
107 riscos_set_filetype_by_number(const char *filename, int type)
108 {
109     if (_swix(OS_File, _INR(0,2), 18, filename, type))
110         log_fatal("Can't set filetype for file %s!\n"
111                   "Is the file on a read-only file system?\n", filename);
112 }        
113
114 void
115 riscos_set_filetype(const char *filename, const char *mimetype)
116 {
117     int result;
118
119     if (_swix(MimeMap_Translate, _INR(0,2) | _OUT(3),
120               MMM_TYPE_MIME, mimetype, MMM_TYPE_RISCOS, &result))
121         log_fatal("Can't translate MIME type %s!\n", mimetype);
122
123     riscos_set_filetype_by_number(filename, result);
124 }        
125
126 pid_t
127 riscos_getpid(void)
128 {
129     int state;
130
131     if (_swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 3, &state))
132         log_fatal("Wimp_ReadSysInfo failed: Can't get WimpState (R0=3)!\n");
133
134     if (state)
135         if (_swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 5, &state))
136             log_fatal("Wimp_ReadSysInfo failed: Can't get task handle (R0=5)!\n");
137
138     return (pid_t) state;
139 }
140
141 int
142 riscos_kill(pid_t pid, int sig)
143 {
144     int buf[4], iter = 0;
145
146     if (sig)
147         kill(pid, sig);
148
149     do {
150         if (_swix(TaskManager_EnumerateTasks, _INR(0,2) | _OUT(0),
151                   iter, buf, 16, &iter))
152             log_fatal("TaskManager_EnumerateTasks failed!\n");
153         if (buf[0] == pid)
154             return 0;
155     } while (iter >= 0);
156
157     return __set_errno(ESRCH);
158 }
159
160 int
161 riscos_access(const char *path, int amode)
162 {
163     /* Do additional check, i.e. whether path is on write-protected floppy */
164     if ((amode & W_OK) && is_read_only(path))
165         return 1;
166     return access(path, amode);
167 }
168
169 int
170 riscos_getchar(void)
171 {
172     int c, flags;
173
174     if (_swix(OS_ReadC, _OUT(0) | _OUT(_FLAGS), &c, &flags))
175         log_fatal("OS_ReadC failed: Couldn't read from keyboard!\n");
176     if (flags & _C)
177         log_fatal("OS_ReadC failed: Return Code = %i!\n", c);
178
179     return c;
180 }
181
182 #ifdef DEBUG
183 void
184 dump_fdlist(void)
185 {
186     struct fds_item *iter = fds_list;
187     printf("List of open file descriptors:\n");
188     while (iter) {
189         printf("  %i\n", iter->fd);
190         iter = iter->next;
191     }
192 }
193 #endif /* DEBUG */
194
195 int
196 fdopenfile(const char *filename, const int allow_write)
197 {
198     struct fds_item *h;
199     int fd;
200     if (allow_write)
201         fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
202     else
203         fd = open(filename, O_RDONLY);
204     if (fd == -1)
205         log_error("Can't open file %s: %i, %s!\n", filename, errno, strerror(errno));
206
207     if (!initialized) {
208         atexit (close_fds);
209         initialized = 1;
210     }
211
212     h = fds_list;
213     fds_list = (struct fds_item *) m_alloc(sizeof(struct fds_item));
214     if (!fds_list)
215         log_fatal("Can't claim memory for fdopenfile() buffer!\n");
216     fds_list->fd = fd;
217     fds_list->next = h;
218
219     return fd;
220 }
221
222 void
223 close_fds(void)
224 {
225     FILE *fp;
226     struct fds_item *h = fds_list;
227     while( fds_list ) {
228         h = fds_list->next;
229         fp = fdopen (fds_list->fd, "a");
230         if (fp)
231             fflush(fp);
232         close(fds_list->fd);
233         m_free(fds_list);
234         fds_list = h;
235     }
236 }
237
238 int
239 renamefile(const char *old, const char *new)
240 {
241     _kernel_oserror *e;
242
243     if (e = _swix(OS_FSControl, _INR(0,2), 25, old, new)) {
244         if (e->errnum == 214)
245             return __set_errno(ENOENT);
246         if (e->errnum == 176)
247             return __set_errno(EEXIST);
248         printf("Error during renaming: %i, %s!\n", e->errnum, e->errmess);
249         return __set_errno(EOPSYS);
250     }
251     return 0;
252 }
253
254 char *
255 gstrans(const char *old)
256 {
257     int size = 256, last;
258     char *buf, *tmp;
259
260     buf = (char *) m_alloc(size);
261     if (!buf)
262         log_fatal("Can't claim memory for OS_GSTrans buffer!\n");
263     while (_C & _swi(OS_GSTrans, _INR(0,2) | _OUT(2) | _RETURN(_FLAGS),
264                      old, buf, size, &last)) {
265         size += 256;
266         tmp = (char *) m_realloc(buf, size);
267         if (!tmp)
268              log_fatal("Can't claim memory for OS_GSTrans buffer!\n");
269         buf = tmp;
270     }
271
272     buf[last] = '\0';
273     tmp = (char *) m_realloc(buf, last + 1);
274     if (!tmp)
275         log_fatal("Can't realloc memory after OS_GSTrans!\n");
276
277     return tmp;
278 }
279
280 /***************
281  * Extract from a given path the filename component.
282  * (cloned from util/fileutil.c and then heavily modified)
283  */
284 char *
285 riscos_make_basename(const char *filepath, const char *realfname)
286 {
287     char *p = (char*)filepath-1, *result;
288     int i, filetype;
289
290     if ( !(p=strrchr(filepath, DIRSEP_C)) )
291         if ( !(p=strrchr(filepath, ':')) )
292             ;
293
294     i = strlen(p+1);
295     result = m_alloc(i + 5);
296     if (!result)
297         log_fatal("Can't claim memory for riscos_make_basename() buffer!\n");
298     strcpy(result, p+1);
299     
300     filetype = riscos_get_filetype( realfname );
301     result[i++] = ',';
302     result[i++] = "0123456789abcdef"[(filetype >> 8) & 0xf];
303     result[i++] = "0123456789abcdef"[(filetype >> 4) & 0xf];
304     result[i++] = "0123456789abcdef"[(filetype >> 0) & 0xf];
305     result[i]   = 0;
306
307     for(i=0; i<strlen(result); ++i)
308         if(result[i] == '/')
309             result[i] = '.';
310
311     return result;
312 }
313
314 #ifdef DEBUG
315 void
316 list_openfiles(void)
317 {
318     char *name;
319     int i, len;
320     
321     for (i = 255; i >= 0; --i) {
322         if (_swix(OS_Args, _INR(0,2) | _IN(5) | _OUT(5), 7, i, 0, 0, &len))
323             continue;
324
325         name = (char *) m_alloc(1-len);
326         if (!name)
327             log_fatal("Can't claim memory for OS_Args buffer!\n");
328
329         if (_swix(OS_Args, _INR(0,2) | _IN(5), 7, i, name, 1-len)) {
330             m_free(name);
331             log_fatal("Error when calling OS_Args(7)!\n");
332         }
333         
334         if (_swix(OS_Args, _INR(0,1) | _OUT(0), 254, i, &len)) {
335             m_free(name);
336             log_fatal("Error when calling OS_Args(254)!\n");
337         }
338         
339         printf("%3i: %s (%c%c)\n", i, name,
340                                    (len & 0x40) ? 'R' : 0,
341                                    (len & 0x80) ? 'W' : 0);
342         m_free(name);
343     }
344 }
345 #endif
346
347 void
348 not_implemented(const char *feature)
349 {
350     log_info("%s is not implemented in the RISC OS version!\n", feature);
351 }
352
353 #endif /* !__RISCOS__C__ */