dos.pp 40 KB

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