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