dos.pp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1998-2001 by Nils Sjoholm and Carl Eric Codere
  5. members of the Free Pascal development team
  6. Date conversion routine taken from SWAG
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. Unit Dos;
  14. {--------------------------------------------------------------------}
  15. { LEFT TO DO: }
  16. {--------------------------------------------------------------------}
  17. { o DiskFree / Disksize don't work as expected }
  18. { o Implement SetDate and SetTime }
  19. { o Implement EnvCount,EnvStr }
  20. { o FindFirst should only work with correct attributes }
  21. {--------------------------------------------------------------------}
  22. Interface
  23. {$I os.inc}
  24. type
  25. SearchRec = Packed Record
  26. { watch out this is correctly aligned for all processors }
  27. { don't modify. }
  28. { Replacement for Fill }
  29. {0} AnchorPtr : Pointer; { Pointer to the Anchorpath structure }
  30. {4} Fill: Array[1..15] of Byte; {future use}
  31. {End of replacement for fill}
  32. Attr : BYTE; {attribute of found file}
  33. Time : LongInt; {last modify date of found file}
  34. Size : LongInt; {file size of found file}
  35. Name : String[255]; {name of found file}
  36. End;
  37. {$i dosh.inc}
  38. implementation
  39. {$DEFINE HAS_GETCBREAK}
  40. {$DEFINE HAS_SETCBREAK}
  41. {$DEFINE FPC_FEXPAND_VOLUMES} (* Full paths begin with drive specification *)
  42. {$DEFINE FPC_FEXPAND_DRIVESEP_IS_ROOT}
  43. {$DEFINE FPC_FEXPAND_NO_DEFAULT_PATHS}
  44. {$I dos.inc}
  45. const
  46. DaysPerMonth : Array[1..12] of ShortInt =
  47. (031,028,031,030,031,030,031,031,030,031,030,031);
  48. DaysPerYear : Array[1..12] of Integer =
  49. (031,059,090,120,151,181,212,243,273,304,334,365);
  50. DaysPerLeapYear : Array[1..12] of Integer =
  51. (031,060,091,121,152,182,213,244,274,305,335,366);
  52. SecsPerYear : LongInt = 31536000;
  53. SecsPerLeapYear : LongInt = 31622400;
  54. SecsPerDay : LongInt = 86400;
  55. SecsPerHour : Integer = 3600;
  56. SecsPerMinute : ShortInt = 60;
  57. TICKSPERSECOND = 50;
  58. Type
  59. pClockData = ^tClockData;
  60. tClockData = packed Record
  61. sec : Word;
  62. min : Word;
  63. hour : Word;
  64. mday : Word;
  65. month : Word;
  66. year : Word;
  67. wday : Word;
  68. END;
  69. BPTR = Longint;
  70. BSTR = Longint;
  71. pMinNode = ^tMinNode;
  72. tMinNode = Packed Record
  73. mln_Succ,
  74. mln_Pred : pMinNode;
  75. End;
  76. pMinList = ^tMinList;
  77. tMinList = Packed record
  78. mlh_Head : pMinNode;
  79. mlh_Tail : pMinNode;
  80. mlh_TailPred : pMinNode;
  81. end;
  82. { * List Node Structure. Each member in a list starts with a Node * }
  83. pNode = ^tNode;
  84. tNode = Packed Record
  85. ln_Succ, { * Pointer to next (successor) * }
  86. ln_Pred : pNode; { * Pointer to previous (predecessor) * }
  87. ln_Type : Byte;
  88. ln_Pri : Shortint; { * Priority, for sorting * }
  89. ln_Name : PCHAR; { * ID string, null terminated * }
  90. End; { * Note: Integer aligned * }
  91. pList = ^tList;
  92. tList = Packed record
  93. lh_Head : pNode;
  94. lh_Tail : pNode;
  95. lh_TailPred : pNode;
  96. lh_Type : Byte;
  97. l_pad : Byte;
  98. end;
  99. pMsgPort = ^tMsgPort;
  100. tMsgPort = Packed record
  101. mp_Node : tNode;
  102. mp_Flags : Byte;
  103. mp_SigBit : Byte; { signal bit number }
  104. mp_SigTask : Pointer; { task to be signalled (TaskPtr) }
  105. mp_MsgList : tList; { message linked list }
  106. end;
  107. pTask = ^tTask;
  108. tTask = Packed record
  109. tc_Node : tNode;
  110. tc_Flags : Byte;
  111. tc_State : Byte;
  112. tc_IDNestCnt : Shortint; { intr disabled nesting }
  113. tc_TDNestCnt : Shortint; { task disabled nesting }
  114. tc_SigAlloc : longint; { sigs allocated }
  115. tc_SigWait : longint; { sigs we are waiting for }
  116. tc_SigRecvd : longint; { sigs we have received }
  117. tc_SigExcept : longint; { sigs we will take excepts for }
  118. tc_TrapAlloc : Word; { traps allocated }
  119. tc_TrapAble : Word; { traps enabled }
  120. tc_ExceptData : Pointer; { points to except data }
  121. tc_ExceptCode : Pointer; { points to except code }
  122. tc_TrapData : Pointer; { points to trap data }
  123. tc_TrapCode : Pointer; { points to trap code }
  124. tc_SPReg : Pointer; { stack pointer }
  125. tc_SPLower : Pointer; { stack lower bound }
  126. tc_SPUpper : Pointer; { stack upper bound + 2 }
  127. tc_Switch : Pointer; { task losing CPU }
  128. tc_Launch : Pointer; { task getting CPU }
  129. tc_MemEntry : tList; { allocated memory }
  130. tc_UserData : Pointer; { per task data }
  131. end;
  132. TDateStamp = packed record
  133. ds_Days : Longint; { Number of days since Jan. 1, 1978 }
  134. ds_Minute : Longint; { Number of minutes past midnight }
  135. ds_Tick : Longint; { Number of ticks past minute }
  136. end;
  137. PDateStamp = ^TDateStamp;
  138. { Returned by Examine() and ExInfo(), must be on a 4 byte boundary }
  139. PFileInfoBlock = ^TfileInfoBlock;
  140. TFileInfoBlock = packed record
  141. fib_DiskKey : Longint;
  142. fib_DirEntryType : Longint;
  143. { Type of Directory. If < 0, then a plain file.
  144. If > 0 a directory }
  145. fib_FileName : Array [0..107] of Char;
  146. { Null terminated. Max 30 chars used for now }
  147. fib_Protection : Longint;
  148. { bit mask of protection, rwxd are 3-0. }
  149. fib_EntryType : Longint;
  150. fib_Size : Longint; { Number of bytes in file }
  151. fib_NumBlocks : Longint; { Number of blocks in file }
  152. fib_Date : TDateStamp; { Date file last changed }
  153. fib_Comment : Array [0..79] of Char;
  154. { Null terminated comment associated with file }
  155. fib_Reserved : Array [0..35] of Char;
  156. end;
  157. { returned by Info(), must be on a 4 byte boundary }
  158. pInfoData = ^tInfoData;
  159. tInfoData = packed record
  160. id_NumSoftErrors : Longint; { number of soft errors on disk }
  161. id_UnitNumber : Longint; { Which unit disk is (was) mounted on }
  162. id_DiskState : Longint; { See defines below }
  163. id_NumBlocks : Longint; { Number of blocks on disk }
  164. id_NumBlocksUsed : Longint; { Number of block in use }
  165. id_BytesPerBlock : Longint;
  166. id_DiskType : Longint; { Disk Type code }
  167. id_VolumeNode : BPTR; { BCPL pointer to volume node }
  168. id_InUse : Longint; { Flag, zero if not in use }
  169. end;
  170. { ------ Library Base Structure ---------------------------------- }
  171. { Also used for Devices and some Resources }
  172. pLibrary = ^tLibrary;
  173. tLibrary = packed record
  174. lib_Node : tNode;
  175. lib_Flags,
  176. lib_pad : Byte;
  177. lib_NegSize, { number of bytes before library }
  178. lib_PosSize, { number of bytes after library }
  179. lib_Version, { major }
  180. lib_Revision : Word; { minor }
  181. lib_IdString : PCHAR; { ASCII identification }
  182. lib_Sum : LONGINT; { the checksum itself }
  183. lib_OpenCnt : Word; { number of current opens }
  184. end; { * Warning: size is not a longword multiple ! * }
  185. PChain = ^TChain;
  186. TChain = packed record
  187. an_Child : PChain;
  188. an_Parent: PChain;
  189. an_Lock : BPTR;
  190. an_info : TFileInfoBlock;
  191. an_Flags : shortint;
  192. an_string: Array[0..0] of char;
  193. end;
  194. PAnchorPath = ^TAnchorPath;
  195. TAnchorPath = packed record
  196. ap_Base : PChain; {* pointer to first anchor *}
  197. ap_First : PChain; {* pointer to last anchor *}
  198. ap_BreakBits : LONGINT; {* Bits we want to break on *}
  199. ap_FondBreak : LONGINT; {* Bits we broke on. Also returns ERROR_BREAK *}
  200. ap_Flags : shortint; {* New use for extra word. *}
  201. ap_reserved : BYTE;
  202. ap_StrLen : WORD;
  203. ap_Info : TFileInfoBlock;
  204. ap_Buf : Array[0..0] of Char; {* Buffer for path name, allocated by user *}
  205. END;
  206. pCommandLineInterface = ^TCommandLineInterface;
  207. TCommandLineInterface = packed record
  208. cli_result2 : longint; {* Value of IoErr from last command *}
  209. cli_SetName : BSTR; {* Name of current directory *}
  210. cli_CommandDir : BPTR; {* Head of the path locklist *}
  211. cli_ReturnCode : longint; {* Return code from last command *}
  212. cli_CommandName : BSTR; {* Name of current command *}
  213. cli_FailLevel : longint; {* Fail level (set by FAILAT) *}
  214. cli_Prompt : BSTR; {* Current prompt (set by PROMPT) *}
  215. cli_StandardInput: BPTR; {* Default (terminal) CLI input *}
  216. cli_CurrentInput : BPTR; {* Current CLI input *}
  217. cli_CommandFile : BSTR; {* Name of EXECUTE command file *}
  218. cli_Interactive : longint; {* Boolean; True if prompts required *}
  219. cli_Background : longint; {* Boolean; True if CLI created by RUN*}
  220. cli_CurrentOutput: BPTR; {* Current CLI output *}
  221. cli_DefautlStack : longint; {* Stack size to be obtained in long words *}
  222. cli_StandardOutput : BPTR; {* Default (terminal) CLI output *}
  223. cli_Module : BPTR; {* SegList of currently loaded command*}
  224. END;
  225. pDosList = ^tDosList;
  226. tDosList = packed record
  227. dol_Next : BPTR; { bptr to next device on list }
  228. dol_Type : Longint; { see DLT below }
  229. dol_Task : Pointer; { ptr to handler task }
  230. dol_Lock : BPTR;
  231. dol_Misc : Array[0..23] of Shortint;
  232. dol_Name : BSTR; { bptr to bcpl name }
  233. END;
  234. TProcess = packed record
  235. pr_Task : TTask;
  236. pr_MsgPort : TMsgPort; { This is BPTR address from DOS functions }
  237. {126} pr_Pad : Word; { Remaining variables on 4 byte boundaries }
  238. {128} pr_SegList : Pointer; { Array of seg lists used by this process }
  239. {132} pr_StackSize : Longint; { Size of process stack in bytes }
  240. {136} pr_GlobVec : Pointer; { Global vector for this process (BCPL) }
  241. {140} pr_TaskNum : Longint; { CLI task number of zero if not a CLI }
  242. {144} pr_StackBase : BPTR; { Ptr to high memory end of process stack }
  243. {148} pr_Result2 : Longint; { Value of secondary result from last call }
  244. {152} pr_CurrentDir : BPTR; { Lock associated with current directory }
  245. {156} pr_CIS : BPTR; { Current CLI Input Stream }
  246. {160} pr_COS : BPTR; { Current CLI Output Stream }
  247. {164} pr_ConsoleTask : Pointer; { Console handler process for current window}
  248. {168} pr_FileSystemTask : Pointer; { File handler process for current drive }
  249. {172} pr_CLI : BPTR; { pointer to ConsoleLineInterpreter }
  250. pr_ReturnAddr : Pointer; { pointer to previous stack frame }
  251. pr_PktWait : Pointer; { Function to be called when awaiting msg }
  252. pr_WindowPtr : Pointer; { Window for error printing }
  253. { following definitions are new with 2.0 }
  254. pr_HomeDir : BPTR; { Home directory of executing program }
  255. pr_Flags : Longint; { flags telling dos about process }
  256. pr_ExitCode : Pointer; { code to call on exit of program OR NULL }
  257. pr_ExitData : Longint; { Passed as an argument to pr_ExitCode. }
  258. pr_Arguments : PChar; { Arguments passed to the process at start }
  259. pr_LocalVars : TMinList; { Local environment variables }
  260. pr_ShellPrivate : Longint; { for the use of the current shell }
  261. pr_CES : BPTR; { Error stream - IF NULL, use pr_COS }
  262. end;
  263. PProcess = ^TProcess;
  264. CONST
  265. { DOS Lib Offsets }
  266. _LVOMatchFirst = -822;
  267. _LVOMatchNext = -828;
  268. _LVOMatchEnd = -834;
  269. _LVOCli = -492;
  270. _LVOExecute = -222;
  271. _LVOSystemTagList = -606;
  272. _LVOSetFileDate = -396;
  273. LDF_READ = 1;
  274. LDF_DEVICES = 4;
  275. ERROR_NO_MORE_ENTRIES = 232;
  276. FIBF_SCRIPT = 64; { program is a script }
  277. FIBF_PURE = 32; { program is reentrant }
  278. FIBF_ARCHIVE = 16; { cleared whenever file is changed }
  279. FIBF_READ = 8; { ignoed by old filesystem }
  280. FIBF_WRITE = 4; { ignored by old filesystem }
  281. FIBF_EXECUTE = 2; { ignored by system, used by shell }
  282. FIBF_DELETE = 1; { prevent file from being deleted }
  283. SHARED_LOCK = -2;
  284. {******************************************************************************
  285. --- Internal routines ---
  286. ******************************************************************************}
  287. procedure CurrentTime(var Seconds, Micros : Longint);
  288. Begin
  289. asm
  290. MOVE.L A6,-(A7)
  291. MOVE.L Seconds,a0
  292. MOVE.L Micros,a1
  293. MOVE.L _IntuitionBase,A6
  294. JSR -084(A6)
  295. MOVE.L (A7)+,A6
  296. end;
  297. end;
  298. function Date2Amiga(date : pClockData) : Longint;
  299. Begin
  300. asm
  301. MOVE.L A6,-(A7)
  302. MOVE.L date,a0
  303. MOVE.L _UtilityBase,A6
  304. JSR -126(A6)
  305. MOVE.L (A7)+,A6
  306. MOVE.L d0,@RESULT
  307. end;
  308. end;
  309. procedure Amiga2Date(amigatime : Longint;
  310. resultat : pClockData);
  311. Begin
  312. asm
  313. MOVE.L A6,-(A7)
  314. MOVE.L amigatime,d0
  315. MOVE.L resultat,a0
  316. MOVE.L _UtilityBase,A6
  317. JSR -120(A6)
  318. MOVE.L (A7)+,A6
  319. end;
  320. end;
  321. FUNCTION Examine(lock : BPTR; fileInfoBlock : pFileInfoBlock) : BOOLEAN;
  322. BEGIN
  323. ASM
  324. MOVE.L A6,-(A7)
  325. MOVE.L lock,D1
  326. MOVE.L fileInfoBlock,D2
  327. MOVEA.L _DOSBase,A6
  328. JSR -102(A6)
  329. MOVEA.L (A7)+,A6
  330. TST.L D0
  331. BEQ.B @end
  332. MOVE.B #1,D0
  333. @end: MOVE.B D0,@RESULT
  334. END;
  335. END;
  336. function Lock(const name : string;
  337. accessmode : Longint) : BPTR;
  338. var
  339. buffer: Array[0..255] of char;
  340. Begin
  341. move(name[1],buffer,length(name));
  342. buffer[length(name)]:=#0;
  343. asm
  344. MOVEM.L d2/a6,-(A7)
  345. LEA buffer,a0
  346. MOVE.L a0,d1
  347. MOVE.L accessmode,d2
  348. MOVE.L _DOSBase,A6
  349. JSR -084(A6)
  350. MOVEM.L (A7)+,d2/a6
  351. MOVE.L d0,@RESULT
  352. end;
  353. end;
  354. procedure UnLock(lock : BPTR);
  355. Begin
  356. asm
  357. MOVE.L A6,-(A7)
  358. MOVE.L lock,d1
  359. MOVE.L _DOSBase,A6
  360. JSR -090(A6)
  361. MOVE.L (A7)+,A6
  362. end;
  363. end;
  364. FUNCTION Info(lock : BPTR; parameterBlock : pInfoData) : BOOLEAN;
  365. BEGIN
  366. ASM
  367. MOVE.L A6,-(A7)
  368. MOVE.L lock,D1
  369. MOVE.L parameterBlock,D2
  370. MOVEA.L _DOSBase,A6
  371. JSR -114(A6)
  372. MOVEA.L (A7)+,A6
  373. TST.L D0
  374. BEQ.B @end
  375. MOVE.B #1,D0
  376. @end:
  377. MOVE.B D0,@RESULT
  378. END;
  379. END;
  380. FUNCTION NameFromLock(lock : BPTR; buffer : pCHAR; len : LONGINT) : BOOLEAN;
  381. BEGIN
  382. ASM
  383. MOVE.L A6,-(A7)
  384. MOVE.L lock,D1
  385. MOVE.L buffer,D2
  386. MOVE.L len,D3
  387. MOVEA.L _DOSBase,A6
  388. JSR -402(A6)
  389. MOVEA.L (A7)+,A6
  390. TST.L D0
  391. BEQ.B @end
  392. MOVE.B #1,D0
  393. @end: MOVE.B D0,@RESULT
  394. END;
  395. END;
  396. FUNCTION GetVar(name : pCHAR; buffer : pCHAR; size : LONGINT; flags : LONGINT) : LONGINT;
  397. BEGIN
  398. ASM
  399. MOVE.L A6,-(A7)
  400. MOVE.L name,D1
  401. MOVE.L buffer,D2
  402. MOVE.L size,D3
  403. MOVE.L flags,D4
  404. MOVEA.L _DOSBase,A6
  405. JSR -906(A6)
  406. MOVEA.L (A7)+,A6
  407. MOVE.L D0,@RESULT
  408. END;
  409. END;
  410. FUNCTION FindTask(name : pCHAR) : pTask;
  411. BEGIN
  412. ASM
  413. MOVE.L A6,-(A7)
  414. MOVEA.L name,A1
  415. MOVEA.L _ExecBase,A6
  416. JSR -294(A6)
  417. MOVEA.L (A7)+,A6
  418. MOVE.L D0,@RESULT
  419. END;
  420. END;
  421. FUNCTION MatchFirst(pat : pCHAR; anchor : pAnchorPath) : LONGINT;
  422. BEGIN
  423. ASM
  424. MOVE.L A6,-(A7)
  425. MOVE.L pat,D1
  426. MOVE.L anchor,D2
  427. MOVEA.L _DOSBase,A6
  428. JSR -822(A6)
  429. MOVEA.L (A7)+,A6
  430. MOVE.L D0,@RESULT
  431. END;
  432. END;
  433. FUNCTION MatchNext(anchor : pAnchorPath) : LONGINT;
  434. BEGIN
  435. ASM
  436. MOVE.L A6,-(A7)
  437. MOVE.L anchor,D1
  438. MOVEA.L _DOSBase,A6
  439. JSR -828(A6)
  440. MOVEA.L (A7)+,A6
  441. MOVE.L D0,@RESULT
  442. END;
  443. END;
  444. PROCEDURE MatchEnd(anchor : pAnchorPath);
  445. BEGIN
  446. ASM
  447. MOVE.L A6,-(A7)
  448. MOVE.L anchor,D1
  449. MOVEA.L _DOSBase,A6
  450. JSR -834(A6)
  451. MOVEA.L (A7)+,A6
  452. END;
  453. END;
  454. FUNCTION Cli : pCommandLineInterface;
  455. BEGIN
  456. ASM
  457. MOVE.L A6,-(A7)
  458. MOVEA.L _DOSBase,A6
  459. JSR -492(A6)
  460. MOVEA.L (A7)+,A6
  461. MOVE.L D0,@RESULT
  462. END;
  463. END;
  464. Function _Execute(p: pchar): longint;
  465. Begin
  466. asm
  467. move.l a6,d6 { save base pointer }
  468. move.l d2,-(sp)
  469. move.l p,d1 { command to execute }
  470. clr.l d2 { No TagList for command }
  471. move.l _DosBase,a6
  472. jsr _LVOSystemTagList(a6)
  473. move.l (sp)+,d2
  474. move.l d6,a6 { restore base pointer }
  475. move.l d0,@RESULT
  476. end;
  477. end;
  478. FUNCTION LockDosList(flags : longint) : pDosList;
  479. BEGIN
  480. ASM
  481. MOVE.L A6,-(A7)
  482. MOVE.L flags,D1
  483. MOVEA.L _DOSBase,A6
  484. JSR -654(A6)
  485. MOVEA.L (A7)+,A6
  486. MOVE.L D0,@RESULT
  487. END;
  488. END;
  489. PROCEDURE UnLockDosList(flags : longint);
  490. BEGIN
  491. ASM
  492. MOVE.L A6,-(A7)
  493. MOVE.L flags,D1
  494. MOVEA.L _DOSBase,A6
  495. JSR -660(A6)
  496. MOVEA.L (A7)+,A6
  497. END;
  498. END;
  499. FUNCTION NextDosEntry(dlist : pDosList; flags : longint) : pDosList;
  500. BEGIN
  501. ASM
  502. MOVE.L A6,-(A7)
  503. MOVE.L dlist,D1
  504. MOVE.L flags,D2
  505. MOVEA.L _DOSBase,A6
  506. JSR -690(A6)
  507. MOVEA.L (A7)+,A6
  508. MOVE.L D0,@RESULT
  509. END;
  510. END;
  511. FUNCTION BADDR(bval : BPTR): POINTER;
  512. BEGIN
  513. BADDR := POINTER( bval shl 2);
  514. END;
  515. function PasToC(var s: string): Pchar;
  516. var i: integer;
  517. begin
  518. i := Length(s) + 1;
  519. if i > 255 then
  520. begin
  521. Delete(s, 255, 1); { ensure there is a spare byte }
  522. Dec(i)
  523. end;
  524. s[i] := #0;
  525. PasToC := @s[1]
  526. end;
  527. Function SetProtection(const name: string; mask:longint): longint;
  528. var
  529. buffer : array[0..255] of char;
  530. Begin
  531. move(name[1],buffer,length(name));
  532. buffer[length(name)]:=#0;
  533. asm
  534. move.l a6,d6
  535. lea buffer,a0
  536. move.l a0,d1
  537. move.l mask,d2
  538. move.l _DosBase,a6
  539. jsr -186(a6)
  540. move.l d6,a6
  541. move.l d0,@RESULT
  542. end;
  543. end;
  544. Function IsLeapYear(Source : Word) : Boolean;
  545. Begin
  546. If (Source mod 400 = 0) or ((Source mod 4 = 0) and (Source mod 100 <> 0))
  547. Then
  548. IsLeapYear := True
  549. Else
  550. IsLeapYear := False;
  551. End;
  552. Procedure Amiga2DateStamp(Date : LongInt; Var TotalDays,Minutes,Ticks: longint);
  553. { Converts a value in seconds past 1978 to a value in AMIGA DateStamp format }
  554. { Taken from SWAG and modified to work with the Amiga format - CEC }
  555. Var
  556. LocalDate : LongInt; Done : Boolean; X : ShortInt; TotDays : Integer;
  557. Y: Word;
  558. M: Word;
  559. D: Word;
  560. H: Word;
  561. Min: Word;
  562. S : Word;
  563. Begin
  564. Y := 1978; M := 1; D := 1; H := 0; Min := 0; S := 0;
  565. TotalDays := 0;
  566. Minutes := 0;
  567. Ticks := 0;
  568. LocalDate := Date;
  569. Done := False;
  570. While Not Done Do
  571. Begin
  572. If LocalDate >= SecsPerYear Then
  573. Begin
  574. Inc(Y,1);
  575. Dec(LocalDate,SecsPerYear);
  576. Inc(TotalDays,DaysPerYear[12]);
  577. End
  578. Else
  579. Done := True;
  580. If (IsLeapYear(Y+1)) And (LocalDate >= SecsPerLeapYear) And
  581. (Not Done) Then
  582. Begin
  583. Inc(Y,1);
  584. Dec(LocalDate,SecsPerLeapYear);
  585. Inc(TotalDays,DaysPerLeapYear[12]);
  586. End;
  587. End; { END WHILE }
  588. M := 1; D := 1;
  589. Done := False;
  590. TotDays := LocalDate Div SecsPerDay;
  591. { Total number of days }
  592. TotalDays := TotalDays + TotDays;
  593. Dec(LocalDate,TotDays*SecsPerDay);
  594. { Absolute hours since start of day }
  595. H := LocalDate Div SecsPerHour;
  596. { Convert to minutes }
  597. Minutes := H*60;
  598. Dec(LocalDate,(H * SecsPerHour));
  599. { Find the remaining minutes to add }
  600. Min := LocalDate Div SecsPerMinute;
  601. Dec(LocalDate,(Min * SecsPerMinute));
  602. Minutes:=Minutes+Min;
  603. { Find the number of seconds and convert to ticks }
  604. S := LocalDate;
  605. Ticks:=TICKSPERSECOND*S;
  606. End;
  607. Function SetFileDate(name: string; p : pDateStamp): longint;
  608. var
  609. buffer : array[0..255] of char;
  610. Begin
  611. move(name[1],buffer,length(name));
  612. buffer[length(name)]:=#0;
  613. asm
  614. move.l a6,d6 { save base pointer }
  615. move.l d2,-(sp) { save reserved reg }
  616. lea buffer,a0
  617. move.l a0,d1
  618. move.l p,d2
  619. move.l _DosBase,a6
  620. jsr _LVOSetFileDate(a6)
  621. move.l (sp)+,d2 { restore reserved reg }
  622. move.l d6,a6 { restore base pointer }
  623. move.l d0,@Result
  624. end;
  625. end;
  626. {******************************************************************************
  627. --- Info / Date / Time ---
  628. ******************************************************************************}
  629. Function DosVersion: Word;
  630. var p: pLibrary;
  631. Begin
  632. p:=pLibrary(_DosBase);
  633. DosVersion:= p^.lib_Version or (p^.lib_Revision shl 8);
  634. End;
  635. Procedure GetDate(Var Year, Month, MDay, WDay: Word);
  636. Var
  637. cd : pClockData;
  638. mysec,
  639. tick : Longint;
  640. begin
  641. New(cd);
  642. CurrentTime(mysec,tick);
  643. Amiga2Date(mysec,cd);
  644. Year := cd^.year;
  645. Month := cd^.month;
  646. MDay := cd^.mday;
  647. WDay := cd^.wday;
  648. Dispose(cd);
  649. end;
  650. Procedure SetDate(Year, Month, Day: Word);
  651. Begin
  652. { !! }
  653. End;
  654. Procedure GetTime(Var Hour, Minute, Second, Sec100: Word);
  655. Var
  656. mysec,
  657. tick : Longint;
  658. cd : pClockData;
  659. begin
  660. New(cd);
  661. CurrentTime(mysec,tick);
  662. Amiga2Date(mysec,cd);
  663. Hour := cd^.hour;
  664. Minute := cd^.min;
  665. Second := cd^.sec;
  666. Sec100 := 0;
  667. Dispose(cd);
  668. END;
  669. Procedure SetTime(Hour, Minute, Second, Sec100: Word);
  670. Begin
  671. { !! }
  672. End;
  673. {******************************************************************************
  674. --- Exec ---
  675. ******************************************************************************}
  676. Procedure Exec (Const Path: PathStr; Const ComLine: ComStr);
  677. var
  678. p : string;
  679. buf: array[0..255] of char;
  680. result : longint;
  681. MyLock : longint;
  682. i : Integer;
  683. Begin
  684. DosError := 0;
  685. LastdosExitCode := 0;
  686. p:=Path+' '+ComLine;
  687. { allow backslash as slash }
  688. for i:=1 to length(p) do
  689. if p[i]='\' then p[i]:='/';
  690. Move(p[1],buf,length(p));
  691. buf[Length(p)]:=#0;
  692. { Here we must first check if the command we wish to execute }
  693. { actually exists, because this is NOT handled by the }
  694. { _SystemTagList call (program will abort!!) }
  695. { Try to open with shared lock }
  696. MyLock:=Lock(path,SHARED_LOCK);
  697. if MyLock <> 0 then
  698. Begin
  699. { File exists - therefore unlock it }
  700. Unlock(MyLock);
  701. result:=_Execute(buf);
  702. { on return of -1 the shell could not be executed }
  703. { probably because there was not enough memory }
  704. if result = -1 then
  705. DosError:=8
  706. else
  707. LastDosExitCode:=word(result);
  708. end
  709. else
  710. DosError:=3;
  711. End;
  712. Procedure GetCBreak(Var BreakValue: Boolean);
  713. Begin
  714. breakvalue := system.BreakOn;
  715. End;
  716. Procedure SetCBreak(BreakValue: Boolean);
  717. Begin
  718. system.Breakon := BreakValue;
  719. End;
  720. {******************************************************************************
  721. --- Disk ---
  722. ******************************************************************************}
  723. { How to solve the problem with this: }
  724. { We could walk through the device list }
  725. { at startup to determine possible devices }
  726. const
  727. not_to_use_devs : array[0..12] of string =(
  728. 'DF0:',
  729. 'DF1:',
  730. 'DF2:',
  731. 'DF3:',
  732. 'PED:',
  733. 'PRJ:',
  734. 'PIPE:',
  735. 'RAM:',
  736. 'CON:',
  737. 'RAW:',
  738. 'SER:',
  739. 'PAR:',
  740. 'PRT:');
  741. var
  742. deviceids : array[1..20] of byte;
  743. devicenames : array[1..20] of string[20];
  744. numberofdevices : Byte;
  745. Function DiskFree(Drive: Byte): Longint;
  746. Var
  747. MyLock : BPTR;
  748. Inf : pInfoData;
  749. Free : Longint;
  750. myproc : pProcess;
  751. OldWinPtr : Pointer;
  752. Begin
  753. Free := -1;
  754. { Here we stop systemrequesters to appear }
  755. myproc := pProcess(FindTask(nil));
  756. OldWinPtr := myproc^.pr_WindowPtr;
  757. myproc^.pr_WindowPtr := Pointer(-1);
  758. { End of systemrequesterstop }
  759. New(Inf);
  760. MyLock := Lock(devicenames[deviceids[Drive]],SHARED_LOCK);
  761. If MyLock <> 0 then begin
  762. if Info(MyLock,Inf) then begin
  763. Free := (Inf^.id_NumBlocks * Inf^.id_BytesPerBlock) -
  764. (Inf^.id_NumBlocksUsed * Inf^.id_BytesPerBlock);
  765. end;
  766. Unlock(MyLock);
  767. end;
  768. Dispose(Inf);
  769. { Restore systemrequesters }
  770. myproc^.pr_WindowPtr := OldWinPtr;
  771. diskfree := Free;
  772. end;
  773. Function DiskSize(Drive: Byte): Longint;
  774. Var
  775. MyLock : BPTR;
  776. Inf : pInfoData;
  777. Size : Longint;
  778. myproc : pProcess;
  779. OldWinPtr : Pointer;
  780. Begin
  781. Size := -1;
  782. { Here we stop systemrequesters to appear }
  783. myproc := pProcess(FindTask(nil));
  784. OldWinPtr := myproc^.pr_WindowPtr;
  785. myproc^.pr_WindowPtr := Pointer(-1);
  786. { End of systemrequesterstop }
  787. New(Inf);
  788. MyLock := Lock(devicenames[deviceids[Drive]],SHARED_LOCK);
  789. If MyLock <> 0 then begin
  790. if Info(MyLock,Inf) then begin
  791. Size := (Inf^.id_NumBlocks * Inf^.id_BytesPerBlock);
  792. end;
  793. Unlock(MyLock);
  794. end;
  795. Dispose(Inf);
  796. { Restore systemrequesters }
  797. myproc^.pr_WindowPtr := OldWinPtr;
  798. disksize := Size;
  799. end;
  800. Procedure FindFirst(Path: PathStr; Attr: Word; Var f: SearchRec);
  801. var
  802. buf: Array[0..255] of char;
  803. Anchor : pAnchorPath;
  804. Result : Longint;
  805. index : Integer;
  806. s : string;
  807. j : integer;
  808. Begin
  809. DosError:=0;
  810. New(Anchor);
  811. {----- allow backslash as slash -----}
  812. for index:=1 to length(path) do
  813. if path[index]='\' then path[index]:='/';
  814. { remove any dot characters and replace by their current }
  815. { directory equivalent. }
  816. if pos('../',path) = 1 then
  817. { look for parent directory }
  818. Begin
  819. delete(path,1,3);
  820. getdir(0,s);
  821. j:=length(s);
  822. while (s[j] <> '/') AND (s[j] <> ':') AND (j > 0 ) do
  823. dec(j);
  824. if j > 0 then
  825. s:=copy(s,1,j);
  826. path:=s+path;
  827. end
  828. else
  829. if pos('./',path) = 1 then
  830. { look for current directory }
  831. Begin
  832. delete(path,1,2);
  833. getdir(0,s);
  834. if (s[length(s)] <> '/') and (s[length(s)] <> ':') then
  835. s:=s+'/';
  836. path:=s+path;
  837. end;
  838. {----- replace * by #? AmigaOs strings -----}
  839. repeat
  840. index:= pos('*',Path);
  841. if index <> 0 then
  842. Begin
  843. delete(Path,index,1);
  844. insert('#?',Path,index);
  845. end;
  846. until index =0;
  847. {--------------------------------------------}
  848. FillChar(Anchor^,sizeof(TAnchorPath),#0);
  849. move(path[1],buf,length(path));
  850. buf[length(path)]:=#0;
  851. Result:=MatchFirst(@buf,Anchor);
  852. f.AnchorPtr:=Anchor;
  853. if Result = ERROR_NO_MORE_ENTRIES then
  854. DosError:=18
  855. else
  856. if Result <> 0 then
  857. DosError:=3;
  858. { If there is an error, deallocate }
  859. { the anchorpath structure }
  860. if DosError <> 0 then
  861. Begin
  862. MatchEnd(Anchor);
  863. if assigned(Anchor) then
  864. Dispose(Anchor);
  865. end
  866. else
  867. {-------------------------------------------------------------------}
  868. { Here we fill up the SearchRec attribute, but we also do check }
  869. { something else, if the it does not match the mask we are looking }
  870. { for we should go to the next file or directory. }
  871. {-------------------------------------------------------------------}
  872. Begin
  873. with Anchor^.ap_Info do
  874. Begin
  875. f.Time := fib_Date.ds_Days * (24 * 60 * 60) +
  876. fib_Date.ds_Minute * 60 +
  877. fib_Date.ds_Tick div 50;
  878. {*------------------------------------*}
  879. {* Determine if is a file or a folder *}
  880. {*------------------------------------*}
  881. if fib_DirEntryType > 0 then
  882. f.attr:=f.attr OR DIRECTORY;
  883. {*------------------------------------*}
  884. {* Determine if Read only *}
  885. {* Readonly if R flag on and W flag *}
  886. {* off. *}
  887. {* Should we check also that EXEC *}
  888. {* is zero? for read only? *}
  889. {*------------------------------------*}
  890. if ((fib_Protection and FIBF_READ) <> 0)
  891. AND ((fib_Protection and FIBF_WRITE) = 0)
  892. then
  893. f.attr:=f.attr or READONLY;
  894. f.Name := strpas(fib_FileName);
  895. f.Size := fib_Size;
  896. end; { end with }
  897. end;
  898. End;
  899. Procedure FindNext(Var f: SearchRec);
  900. var
  901. Result: longint;
  902. Anchor : pAnchorPath;
  903. Begin
  904. DosError:=0;
  905. Result:=MatchNext(f.AnchorPtr);
  906. if Result = ERROR_NO_MORE_ENTRIES then
  907. DosError:=18
  908. else
  909. if Result <> 0 then
  910. DosError:=3;
  911. { If there is an error, deallocate }
  912. { the anchorpath structure }
  913. if DosError <> 0 then
  914. Begin
  915. MatchEnd(f.AnchorPtr);
  916. if assigned(f.AnchorPtr) then
  917. {Dispose}FreeMem(f.AnchorPtr);
  918. end
  919. else
  920. { Fill up the Searchrec information }
  921. { and also check if the files are with }
  922. { the correct attributes }
  923. Begin
  924. Anchor:=pAnchorPath(f.AnchorPtr);
  925. with Anchor^.ap_Info do
  926. Begin
  927. f.Time := fib_Date.ds_Days * (24 * 60 * 60) +
  928. fib_Date.ds_Minute * 60 +
  929. fib_Date.ds_Tick div 50;
  930. {*------------------------------------*}
  931. {* Determine if is a file or a folder *}
  932. {*------------------------------------*}
  933. if fib_DirEntryType > 0 then
  934. f.attr:=f.attr OR DIRECTORY;
  935. {*------------------------------------*}
  936. {* Determine if Read only *}
  937. {* Readonly if R flag on and W flag *}
  938. {* off. *}
  939. {* Should we check also that EXEC *}
  940. {* is zero? for read only? *}
  941. {*------------------------------------*}
  942. if ((fib_Protection and FIBF_READ) <> 0)
  943. AND ((fib_Protection and FIBF_WRITE) = 0)
  944. then
  945. f.attr:=f.attr or READONLY;
  946. f.Name := strpas(fib_FileName);
  947. f.Size := fib_Size;
  948. end; { end with }
  949. end;
  950. End;
  951. Procedure FindClose(Var f: SearchRec);
  952. begin
  953. end;
  954. {******************************************************************************
  955. --- File ---
  956. ******************************************************************************}
  957. (*
  958. Function FExpand(Path: PathStr): PathStr;
  959. var
  960. FLock : BPTR;
  961. buffer : array[0..255] of char;
  962. i :integer;
  963. j :integer;
  964. temp : string;
  965. begin
  966. { allow backslash as slash }
  967. for i:=1 to length(path) do
  968. if path[i]='\' then path[i]:='/';
  969. temp:=path;
  970. if pos('../',temp) = 1 then
  971. delete(temp,1,3);
  972. if pos('./',temp) = 1 then
  973. delete(temp,1,2);
  974. {First remove all references to '/./'}
  975. while pos('/./',temp)<>0 do
  976. delete(temp,pos('/./',temp),3);
  977. {Now remove also all references to '/../' + of course previous dirs..}
  978. repeat
  979. i:=pos('/../',temp);
  980. {Find the pos of the previous dir}
  981. if i>1 then
  982. begin
  983. j:=i-1;
  984. while (j>1) and (temp[j]<>'/') do
  985. dec (j);{temp[1] is always '/'}
  986. delete(temp,j,i-j+4);
  987. end
  988. else
  989. if i=1 then {i=1, so we have temp='/../something', just delete '/../'}
  990. delete(temp,1,4);
  991. until i=0;
  992. FLock := Lock(temp,-2);
  993. if FLock <> 0 then begin
  994. if NameFromLock(FLock,buffer,255) then begin
  995. Unlock(FLock);
  996. FExpand := strpas(buffer);
  997. end else begin
  998. Unlock(FLock);
  999. FExpand := '';
  1000. end;
  1001. end else FExpand := '';
  1002. end;
  1003. *)
  1004. Function fsearch(path : pathstr;dirlist : string) : pathstr;
  1005. var
  1006. i,p1 : longint;
  1007. s : searchrec;
  1008. newdir : pathstr;
  1009. begin
  1010. { No wildcards allowed in these things }
  1011. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  1012. fsearch:=''
  1013. else
  1014. begin
  1015. { allow slash as backslash }
  1016. for i:=1 to length(dirlist) do
  1017. if dirlist[i]='\' then dirlist[i]:='/';
  1018. repeat
  1019. p1:=pos(';',dirlist);
  1020. if p1<>0 then
  1021. begin
  1022. newdir:=copy(dirlist,1,p1-1);
  1023. delete(dirlist,1,p1);
  1024. end
  1025. else
  1026. begin
  1027. newdir:=dirlist;
  1028. dirlist:='';
  1029. end;
  1030. if (newdir<>'') and (not (newdir[length(newdir)] in ['/',':'])) then
  1031. newdir:=newdir+'/';
  1032. findfirst(newdir+path,anyfile,s);
  1033. if doserror=0 then
  1034. newdir:=newdir+path
  1035. else
  1036. newdir:='';
  1037. until (dirlist='') or (newdir<>'');
  1038. fsearch:=newdir;
  1039. end;
  1040. end;
  1041. Procedure getftime (var f; var time : longint);
  1042. {
  1043. This function returns a file's date and time as the number of
  1044. seconds after January 1, 1978 that the file was created.
  1045. }
  1046. var
  1047. FInfo : pFileInfoBlock;
  1048. FTime : Longint;
  1049. FLock : Longint;
  1050. Str : String;
  1051. i : integer;
  1052. begin
  1053. DosError:=0;
  1054. FTime := 0;
  1055. Str := StrPas(filerec(f).name);
  1056. for i:=1 to length(Str) do
  1057. if str[i]='\' then str[i]:='/';
  1058. FLock := Lock(Str, SHARED_LOCK);
  1059. IF FLock <> 0 then begin
  1060. New(FInfo);
  1061. if Examine(FLock, FInfo) then begin
  1062. with FInfo^.fib_Date do
  1063. FTime := ds_Days * (24 * 60 * 60) +
  1064. ds_Minute * 60 +
  1065. ds_Tick div 50;
  1066. end else begin
  1067. FTime := 0;
  1068. end;
  1069. Unlock(FLock);
  1070. Dispose(FInfo);
  1071. end
  1072. else
  1073. DosError:=6;
  1074. time := FTime;
  1075. end;
  1076. Procedure setftime(var f; time : longint);
  1077. var
  1078. DateStamp: pDateStamp;
  1079. Str: String;
  1080. i: Integer;
  1081. Days, Minutes,Ticks: longint;
  1082. FLock: longint;
  1083. Begin
  1084. new(DateStamp);
  1085. Str := StrPas(filerec(f).name);
  1086. for i:=1 to length(Str) do
  1087. if str[i]='\' then str[i]:='/';
  1088. { Check first of all, if file exists }
  1089. FLock := Lock(Str, SHARED_LOCK);
  1090. IF FLock <> 0 then
  1091. begin
  1092. Unlock(FLock);
  1093. Amiga2DateStamp(time,Days,Minutes,ticks);
  1094. DateStamp^.ds_Days:=Days;
  1095. DateStamp^.ds_Minute:=Minutes;
  1096. DateStamp^.ds_Tick:=Ticks;
  1097. if SetFileDate(Str,DateStamp) <> 0 then
  1098. DosError:=0
  1099. else
  1100. DosError:=6;
  1101. end
  1102. else
  1103. DosError:=2;
  1104. if assigned(DateStamp) then Dispose(DateStamp);
  1105. End;
  1106. Procedure getfattr(var f; var attr : word);
  1107. var
  1108. info : pFileInfoBlock;
  1109. MyLock : Longint;
  1110. flags: word;
  1111. Str: String;
  1112. i: integer;
  1113. Begin
  1114. DosError:=0;
  1115. flags:=0;
  1116. New(info);
  1117. Str := StrPas(filerec(f).name);
  1118. for i:=1 to length(Str) do
  1119. if str[i]='\' then str[i]:='/';
  1120. { open with shared lock to check if file exists }
  1121. MyLock:=Lock(Str,SHARED_LOCK);
  1122. if MyLock <> 0 then
  1123. Begin
  1124. Examine(MyLock,info);
  1125. {*------------------------------------*}
  1126. {* Determine if is a file or a folder *}
  1127. {*------------------------------------*}
  1128. if info^.fib_DirEntryType > 0 then
  1129. flags:=flags OR DIRECTORY;
  1130. {*------------------------------------*}
  1131. {* Determine if Read only *}
  1132. {* Readonly if R flag on and W flag *}
  1133. {* off. *}
  1134. {* Should we check also that EXEC *}
  1135. {* is zero? for read only? *}
  1136. {*------------------------------------*}
  1137. if ((info^.fib_Protection and FIBF_READ) <> 0)
  1138. AND ((info^.fib_Protection and FIBF_WRITE) = 0)
  1139. then
  1140. flags:=flags OR ReadOnly;
  1141. Unlock(mylock);
  1142. end
  1143. else
  1144. DosError:=3;
  1145. attr:=flags;
  1146. Dispose(info);
  1147. End;
  1148. Procedure setfattr (var f;attr : word);
  1149. var
  1150. flags: longint;
  1151. MyLock : longint;
  1152. str: string;
  1153. i: integer;
  1154. Begin
  1155. DosError:=0;
  1156. flags:=FIBF_WRITE;
  1157. { open with shared lock }
  1158. Str := StrPas(filerec(f).name);
  1159. for i:=1 to length(Str) do
  1160. if str[i]='\' then str[i]:='/';
  1161. MyLock:=Lock(Str,SHARED_LOCK);
  1162. { By default files are read-write }
  1163. if attr AND ReadOnly <> 0 then
  1164. { Clear the Fibf_write flags }
  1165. flags:=FIBF_READ;
  1166. if MyLock <> 0 then
  1167. Begin
  1168. Unlock(MyLock);
  1169. if SetProtection(Str,flags) = 0 then
  1170. DosError:=5;
  1171. end
  1172. else
  1173. DosError:=3;
  1174. End;
  1175. {******************************************************************************
  1176. --- Environment ---
  1177. ******************************************************************************}
  1178. var
  1179. StrofPaths : string[255];
  1180. function getpathstring: string;
  1181. var
  1182. f : text;
  1183. s : string;
  1184. found : boolean;
  1185. temp : string[255];
  1186. begin
  1187. found := true;
  1188. temp := '';
  1189. assign(f,'ram:makepathstr');
  1190. rewrite(f);
  1191. writeln(f,'path >ram:temp.lst');
  1192. close(f);
  1193. exec('c:protect','ram:makepathstr sarwed');
  1194. exec('C:execute','ram:makepathstr');
  1195. exec('c:delete','ram:makepathstr quiet');
  1196. assign(f,'ram:temp.lst');
  1197. reset(f);
  1198. { skip the first line, garbage }
  1199. if not eof(f) then readln(f,s);
  1200. while not eof(f) do begin
  1201. readln(f,s);
  1202. if found then begin
  1203. temp := s;
  1204. found := false;
  1205. end else begin;
  1206. if (length(s) + length(temp)) < 255 then
  1207. temp := temp + ';' + s;
  1208. end;
  1209. end;
  1210. close(f);
  1211. exec('C:delete','ram:temp.lst quiet');
  1212. getpathstring := temp;
  1213. end;
  1214. Function EnvCount: Longint;
  1215. { HOW TO GET THIS VALUE: }
  1216. { Each time this function is called, we look at the }
  1217. { local variables in the Process structure (2.0+) }
  1218. { And we also read all files in the ENV: directory }
  1219. Begin
  1220. End;
  1221. Function EnvStr(Index: longint): String;
  1222. Begin
  1223. EnvStr:='';
  1224. End;
  1225. function GetEnv(envvar : String): String;
  1226. var
  1227. bufarr : array[0..255] of char;
  1228. strbuffer : array[0..255] of char;
  1229. temp : Longint;
  1230. begin
  1231. if UpCase(envvar) = 'PATH' then begin
  1232. if StrOfpaths = '' then StrOfPaths := GetPathString;
  1233. GetEnv := StrofPaths;
  1234. end else begin
  1235. move(envvar,strbuffer,length(envvar));
  1236. strbuffer[length(envvar)] := #0;
  1237. temp := GetVar(strbuffer,bufarr,255,$100);
  1238. if temp = -1 then
  1239. GetEnv := ''
  1240. else GetEnv := StrPas(bufarr);
  1241. end;
  1242. end;
  1243. procedure AddDevice(str : String);
  1244. begin
  1245. inc(numberofdevices);
  1246. deviceids[numberofdevices] := numberofdevices;
  1247. devicenames[numberofdevices] := str;
  1248. end;
  1249. function MakeDeviceName(str : pchar): string;
  1250. var
  1251. temp : string[20];
  1252. begin
  1253. temp := strpas(str);
  1254. temp := temp + ':';
  1255. MakeDeviceName := temp;
  1256. end;
  1257. function IsInDeviceList(str : string): boolean;
  1258. var
  1259. i : byte;
  1260. theresult : boolean;
  1261. begin
  1262. theresult := false;
  1263. for i := low(not_to_use_devs) to high(not_to_use_devs) do
  1264. begin
  1265. if str = not_to_use_devs[i] then begin
  1266. theresult := true;
  1267. break;
  1268. end;
  1269. end;
  1270. IsInDeviceList := theresult;
  1271. end;
  1272. function BSTR2STRING(s : BSTR): pchar;
  1273. begin
  1274. BSTR2STRING := Pointer(Longint(BADDR(s))+1);
  1275. end;
  1276. procedure ReadInDevices;
  1277. var
  1278. dl : pDosList;
  1279. temp : pchar;
  1280. str : string[20];
  1281. begin
  1282. dl := LockDosList(LDF_DEVICES or LDF_READ );
  1283. repeat
  1284. dl := NextDosEntry(dl,LDF_DEVICES );
  1285. if dl <> nil then begin
  1286. temp := BSTR2STRING(dl^.dol_Name);
  1287. str := MakeDeviceName(temp);
  1288. if not IsInDeviceList(str) then
  1289. AddDevice(str);
  1290. end;
  1291. until dl = nil;
  1292. UnLockDosList(LDF_DEVICES or LDF_READ );
  1293. end;
  1294. Begin
  1295. DosError:=0;
  1296. numberofdevices := 0;
  1297. StrOfPaths := '';
  1298. AddDevice('DF0:');
  1299. AddDevice('DF1:');
  1300. AddDevice('DF2:');
  1301. AddDevice('DF3:');
  1302. ReadInDevices;
  1303. End.
  1304. {
  1305. $Log$
  1306. Revision 1.9 2004-12-05 16:44:43 hajny
  1307. * GetMsCount added, platform independent routines moved to single include file
  1308. Revision 1.8 2004/02/17 17:37:25 daniel
  1309. * Enable threadvars again
  1310. Revision 1.7 2004/02/16 22:16:55 hajny
  1311. * LastDosExitCode changed back from threadvar temporarily
  1312. Revision 1.6 2004/02/15 21:26:37 hajny
  1313. * overloaded ExecuteProcess added, EnvStr param changed to longint
  1314. Revision 1.5 2004/02/09 12:03:16 michael
  1315. + Switched to single interface in dosh.inc
  1316. Revision 1.4 2002/09/07 16:01:16 peter
  1317. * old logs removed and tabs fixed
  1318. }