1/* 2 Copyright (c) 1990-2002 Info-ZIP. All rights reserved. 3 4 See the accompanying file LICENSE, version 2000-Apr-09 or later 5 (the contents of which are also included in zip.h) for terms of use. 6 If, for some reason, all these files are missing, the Info-ZIP license 7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html 8*/ 9/* Low-level Amiga routines shared between Zip and UnZip. 10 * 11 * Contains: FileDate() 12 * getenv() [replaces inadequate standard library version] 13 * setenv() [SAS/C only, replaces standard library version] 14 * set_TZ() [SAS/C only] 15 * GetPlatformLocalTimezone() [callback from timezone.c tzset()] 16 * time() 17 * sendpkt() 18 * Agetch() 19 * 20 * The first five are used by most Info-ZIP programs except fUnZip. 21 * The last two are used by all except the non-CRYPT version of fUnZip. 22 * Probably some of the stuff in here is unused by ZipNote and ZipSplit too... 23 * sendpkt() is used by Agetch() and FileDate(), and by screensize() in 24 * amiga/amiga.c (UnZip); time() is used only by Zip. 25 */ 26 27 28/* HISTORY/CHANGES 29 * 2 Sep 92, Greg Roelofs, Original coding. 30 * 6 Sep 92, John Bush, Incorporated into UnZip 5.1 31 * 6 Sep 92, John Bush, Interlude "FileDate()" defined, which calls or 32 * redefines SetFileDate() depending upon AMIGADOS2 definition. 33 * 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining 34 * revision via OpenLibrary() call. Now only one version of 35 * the program runs on both platforms (1.3.x vs. 2.x) 36 * 11 Oct 92, John Bush, Merged with Zip version and changed arg passing 37 * to take time_t input instead of struct DateStamp. 38 * Arg passing made to conform with utime(). 39 * 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some 40 * lint-ish errors; simplified test for AmigaDOS version. 41 * 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and 42 * UnZip's "More" prompt -- simplifies crypt.h and avoids 43 * use of library code redundant with sendpkt(). Made it 44 * available to fUnZip, which does not use FileDate(). 45 * 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current 46 * timezone from the Locale preferences. These exist only under 47 * AmigaDOS 2.1 and up, but it is probably correctly set on more 48 * Amigas than the TZ environment variable is. We check that 49 * only if TZ is not validly set. We do not parse daylight 50 * savings syntax except to check for presence vs. absence of a 51 * DST part; United States rules are assumed. This is better 52 * than the tzset()s in the Amiga compilers' libraries do. 53 * 15 Jan 96, Chr. Spieler, corrected the logic when to select low level 54 * sendpkt() (when FileDate(), Agetch() or windowheight() is used), 55 * and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()). 56 * 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved 57 * stuff around for clarity. 58 * 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the 59 * new tzset(), because Aztec's is hopelessly broken. Also 60 * gmtime(), which localtime() calls. 61 * 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly. 62 * 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns 63 * local time instead of GMT. That's why their localtime() was bad, 64 * because it assumed time_t was already local, and gmtime() was 65 * the one that checked TZ. 66 * 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff. 67 * Currently, the UnZip sources do not make use of time() (and do 68 * not supply the working mktime() replacement, either!). 69 * 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that 70 * was previously embedded in tzset(), for reliable global test 71 * of whether TZ is set or not. 72 * 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler. 73 * 7 Jul 96, Paul Kienitz, smoothed together compiler-related changes. 74 * 4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C. 75 * 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding 76 * mkgmtime() so localtime() could be used. 77 * 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP; 78 * the Zip sources supply this function as part of util.c. 79 * 24 May 97, Haidinger Walter, added time_lib support for SAS/C and moved 80 * set_TZ() to time_lib.c. 81 * 12 Jul 97, Paul Kienitz, adapted time_lib stuff for Aztec. 82 * 26 Jul 97, Chr. Spieler, old mkgmtime() fixed (ydays[] def, sign vs unsign). 83 * 30 Dec 97, Haidinger Walter, adaptation for SAS/C using z-stat.h functions. 84 * 19 Feb 98, Haidinger Walter, removed alloc_remember, more SAS.C fixes. 85 * 23 Apr 98, Chr. Spieler, removed mkgmtime(), changed FileDate to convert to 86 * Amiga file-time directly. 87 * 24 Apr 98, Paul Kienitz, clip Unix dates earlier than 1978 in FileDate(). 88 * 02 Sep 98, Paul Kienitz, C. Spieler, always include zip.h to get a defined 89 * header inclusion sequence that resolves all header dependencies. 90 * 06 Jun 00, Paul Kienitz, removed time_lib.c due to its incompatible license, 91 * moved set_TZ() back here, replaced minimal tzset() and localtime() 92 * with new versions derived from GNU glibc source. Gave locale_TZ() 93 * reasonable European defaults for daylight savings. 94 * 17 Jun 00, Paul Kienitz, threw out GNU code because of objections to the GPL 95 * virus, replaced with similar functions based on the public domain 96 * timezone code at ftp://elsie.nci.nih.gov/pub. As with the GNU 97 * stuff, support for timezone files and leap seconds was removed. 98 * 23 Aug 00, Paul Kienitz, moved timezone code out from here into separate 99 * platform-independent module 'timezone.c'. 100 * 31 Dec 00, Christian Spieler, moved system-specific timezone help funcions 101 * back in here, from 'timezone.c'. 102 * 07 Jan 01, Paul Kienitz, Chr. Spieler, added missing #include "timezone.h" 103 * and "symbolic" preprocessor constants for time calculations. 104 * 15 Jan 02, Paul Kienitz, excluded all time handling code from compilation 105 * for Zip utilities (when "defined(UTIL)") 106 */ 107 108#ifndef __amiga_filedate_c 109#define __amiga_filedate_c 110 111 112#include "zip.h" 113#include <ctype.h> 114#include <errno.h> 115 116#include <exec/types.h> 117#include <exec/execbase.h> 118#include <exec/memory.h> 119#include <dos/dosextens.h> 120 121#ifdef AZTEC_C 122# include <libraries/dos.h> 123# include <libraries/dosextens.h> 124# include <clib/exec_protos.h> 125# include <clib/dos_protos.h> 126# include <clib/locale_protos.h> 127# include <pragmas/exec_lib.h> 128# include <pragmas/dos_lib.h> 129# include <pragmas/locale_lib.h> 130# define ESRCH ENOENT 131# define EOSERR EIO 132#endif 133 134#ifdef __SASC 135# include <stdlib.h> 136# if (defined(_M68020) && (!defined(__USE_SYSBASE))) 137 /* on 68020 or higher processors it is faster */ 138# define __USE_SYSBASE /* to use the pragma libcall instead of syscall */ 139# endif /* to access functions of the exec.library */ 140# include <proto/exec.h> /* see SAS/C manual:part 2,chapter 2,pages 6-7 */ 141# include <proto/dos.h> 142# include <proto/locale.h> 143# ifdef DEBUG 144# include <sprof.h> 145# endif 146# ifdef MWDEBUG 147# include <stdio.h> /* include both before memwatch.h again just */ 148# include <stdlib.h> /* to be safe */ 149# include "memwatch.h" 150# endif /* MWDEBUG */ 151#endif /* __SASC */ 152 153#include "crypt.h" /* just so we can tell if CRYPT is supported */ 154 155 156#if (!defined(FUNZIP) && !defined(UTIL)) 157 158#include "timezone.h" /* for AMIGA-specific timezone callbacks */ 159 160#ifndef SUCCESS 161# define SUCCESS (-1L) 162# define FAILURE 0L 163#endif 164 165#define ReqVers 36L /* required library version for SetFileDate() */ 166#define ENVSIZE 100 /* max space allowed for an environment var */ 167 168extern struct ExecBase *SysBase; 169 170#ifndef min 171# define min(a, b) ((a) < (b) ? (a) : (b)) 172# define max(a, b) ((a) < (b) ? (b) : (a)) 173#endif 174 175#if defined(ZIP) || defined(HAVE_MKTIME) 176static const unsigned short ydays[] = 177 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; 178#else 179extern const unsigned short ydays[]; /* in unzip's fileio.c */ 180#endif 181 182#define LEAP(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0) 183#define YDAYS(m, y) (ydays[m] + (m > 1 && LEAP(y))) 184/* Number of leap years from 1978 to `y' (not including `y' itself). */ 185#define ANLEAP(y) (((y) - 1977) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400) 186#define SECSPERMIN 60 187#define MINSPERHOUR 60 188#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) 189#define SECSPERDAY 86400L 190 191/* prototypes */ 192char *getenv(const char *var); 193#ifdef __SASC 194/* XXX !! We have really got to find a way to operate without these. */ 195int setenv(const char *var, const char *value, int overwrite); 196void set_TZ(long time_zone, int day_light); 197#endif 198 199LONG FileDate(char *filename, time_t u[]); 200LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); 201int Agetch(void); 202 203/* =============================================================== */ 204 205/***********************/ 206/* Function filedate() */ 207/***********************/ 208 209/* FileDate() (originally utime.c), by Paul Wells. Modified by John Bush 210 * and others (see also sendpkt() comments, below); NewtWare SetFileDate() 211 * clone cheaply ripped off from utime(). 212 */ 213 214/* DESCRIPTION 215 * This routine chooses between 2 methods to set the file date on AMIGA. 216 * Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36 217 * and higher). Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate() 218 * must be accomplished by constructing a message packet and sending it 219 * to the file system handler of the file to be stamped. 220 * 221 * The system's ROM version is extracted from the external system Library 222 * base. 223 * 224 * NOTE: although argument passing conforms with utime(), note the 225 * following differences: 226 * - Return value is boolean success/failure. 227 * - If a structure or array is passed, only the first value 228 * is used, which *may* correspond to date accessed and not 229 * date modified. 230 */ 231 232LONG FileDate(filename, u) 233 char *filename; 234 time_t u[]; 235{ 236 LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate); 237 LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); 238 struct MsgPort *taskport; 239 BPTR dirlock, lock; 240 struct FileInfoBlock *fib; 241 LONG pktargs[4]; 242 UBYTE *ptr; 243 long ret; 244 245 struct DateStamp pDate; 246 struct tm *ltm; 247 int years; 248 249 tzset(); 250 /* Amiga file date is based on 01-Jan-1978 00:00:00 (local time): 251 * 8 years and 2 leapdays difference from Unix time. 252 */ 253 ltm = localtime(&u[0]); 254 years = ltm->tm_year + 1900; 255 if (years < 1978) 256 pDate.ds_Days = pDate.ds_Minute = pDate.ds_Tick = 0; 257 else { 258 pDate.ds_Days = (years - 1978) * 365L + (ANLEAP(years)) + 259 YDAYS(ltm->tm_mon, years) + (ltm->tm_mday - 1); 260 pDate.ds_Minute = ltm->tm_hour * 60 + ltm->tm_min; 261 pDate.ds_Tick = ltm->tm_sec * TICKS_PER_SECOND; 262 } 263 264 if (SysBase->LibNode.lib_Version >= ReqVers) 265 { 266 return (SetFileDate(filename,&pDate)); /* native routine at 2.0+ */ 267 } 268 else /* !(SysBase->lib_Version >=ReqVers) */ 269 { 270 if( !(taskport = (struct MsgPort *)DeviceProc(filename)) ) 271 { 272 errno = ESRCH; /* no such process */ 273 return FAILURE; 274 } 275 276 if( !(lock = Lock(filename,SHARED_LOCK)) ) 277 { 278 errno = ENOENT; /* no such file */ 279 return FAILURE; 280 } 281 282 if( !(fib = (struct FileInfoBlock *)AllocMem( 283 (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) ) 284 { 285 errno = ENOMEM; /* insufficient memory */ 286 UnLock(lock); 287 return FAILURE; 288 } 289 290 if( Examine(lock,fib)==FAILURE ) 291 { 292 errno = EOSERR; /* operating system error */ 293 UnLock(lock); 294 FreeMem(fib,(long)sizeof(*fib)); 295 return FAILURE; 296 } 297 298 dirlock = ParentDir(lock); 299 ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC); 300 strcpy((ptr+1),fib->fib_FileName); 301 *ptr = strlen(fib->fib_FileName); 302 FreeMem(fib,(long)sizeof(*fib)); 303 UnLock(lock); 304 305 /* now fill in argument array */ 306 307 pktargs[0] = 0; 308 pktargs[1] = (LONG)dirlock; 309 pktargs[2] = (LONG)&ptr[0] >> 2; 310 pktargs[3] = (LONG)&pDate; 311 312 errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L); 313 314 FreeMem(ptr,64L); 315 UnLock(dirlock); 316 317 return SUCCESS; 318 } /* ?(SysBase->lib_Version >= ReqVers) */ 319} /* FileDate() */ 320 321 322char *getenv(const char *var) /* not reentrant! */ 323{ 324 static char space[ENVSIZE]; 325 struct Process *me = (void *) FindTask(NULL); 326 void *old_window = me->pr_WindowPtr; 327 char *ret = NULL; 328 329 me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */ 330 if (SysBase->LibNode.lib_Version >= ReqVers) { 331 if (GetVar((char *) var, space, ENVSIZE - 1, /*GVF_GLOBAL_ONLY*/ 0) > 0) 332 ret = space; 333 } else { /* early AmigaDOS, get env var the crude way */ 334 BPTR hand, foot, spine; 335 int z = 0; 336 if (foot = Lock("ENV:", ACCESS_READ)) { 337 spine = CurrentDir(foot); 338 if (hand = Open((char *) var, MODE_OLDFILE)) { 339 z = Read(hand, space, ENVSIZE - 1); 340 Close(hand); 341 } 342 UnLock(CurrentDir(spine)); 343 } 344 if (z > 0) { 345 space[z] = '\0'; 346 ret = space; 347 } 348 } 349 me->pr_WindowPtr = old_window; 350 return ret; 351} 352 353#ifdef __SASC 354int setenv(const char *var, const char *value, int overwrite) 355{ 356 struct Process *me = (void *) FindTask(NULL); 357 void *old_window = me->pr_WindowPtr; 358 int ret = -1; 359 360 me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */ 361 if (SysBase->LibNode.lib_Version >= ReqVers) 362 ret = !SetVar((char *)var, (char *)value, -1, GVF_GLOBAL_ONLY | LV_VAR); 363 else { 364 BPTR hand, foot, spine; 365 long len = value ? strlen(value) : 0; 366 if (foot = Lock("ENV:", ACCESS_READ)) { 367 spine = CurrentDir(foot); 368 if (len) { 369 if (hand = Open((char *) var, MODE_NEWFILE)) { 370 ret = Write(hand, (char *) value, len + 1) >= len; 371 Close(hand); 372 } 373 } else 374 ret = DeleteFile((char *) var); 375 UnLock(CurrentDir(spine)); 376 } 377 } 378 me->pr_WindowPtr = old_window; 379 return ret; 380} 381 382/* Stores data from timezone and daylight to ENV:TZ. */ 383/* ENV:TZ is required to exist by some other SAS/C library functions, */ 384/* like stat() or fstat(). */ 385void set_TZ(long time_zone, int day_light) 386{ 387 char put_tz[MAXTIMEZONELEN]; /* string for putenv: "TZ=aaabbb:bb:bbccc" */ 388 int offset; 389 void *exists; /* dummy ptr to see if global envvar TZ already exists */ 390 exists = (void *)getenv(TZ_ENVVAR); 391 /* see if there is already an envvar TZ_ENVVAR. If not, create it */ 392 if (exists == NULL) { 393 /* create TZ string by pieces: */ 394 sprintf(put_tz, "GMT%+ld", time_zone / 3600L); 395 if (time_zone % 3600L) { 396 offset = (int) labs(time_zone % 3600L); 397 sprintf(put_tz + strlen(put_tz), ":%02d", offset / 60); 398 if (offset % 60) 399 sprintf(put_tz + strlen(put_tz), ":%02d", offset % 60); 400 } 401 if (day_light) 402 strcat(put_tz,"DST"); 403 setenv(TZ_ENVVAR, put_tz, 1); 404 } 405} 406#endif /* __SASC */ 407 408/* set state as well as possible from settings found in locale.library */ 409int GetPlatformLocalTimezone(sp, fill_tzstate_from_rules) 410 register struct state * ZCONST sp; 411 void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res, 412 ZCONST struct rule * ZCONST start, 413 ZCONST struct rule * ZCONST end); 414{ 415 struct Library *LocaleBase; 416 struct Locale *ll; 417 struct Process *me = (void *) FindTask(NULL); 418 void *old_window = me->pr_WindowPtr; 419 BPTR eh; 420 int z, valid = FALSE; 421 422 /* read timezone from locale.library if TZ envvar missing */ 423 me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */ 424 if (LocaleBase = OpenLibrary("locale.library", 0)) { 425 if (ll = OpenLocale(NULL)) { 426 z = ll->loc_GMTOffset; /* in minutes */ 427 if (z == -300) { 428 if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ)) { 429 UnLock(eh); 430 valid = TRUE; 431 } else 432 z = 300; /* bug: locale not initialized, default bogus! */ 433 } else 434 valid = TRUE; 435 if (valid) { 436 struct rule startrule, stoprule; 437 438 sp->timecnt = 0; 439 sp->typecnt = 1; 440 sp->charcnt = 2; 441 sp->chars[0] = sp->chars[1] = '\0'; 442 sp->ttis[0].tt_abbrind = 0; 443 sp->ttis[1].tt_abbrind = 1; 444 sp->ttis[0].tt_gmtoff = -z * MINSPERHOUR; 445 sp->ttis[1].tt_gmtoff = -z * MINSPERHOUR + SECSPERHOUR; 446 sp->ttis[0].tt_isdst = 0; 447 sp->ttis[1].tt_isdst = 1; 448 stoprule.r_type = MONTH_NTH_DAY_OF_WEEK; 449 stoprule.r_day = 0; 450 stoprule.r_week = 5; 451 stoprule.r_mon = 10; 452 stoprule.r_time = 2 * SECSPERHOUR; 453 startrule = stoprule; 454 startrule.r_mon = 4; 455 startrule.r_week = 1; 456 if (z >= -180 && z < 150) { 457 /* At this point we make a really gratuitous assumption: */ 458 /* if the time zone could be Europe, we use the European */ 459 /* Union rules without checking what country we're in. */ 460 /* The AmigaDOS locale country codes do not, at least in */ 461 /* 2.x versions of the OS, recognize very many countries */ 462 /* outside of Europe and North America. */ 463 sp->typecnt = 2; 464 startrule.r_mon = 3; /* one week earlier than US DST */ 465 startrule.r_week = 5; 466 } else if (z >= 150 && z <= 480 && 467 /* no DST in alaska, hawaii */ 468 (ll->loc_CountryCode == 0x55534100 /*"USA"*/ || 469 ll->loc_CountryCode == 0x43414E00 /*"CAN"*/)) 470 sp->typecnt = 2; 471 /* We check the country code for U.S. or Canada because */ 472 /* most of Latin America has no DST. Even in these two */ 473 /* countries there are some exceptions... */ 474 /* else if... Feel free to add more cases here! */ 475 476 if (sp->typecnt > 1) 477 (*fill_tzstate_from_rules)(sp, &startrule, &stoprule); 478 } 479 CloseLocale(ll); 480 } 481 CloseLibrary(LocaleBase); 482 } 483 me->pr_WindowPtr = old_window; 484 return valid; 485} 486 487#ifdef ZIP 488time_t time(time_t *tp) 489{ 490 time_t t; 491 struct DateStamp ds; 492 DateStamp(&ds); 493 t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60 494 + (ds.ds_Days + 2922) * SECSPERDAY; 495 t = mktime(gmtime(&t)); 496 /* gmtime leaves ds in the local timezone, mktime converts it to GMT */ 497 if (tp) *tp = t; 498 return t; 499} 500#endif /* ZIP */ 501 502#endif /* !FUNZIP && !UTIL */ 503 504 505#if CRYPT || !defined(FUNZIP) 506 507/* sendpkt.c 508 * by A. Finkel, P. Lindsay, C. Sheppner 509 * returns Res1 of the reply packet 510 */ 511/* 512#include <exec/types.h> 513#include <exec/memory.h> 514#include <libraries/dos.h> 515#include <libraries/dosextens.h> 516#include <proto/exec.h> 517#include <proto/dos.h> 518*/ 519 520LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); 521 522LONG sendpkt(pid,action,args,nargs) 523struct MsgPort *pid; /* process identifier (handler message port) */ 524LONG action, /* packet type (desired action) */ 525 *args, /* a pointer to argument list */ 526 nargs; /* number of arguments in list */ 527{ 528 529 struct MsgPort *replyport, *CreatePort(UBYTE *, long); 530 void DeletePort(struct MsgPort *); 531 struct StandardPacket *packet; 532 LONG count, *pargs, res1; 533 534 replyport = CreatePort(NULL,0L); 535 if( !replyport ) return(0); 536 537 packet = (struct StandardPacket *)AllocMem( 538 (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR); 539 if( !packet ) 540 { 541 DeletePort(replyport); 542 return(0); 543 } 544 545 packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt); 546 packet->sp_Pkt.dp_Link = &(packet->sp_Msg); 547 packet->sp_Pkt.dp_Port = replyport; 548 packet->sp_Pkt.dp_Type = action; 549 550 /* copy the args into the packet */ 551 pargs = &(packet->sp_Pkt.dp_Arg1); /* address of 1st argument */ 552 for( count=0; count<nargs; count++ ) 553 pargs[count] = args[count]; 554 555 PutMsg(pid,(struct Message *)packet); /* send packet */ 556 557 WaitPort(replyport); 558 GetMsg(replyport); 559 560 res1 = packet->sp_Pkt.dp_Res1; 561 562 FreeMem((char *)packet,(long)sizeof(*packet)); 563 DeletePort(replyport); 564 565 return(res1); 566 567} /* sendpkt() */ 568 569#endif /* CRYPT || !FUNZIP */ 570 571 572#if CRYPT || (defined(UNZIP) && !defined(FUNZIP)) 573 574/* Agetch() reads one raw keystroke -- uses sendpkt() */ 575 576int Agetch(void) 577{ 578 LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); 579 struct Task *me = FindTask(NULL); 580 struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI); 581 BPTR fh = cli->cli_StandardInput; /* this is immune to < redirection */ 582 void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type; 583 char longspace[8]; 584 long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */ 585 UBYTE c; 586 587 *flag = 1; 588 sendpkt(conp, ACTION_SCREEN_MODE, flag, 1); /* assume success */ 589 Read(fh, &c, 1); 590 *flag = 0; 591 sendpkt(conp, ACTION_SCREEN_MODE, flag, 1); 592 if (c == 3) /* ^C in input */ 593 Signal(me, SIGBREAKF_CTRL_C); 594 return c; 595} 596 597#endif /* CRYPT || (UNZIP && !FUNZIP) */ 598 599#endif /* __amiga_filedate_c*/ 600