Advertisement
Guest User

Untitled

a guest
Sep 28th, 2016
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.94 KB | None | 0 0
  1. -- disable terminate
  2. local pullEvent = os.pullEvent
  3. os.pullEvent = os.pullEventRaw
  4.  
  5. if not term.isColor() then
  6. shell.run("clear")
  7. print("No color!\nSetup will now exit...")
  8. sleep(3)
  9. os.shutdown()
  10. end
  11.  
  12. -- returns <disk name>/
  13. local function getDiskPath()
  14. local p = shell.getRunningProgram()
  15. p = string.sub(p, 1, string.find(p, "/"))
  16. return p
  17. end
  18.  
  19. local perm = 0 -- permission level (0: not logged in, 1: guest, 2: user, 3: super)
  20. local displayName
  21. local native = {}
  22.  
  23. local maxUsername, maxPassword = 10, 10
  24.  
  25. -- paths
  26. -- 1 ***** User's Renamed File, Named To Be Hidden
  27. local userStartup = "1userStartupURFNTOBH" -- the name given to the renamed "startup"
  28. local usersFile = "osData/crd" -- the file containing the users' credentials, is would be awesome to encode this
  29. local bin = "osData/bin"
  30. local cache = getDiskPath() .. "cache"
  31. local tmp = getDiskPath() .. "tmp"
  32. shell.setAlias("cls", "clear")
  33. shell.setAlias("del", "delete")
  34. shell.setAlias("ren", "rename")
  35. shell.setAlias("shell", "cmd")
  36.  
  37. local URL = {
  38. ['core'] = "http://cc.etk2000.com/alb%C3%BFno/src/core", -- the startup file
  39. ['modules'] = "http://cc.etk2000.com/alb%C3%BFno/modules", -- the modules index
  40. ['native'] = "http://cc.etk2000.com/alb%C3%BFno/src/native", -- the native file
  41. ['version'] = "http://cc.etk2000.com/alb%C3%BFno/version" -- the current version
  42. }
  43.  
  44. -- cache
  45. local w, h = term.getSize()
  46. local hasOS = fs.exists("osData/.ver")
  47.  
  48. ----------------------
  49. -- Helper functions --
  50. ----------------------
  51.  
  52. local sb = term.setBackgroundColor
  53. local sf = term.setTextColor
  54. local curb = colors.black
  55. local curf = colors.white
  56.  
  57. function term.setBackgroundColor(col)
  58. sb(col)
  59. curb = col
  60. end
  61.  
  62. function term.setTextColor(col)
  63. sf(col)
  64. curf = col
  65. end
  66.  
  67. function term.getBackgroundColor()
  68. return curb
  69. end
  70.  
  71. function term.getTextColor()
  72. return curf
  73. end
  74.  
  75. function term.writeCentered(text, fgc, bgc)
  76. local x, y = term.getCursorPos()
  77. local bg = term.getBackgroundColor()
  78. local fg = term.getTextColor()
  79. if bgc ~= nil then
  80. term.setBackgroundColor(bgc)
  81. end
  82. if fgc ~= nil then
  83. term.setBackgroundColor(fgc)
  84. end
  85. term.setCursorPos((w - string.len(text) - 1) / 2, y) -- -1 to align text on left side
  86. write(text)
  87. if bgc ~= nil then
  88. term.setBackgroundColor(bg)
  89. end
  90. if fgc ~= nil then
  91. term.setBackgroundColor(fg)
  92. end
  93. end
  94.  
  95. function term.YN()
  96. while true do
  97. local x, y = term.getCursorPos()
  98. local r = read()
  99. if string.lower(string.sub(r, 1, 1)) == 'y' then
  100. return true
  101. elseif string.lower(string.sub(r, 1, 1)) == 'n' then
  102. return false
  103. end
  104. term.setCursorPos(x, y)
  105. for i=1, string.len(r) do
  106. write(' ')
  107. end
  108. term.setCursorPos(x, y)
  109. end
  110. end
  111.  
  112. function term.writeColored(text, fgc, bgc)
  113. local bg = term.getBackgroundColor()
  114. local fg = term.getTextColor()
  115. if bgc ~= nil then
  116. term.setBackgroundColor(bgc)
  117. end
  118. term.setTextColor(fgc)
  119. write(text)
  120. if bgc ~= nil then
  121. term.setBackgroundColor(bg)
  122. end
  123. term.setTextColor(fg)
  124. end
  125.  
  126. -- term.clear() already exists
  127. function os.clear()
  128. term.clear()
  129. term.setCursorPos(1, 1)
  130. end
  131. os.clear()
  132.  
  133. function os.pause()
  134. write("Press any key to continue")
  135. os.pullEvent("key")
  136. end
  137.  
  138. function os.loading(color, func) -- func is a function that returns a boolean (that is all), true means stop
  139. local anim = { '|', '/', '-', '\\' }
  140. local i = 1;
  141. local x, y = term.getCursorPos()
  142. while (func == nil and true) or not func() do
  143. local x1, y1 = term.getCursorPos()
  144. term.setCursorPos(x, y)
  145. term.writeColored(anim[i], color ~= nil and color or term.getTextColor())
  146. if x1 ~= x and y1 ~= y then
  147. term.setCursorPos(x1, y1)
  148. end
  149. i = i + 1
  150. if i > 4 then
  151. i = 1
  152. end
  153. sleep(0.1)
  154. end
  155. end
  156.  
  157. function os.spinner(color, func)
  158. local anim = {{
  159. " O ",
  160. " O O ",
  161. "O O",
  162. "O O",
  163. " O O ",
  164. " O O "
  165. }, {
  166. " O O ",
  167. " O ",
  168. "O O",
  169. "O O",
  170. " O O ",
  171. " O O "
  172. }, {
  173. " O O ",
  174. " O O ",
  175. "O ",
  176. "O O",
  177. " O O ",
  178. " O O "
  179. }, {
  180. " O O ",
  181. " O O ",
  182. "O O",
  183. "O ",
  184. " O O ",
  185. " O O "
  186. }, {
  187. " O O ",
  188. " O O ",
  189. "O O",
  190. "O O",
  191. " O ",
  192. " O O "
  193. }, {
  194. " O O ",
  195. " O O ",
  196. "O O",
  197. "O O",
  198. " O O ",
  199. " O "
  200. }, {
  201. " O O ",
  202. " O O ",
  203. "O O",
  204. "O O",
  205. " O O ",
  206. " O "
  207. }, {
  208. " O O ",
  209. " O O ",
  210. "O O",
  211. "O O",
  212. " O ",
  213. " O O "
  214. }, {
  215. " O O ",
  216. " O O ",
  217. "O O",
  218. " O",
  219. " O O ",
  220. " O O "
  221. }, {
  222. " O O ",
  223. " O O ",
  224. " O",
  225. "O O",
  226. " O O ",
  227. " O O "
  228. }, {
  229. " O O ",
  230. " O ",
  231. "O O",
  232. "O O",
  233. " O O ",
  234. " O O "
  235. }, {
  236. " O ",
  237. " O O ",
  238. "O O",
  239. "O O",
  240. " O O ",
  241. " O O "
  242. }}
  243. local frame = 1
  244. local sw, sh = string.len(anim[1][1]), #anim[1]
  245. while true do
  246. for i=1,sh do
  247. term.setCursorPos(math.ceil(w / 2 - sw / 2), math.ceil(h / 2) - sh / 2 + i - 1)
  248. term.writeColored(anim[frame][i], color ~= nil and color or term.getTextColor())
  249. end
  250. frame = frame + 1
  251. if frame > #anim then
  252. frame = 1
  253. end
  254. sleep(0.075)
  255. end
  256. end
  257.  
  258. function http.download(url, file)
  259. local req = http.get(url)
  260. if not req then
  261. error("Could not reach " .. url, 2)
  262. end
  263. local content = req.readAll()
  264. if not content then
  265. error("Could not connect to " .. url)
  266. end
  267. f = fs.open(file, "w")
  268. f.write(content)
  269. f.close()
  270. end
  271.  
  272. function string.explode(str, div)
  273. if (div == '') then
  274. return false
  275. end
  276. local pos, res = 0, {}
  277. -- for each divider found
  278. for st,sp in function() return string.find(str, div, pos, true) end do
  279. res[#res + 1] = string.sub(str, pos, st - 1) -- Attach chars left of current divider
  280. pos = sp + 1 -- Jump past current divider
  281. end
  282. res[#res + 1] = string.sub(str, pos) -- Attach chars right of last divider
  283. return res
  284. end
  285.  
  286. function string.last(String, needle)
  287. local i=String:match(".*"..needle.."()")
  288. if i==nil then return nil else return i-1 end
  289. end
  290.  
  291. function string.starts(String, Start)
  292. return string.sub(String, 1, string.len(Start)) == Start
  293. end
  294.  
  295. function table.contains(tbl, element)
  296. for k, v in pairs(tbl) do
  297. if v == element then
  298. return true
  299. end
  300. end
  301. return false
  302. end
  303.  
  304. function os.try(func, ...)
  305. return pcall(func, ...)
  306. end
  307.  
  308. local function catchTerminate()
  309. os.pullEventRaw("terminate")
  310. end
  311.  
  312. ----------------------
  313. -- Auth's functions --
  314. ----------------------
  315.  
  316. -- auth is verified as:
  317. -- USERNAME
  318. -- PASSWORD
  319. -- AUTH_LEVEL
  320. local function doAuth(username, password)
  321. local file = native.open(usersFile, "r")
  322. local line = file.readLine() -- read USERNAME
  323. while line ~= nil do
  324. if string.lower(username) == string.lower(line) then -- validate USERNAME
  325. if password == file.readLine() then -- validate PASSWORD
  326. local res = file.readLine() -- return PERM_LEVEL
  327. file.close()
  328. displayName = line
  329. return line .. res -- {USERNAME}{AUTH_LEVEL}
  330. end
  331. else
  332. file.readLine() -- skip PASSWORD
  333. end
  334. file.readLine() -- skip PERM_LEVEL
  335. line = file.readLine() -- continue to next USERNAME
  336. end
  337. file.close()
  338. return 0
  339. end
  340.  
  341. -- NOTE: returns the completed, result, can cause errors if opening OS files then trying to modify not as OS
  342. -- NEVER RUN THIS WITHIN parallel.waitForAny WITH OTHER FINITE FUNCTIONS!!! IT MAY CAUSE PERMISSION LEAKS
  343. local function doAsOS(func, ...)
  344. local p = perm
  345. perm = 4
  346. local ok, res = os.try(func, ...)
  347. perm = p
  348. return ok, res
  349. end
  350.  
  351. local function hasPerms(perm_level)
  352. if perm_level < 1 or perm_level > 3 then
  353. throw("invalid perm_level, range is 1-3")
  354. end
  355. return perm >= perm_level
  356. end
  357.  
  358. local function createUser(perm_level)
  359. if not hasPerms(3) then
  360. error("You are not permitted to create users")
  361. end
  362. if perm_level < 1 or perm_level > 3 then
  363. error("Invalid perm_level, range is 1-3")
  364. end
  365.  
  366. local username
  367. local password
  368.  
  369. while true do
  370. os.clear()
  371. write("Username: ")
  372. username = io.read()
  373. if username:len() <= maxUsername then
  374. write("Password: ")
  375. password = read('*')
  376. if password:len() <= maxPassword then
  377. write("Confirm: ")
  378. if password == read('*') then
  379. break
  380. end
  381. term.writeColored("Passwords do not match!", colors.red)
  382. else
  383. term.writeColored("Passwords is too long! (max: " .. maxPassword .. ")", colors.red)
  384. end
  385. else
  386. term.writeColored("Username is too long! (max: " .. maxUsername .. ")", colors.red)
  387. end
  388. sleep(2)
  389. end
  390. os.clear()
  391. -- save the user
  392. fs.makeDir(string.sub(usersFile, 1, string.last(usersFile, '/') - 1))
  393. local file = fs.open(usersFile, fs.exists(usersFile) and "a" or "w")
  394. file.writeLine(username)
  395. file.writeLine(password)
  396. file.writeLine(tostring(perm_level))
  397. file.close()
  398. end
  399.  
  400. -----------------------
  401. -- backup functions --
  402. -----------------------
  403. native.copy = fs.copy
  404. native.delete = fs.delete
  405. native.exists = fs.exists
  406. native.find = fs.find
  407. native.getSize = fs.getSize
  408. native.isDir = fs.isDir
  409. native.isReadOnly = fs.isReadOnly
  410. native.list = fs.list
  411. native.makeDir = fs.makeDir
  412. native.move = fs.move
  413. native.open = fs.open
  414. native.ioOpen = io.open
  415.  
  416. ----------------------
  417. -- define functions --
  418. ----------------------
  419.  
  420. function table.size(t)
  421. local res = 0
  422. for k,v in pairs(t) do
  423. res = res + 1
  424. end
  425. return res
  426. end
  427.  
  428. -- ordered pairs
  429. function __genOrderedIndex( t )
  430. local orderedIndex = {}
  431. for key in pairs(t) do
  432. table.insert(orderedIndex, key)
  433. end
  434. table.sort(orderedIndex)
  435. return orderedIndex
  436. end
  437.  
  438. function orderedNext(t, state)
  439. -- Equivalent of the next function, but returns the keys in the alphabetic
  440. -- order. We use a temporary ordered key table that is stored in the
  441. -- table being iterated.
  442. key = nil
  443. if state == nil then
  444. -- the first time, generate the index
  445. t.__orderedIndex = __genOrderedIndex(t)
  446. key = t.__orderedIndex[1]
  447. else
  448. -- fetch the next value
  449. for i = 1, table.getn(t.__orderedIndex) do
  450. if t.__orderedIndex[i] == state then
  451. key = t.__orderedIndex[i + 1]
  452. end
  453. end
  454. end
  455.  
  456. if key then
  457. return key, t[key]
  458. end
  459.  
  460. -- no more value to return, cleanup
  461. t.__orderedIndex = nil
  462. return
  463. end
  464.  
  465. -- Equivalent of the pairs() function on tables. Allows to iterate in order
  466. function orderedPairs(t)
  467. return orderedNext, t, nil
  468. end
  469.  
  470. -- moves the specified file replacing any existing one
  471. function fs.replace(from, to)
  472. if shell.getRunningProgram() == getDiskPath() .. "startup" or shell.getRunningProgram() == (bin .. "/apt-get") then -- a little hack to allow apt-get to update system files
  473. if native.exists(to) then
  474. native.delete(to)
  475. end
  476. native.move(from, to)
  477. else
  478. if fs.exists(to) then
  479. fs.delete(to)
  480. end
  481. fs.move(from, to)
  482. end
  483. end
  484.  
  485. -- copies the specified file replacing any existing one
  486. function fs.replaceCopy(from, to)
  487. if shell.getRunningProgram() == getDiskPath() .. "startup" then
  488. if native.exists(to) then
  489. native.delete(to)
  490. end
  491. native.copy(from, to)
  492. else
  493. if fs.exists(to) then
  494. fs.delete(to)
  495. end
  496. fs.copy(from, to)
  497. end
  498. end
  499.  
  500. local downOS = false
  501. local function downloadOS() -- download OS core
  502. downOS = true
  503. local downloaded
  504. parallel.waitForAny(
  505. function()
  506. local res
  507. downloaded, res = doAsOS(http.download, URL['version'], tmp .. "/ver")
  508. if not downloaded then
  509. res = string.sub(res, 8, string.len(res)) -- remove the "pcall: "
  510. local f = string.sub(URL['version'], 1, 7) -- get the beginning of the URL
  511. res = string.sub(res, 1, string.find(res, f) - 1) -- remove the URL
  512. res = res .. 'update URL!'
  513. term.writeColored(res, colors.red)
  514. end
  515. end,
  516. function()
  517. catchTerminate()
  518. term.writeColored("cancelled", colors.red)
  519. downloaded = false
  520. end,
  521. function()
  522. os.loading(colors.blue)
  523. end)
  524.  
  525. write("\n") -- just to make it look better
  526. local file = fs.open(tmp .. "/ver", "r") -- basically doAsOS
  527. local version = tonumber(file.readLine()) -- only one line
  528. file.close()
  529. native.delete(tmp .. "/ver")
  530. if downloaded then
  531. if os.getVersion() == 0 then
  532. local ok, res = doAsOS(http.download, URL['core'], cache .. "/startup") -- download the OS
  533. if not ok then
  534. term.writeColored("Failed to download OS!\n", colors.red)
  535. term.writeColored(res .. "\n", colors.red)
  536. native.delete(cache)
  537. else
  538. ok, res = doAsOS(http.download, URL['native'], cache .. "/native") -- download the OS
  539. if not ok then
  540. term.writeColored("Failed to download OS!\n", colors.red)
  541. term.writeColored(res .. "\n", colors.red)
  542. native.delete(cache)
  543. else
  544. file = native.open(cache .. "/ver", "w")
  545. file.write("[core]=" .. tostring(version))
  546. file.close()
  547. end
  548. end
  549. elseif version > os.getVersion() then
  550. term.writeColored("A new version (" .. version .. ") is available!\n", colors.yellow)
  551. term.writeColored("Update [Y/n]? ", colors.cyan)
  552. local c = term.getTextColor()
  553. term.setTextColor(colors.orange)
  554. local a = term.YN()
  555. term.setTextColor(c)
  556. if a then
  557. local ok, res = doAsOS(http.download, URL['core'], cache .. "/startup") -- download the OS
  558. if not ok then
  559. term.writeColored("Failed to download OS!\n", colors.red)
  560. term.writeColored(res .. "\n", colors.red)
  561. end
  562. end
  563. else
  564. term.writeColored("OS is up to date!\n", colors.green)
  565. end
  566. end
  567. downOS = false
  568. end
  569.  
  570. local moduleNames, modules = { "add-apt-repository", "apt-get", "cmd", "config", "explorer", "su", "sudo" }, {}
  571. local function downloadModule(moduleName)
  572. local url = modules["|base"]:gsub("%$name", moduleName)
  573. local downloaded
  574. parallel.waitForAny(
  575. function()
  576. local res
  577. downloaded, res = doAsOS(http.download, url, cache .. "/" .. moduleName)
  578. if not downloaded then
  579. res = string.sub(res, 8, string.len(res)) -- remove the "pcall: "
  580. local f = string.sub(url, 1, 7) -- get the beginning of the URL
  581. res = string.sub(res, 1, string.find(res, f) - 1) -- remove the URL
  582. res = res .. 'update URL!' .. url .. "\n"
  583. term.writeColored(res, colors.red)
  584. else
  585. local arr = {}
  586. local found = false
  587. local p = perm
  588. perm = 4 -- doAsOS for io.lines
  589. for line in io.lines(cache .. "/ver") do
  590. if string.starts(line, "[" .. moduleName .. "]=") then
  591. table.insert(arr, "[" .. moduleName .. "]=" .. modules[moduleName]["ver"]);
  592. found = true
  593. else
  594. table.insert(arr, line);
  595. end
  596. end
  597. perm = p
  598. if not found then -- newly installed
  599. table.insert(arr, "[" .. moduleName .. "]=" .. modules[moduleName]["ver"]);
  600. end
  601.  
  602. file = native.open(cache .. "/ver", "w")
  603. for k, v in pairs(arr) do
  604. file.writeLine(v)
  605. end
  606. file.close()
  607. end
  608. end,
  609. function()
  610. catchTerminate()
  611. term.writeColored("cancelled", colors.red)
  612. downloaded = false
  613. end,
  614. function()
  615. os.loading(colors.blue)
  616. end)
  617. end
  618.  
  619. local function removeModule(moduleName)
  620. local arr = {}
  621. local p = perm
  622. native.delete(cache .. "/" .. moduleName)
  623. perm = 4 -- doAsOS for io.lines
  624. for line in io.lines(cache .. "/ver") do
  625. if not string.starts(line, "[" .. moduleName .. "]=") then
  626. table.insert(arr, line);
  627. end
  628. end
  629. perm = p
  630.  
  631. file = native.open(cache .. "/ver", "w")
  632. for k, v in pairs(arr) do
  633. file.writeLine(v)
  634. end
  635. file.close()
  636. end
  637.  
  638. local function getModules()
  639. local downloaded
  640. parallel.waitForAny(
  641. function()
  642. local res
  643. downloaded, res = os.try(http.download, URL['modules'], tmp .. "/mod")
  644. if not downloaded then
  645. res = string.sub(res, 8, string.len(res)) -- remove the "pcall: "
  646. local f = string.sub(URL['modules'], 1, 7) -- get the beginning of the URL
  647. res = string.sub(res, 1, string.find(res, f) - 1) -- remove the URL
  648. res = res .. 'update URL!'
  649. term.writeColored(res, colors.red)
  650. end
  651. end,
  652. function()
  653. catchTerminate()
  654. term.writeColored("cancelled", colors.red)
  655. downloaded = false
  656. end,
  657. function()
  658. os.loading(colors.blue)
  659. end)
  660.  
  661. -- apt-get update
  662. local file = fs.open(tmp .. "/_m", "w")
  663. local fine, base, form = true
  664. for line in io.lines(tmp .. "/mod") do
  665. if not string.starts(line, "#") then -- ignore comments
  666. if fine then
  667. if string.starts(line, '[basepath]=') then
  668. base = string.sub(line, 12, string.len(line))
  669. file.write(base .. "\n")
  670. elseif string.starts(line, '[format]=') then
  671. form = string.explode(string.sub(line, 10, string.len(line)), ",")
  672. for i=1, #form do
  673. if not fine or not string.starts(form[i], "$") then
  674. fine = false
  675. else
  676. form[i] = string.sub(form[i], 2, string.len(form[i]))
  677. end
  678. end
  679. else
  680. if base and form then
  681. local mod = string.explode(line, ",")
  682. for i=#mod, 1, -1 do
  683. mod[form[i]] = mod[i]
  684. table.remove(mod, i)
  685. end
  686. if table.contains(moduleNames, mod["name"]) then
  687. file.write("\t" .. mod["name"] .. "\n")
  688. for k,v in pairs(mod) do
  689. if k ~= "name" then
  690. file.write("\t\t" .. k .. "=" .. v .. "\n")
  691. end
  692. end
  693. end
  694. else
  695. fine = false
  696. end
  697. end
  698. end
  699. end
  700. end
  701. file.close()
  702. fs.delete(tmp .. "/mod")
  703.  
  704. local repo, curM = {}
  705. for line in io.lines(tmp .. "/_m") do
  706. if string.starts(line, "\t\t") then
  707. local v = string.explode(string.sub(line, 3, string.len(line)), "=") -- should only produce string[2]
  708. repo[curM][v[1]] = v[2]
  709. elseif string.starts(line, "\t") then -- found a module definition
  710. curM = string.sub(line, 2, string.len(line))
  711. repo[curM] = {}
  712. else
  713. repo["|base"] = string.sub(line, 1, string.len(line))
  714. end
  715. end
  716. modules = repo
  717. for k, v in pairs(repo) do
  718. if v["req"] == '1' and not fs.exists(cache .. "/" .. k) then
  719. os.clear()
  720. downloadModule(k)
  721. end
  722. end
  723. os.clear()
  724. end
  725.  
  726. function os.getName()
  727. return "Albyno"--"Alb??no"
  728. end
  729.  
  730. function os.getVersion()
  731. if not native.exists(cache .. "/ver") then
  732. if downOS then
  733. return 0
  734. end
  735. downloadOS()
  736. end
  737. local r
  738. while not r do
  739. local p = perm
  740. perm = 4 -- doAsOS for io.lines
  741. for line in io.lines(cache .. "/ver") do
  742. if string.starts(line, "[core]=") then
  743. r = tonumber(string.sub(line, 8, string.len(line)))
  744. end
  745. end
  746. perm = p
  747. if not r then -- corrupted data, re-download the OS core
  748. downloadOS()
  749. end
  750. end
  751. return r
  752. end
  753.  
  754. function os.version()
  755. return os.getName() .. " " .. os.getVersion() .. " setup"
  756. end
  757.  
  758. function doLogin()
  759. if not native.exists(usersFile) then -- no users, create one
  760. term.writeColored("Please create an account", colors.green)
  761. sleep(2)
  762. perm = 3 -- allow user creation
  763. createUser(3) -- create an admin
  764. perm = 0
  765. else
  766. while perm < 3 do -- while not loggedin, try to login
  767. os.clear()
  768. term.writeColored("A user exists, Please login!\n", colors.green)
  769. write("Username: ")
  770. username = io.read()
  771. write("Password: ")
  772. local password = read('*')
  773. perm = doAuth(username, password)
  774. if perm ~= 0 then
  775. username = string.sub(perm, 1, string.len(perm) - 1)
  776. perm = tonumber(string.sub(perm, string.len(perm) - 1, string.len(perm)))
  777. if perm == 3 then
  778. term.writeColored("Login successful!\n", colors.green)
  779. os.getPermLevel = function()
  780. return perm
  781. end
  782. os.getUsername = function()
  783. return username
  784. end
  785. else
  786. term.writeColored("Admin required!\n", colors.red)
  787. end
  788. else
  789. term.writeColored("Login failure!\n", colors.red)
  790. end
  791. sleep(1)
  792. end
  793. end
  794. os.clear()
  795. end
  796.  
  797. function configure()
  798. getModules()
  799. local vers = {}
  800. for k, v in pairs(moduleNames) do
  801. vers[v] = false
  802. end
  803.  
  804. local p = perm
  805. perm = 4 -- doAsOS for io.lines
  806. for line in io.lines(cache .. "/ver") do
  807. for k, v in pairs(vers) do
  808. if not v and string.starts(line, "[" .. k .. "]=") and fs.exists(cache .. "/" .. k) then
  809. vers[k] = tonumber(string.sub(line, 4 + string.len(k), string.len(line)))
  810. end
  811. end
  812. end
  813. perm = p
  814.  
  815. lastColor = term.getBackgroundColor()
  816. term.setCursorPos(1, 1)
  817. term.writeColored("core", colors.green)
  818. term.writeCentered("" .. os.getVersion())
  819. term.setCursorPos(w - 9, 1)
  820. term.setBackgroundColor(colors.blue)
  821. write("redownload")
  822. term.setBackgroundColor(lastColor)
  823. term.setCursorPos(1, 2)
  824. term.writeColored("modules:", colors.cyan)
  825. for i, v in ipairs(moduleNames) do
  826. term.setCursorPos(4, 2 + i)
  827. term.writeColored(v, vers[v] and colors.green or colors.red)
  828. if vers[v] then
  829. term.writeCentered(vers[v])
  830. end
  831. term.setBackgroundColor(vers[v] and (modules[v]["req"] == '1' and colors.blue or colors.red) or colors.green)
  832. term.setCursorPos(w - 9, 2 + i)
  833. write(vers[v] and (modules[v]["req"] == '1' and "redownload" or " remove ") or " download ")
  834. term.setBackgroundColor(lastColor)
  835. end
  836. term.setCursorPos(w, h)
  837. term.writeColored("x", colors.red)
  838.  
  839. -- wait for input
  840. parallel.waitForAny(
  841. function()
  842. local event, button, xPos, yPos = pullEvent("mouse_click")
  843. while yPos ~= h or xPos ~= w do
  844. -- do some calculations
  845. if yPos == 1 and xPos >= w - 9 then
  846. os.clear()
  847. downloadOS()
  848. sleep(2)
  849. os.clear()
  850. configure()
  851. break
  852. elseif yPos > 2 and yPos <= 2 + table.size(vers) and xPos >= w - 9 then
  853. local i, m = 1
  854. for k, v in orderedPairs(vers) do
  855. if i == (yPos - 2) then
  856. m = k
  857. end
  858. i = i + 1
  859. end
  860. os.clear()
  861. if not vers[m] or modules[m]["req"] == '1' then
  862. write("downloading...")
  863. downloadModule(m)
  864. else
  865. removeModule(m)
  866. end
  867. os.clear()
  868. configure()
  869. break
  870. end
  871. event, button, xPos, yPos = pullEvent("mouse_click")
  872. end
  873. end)
  874. end
  875.  
  876. ----------------------
  877. -- Main entry point --
  878. ----------------------
  879. term.setTextColor(colors.white)
  880.  
  881. -- no OS cached, download is required
  882. while not native.exists(cache) do
  883. term.writeColored("No OS found on disk!\n", colors.red)
  884. term.writeColored("Downloading...", colors.orange)
  885. downloadOS()
  886. getModules()
  887. end
  888.  
  889. -- show UI
  890. local ok, res = os.try(
  891. function()
  892. while true do
  893. os.clear()
  894. if w > 22 then
  895. local width = math.floor(w / 2 - 2)
  896. local lastColor = term.getBackgroundColor()
  897. for i=1, 10 do
  898. term.setBackgroundColor(colors.red)
  899. term.setCursorPos(3, math.ceil(h / 2 - 6 + i))
  900. for j=1, width do
  901. if i == 5 and j >= math.ceil(width / 2 - 3) and j < math.ceil(width / 2 - 3) + 7 then
  902. write(string.sub('Install', j - 2 - width / 2 - 3, j - 2 - width / 2 - 3))
  903. else
  904. write(" ")
  905. end
  906. end
  907. term.setCursorPos(width + 4, math.ceil(h / 2 - 6 + i))
  908. for j=1, width do
  909. if i == 1 or i == 10 or j == 1 or j == width then
  910. term.setBackgroundColor(colors.blue)
  911. else
  912. term.setBackgroundColor(colors.cyan)
  913. end
  914. if i == 5 and j >= math.ceil(width / 2 - 4) and j < math.ceil(width / 2 - 3) + 8 then
  915. write(string.sub('Configure', j - 2 - width / 2 - 4, j - 2 - width / 2 - 4))
  916. else
  917. write(" ")
  918. end
  919. end
  920. end
  921. if fs.exists(cache .. "/cmd") then
  922. term.setCursorPos(1, h)
  923. term.setBackgroundColor(colors.brown)
  924. write("cmd")
  925. end
  926. term.setBackgroundColor(lastColor)
  927. term.setCursorPos(w, h)
  928. lastColor = term.getTextColor()
  929. term.setTextColor(colors.red)
  930. write("x")
  931. term.setTextColor(lastColor)
  932.  
  933. -- wait for input
  934. parallel.waitForAny(
  935. function()
  936. local event, button, xPos, yPos = pullEvent("mouse_click")
  937. if yPos > math.ceil(h / 2 - 6) and yPos <= (math.ceil(h / 2 - 6) + 10) then
  938. if xPos > 2 and xPos <= (2 + width) then -- Install clicked
  939. os.clear()
  940. term.writeColored("Install [Y/n]? ", colors.orange)
  941. if term.YN() then
  942. doLogin()
  943. local done = false
  944. parallel.waitForAny(
  945. function()
  946. os.spinner(colors.cyan, function() return done end)
  947. end,
  948. function()
  949. if not hasOS and fs.exists("startup") --[[ and not fs.exists(userStartup) ]] then
  950. fs.move("startup", userStartup)
  951. end
  952.  
  953. -- install required packages
  954. fs.replaceCopy(cache .. "/startup", "startup")
  955. fs.replaceCopy(cache .. "/native", "osData/native")
  956. fs.replaceCopy(cache .. "/add-apt-repository", "osData/bin/add-apt-repository")
  957. fs.replaceCopy(cache .. "/apt-get", "osData/bin/apt-get")
  958. fs.replaceCopy(cache .. "/cmd", "osData/bin/cmd")
  959. fs.replaceCopy(cache .. "/config", "osData/bin/config")
  960.  
  961. -- install optional packages
  962. if fs.exists(cache .. "/explorer") then
  963. fs.replaceCopy(cache .. "/explorer", "osData/bin/explorer")
  964. end
  965. if fs.exists(cache .. "/su") then
  966. fs.replaceCopy(cache .. "/su", "osData/bin/su")
  967. end
  968. if fs.exists(cache .. "/sudo") then
  969. fs.replaceCopy(cache .. "/sudo", "osData/bin/sudo")
  970. end
  971.  
  972. -- write current version
  973. file = native.open("osData/.ver", "w")
  974. file.write(os.getVersion())
  975. file.close()
  976.  
  977. -- set the versions of the installed packages in the progs
  978. file = native.open("osData/cfg/progs", "w")
  979. -- get the module path
  980. for line in io.lines(tmp .. "/_m") do
  981. if not string.starts(line, "#") and not string.starts(line, "\t") then
  982. file.write(line .. "\n")
  983. break
  984. end
  985. end
  986. -- get the installed programs
  987. for line in io.lines(cache .. "/ver") do
  988. if not string.starts(line, "[core]") then
  989. local i = string.find(line, "%]")
  990. file.write("\t" .. string.sub(line, 1, i - 1) .. "\n")
  991. file.write("\t\t" .. string.sub(line, i + 1) .. "\n")
  992. break
  993. end
  994. end
  995. file.close()
  996.  
  997. hasOS = true
  998. done = true
  999. end)
  1000. else
  1001. term.writeColored("Cancelled...\n", colors.red)
  1002. end
  1003. sleep(1)
  1004. elseif xPos > (3 + width) and xPos < (w - 1) then
  1005. os.clear()
  1006. configure()
  1007. end
  1008. elseif yPos == h and xPos < 4 and fs.exists(cache .. "/cmd") then
  1009. os.clear()
  1010. parallel.waitForAny(catchTerminate,
  1011. function()
  1012. shell.run(cache .. "/cmd")
  1013. -- TODO: fix cmd crashing after entering command
  1014. end)
  1015. term.setCursorBlink(false)
  1016. elseif yPos == h and xPos == w then
  1017. os.queueEvent("terminate")
  1018. end
  1019. end)
  1020. else
  1021. end
  1022. end
  1023. end)
  1024. if not ok then
  1025. if res == "Terminated" then
  1026. os.clear()
  1027. term.writeColored("Bye bye!\n", colors.yellow)
  1028. else
  1029. term.writeColored(res .. "\n", colors.red)
  1030. end
  1031. os.pause()
  1032. os.shutdown()
  1033. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement