xref: /openbsd-src/gnu/usr.bin/binutils/gdb/rdi-share/hsys.c (revision 63addd46c1e40ca0f49488ddcdc4ab598023b0c1)
1b725ae77Skettenis /*
2b725ae77Skettenis  * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
3b725ae77Skettenis  *
4b725ae77Skettenis  * This software may be freely used, copied, modified, and distributed
5b725ae77Skettenis  * provided that the above copyright notice is preserved in all copies of the
6b725ae77Skettenis  * software.
7b725ae77Skettenis  */
8b725ae77Skettenis 
9b725ae77Skettenis /*
10b725ae77Skettenis  * Host C Library support functions.
11b725ae77Skettenis  *
12*63addd46Skettenis  * $Revision: 1.3 $
13*63addd46Skettenis  *     $Date: 2004/12/27 14:00:54 $
14b725ae77Skettenis  */
15b725ae77Skettenis 
16b725ae77Skettenis #ifdef DEBUG
17b725ae77Skettenis #  include <ctype.h>
18b725ae77Skettenis #endif
19b725ae77Skettenis 
20b725ae77Skettenis #include <stdio.h>
21b725ae77Skettenis #include <stdlib.h>
22b725ae77Skettenis #include <string.h>
23b725ae77Skettenis #include <stdarg.h>
24b725ae77Skettenis #include <errno.h>
25b725ae77Skettenis #include <time.h>
26b725ae77Skettenis 
27b725ae77Skettenis #include "adp.h"
28b725ae77Skettenis #include "host.h"
29b725ae77Skettenis #include "ardi.h"
30b725ae77Skettenis #include "buffers.h"
31b725ae77Skettenis #include "channels.h"        /* Channel interface. */
32b725ae77Skettenis #include "angel_endian.h"
33b725ae77Skettenis #include "logging.h"         /* Angel support functions. */
34b725ae77Skettenis #include "msgbuild.h"
35b725ae77Skettenis #include "sys.h"
36b725ae77Skettenis #include "hsys.h"      /* Function and structure declarations. */
37b725ae77Skettenis #include "hostchan.h"
38b725ae77Skettenis 
39b725ae77Skettenis #define FILEHANDLE int
40b725ae77Skettenis 
41b725ae77Skettenis /* Note: no statics allowed.  All globals must be malloc()ed on the heap.
42b725ae77Skettenis    The state struct is used for this purpose.  See 'hsys.h'.                */
43b725ae77Skettenis /* This is the message handler function passed to the channel manager in
44b725ae77Skettenis    HostSysInit.  It is called whenever a message is received. 'buffptr'
45b725ae77Skettenis    points to the message body.  Functionality is provided by the debugger
46b725ae77Skettenis    toolkit.  The routine is very loosely based on the HandleSWI routine from
47b725ae77Skettenis    armos.c in the armulator source.                                         */
48b725ae77Skettenis /* These routines could be tested by providing a simple interface to armsd,
49b725ae77Skettenis    and running them in that.   */
50b725ae77Skettenis 
51b725ae77Skettenis 
52b725ae77Skettenis /* taken staight from armulator source */
53b725ae77Skettenis #ifdef __riscos
54b725ae77Skettenis   extern int _fisatty(FILE *);
55b725ae77Skettenis # define isatty_(f) _fisatty(f)
56b725ae77Skettenis # define EMFILE -1
57b725ae77Skettenis # define EBADF -1
_kernel_escape_seen(void)58b725ae77Skettenis   int _kernel_escape_seen(void) { return 0 ;}
59b725ae77Skettenis #else
60b725ae77Skettenis # if defined(_WINDOWS) || defined(_CONSOLE)
61b725ae77Skettenis #   define isatty_(f) (f == stdin || f == stdout)
62b725ae77Skettenis # else
63b725ae77Skettenis #   ifdef __ZTC__
64b725ae77Skettenis #     include <io.h>
65b725ae77Skettenis #     define isatty_(f) isatty((f)->_file)
66b725ae77Skettenis #   else
67b725ae77Skettenis #     ifdef macintosh
68b725ae77Skettenis #       include <ioctl.h>
69b725ae77Skettenis #       define isatty_(f) (~ioctl((f)->_file,FIOINTERACTIVE,NULL))
70b725ae77Skettenis #     else
71b725ae77Skettenis #       define isatty_(f) isatty(fileno(f))
72b725ae77Skettenis #     endif
73b725ae77Skettenis #   endif
74b725ae77Skettenis # endif
75b725ae77Skettenis #endif
76b725ae77Skettenis 
77b725ae77Skettenis /* Set up the state block, filetable and register the C lib callback fn */
HostSysInit(const struct Dbg_HostosInterface * hostif,char ** cmdline,hsys_state ** stateptr)78b725ae77Skettenis int HostSysInit(const struct Dbg_HostosInterface *hostif, char **cmdline,
79b725ae77Skettenis                 hsys_state **stateptr)
80b725ae77Skettenis {
81b725ae77Skettenis   ChannelCallback HandleMessageFPtr = (ChannelCallback) HandleSysMessage;
82b725ae77Skettenis   int i;
83b725ae77Skettenis   *stateptr = (hsys_state *)malloc(sizeof(hsys_state));
84b725ae77Skettenis 
85b725ae77Skettenis   if (*stateptr == NULL) return RDIError_OutOfStore;
86b725ae77Skettenis 
87b725ae77Skettenis   (*stateptr)->hostif=hostif;
88b725ae77Skettenis   (*stateptr)->last_errno=0;
89b725ae77Skettenis   (*stateptr)->OSptr=(OSblock *)malloc(sizeof(OSblock));
90b725ae77Skettenis   if ((*stateptr)->OSptr == NULL) return RDIError_OutOfStore;
91b725ae77Skettenis   for (i=0; i<UNIQUETEMPS; i++) (*stateptr)->OSptr->TempNames[i]=NULL;
92b725ae77Skettenis   for (i=0; i<HSYS_FOPEN_MAX; i++) {
93b725ae77Skettenis        (*stateptr)->OSptr->FileTable[i]=NULL;
94b725ae77Skettenis        (*stateptr)->OSptr->FileFlags[i]=0;
95b725ae77Skettenis   }
96b725ae77Skettenis   (*stateptr)->CommandLine=cmdline;
97b725ae77Skettenis 
98b725ae77Skettenis   return Adp_ChannelRegisterRead(CI_CLIB, (ChannelCallback)HandleMessageFPtr,
99b725ae77Skettenis                                  *stateptr);
100b725ae77Skettenis }
101b725ae77Skettenis 
102b725ae77Skettenis /* Shut down the Clib support, this will probably never get called though */
HostSysExit(hsys_state * stateptr)103b725ae77Skettenis int HostSysExit(hsys_state *stateptr)
104b725ae77Skettenis {
105b725ae77Skettenis   free(stateptr->OSptr);
106b725ae77Skettenis   free(stateptr);
107b725ae77Skettenis   return RDIError_NoError;
108b725ae77Skettenis }
109b725ae77Skettenis 
110b725ae77Skettenis #ifdef DEBUG
DebugCheckNullTermString(char * prefix,bool nl,unsigned int len,unsigned char * strp)111b725ae77Skettenis static void DebugCheckNullTermString(char *prefix, bool nl,
112b725ae77Skettenis                                      unsigned int len, unsigned char *strp)
113b725ae77Skettenis {
114b725ae77Skettenis     printf("%s: %d: ", prefix, len);
115b725ae77Skettenis     if (strp[len]=='\0')
116b725ae77Skettenis        printf("\"%s\"", strp);
117b725ae77Skettenis     else
118b725ae77Skettenis        printf("NOT NULL TERMINATED");
119b725ae77Skettenis     if (nl)
120b725ae77Skettenis        printf("\n");
121b725ae77Skettenis     else
122b725ae77Skettenis     {
123b725ae77Skettenis         printf(" ");
124b725ae77Skettenis         fflush(stdout);
125b725ae77Skettenis     }
126b725ae77Skettenis }
127b725ae77Skettenis 
128b725ae77Skettenis #ifdef NEED_SYSERRLIST
129b725ae77Skettenis extern int sys_nerr;
130b725ae77Skettenis extern char *sys_errlist[];
131b725ae77Skettenis #endif
132b725ae77Skettenis 
DebugStrError(int last_errno)133b725ae77Skettenis static char *DebugStrError(int last_errno)
134b725ae77Skettenis {
135b725ae77Skettenis     if (last_errno < sys_nerr)
136b725ae77Skettenis        return sys_errlist[last_errno];
137b725ae77Skettenis     else
138b725ae77Skettenis        return "NO MSG (errno>sys_nerr)";
139b725ae77Skettenis }
140b725ae77Skettenis 
DebugCheckErr(char * prefix,bool nl,int err,int last_errno)141b725ae77Skettenis static void DebugCheckErr(char *prefix, bool nl, int err, int last_errno)
142b725ae77Skettenis {
143b725ae77Skettenis     printf("\t%s: returned ", prefix);
144b725ae77Skettenis     if (err == 0)
145b725ae77Skettenis        printf("okay");
146b725ae77Skettenis     else
147b725ae77Skettenis        printf("%d, errno = %d \"%s\"", err, last_errno,
148b725ae77Skettenis               DebugStrError(last_errno));
149b725ae77Skettenis     if (nl)
150b725ae77Skettenis        printf("\n");
151b725ae77Skettenis     else
152b725ae77Skettenis     {
153b725ae77Skettenis         printf(" ");
154b725ae77Skettenis         fflush(stdout);
155b725ae77Skettenis     }
156b725ae77Skettenis }
157b725ae77Skettenis 
DebugCheckNonNull(char * prefix,bool nl,void * handle,int last_errno)158b725ae77Skettenis static void DebugCheckNonNull(char *prefix, bool nl,
159b725ae77Skettenis                               void *handle, int last_errno)
160b725ae77Skettenis {
161b725ae77Skettenis     printf("\t%s: returned ", prefix);
162b725ae77Skettenis     if (handle != NULL)
163b725ae77Skettenis        printf("okay [%08x]", (unsigned int)handle);
164b725ae77Skettenis     else
165b725ae77Skettenis        printf("NULL, errno = %d \"%s\"", last_errno,
166b725ae77Skettenis               DebugStrError(last_errno));
167b725ae77Skettenis     if (nl)
168b725ae77Skettenis        printf("\n");
169b725ae77Skettenis     else
170b725ae77Skettenis     {
171b725ae77Skettenis         printf(" ");
172b725ae77Skettenis         fflush(stdout);
173b725ae77Skettenis     }
174b725ae77Skettenis }
175b725ae77Skettenis 
176b725ae77Skettenis #define DebugPrintF(c) printf c;
177b725ae77Skettenis 
178b725ae77Skettenis #else
179b725ae77Skettenis 
180b725ae77Skettenis #define DebugCheckNullTermString(p, n, l, s)    ((void)(0))
181b725ae77Skettenis #define DebugCheckErr(p, n, e, l)               ((void)(0))
182b725ae77Skettenis #define DebugCheckNonNull(p, n, h, l)           ((void)(0))
183b725ae77Skettenis #define DebugPrintF(c)                          ((void)(0))
184b725ae77Skettenis 
185b725ae77Skettenis #endif /* ifdef DEBUG ... else */
186b725ae77Skettenis 
hsysGetRealFileHandle(hsys_state * stateptr,int fh,char * flags)187b725ae77Skettenis static FILE *hsysGetRealFileHandle(hsys_state *stateptr, int fh, char *flags)
188b725ae77Skettenis {
189b725ae77Skettenis     FILE *file_p = NULL;
190b725ae77Skettenis 
191b725ae77Skettenis     if (fh < 0 || fh >= HSYS_FOPEN_MAX)
192b725ae77Skettenis     {
193b725ae77Skettenis         stateptr->last_errno = EBADF;
194b725ae77Skettenis         DebugPrintF(("\tfh %d out-of-bounds!\n", fh));
195b725ae77Skettenis         return NULL;
196b725ae77Skettenis     }
197b725ae77Skettenis     else
198b725ae77Skettenis     {
199b725ae77Skettenis         file_p = stateptr->OSptr->FileTable[fh];
200b725ae77Skettenis         if (file_p != NULL) {
201b725ae77Skettenis             if (flags != NULL)
202b725ae77Skettenis                *flags = stateptr->OSptr->FileFlags[fh];
203b725ae77Skettenis         }
204b725ae77Skettenis         else {
205b725ae77Skettenis           stateptr->last_errno = EBADF;
206b725ae77Skettenis           DebugPrintF(("\tFileTable[%d] is NULL\n", fh));
207b725ae77Skettenis         }
208b725ae77Skettenis 
209b725ae77Skettenis         return file_p;
210b725ae77Skettenis     }
211b725ae77Skettenis }
212b725ae77Skettenis 
HandleSysMessage(Packet * packet,hsys_state * stateptr)213b725ae77Skettenis int HandleSysMessage(Packet *packet, hsys_state *stateptr)
214b725ae77Skettenis {
215b725ae77Skettenis   unsigned int reason_code, mode, len, c, nbytes, nbtotal, nbtogo = 0;
216b725ae77Skettenis   long posn, fl;
217b725ae77Skettenis   char character;
218b725ae77Skettenis   int err;
219b725ae77Skettenis 
220b725ae77Skettenis   /* Note: We must not free the buffer passed in as the callback handler */
221b725ae77Skettenis   /* expects to do this.  Freeing any other buffers we have malloced */
222b725ae77Skettenis   /* ourselves is acceptable */
223b725ae77Skettenis 
224b725ae77Skettenis   unsigned char *buffp = ((unsigned char *)BUFFERDATA(packet->pk_buffer))+16;
225b725ae77Skettenis                                           /* buffp points to the parameters*/
226b725ae77Skettenis                                           /* the invidual messages, excluding*/
227b725ae77Skettenis                                           /* standard SYS fields (debugID, */
228b725ae77Skettenis                                           /* osinfo and reasoncode) */
229b725ae77Skettenis   unsigned char *buffhead = (unsigned char *)(packet->pk_buffer);
230b725ae77Skettenis 
231b725ae77Skettenis   int DebugID, OSInfo1, OSInfo2, count;
232b725ae77Skettenis 
233b725ae77Skettenis   const char* fmode[] = {"r","rb","r+","r+b",
234b725ae77Skettenis                                "w","wb","w+","w+b",
235b725ae77Skettenis                                "a","ab","a+","a+b",
236b725ae77Skettenis                                "r","r","r","r"} /* last 4 are illegal */ ;
237b725ae77Skettenis 
238b725ae77Skettenis   FILEHANDLE fh;  /* fh is used as an index to the real file handle
239b725ae77Skettenis                          * in OSptr */
240b725ae77Skettenis   FILE *fhreal;
241b725ae77Skettenis   unpack_message(BUFFERDATA(buffhead), "%w%w%w%w", &reason_code,
242b725ae77Skettenis                  &DebugID, &OSInfo1, &OSInfo2);
243b725ae77Skettenis                                         /* Extract reason code from buffer. */
244b725ae77Skettenis   reason_code &= 0xFFFF;        /* Strip away direction bit, OSInfo and     */
245b725ae77Skettenis                                 /* DebugInfo fields.  Will want to do some  */
246b725ae77Skettenis                                 /* sort of validation on this later.        */
247b725ae77Skettenis 
248b725ae77Skettenis   switch(reason_code)
249b725ae77Skettenis   {
250b725ae77Skettenis 
251b725ae77Skettenis   case CL_WriteC:   /* Write a character to the terminal. */
252b725ae77Skettenis                     /* byte data -> word status           */
253b725ae77Skettenis     {
254b725ae77Skettenis #ifdef DEBUG
255b725ae77Skettenis       int c = (int)(*buffp);
256b725ae77Skettenis       printf("CL_WriteC: [%02x]>%c<", c, isprint(c) ? c : '.');
257b725ae77Skettenis #endif
258b725ae77Skettenis       stateptr->hostif->writec(stateptr->hostif->hostosarg, (int)(*buffp));
259b725ae77Skettenis       DevSW_FreePacket(packet);
260b725ae77Skettenis       return msgsend(CI_CLIB,"%w%w%w%w%w", CL_WriteC|HtoT,
261b725ae77Skettenis                     DebugID, OSInfo1, OSInfo2, NoError);
262b725ae77Skettenis     }
263b725ae77Skettenis 
264b725ae77Skettenis   case CL_Write0:  /* Write a null terminated string to the terminal. */
265b725ae77Skettenis     {
266b725ae77Skettenis       unpack_message(buffp, "%w", &len);
267b725ae77Skettenis       DebugCheckNullTermString("CL_Write0", TRUE, len, buffp+4);
268b725ae77Skettenis       stateptr->hostif->write(stateptr->hostif->hostosarg,
269b725ae77Skettenis                               (char *) buffp+4, len);
270b725ae77Skettenis       DevSW_FreePacket(packet);
271b725ae77Skettenis       return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Write0|HtoT, DebugID,
272b725ae77Skettenis                     OSInfo1, OSInfo2, NoError);
273b725ae77Skettenis     }
274b725ae77Skettenis 
275b725ae77Skettenis   case CL_ReadC:   /* Read a byte from the terminal */
276b725ae77Skettenis     {
277b725ae77Skettenis       DebugPrintF(("CL_ReadC: "));
278b725ae77Skettenis       DevSW_FreePacket(packet);
279b725ae77Skettenis 
280b725ae77Skettenis       character = stateptr->hostif->readc(stateptr->hostif->hostosarg);
281b725ae77Skettenis       DebugPrintF(("\nCL_ReadC returning [%02x]>%c<\n", character,
282b725ae77Skettenis                    isprint(character) ? character : '.'));
283b725ae77Skettenis 
284b725ae77Skettenis       return msgsend(CI_CLIB, "%w%w%w%w%w%b", CL_ReadC|HtoT,
285b725ae77Skettenis                     DebugID, OSInfo1, OSInfo2, NoError, character);
286b725ae77Skettenis     }
287b725ae77Skettenis 
288b725ae77Skettenis   case CL_System:  /* Pass NULL terminated string to the hosts command
289b725ae77Skettenis                     * interpreter. As it is nULL terminated we dont need
290b725ae77Skettenis                     * the length
291b725ae77Skettenis                     */
292b725ae77Skettenis     {
293b725ae77Skettenis       unpack_message(buffp, "%w", &len);
294b725ae77Skettenis       DebugCheckNullTermString("CL_System", TRUE, len, buffp+4);
295b725ae77Skettenis 
296b725ae77Skettenis       err = system((char *)buffp+4); /* Use the string in the buffer */
297b725ae77Skettenis       stateptr->last_errno = errno;
298b725ae77Skettenis       DebugCheckErr("system", TRUE, err, stateptr->last_errno);
299b725ae77Skettenis 
300b725ae77Skettenis       err = msgsend(CI_CLIB, "%w%w%w%w%w%w", CL_System|HtoT,
301b725ae77Skettenis                     DebugID, OSInfo1, OSInfo2, NoError, err);
302b725ae77Skettenis       DevSW_FreePacket(packet);
303b725ae77Skettenis       return err;
304b725ae77Skettenis     }
305b725ae77Skettenis 
306b725ae77Skettenis   case CL_GetCmdLine:  /* Returns the command line used to call the program */
307b725ae77Skettenis     {
308b725ae77Skettenis       /* Note: we reuse the packet here, this may not always be desirable */
309b725ae77Skettenis       /* /* TODO: Use long buffers if possible */
310b725ae77Skettenis       DebugPrintF(("CL_GetCmdLine: \"%s\"\n", *(stateptr->CommandLine)));
311b725ae77Skettenis 
312b725ae77Skettenis       if (buffhead!=NULL) {
313b725ae77Skettenis         len = strlen(*(stateptr->CommandLine));
314b725ae77Skettenis         if (len > Armsd_BufferSize-24) len = Armsd_BufferSize-24;
315b725ae77Skettenis         packet->pk_length = len + msgbuild(BUFFERDATA(buffhead),
316b725ae77Skettenis                                            "%w%w%w%w%w%w", CL_GetCmdLine|HtoT,
317b725ae77Skettenis                                            DebugID, OSInfo1, OSInfo2,
318b725ae77Skettenis                                            NoError, len);
319b725ae77Skettenis         strncpy((char *) BUFFERDATA(buffhead)+24,*(stateptr->CommandLine),
320b725ae77Skettenis                 len);
321b725ae77Skettenis 
322b725ae77Skettenis         Adp_ChannelWrite(CI_CLIB, packet);/* Send message. */
323b725ae77Skettenis         return 0;
324b725ae77Skettenis       }
325b725ae77Skettenis       else return -1;
326b725ae77Skettenis     }
327b725ae77Skettenis 
328b725ae77Skettenis   case CL_Clock:   /* Return the number of centiseconds since the support */
329b725ae77Skettenis                    /* code started executing */
330b725ae77Skettenis     {
331b725ae77Skettenis       time_t retTime = time(NULL);
332b725ae77Skettenis       if (retTime == (time_t)-1)
333b725ae77Skettenis              stateptr->last_errno = errno;
334b725ae77Skettenis       else
335b725ae77Skettenis              retTime *=100;
336b725ae77Skettenis 
337b725ae77Skettenis       DebugPrintF(("CL_Clock: %lu\n", retTime));
338b725ae77Skettenis       DebugCheckErr("time", TRUE, (retTime == (time_t)-1),
339b725ae77Skettenis                     stateptr->last_errno);
340b725ae77Skettenis 
341b725ae77Skettenis       DevSW_FreePacket(packet);
342b725ae77Skettenis       return msgsend(CI_CLIB, "%w%w%w%w%w%w",CL_Clock|HtoT,
343b725ae77Skettenis                          DebugID, OSInfo1, OSInfo2, NoError, retTime);
344b725ae77Skettenis     }
345b725ae77Skettenis 
346b725ae77Skettenis   case CL_Time:    /* return time, in seconds since the start of 1970 */
347b725ae77Skettenis     {
348b725ae77Skettenis       time_t retTime = time(NULL);
349b725ae77Skettenis       if (retTime == (time_t)-1)
350b725ae77Skettenis               stateptr->last_errno = errno;
351b725ae77Skettenis 
352b725ae77Skettenis       DebugPrintF(("CL_Time: %lu\n", retTime));
353b725ae77Skettenis       DebugCheckErr("time", TRUE, (retTime == (time_t)-1),
354b725ae77Skettenis                     stateptr->last_errno);
355b725ae77Skettenis 
356b725ae77Skettenis       DevSW_FreePacket(packet);
357b725ae77Skettenis       return msgsend(CI_CLIB,"%w%w%w%w%w%w",CL_Time|HtoT,
358b725ae77Skettenis                          DebugID, OSInfo1, OSInfo2, NoError, retTime);
359b725ae77Skettenis     }
360b725ae77Skettenis 
361b725ae77Skettenis   case CL_Remove:  /* delete named in the null terminated string */
362b725ae77Skettenis     {
363b725ae77Skettenis       /* Removing an open file will cause problems but once again
364b725ae77Skettenis        * its not our problem, likely result is a tangled FileTable */
365b725ae77Skettenis       /* As the filename is passed with a null terminator we can use it
366b725ae77Skettenis        * straight out of the buffer without copying it.*/
367b725ae77Skettenis 
368b725ae77Skettenis       unpack_message(buffp, "%w", &len);
369b725ae77Skettenis       DebugCheckNullTermString("CL_Remove", TRUE, len, buffp+4);
370b725ae77Skettenis 
371b725ae77Skettenis       err=remove((char *)buffp+4);
372b725ae77Skettenis       stateptr->last_errno = errno;
373b725ae77Skettenis       DevSW_FreePacket(packet);
374b725ae77Skettenis       DebugCheckErr("remove", TRUE, err, stateptr->last_errno);
375b725ae77Skettenis 
376b725ae77Skettenis       return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Remove|HtoT,
377b725ae77Skettenis                      DebugID, OSInfo1, OSInfo2, err?-1:NoError);
378b725ae77Skettenis     }
379b725ae77Skettenis 
380b725ae77Skettenis   case CL_Rename:  /* rename file */
381b725ae77Skettenis     {
382b725ae77Skettenis       /* Rename(word nbytes, bytes oname, word nbytes, bytes nname)
383b725ae77Skettenis       * return(byte status)
384b725ae77Skettenis       */
385b725ae77Skettenis       unsigned int len2;
386b725ae77Skettenis 
387b725ae77Skettenis       unpack_message(buffp, "%w", &len);
388b725ae77Skettenis       DebugCheckNullTermString("CL_Rename", FALSE, len, buffp+4);
389b725ae77Skettenis       unpack_message(buffp+5+len, "%w", &len2);
390b725ae77Skettenis       DebugCheckNullTermString("to", TRUE, len2, buffp+9+len);
391b725ae77Skettenis 
392b725ae77Skettenis       /* Both names are passed with null terminators so we can use them
393b725ae77Skettenis        * directly from the buffer. */
394b725ae77Skettenis       err = rename((char *)buffp+4, (char *)buffp+9+len);
395b725ae77Skettenis       stateptr->last_errno = errno;
396b725ae77Skettenis       DebugCheckErr("rename", TRUE, err, stateptr->last_errno);
397b725ae77Skettenis       DevSW_FreePacket(packet);
398b725ae77Skettenis 
399b725ae77Skettenis       return msgsend(CI_CLIB, "%w%w%w%w%w",  CL_Rename|HtoT,
400b725ae77Skettenis                      DebugID, OSInfo1, OSInfo2, (err==0)? NoError : -1);
401b725ae77Skettenis     }
402b725ae77Skettenis 
403b725ae77Skettenis   case CL_Open:    /* open the file */
404b725ae77Skettenis     {
405b725ae77Skettenis       /* Open(word nbytes, bytes name, byte mode)
406b725ae77Skettenis       * return(word handle)
407b725ae77Skettenis       */
408b725ae77Skettenis       unpack_message(buffp, "%w", &len);
409b725ae77Skettenis       /* get the open mode */
410b725ae77Skettenis       unpack_message((buffp)+4+len+1, "%w", &mode);
411b725ae77Skettenis       DebugCheckNullTermString("CL_Open", FALSE, len, buffp+4);
412b725ae77Skettenis       DebugPrintF(("mode: %d\n", mode));
413b725ae77Skettenis 
414b725ae77Skettenis       /* do some checking on the file first? */
415b725ae77Skettenis       /* check if its a tty */
416b725ae77Skettenis       if (strcmp((char *)buffp+4, ":tt")==0 && (mode==0||mode==1)) {
417b725ae77Skettenis         /* opening tty "r" */
418b725ae77Skettenis         fhreal = stdin;
419b725ae77Skettenis         stateptr->last_errno = errno;
420b725ae77Skettenis         DebugPrintF(("\tstdin "));
421b725ae77Skettenis       }
422b725ae77Skettenis       else if (strcmp((char *)buffp+4, ":tt")== 0 && (mode==4||mode==5)) {
423b725ae77Skettenis         /* opening tty "w" */
424b725ae77Skettenis         fhreal = stdout;
425b725ae77Skettenis         stateptr->last_errno = errno;
426b725ae77Skettenis         DebugPrintF(("\tstdout "));
427b725ae77Skettenis       }
428b725ae77Skettenis       else
429b725ae77Skettenis       {
430b725ae77Skettenis         fhreal = fopen((char *)buffp+4, fmode[mode&0xFF]);
431b725ae77Skettenis         stateptr->last_errno = errno;
432b725ae77Skettenis         DebugCheckNonNull("fopen", FALSE, fhreal, stateptr->last_errno);
433b725ae77Skettenis       }
434b725ae77Skettenis       DevSW_FreePacket(packet);
435b725ae77Skettenis 
436b725ae77Skettenis       c = NONHANDLE;
437b725ae77Skettenis       if (fhreal != NULL) {
438b725ae77Skettenis         /* update filetable */
439b725ae77Skettenis         for (c=3; c < HSYS_FOPEN_MAX; c++) {
440b725ae77Skettenis           /* allow for stdin, stdout, stderr (!!! WHY? MJG) */
441b725ae77Skettenis           if (stateptr->OSptr->FileTable[c] == NULL) {
442b725ae77Skettenis             stateptr->OSptr->FileTable[c]= fhreal;
443b725ae77Skettenis             stateptr->OSptr->FileFlags[c]= mode & 1;
444b725ae77Skettenis             DebugPrintF(("fh: %d\n", c));
445b725ae77Skettenis             break;
446b725ae77Skettenis           }
447b725ae77Skettenis           else if (c == HSYS_FOPEN_MAX) {
448b725ae77Skettenis           /* no filehandles free */
449b725ae77Skettenis           DebugPrintF(("no free fh: %d\n", c));
450b725ae77Skettenis           stateptr->last_errno = EMFILE;
451b725ae77Skettenis           }
452b725ae77Skettenis         }
453b725ae77Skettenis       }
454b725ae77Skettenis       else {
455b725ae77Skettenis         /*        c = NULL;*/
456b725ae77Skettenis         DebugPrintF(("error fh: %d\n", c));
457b725ae77Skettenis       }
458b725ae77Skettenis       (void) msgsend(CI_CLIB, "%w%w%w%w%w",  CL_Open|HtoT,
459b725ae77Skettenis                      DebugID, OSInfo1, OSInfo2, c);
460b725ae77Skettenis       return 0;
461b725ae77Skettenis     }
462b725ae77Skettenis 
463b725ae77Skettenis   case CL_Close:   /* close the file pointed to by the filehandle */
464b725ae77Skettenis     {
465b725ae77Skettenis       unpack_message(buffp, "%w", &fh);
466b725ae77Skettenis       DebugPrintF(("CL_Close: fh %d\n", fh));
467b725ae77Skettenis       DevSW_FreePacket(packet);
468b725ae77Skettenis 
469b725ae77Skettenis       fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
470b725ae77Skettenis       if (fhreal == NULL)
471b725ae77Skettenis          err = -1;
472b725ae77Skettenis       else {
473b725ae77Skettenis           if (fhreal == stdin || fhreal == stdout || fhreal == stderr) {
474b725ae77Skettenis               stateptr->last_errno = errno;
475b725ae77Skettenis               DebugPrintF(("\tskipping close of std*\n"));
476b725ae77Skettenis               err = 0;
477b725ae77Skettenis           }
478b725ae77Skettenis           else {
479b725ae77Skettenis               err = fclose(fhreal);
480b725ae77Skettenis               if (err == 0)
481b725ae77Skettenis                  stateptr->OSptr->FileTable[fh]=NULL;
482b725ae77Skettenis               stateptr->last_errno = errno;
483b725ae77Skettenis               DebugCheckErr("fclose", TRUE, err, stateptr->last_errno);
484b725ae77Skettenis           }
485b725ae77Skettenis       }
486b725ae77Skettenis       return msgsend(CI_CLIB,"%w%w%w%w%w",  CL_Close|HtoT, DebugID,
487b725ae77Skettenis                      OSInfo1, OSInfo2, err);
488b725ae77Skettenis     }
489b725ae77Skettenis 
490b725ae77Skettenis   case CL_Write:
491b725ae77Skettenis     {
492b725ae77Skettenis         /* Write(word handle, word nbtotal, word nbytes, bytes data)
493b725ae77Skettenis          * return(word nbytes)
494b725ae77Skettenis          * WriteX(word nbytes, bytes data)
495b725ae77Skettenis          * return(word nbytes)
496b725ae77Skettenis          */
497b725ae77Skettenis       unsigned char *rwdata = NULL, *rwhead = NULL;
498b725ae77Skettenis       unsigned char *write_source = NULL;
499b725ae77Skettenis       char flags;
500b725ae77Skettenis       FILE *fhreal;
501b725ae77Skettenis       unsigned int ack_reason = CL_Write; /* first ack is for CL_Write */
502b725ae77Skettenis 
503b725ae77Skettenis       err = -1;                 /* err == 0 is fwrite() error indication */
504b725ae77Skettenis       unpack_message(buffp, "%w%w%w", &fh, &nbtotal, &nbytes);
505b725ae77Skettenis       DebugPrintF(("CL_Write: fh %d nbtotal %u nbytes %u\n",
506b725ae77Skettenis                    fh, nbtotal, nbytes));
507b725ae77Skettenis 
508b725ae77Skettenis       fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
509b725ae77Skettenis       nbtogo = nbtotal;
510b725ae77Skettenis 
511b725ae77Skettenis       /* deal with the file handle */
512b725ae77Skettenis       if (fhreal == NULL)
513b725ae77Skettenis          err = 0;
514b725ae77Skettenis       else {
515b725ae77Skettenis         if (flags & READOP)
516b725ae77Skettenis            fseek(fhreal,0,SEEK_CUR);
517b725ae77Skettenis         stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;
518b725ae77Skettenis 
519b725ae77Skettenis         nbtogo -= nbytes;
520b725ae77Skettenis 
521b725ae77Skettenis         if (nbtogo > 0) {
522b725ae77Skettenis           write_source = rwdata = rwhead = (unsigned char *)malloc(nbtotal);
523b725ae77Skettenis           if (rwhead == NULL) {
524b725ae77Skettenis             fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
525b725ae77Skettenis                     __LINE__, __FILE__);
526b725ae77Skettenis             return -1;
527b725ae77Skettenis           }
528b725ae77Skettenis           memcpy(rwdata, buffp+12, nbytes);
529b725ae77Skettenis           rwdata += nbytes;
530b725ae77Skettenis         }
531b725ae77Skettenis         else
532b725ae77Skettenis            write_source = buffp+12;
533b725ae77Skettenis       }
534b725ae77Skettenis 
535b725ae77Skettenis       do {
536b725ae77Skettenis         /* at least once!! */
537b725ae77Skettenis 
538b725ae77Skettenis         if (nbtogo == 0 && err != 0) {
539b725ae77Skettenis           /* Do the actual write! */
540b725ae77Skettenis           if (fhreal == stdout || fhreal == stderr) {
541b725ae77Skettenis             stateptr->hostif->write(stateptr->hostif->hostosarg,
542b725ae77Skettenis                                     (char *)write_source, nbtotal);
543b725ae77Skettenis           }
544b725ae77Skettenis           else
545b725ae77Skettenis              err = fwrite(write_source, 1, nbtotal, fhreal);
546b725ae77Skettenis           stateptr->last_errno = errno;
547b725ae77Skettenis           DebugCheckErr("fwrite", TRUE, (err == 0), stateptr->last_errno);
548b725ae77Skettenis         }
549b725ae77Skettenis 
550b725ae77Skettenis         DevSW_FreePacket(packet);
551b725ae77Skettenis         if (msgsend(CI_CLIB,"%w%w%w%w%w%w", ack_reason|HtoT,
552b725ae77Skettenis                     DebugID, OSInfo1, OSInfo2, (err == 0), nbtogo))
553b725ae77Skettenis         {
554b725ae77Skettenis             fprintf(stderr, "COULD NOT REPLY at line %d in %s\n",
555b725ae77Skettenis                     __LINE__, __FILE__);
556b725ae77Skettenis             if (rwhead != NULL)
557b725ae77Skettenis                free(rwhead);
558b725ae77Skettenis             return -1;
559b725ae77Skettenis         }
560b725ae77Skettenis 
561b725ae77Skettenis         if (nbtogo == 0 || err == 0) {
562b725ae77Skettenis           DebugPrintF(("\twrite complete - returning\n"));
563b725ae77Skettenis           if (rwhead != NULL)
564b725ae77Skettenis              free(rwhead);
565b725ae77Skettenis           return 0;
566b725ae77Skettenis         }
567b725ae77Skettenis         else {
568b725ae77Skettenis           /* await extension */
569b725ae77Skettenis           ack_reason = CL_WriteX;
570b725ae77Skettenis 
571b725ae77Skettenis           packet = DevSW_AllocatePacket(Armsd_BufferSize);
572b725ae77Skettenis           if (packet == NULL)
573b725ae77Skettenis           {
574b725ae77Skettenis             fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
575b725ae77Skettenis                     __LINE__, __FILE__);
576b725ae77Skettenis             if (rwhead != NULL)
577b725ae77Skettenis                free(rwhead);
578b725ae77Skettenis             return -1;
579b725ae77Skettenis           }
580b725ae77Skettenis           Adp_ChannelRegisterRead(CI_CLIB, NULL, NULL);
581b725ae77Skettenis           Adp_ChannelRead(CI_CLIB, &packet);
582b725ae77Skettenis           Adp_ChannelRegisterRead(CI_CLIB,
583b725ae77Skettenis                                   (ChannelCallback)HandleSysMessage,
584b725ae77Skettenis                                   stateptr);
585b725ae77Skettenis 
586b725ae77Skettenis           buffhead = packet->pk_buffer;
587b725ae77Skettenis           unpack_message(BUFFERDATA(buffhead), "%w%w%w%w%w", &reason_code,
588b725ae77Skettenis                          &DebugID, &OSInfo1, &OSInfo2, &nbytes);
589b725ae77Skettenis           if (reason_code != (CL_WriteX|TtoH)) {
590b725ae77Skettenis             DevSW_FreePacket(packet);
591b725ae77Skettenis             free(rwhead);
592b725ae77Skettenis             fprintf(stderr, "EXPECTING CL_WriteX GOT %u at line %d in %s\n",
593b725ae77Skettenis                     reason_code, __LINE__, __FILE__);
594b725ae77Skettenis             return -1;
595b725ae77Skettenis           }
596b725ae77Skettenis 
597b725ae77Skettenis           DebugPrintF(("CL_WriteX: nbytes %u\n", nbytes));
598b725ae77Skettenis           memcpy(rwdata, BUFFERDATA(buffhead)+20, nbytes);
599b725ae77Skettenis           rwdata += nbytes;
600b725ae77Skettenis           nbtogo -= nbytes;
601b725ae77Skettenis         }
602b725ae77Skettenis 
603b725ae77Skettenis       } while (TRUE);           /* will return when done */
604b725ae77Skettenis     }
605b725ae77Skettenis 
606b725ae77Skettenis   case CL_WriteX:     /*
607b725ae77Skettenis                        * NOTE: if we've got here something has gone wrong
608b725ae77Skettenis                        * CL_WriteX's should all be picked up within the
609b725ae77Skettenis                        * CL_Write loop, probably best to return an error here
610b725ae77Skettenis                        * do this for the moment just so we do actually return
611b725ae77Skettenis                        */
612b725ae77Skettenis     fprintf(stderr, "ERROR: unexpected CL_WriteX message received\n");
613b725ae77Skettenis     return -1;
614b725ae77Skettenis 
615b725ae77Skettenis   case CL_Read:
616b725ae77Skettenis     {
617b725ae77Skettenis                    /* Read(word handle, word nbtotal)
618b725ae77Skettenis                     * return(word nbytes, word nbmore, bytes data)
619b725ae77Skettenis                     */
620b725ae77Skettenis                    /* ReadX()
621b725ae77Skettenis                     * return(word nbytes, word nbmore, bytes data) */
622b725ae77Skettenis       unsigned char *rwdata, *rwhead;
623b725ae77Skettenis       int gotlen;
624b725ae77Skettenis       unsigned int max_data_in_buffer=Armsd_BufferSize-28;
625b725ae77Skettenis       char flags;
626b725ae77Skettenis       FILE *fhreal;
627b725ae77Skettenis       unsigned int nbleft = 0, reason = CL_Read;
628b725ae77Skettenis 
629b725ae77Skettenis       err = NoError;
630b725ae77Skettenis 
631b725ae77Skettenis       unpack_message(buffp, "%w%w", &fh, &nbtotal);
632b725ae77Skettenis       DebugPrintF(("CL_Read: fh %d, nbtotal %d: ", fh, nbtotal));
633b725ae77Skettenis 
634b725ae77Skettenis       rwdata = rwhead = (unsigned char *)malloc(nbtotal);
635b725ae77Skettenis       if (rwdata == NULL) {
636b725ae77Skettenis         fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
637b725ae77Skettenis                 __LINE__, __FILE__);
638b725ae77Skettenis         DevSW_FreePacket(packet);
639b725ae77Skettenis         return -1;
640b725ae77Skettenis       }
641b725ae77Skettenis 
642b725ae77Skettenis       /* perform the actual read */
643b725ae77Skettenis       fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
644b725ae77Skettenis       if (fhreal == NULL)
645b725ae77Skettenis       {
646b725ae77Skettenis         /* bad file handle */
647b725ae77Skettenis         err = -1;
648b725ae77Skettenis         nbytes = 0;
649b725ae77Skettenis         gotlen = 0;
650b725ae77Skettenis       }
651b725ae77Skettenis       else
652b725ae77Skettenis       {
653b725ae77Skettenis         if (flags & WRITEOP)
654b725ae77Skettenis           fseek(fhreal,0,SEEK_CUR);
655b725ae77Skettenis         stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;
656b725ae77Skettenis         if (isatty_(fhreal)) {
657b725ae77Skettenis           /* reading from a tty, so do some nasty stuff, reading into rwdata */
658b725ae77Skettenis           if (angel_hostif->gets(stateptr->hostif->hostosarg, (char *)rwdata,
659b725ae77Skettenis                                  nbtotal) != 0)
660b725ae77Skettenis              gotlen = strlen((char *)rwdata);
661b725ae77Skettenis           else
662b725ae77Skettenis              gotlen = 0;
663b725ae77Skettenis           stateptr->last_errno = errno;
664b725ae77Skettenis           DebugPrintF(("ttyread %d\n", gotlen));
665b725ae77Skettenis         }
666b725ae77Skettenis         else {
667b725ae77Skettenis           /* not a tty, reading from a real file */
668b725ae77Skettenis           gotlen = fread(rwdata, 1, nbtotal, fhreal);
669b725ae77Skettenis           stateptr->last_errno = errno;
670b725ae77Skettenis           DebugCheckErr("fread", FALSE, (gotlen == 0), stateptr->last_errno);
671b725ae77Skettenis           DebugPrintF(("(%d)\n", gotlen));
672b725ae77Skettenis         }
673b725ae77Skettenis       }
674b725ae77Skettenis 
675b725ae77Skettenis       nbtogo = gotlen;
676b725ae77Skettenis 
677b725ae77Skettenis       do {
678b725ae77Skettenis         /* at least once */
679b725ae77Skettenis 
680b725ae77Skettenis         if ((unsigned int) nbtogo <= max_data_in_buffer)
681b725ae77Skettenis            nbytes = nbtogo;
682b725ae77Skettenis         else
683b725ae77Skettenis            nbytes = max_data_in_buffer;
684b725ae77Skettenis         nbtogo -= nbytes;
685b725ae77Skettenis 
686b725ae77Skettenis         /* last ReadX needs subtle adjustment to returned nbtogo */
687b725ae77Skettenis         if (nbtogo == 0 && err == NoError && reason == CL_ReadX)
688b725ae77Skettenis            nbleft = nbtotal - gotlen;
689b725ae77Skettenis         else
690b725ae77Skettenis            nbleft = nbtogo;
691b725ae77Skettenis 
692b725ae77Skettenis         count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w%w%w",
693b725ae77Skettenis                          reason|HtoT, 0, ADP_HandleUnknown,
694b725ae77Skettenis                          ADP_HandleUnknown, err, nbytes, nbleft);
695b725ae77Skettenis 
696b725ae77Skettenis         if (err == NoError) {
697b725ae77Skettenis           /* copy data into buffptr */
698b725ae77Skettenis           memcpy(BUFFERDATA(buffhead)+28, rwdata, nbytes);
699b725ae77Skettenis           rwdata += nbytes;
700b725ae77Skettenis           count += nbytes;
701b725ae77Skettenis         }
702b725ae77Skettenis 
703b725ae77Skettenis         DebugPrintF(("\treplying err %d, nbytes %d, nbtogo %d\n",
704b725ae77Skettenis                      err, nbytes, nbtogo));
705b725ae77Skettenis 
706b725ae77Skettenis         packet->pk_length = count;
707b725ae77Skettenis         Adp_ChannelWrite(CI_CLIB, packet);
708b725ae77Skettenis 
709b725ae77Skettenis         if (nbtogo == 0 || err != NoError) {
710b725ae77Skettenis           /* done */
711b725ae77Skettenis           free(rwhead);
712b725ae77Skettenis           return 0;
713b725ae77Skettenis         }
714b725ae77Skettenis         else {
715b725ae77Skettenis           /* await extension */
716b725ae77Skettenis           reason = CL_ReadX;
717b725ae77Skettenis 
718b725ae77Skettenis           packet = DevSW_AllocatePacket(Armsd_BufferSize);
719b725ae77Skettenis           if (packet == NULL) {
720b725ae77Skettenis             fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
721b725ae77Skettenis                     __LINE__, __FILE__);
722b725ae77Skettenis             free(rwhead);
723b725ae77Skettenis             return -1;
724b725ae77Skettenis           }
725b725ae77Skettenis           Adp_ChannelRegisterRead(CI_CLIB, NULL, NULL);
726b725ae77Skettenis           Adp_ChannelRead(CI_CLIB, &packet);
727b725ae77Skettenis           Adp_ChannelRegisterRead(CI_CLIB,
728b725ae77Skettenis                                   (ChannelCallback)HandleSysMessage,
729b725ae77Skettenis                                   stateptr);
730b725ae77Skettenis           buffhead = packet->pk_buffer;
731b725ae77Skettenis           unpack_message(BUFFERDATA(buffhead),"%w", &reason_code);
732b725ae77Skettenis           if (reason_code != (CL_ReadX|TtoH)) {
733b725ae77Skettenis             fprintf(stderr, "EXPECTING CL_ReadX GOT %u at line %d in %s\n",
734b725ae77Skettenis                     reason_code, __LINE__, __FILE__);
735b725ae77Skettenis             DevSW_FreePacket(packet);
736b725ae77Skettenis             free(rwdata);
737b725ae77Skettenis             return -1;
738b725ae77Skettenis           }
739b725ae77Skettenis         }
740b725ae77Skettenis 
741b725ae77Skettenis       } while (TRUE);           /* will return above on error or when done */
742b725ae77Skettenis     }
743b725ae77Skettenis 
744b725ae77Skettenis   case CL_ReadX:      /* If we're here something has probably gone wrong */
745b725ae77Skettenis     fprintf(stderr, "ERROR: Got unexpected CL_ReadX message\n");
746b725ae77Skettenis     return -1;
747b725ae77Skettenis 
748b725ae77Skettenis   case CL_Seek:
749b725ae77Skettenis     {
750b725ae77Skettenis       unpack_message(buffp, "%w%w", &fh, &posn);
751b725ae77Skettenis       DebugPrintF(("CL_Seek: fh %d, posn %ld\n", fh, posn));
752b725ae77Skettenis       DevSW_FreePacket(packet);
753b725ae77Skettenis 
754b725ae77Skettenis       fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
755b725ae77Skettenis       if (fhreal == NULL)
756b725ae77Skettenis          err = -1;
757b725ae77Skettenis       else {
758b725ae77Skettenis         err = fseek(fhreal, posn, SEEK_SET);
759b725ae77Skettenis         stateptr->last_errno = errno;
760b725ae77Skettenis         DebugCheckErr("fseek", TRUE, err, stateptr->last_errno);
761b725ae77Skettenis       }
762b725ae77Skettenis 
763b725ae77Skettenis       return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Seek|HtoT,
764b725ae77Skettenis                          DebugID, OSInfo1, OSInfo2, err);
765b725ae77Skettenis     }
766b725ae77Skettenis 
767b725ae77Skettenis   case CL_Flen:
768b725ae77Skettenis     {
769b725ae77Skettenis       unpack_message(buffp, "%w", &fh);
770b725ae77Skettenis       DebugPrintF(("CL_Flen: fh %d ", fh));
771b725ae77Skettenis       DevSW_FreePacket(packet);
772b725ae77Skettenis 
773b725ae77Skettenis       fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
774b725ae77Skettenis       if (fhreal == NULL)
775b725ae77Skettenis         fl = -1;
776b725ae77Skettenis       else {
777b725ae77Skettenis         posn = ftell(fhreal);
778b725ae77Skettenis         if (fseek(fhreal, 0L, SEEK_END) < 0) {
779b725ae77Skettenis           fl=-1;
780b725ae77Skettenis         }
781b725ae77Skettenis         else {
782b725ae77Skettenis           fl = ftell(fhreal);
783b725ae77Skettenis           fseek(fhreal, posn, SEEK_SET);
784b725ae77Skettenis         }
785b725ae77Skettenis         stateptr->last_errno = errno;
786b725ae77Skettenis       }
787b725ae77Skettenis       DebugPrintF(("returning len %ld\n", fl));
788b725ae77Skettenis       return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Flen|HtoT, DebugID, OSInfo1,
789b725ae77Skettenis                      OSInfo2, fl);
790b725ae77Skettenis     }
791b725ae77Skettenis 
792b725ae77Skettenis   case CL_IsTTY:
793b725ae77Skettenis     {
794b725ae77Skettenis       int  ttyOrNot;
795b725ae77Skettenis       unpack_message(buffp, "%w", &fh);
796b725ae77Skettenis       DebugPrintF(("CL_IsTTY: fh %d ", fh));
797b725ae77Skettenis       DevSW_FreePacket(packet);
798b725ae77Skettenis 
799b725ae77Skettenis       fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
800b725ae77Skettenis       if (fhreal == NULL)
801b725ae77Skettenis          ttyOrNot = FALSE;
802b725ae77Skettenis       else {
803b725ae77Skettenis         ttyOrNot = isatty_(fhreal);
804b725ae77Skettenis         stateptr->last_errno = errno;
805b725ae77Skettenis       }
806b725ae77Skettenis       DebugPrintF(("returning %s\n", ttyOrNot ? "tty (1)" : "not (0)"));
807b725ae77Skettenis 
808b725ae77Skettenis       return msgsend(CI_CLIB, "%w%w%w%w%w",CL_IsTTY|HtoT,
809b725ae77Skettenis                          DebugID, OSInfo1, OSInfo2, ttyOrNot);
810b725ae77Skettenis     }
811b725ae77Skettenis 
812b725ae77Skettenis   case CL_TmpNam:
813b725ae77Skettenis     {
814b725ae77Skettenis       char *name;
815b725ae77Skettenis       unsigned int tnamelen, TargetID;
816b725ae77Skettenis       unpack_message(buffp, "%w%w", &tnamelen, &TargetID);
817b725ae77Skettenis       DebugPrintF(("CL_TmpNam: tnamelen %d TargetID %d: ",
818b725ae77Skettenis                    tnamelen, TargetID));
819b725ae77Skettenis       DevSW_FreePacket(packet);
820b725ae77Skettenis 
821b725ae77Skettenis       TargetID = TargetID & 0xFF;
822b725ae77Skettenis       if (stateptr->OSptr->TempNames[TargetID] == NULL) {
823b725ae77Skettenis         if ((stateptr->OSptr->TempNames[TargetID] =
824b725ae77Skettenis              (char *)malloc(L_tmpnam)) == NULL)
825b725ae77Skettenis         {
826b725ae77Skettenis           fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
827b725ae77Skettenis                   __LINE__, __FILE__);
828b725ae77Skettenis           return -1;
829b725ae77Skettenis         }
830b725ae77Skettenis         tmpnam(stateptr->OSptr->TempNames[TargetID]);
831b725ae77Skettenis       }
832b725ae77Skettenis       name = stateptr->OSptr->TempNames[TargetID];
833b725ae77Skettenis       len = strlen(name) + 1;
834b725ae77Skettenis       packet = DevSW_AllocatePacket(Armsd_BufferSize);
835b725ae77Skettenis       if (packet == NULL)
836b725ae77Skettenis       {
837b725ae77Skettenis           fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
838b725ae77Skettenis                   __LINE__, __FILE__);
839b725ae77Skettenis           return -1;
840b725ae77Skettenis       }
841b725ae77Skettenis       buffhead = packet->pk_buffer;
842b725ae77Skettenis       if (len > tnamelen) {
843b725ae77Skettenis         DebugPrintF(("TMPNAME TOO LONG!\n"));
844b725ae77Skettenis         count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w",
845b725ae77Skettenis                            CL_TmpNam|HtoT, DebugID, OSInfo1, OSInfo2, -1);
846b725ae77Skettenis       }
847b725ae77Skettenis       else {
848b725ae77Skettenis         DebugPrintF(("returning \"%s\"\n", name));
849b725ae77Skettenis         count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w%w", CL_TmpNam|HtoT,
850b725ae77Skettenis                          DebugID, OSInfo1, OSInfo2, 0, len);
851b725ae77Skettenis         strcpy((char *)BUFFERDATA(buffhead)+count, name);
852b725ae77Skettenis         count +=len+1;
853b725ae77Skettenis       }
854b725ae77Skettenis       packet->pk_length = count;
855b725ae77Skettenis       Adp_ChannelWrite(CI_CLIB, packet);/* Send message. */
856b725ae77Skettenis       return 0;
857b725ae77Skettenis     }
858b725ae77Skettenis 
859b725ae77Skettenis   case CL_Unrecognised:
860b725ae77Skettenis     DebugPrintF(("CL_Unrecognised!!\n"));
861b725ae77Skettenis     return 0;
862b725ae77Skettenis 
863b725ae77Skettenis   default:
864b725ae77Skettenis     fprintf(stderr, "UNRECOGNISED CL code %08x\n", reason_code);
865b725ae77Skettenis     break;
866b725ae77Skettenis /* Need some sort of error handling here. */
867b725ae77Skettenis /* A call to CL_Unrecognised should suffice */
868b725ae77Skettenis   }
869b725ae77Skettenis   return -1;  /* Stop a potential compiler warning */
870b725ae77Skettenis }
871b725ae77Skettenis 
872b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
873b725ae77Skettenis 
874b725ae77Skettenis #include <windows.h>
875b725ae77Skettenis 
876b725ae77Skettenis extern HWND hwndParent;
877b725ae77Skettenis 
panic(const char * format,...)878b725ae77Skettenis void panic(const char *format, ...)
879b725ae77Skettenis {
880b725ae77Skettenis     char buf[2048];
881b725ae77Skettenis     va_list args;
882b725ae77Skettenis 
883b725ae77Skettenis     Adp_CloseDevice();
884b725ae77Skettenis 
885b725ae77Skettenis     va_start(args, format);
886b725ae77Skettenis     vsprintf(buf, format, args);
887b725ae77Skettenis 
888b725ae77Skettenis     MessageBox(hwndParent, (LPCTSTR)buf, (LPCTSTR)"Fatal Error:", MB_OK);
889b725ae77Skettenis 
890b725ae77Skettenis     /* SJ - Not the proper way to shutdown the app */
891b725ae77Skettenis     exit(EXIT_FAILURE);
892b725ae77Skettenis 
893b725ae77Skettenis /*
894b725ae77Skettenis     if (hwndParent != NULL)
895b725ae77Skettenis         SendMessage(hwndParent, WM_QUIT, 0, 0);
896b725ae77Skettenis */
897b725ae77Skettenis 
898b725ae77Skettenis     va_end(args);
899b725ae77Skettenis }
900b725ae77Skettenis 
901b725ae77Skettenis #else
902b725ae77Skettenis 
panic(const char * format,...)903b725ae77Skettenis void panic(const char *format, ...)
904b725ae77Skettenis {
905b725ae77Skettenis     va_list args;
906b725ae77Skettenis 
907b725ae77Skettenis     va_start(args, format);
908b725ae77Skettenis     fprintf(stderr, "Fatal error: ");
909b725ae77Skettenis     vfprintf(stderr, format, args);
910b725ae77Skettenis     fprintf(stderr,"\n");
911b725ae77Skettenis 
912b725ae77Skettenis     exit(EXIT_FAILURE);
913b725ae77Skettenis }
914b725ae77Skettenis 
915b725ae77Skettenis #endif
916b725ae77Skettenis 
917b725ae77Skettenis /* EOF hsys.c */
918