Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Passlock v0
- -- (C) 2012 User 'Advert' at http://www.computercraft.info/forums2/
- -- X11/mit licence (use/modify at your will, but please, leave credit where due)
- -- Settings.
- local dConfig = {} -- Marking defaults, so we can revert to them easily.
- do -- Because I like do statements.
- dConfig["sUserPassword"] = "open"
- dConfig["sRootPassword"] = "2good4u"
- dConfig["nOpenTime"] = 3 -- Number of seconds to keep the door open.
- dConfig["nUserPassFailLock"]= 3 -- Number of user password fails before lock. (0 = disable, 1 = 1 fail, 2 = 2 fails, etc.) Reset at success (root can still login)
- dConfig["nUserPassFailLockDuration"] = 15 -- Number of seconds to lock after nUserPassFailLock password fails
- dConfig["bRootForceOpen"] = false -- Door is forced open by Root user.
- dConfig["bLockAtStartup"] = true -- This will lock the computer for nUserPassFailLockDuration seconds at startup, to prevent bypassing of nUserLockPassFailLock.
- dConfig["sRedstoneSide"] = "back" -- The side the redstone is at.
- -- Stuff not stored here: door state, etc.
- end
- -- small helper function ;_;
- local function copyTable(o)
- -- Will simply copy a table, non-recursively.
- local t = {}
- for k, v in pairs(o) do t[k] = v end
- return t
- end
- local config = copyTable(dConfig)
- local bRootExit = false
- local bDoorState = true -- true = locked.
- local nUserAttempts = 0
- local nUserLastAttempt = 0
- -- Misc functions
- local function mergeTable(t1, t2)
- -- This function puts everyting in t2 into t1.
- for k, v in pairs(t2) do
- t1[k] = v
- end
- return t1 -- We return t1 because that's the table you'll want afterwards (even though it doesn't make a new table)
- end
- -- Major functions
- -- Making functions local (I don't like messing up _G)
- local renderDisplay, checkEvents, loadFromFile, saveToFile
- local checkDoorTimer, checkUserLockTimer
- -- Core loop components
- function renderDisplay()
- -- Frame timer
- os.startTimer(0.2) -- 5 fps is good enough, can even do less, but meh.
- -- Clean the terminal
- term.clear()
- term.setCursorPos(1,1)
- --TODO
- end
- --
- function checkEvents(event, p1, p2)
- -- Used in our loop to check for new OS events.
- if event == "char" then
- if p1 == "x" then
- error("User pressed 'x'. 'x' is a bad key to press.")
- elseif p1 == "s" then
- saveToFile()
- loadFromFile()
- end
- end
- end
- function checkDoorTimer()
- --TODO
- end
- function checkUserLockTimer()
- --TODO
- end
- -- Door toggler.
- function toggleDoor(bState)
- -- This will toggle the door, or set it's state to bState
- if bState ~= nil then
- bDoorState = bState
- else
- bDoorState = not bDoorState -- not negates the state in boolean: true, any data not nil -> false; false, nil -> true
- end
- return bDoorState -- Good practice to return result, in this case the door's state.
- end
- -- Saving/loading
- do -- This just to make the code neater, really. (And so I can easily collapse the code in ScITE)
- function loadFromFile()
- if not fs.exists("passlock-data") then return end -- We can't load nothing.
- local err, res = pcall(function() return loadfile("passlock-data")() end) -- Yes, I'm doing this the easy and hard way.
- if not err then
- print("Error loading configuration: \n", res)
- print("Enter to continue...")
- read()
- end
- mergeTable(config, res) -- This will ensure the defaults are there if a field is missing.
- end
- -- Saving helper format strings
- local saveHelper = {}
- saveHelper.boolean = [[config[%q] = %s]]
- saveHelper.string = [[config[%q] = %q]]
- saveHelper.number = [[config[%q] = %d]]
- -- Saving function
- function saveToFile()
- -- This is the 'harder' part of the two :(
- local sData = [[local config = {} -- This file, generated by Passlock. Edit at your own risk.]] .. "\n"
- for k, v in pairs(config) do
- local sDataType = type(v)
- local sSaveHelper = saveHelper[sDataType]
- if not sSaveHelper then
- -- We have problem, let's just print it, and continue without saving it.
- print("Warning: (saveToFile) unknown data type, in key: " .. k)
- else
- -- No errors, save it.
- sData = sData .. string.format(sSaveHelper, k, tostring(v)) .. "\n"
- end
- end
- sData = sData .. [[return config]] -- We need to return the config in order to retrieve it.
- -- Delete and save.
- if fs.exists("passlock-data") then
- fs.delete("passlock-data")
- end
- local hHandle = io.open("passlock-data", "w")
- if not hHandle then
- -- We're pissed, let's error.
- error("Unable to open file handle; call to saveToFile", 2)
- end
- hHandle:write(sData)
- hHandle:close()
- end
- end
- -- Looping function
- function doImportantStuff()
- while true do
- if bRootExit then -- Quit if user logged in as Root wishes to.
- break
- end
- local event, p1, p2 = os.pullEvent()
- print("Event: ", event, "\n p1 & p2: ", p1, ",", p2)
- if event == "timer" then
- checkDoorTimer() -- Lock the door if it has been open long enough
- checkUserLockTimer() -- Allow user to login again, if enough time has passed.
- renderDisplay() -- Moved inside checkEvents, to provide a static #FPS (i.e typing will cause an overload of timers)
- end
- checkEvents(event, p1, p2) -- Get our user input, or yet another timer event for updating the screen.
- -- Doesn't seem like much, does it? D:
- end
- end
- -- Startup function, one-time.
- function startup()
- loadFromFile() -- Loads config if it exists.
- end
- -- Loop
- while true do
- local err, res = pcall(doImportantStuff)
- if bRootExit then -- Quit if user logged in as Root wishes to.
- break
- end
- if not err then
- if res ~= "Terminated" then
- print("error: ", string.format("%q", res))
- print("enter to continue... (ctrl-t is SUPER EFFECTIVE right now!)")
- read()
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment