PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/tex/context/base/l-os.lua

https://gitlab.com/brcha/context-serbian
Lua | 463 lines | 311 code | 84 blank | 68 comment | 49 complexity | 6af7b73abafcd65ad3b84d3330a360cb MD5 | raw file
  1. if not modules then modules = { } end modules ['l-os'] = {
  2. version = 1.001,
  3. comment = "companion to luat-lib.mkiv",
  4. author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
  5. copyright = "PRAGMA ADE / ConTeXt Development Team",
  6. license = "see context related readme files"
  7. }
  8. -- This file deals with some operating system issues. Please don't bother me
  9. -- with the pros and cons of operating systems as they all have their flaws
  10. -- and benefits. Bashing one of them won't help solving problems and fixing
  11. -- bugs faster and is a waste of time and energy.
  12. --
  13. -- path separators: / or \ ... we can use / everywhere
  14. -- suffixes : dll so exe <none> ... no big deal
  15. -- quotes : we can use "" in most cases
  16. -- expansion : unless "" are used * might give side effects
  17. -- piping/threads : somewhat different for each os
  18. -- locations : specific user file locations and settings can change over time
  19. --
  20. -- os.type : windows | unix (new, we already guessed os.platform)
  21. -- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
  22. -- os.platform : extended os.name with architecture
  23. -- os.sleep() => socket.sleep()
  24. -- math.randomseed(tonumber(string.sub(string.reverse(tostring(math.floor(socket.gettime()*10000))),1,6)))
  25. -- maybe build io.flush in os.execute
  26. local os = os
  27. local date, time = os.date, os.time
  28. local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
  29. local concat = table.concat
  30. local random, ceil, randomseed = math.random, math.ceil, math.randomseed
  31. local rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring = rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring
  32. -- The following code permits traversing the environment table, at least
  33. -- in luatex. Internally all environment names are uppercase.
  34. -- The randomseed in Lua is not that random, although this depends on the operating system as well
  35. -- as the binary (Luatex is normally okay). But to be sure we set the seed anyway.
  36. math.initialseed = tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
  37. randomseed(math.initialseed)
  38. if not os.__getenv__ then
  39. os.__getenv__ = os.getenv
  40. os.__setenv__ = os.setenv
  41. if os.env then
  42. local osgetenv = os.getenv
  43. local ossetenv = os.setenv
  44. local osenv = os.env local _ = osenv.PATH -- initialize the table
  45. function os.setenv(k,v)
  46. if v == nil then
  47. v = ""
  48. end
  49. local K = upper(k)
  50. osenv[K] = v
  51. if type(v) == "table" then
  52. v = concat(v,";") -- path
  53. end
  54. ossetenv(K,v)
  55. end
  56. function os.getenv(k)
  57. local K = upper(k)
  58. local v = osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k)
  59. if v == "" then
  60. return nil
  61. else
  62. return v
  63. end
  64. end
  65. else
  66. local ossetenv = os.setenv
  67. local osgetenv = os.getenv
  68. local osenv = { }
  69. function os.setenv(k,v)
  70. if v == nil then
  71. v = ""
  72. end
  73. local K = upper(k)
  74. osenv[K] = v
  75. end
  76. function os.getenv(k)
  77. local K = upper(k)
  78. local v = osenv[K] or osgetenv(K) or osgetenv(k)
  79. if v == "" then
  80. return nil
  81. else
  82. return v
  83. end
  84. end
  85. local function __index(t,k)
  86. return os.getenv(k)
  87. end
  88. local function __newindex(t,k,v)
  89. os.setenv(k,v)
  90. end
  91. os.env = { }
  92. setmetatable(os.env, { __index = __index, __newindex = __newindex } )
  93. end
  94. end
  95. -- end of environment hack
  96. local execute, spawn, exec, iopopen, ioflush = os.execute, os.spawn or os.execute, os.exec or os.execute, io.popen, io.flush
  97. function os.execute(...) ioflush() return execute(...) end
  98. function os.spawn (...) ioflush() return spawn (...) end
  99. function os.exec (...) ioflush() return exec (...) end
  100. function io.popen (...) ioflush() return iopopen(...) end
  101. function os.resultof(command)
  102. local handle = io.popen(command,"r")
  103. return handle and handle:read("*all") or ""
  104. end
  105. if not io.fileseparator then
  106. if find(os.getenv("PATH"),";") then
  107. io.fileseparator, io.pathseparator, os.type = "\\", ";", os.type or "mswin"
  108. else
  109. io.fileseparator, io.pathseparator, os.type = "/" , ":", os.type or "unix"
  110. end
  111. end
  112. os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
  113. os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
  114. if os.type == "windows" then
  115. os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
  116. else
  117. os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
  118. end
  119. local launchers = {
  120. windows = "start %s",
  121. macosx = "open %s",
  122. unix = "$BROWSER %s &> /dev/null &",
  123. }
  124. function os.launch(str)
  125. os.execute(format(launchers[os.name] or launchers.unix,str))
  126. end
  127. if not os.times then
  128. -- utime = user time
  129. -- stime = system time
  130. -- cutime = children user time
  131. -- cstime = children system time
  132. function os.times()
  133. return {
  134. utime = os.gettimeofday(), -- user
  135. stime = 0, -- system
  136. cutime = 0, -- children user
  137. cstime = 0, -- children system
  138. }
  139. end
  140. end
  141. os.gettimeofday = os.gettimeofday or os.clock
  142. local startuptime = os.gettimeofday()
  143. function os.runtime()
  144. return os.gettimeofday() - startuptime
  145. end
  146. --~ print(os.gettimeofday()-os.time())
  147. --~ os.sleep(1.234)
  148. --~ print (">>",os.runtime())
  149. --~ print(os.date("%H:%M:%S",os.gettimeofday()))
  150. --~ print(os.date("%H:%M:%S",os.time()))
  151. -- no need for function anymore as we have more clever code and helpers now
  152. -- this metatable trickery might as well disappear
  153. os.resolvers = os.resolvers or { } -- will become private
  154. local resolvers = os.resolvers
  155. local osmt = getmetatable(os) or { __index = function(t,k) t[k] = "unset" return "unset" end } -- maybe nil
  156. local osix = osmt.__index
  157. osmt.__index = function(t,k)
  158. return (resolvers[k] or osix)(t,k)
  159. end
  160. setmetatable(os,osmt)
  161. -- we can use HOSTTYPE on some platforms
  162. local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or ""
  163. local function guess()
  164. local architecture = os.resultof("uname -m") or ""
  165. if architecture ~= "" then
  166. return architecture
  167. end
  168. architecture = os.getenv("HOSTTYPE") or ""
  169. if architecture ~= "" then
  170. return architecture
  171. end
  172. return os.resultof("echo $HOSTTYPE") or ""
  173. end
  174. if platform ~= "" then
  175. os.platform = platform
  176. elseif os.type == "windows" then
  177. -- we could set the variable directly, no function needed here
  178. function os.resolvers.platform(t,k)
  179. local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or ""
  180. if find(architecture,"AMD64") then
  181. platform = "mswin-64"
  182. else
  183. platform = "mswin"
  184. end
  185. os.setenv("MTX_PLATFORM",platform)
  186. os.platform = platform
  187. return platform
  188. end
  189. elseif name == "linux" then
  190. function os.resolvers.platform(t,k)
  191. -- we sometimes have HOSTTYPE set so let's check that first
  192. local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
  193. if find(architecture,"x86_64") then
  194. platform = "linux-64"
  195. elseif find(architecture,"ppc") then
  196. platform = "linux-ppc"
  197. else
  198. platform = "linux"
  199. end
  200. os.setenv("MTX_PLATFORM",platform)
  201. os.platform = platform
  202. return platform
  203. end
  204. elseif name == "macosx" then
  205. --[[
  206. Identifying the architecture of OSX is quite a mess and this
  207. is the best we can come up with. For some reason $HOSTTYPE is
  208. a kind of pseudo environment variable, not known to the current
  209. environment. And yes, uname cannot be trusted either, so there
  210. is a change that you end up with a 32 bit run on a 64 bit system.
  211. Also, some proper 64 bit intel macs are too cheap (low-end) and
  212. therefore not permitted to run the 64 bit kernel.
  213. ]]--
  214. function os.resolvers.platform(t,k)
  215. -- local platform, architecture = "", os.getenv("HOSTTYPE") or ""
  216. -- if architecture == "" then
  217. -- architecture = os.resultof("echo $HOSTTYPE") or ""
  218. -- end
  219. local platform, architecture = "", os.resultof("echo $HOSTTYPE") or ""
  220. if architecture == "" then
  221. -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n")
  222. platform = "osx-intel"
  223. elseif find(architecture,"i386") then
  224. platform = "osx-intel"
  225. elseif find(architecture,"x86_64") then
  226. platform = "osx-64"
  227. else
  228. platform = "osx-ppc"
  229. end
  230. os.setenv("MTX_PLATFORM",platform)
  231. os.platform = platform
  232. return platform
  233. end
  234. elseif name == "sunos" then
  235. function os.resolvers.platform(t,k)
  236. local platform, architecture = "", os.resultof("uname -m") or ""
  237. if find(architecture,"sparc") then
  238. platform = "solaris-sparc"
  239. else -- if architecture == 'i86pc'
  240. platform = "solaris-intel"
  241. end
  242. os.setenv("MTX_PLATFORM",platform)
  243. os.platform = platform
  244. return platform
  245. end
  246. elseif name == "freebsd" then
  247. function os.resolvers.platform(t,k)
  248. local platform, architecture = "", os.resultof("uname -m") or ""
  249. if find(architecture,"amd64") then
  250. platform = "freebsd-amd64"
  251. else
  252. platform = "freebsd"
  253. end
  254. os.setenv("MTX_PLATFORM",platform)
  255. os.platform = platform
  256. return platform
  257. end
  258. elseif name == "kfreebsd" then
  259. function os.resolvers.platform(t,k)
  260. -- we sometimes have HOSTTYPE set so let's check that first
  261. local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
  262. if find(architecture,"x86_64") then
  263. platform = "kfreebsd-amd64"
  264. else
  265. platform = "kfreebsd-i386"
  266. end
  267. os.setenv("MTX_PLATFORM",platform)
  268. os.platform = platform
  269. return platform
  270. end
  271. else
  272. -- platform = "linux"
  273. -- os.setenv("MTX_PLATFORM",platform)
  274. -- os.platform = platform
  275. function os.resolvers.platform(t,k)
  276. local platform = "linux"
  277. os.setenv("MTX_PLATFORM",platform)
  278. os.platform = platform
  279. return platform
  280. end
  281. end
  282. -- beware, we set the randomseed
  283. -- from wikipedia: Version 4 UUIDs use a scheme relying only on random numbers. This algorithm sets the
  284. -- version number as well as two reserved bits. All other bits are set using a random or pseudorandom
  285. -- data source. Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal
  286. -- digits x and hexadecimal digits 8, 9, A, or B for y. e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479.
  287. --
  288. -- as we don't call this function too often there is not so much risk on repetition
  289. local t = { 8, 9, "a", "b" }
  290. function os.uuid()
  291. return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
  292. random(0xFFFF),random(0xFFFF),
  293. random(0x0FFF),
  294. t[ceil(random(4))] or 8,random(0x0FFF),
  295. random(0xFFFF),
  296. random(0xFFFF),random(0xFFFF),random(0xFFFF)
  297. )
  298. end
  299. local d
  300. function os.timezone(delta)
  301. d = d or tonumber(tonumber(date("%H")-date("!%H")))
  302. if delta then
  303. if d > 0 then
  304. return format("+%02i:00",d)
  305. else
  306. return format("-%02i:00",-d)
  307. end
  308. else
  309. return 1
  310. end
  311. end
  312. local timeformat = format("%%s%s",os.timezone(true))
  313. local dateformat = "!%Y-%m-%d %H:%M:%S"
  314. function os.fulltime(t,default)
  315. t = tonumber(t) or 0
  316. if t > 0 then
  317. -- valid time
  318. elseif default then
  319. return default
  320. else
  321. t = nil
  322. end
  323. return format(timeformat,date(dateformat,t))
  324. end
  325. local dateformat = "%Y-%m-%d %H:%M:%S"
  326. function os.localtime(t,default)
  327. t = tonumber(t) or 0
  328. if t > 0 then
  329. -- valid time
  330. elseif default then
  331. return default
  332. else
  333. t = nil
  334. end
  335. return date(dateformat,t)
  336. end
  337. function os.converttime(t,default)
  338. local t = tonumber(t)
  339. if t and t > 0 then
  340. return date(dateformat,t)
  341. else
  342. return default or "-"
  343. end
  344. end
  345. local memory = { }
  346. local function which(filename)
  347. local fullname = memory[filename]
  348. if fullname == nil then
  349. local suffix = file.suffix(filename)
  350. local suffixes = suffix == "" and os.binsuffixes or { suffix }
  351. for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
  352. local df = file.join(directory,filename)
  353. for i=1,#suffixes do
  354. local dfs = file.addsuffix(df,suffixes[i])
  355. if io.exists(dfs) then
  356. fullname = dfs
  357. break
  358. end
  359. end
  360. end
  361. if not fullname then
  362. fullname = false
  363. end
  364. memory[filename] = fullname
  365. end
  366. return fullname
  367. end
  368. os.which = which
  369. os.where = which
  370. function os.today()
  371. return date("!*t") -- table with values
  372. end
  373. function os.now()
  374. return date("!%Y-%m-%d %H:%M:%S") -- 2011-12-04 14:59:12
  375. end
  376. -- print(os.which("inkscape.exe"))
  377. -- print(os.which("inkscape"))
  378. -- print(os.which("gs.exe"))
  379. -- print(os.which("ps2pdf"))