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