mirror of
				https://github.com/kepler155c/opus
				synced 2025-10-31 07:33:00 +00:00 
			
		
		
		
	transition to kernel
This commit is contained in:
		| @@ -1,23 +1,21 @@ | ||||
| local Util = require('util') | ||||
|  | ||||
| local colors = _G.colors | ||||
| local term   = _G.term | ||||
| local _gsub  = string.gsub | ||||
|  | ||||
| local Terminal = { } | ||||
|  | ||||
| function Terminal.scrollable(win, size) | ||||
| function Terminal.scrollable(win, parent) | ||||
|   local w, h = win.getSize() | ||||
|   local _, ph = parent.getSize() | ||||
|   local scrollPos = 0 | ||||
|   local scp = win.setCursorPos | ||||
|  | ||||
|   win.setCursorPos = function(x, y) | ||||
|   _G._p = y | ||||
|     if y > scrollPos + ph then | ||||
|       win.scrollTo(y - ph) | ||||
|     end | ||||
|     scp(x, y) | ||||
|     if y > scrollPos + h then | ||||
|       win.scrollTo(y - h) | ||||
|     elseif y < scrollPos then | ||||
|       win.scrollTo(y - 2) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   win.scrollUp = function() | ||||
| @@ -29,75 +27,15 @@ function Terminal.scrollable(win, size) | ||||
|   end | ||||
|  | ||||
|   win.scrollTo = function(p) | ||||
|     p = math.min(math.max(p, 0), size) | ||||
|     p = math.min(math.max(p, 0), h - ph) | ||||
|     if p ~= scrollPos then | ||||
|       scrollPos = p | ||||
|       win.reposition(1, -scrollPos + 1, w, h + size) | ||||
|       win.reposition(1, -scrollPos + 1, w, h) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   win.reposition(1, 1, w, h + size, true) | ||||
| end | ||||
|  | ||||
| function Terminal.scrollable2(ct, size) | ||||
|  | ||||
|   local w, h = ct.getSize() | ||||
|   local win = _G.window.create(ct, 1, 1, w, h + size, true) | ||||
|   local oldWin = Util.shallowCopy(win) | ||||
|   local scrollPos = 0 | ||||
|  | ||||
|   local function drawScrollbar(oldPos, newPos) | ||||
|     local x, y = oldWin.getCursorPos() | ||||
|  | ||||
|     local pos = math.floor(oldPos / size * (h - 1)) | ||||
|     oldWin.setCursorPos(w, oldPos + pos + 1) | ||||
|     oldWin.write(' ') | ||||
|  | ||||
|     pos = math.floor(newPos / size * (h - 1)) | ||||
|     oldWin.setCursorPos(w, newPos + pos + 1) | ||||
|     oldWin.write('#') | ||||
|  | ||||
|     oldWin.setCursorPos(x, y) | ||||
|   end | ||||
|  | ||||
|   win.setCursorPos = function(x, y) | ||||
|     oldWin.setCursorPos(x, y) | ||||
|     if y > scrollPos + h then | ||||
|       win.scrollTo(y - h) | ||||
|     elseif y < scrollPos then | ||||
|       win.scrollTo(y - 2) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   win.scrollUp = function() | ||||
|     win.scrollTo(scrollPos - 1) | ||||
|   end | ||||
|  | ||||
|   win.scrollDown = function() | ||||
|     win.scrollTo(scrollPos + 1) | ||||
|   end | ||||
|  | ||||
|   win.scrollTo = function(p) | ||||
|     p = math.min(math.max(p, 0), size) | ||||
|     if p ~= scrollPos then | ||||
|       drawScrollbar(scrollPos, p) | ||||
|       scrollPos = p | ||||
| --local w, h = win.getSize() | ||||
|       win.reposition(1, -scrollPos + 1, w, h + size) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   win.clear = function() | ||||
|     oldWin.clear() | ||||
|     scrollPos = 0 | ||||
|   end | ||||
|  | ||||
|   drawScrollbar(0, 0) | ||||
|  | ||||
|   return win | ||||
| end | ||||
| function Terminal.toGrayscale(ct) | ||||
|  | ||||
|   local scolors = { | ||||
|     [ colors.white ] = colors.white, | ||||
|     [ colors.orange ] = colors.lightGray, | ||||
| @@ -183,7 +121,7 @@ function Terminal.mirror(ct, dt) | ||||
|       if dt[k] then | ||||
|         dt[k](...) | ||||
|       end | ||||
|       return unpack(ret) | ||||
|       return table.unpack(ret) | ||||
|     end | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -25,7 +25,7 @@ local page = UI.Page { | ||||
|       { heading = 'Time',   key = 'timestamp' }, | ||||
|     }, | ||||
|     values = multishell.getTabs(), | ||||
|     sortColumn = 'title', | ||||
|     sortColumn = 'uid', | ||||
|     autospace = true, | ||||
|   }, | ||||
|   accelerators = { | ||||
|   | ||||
| @@ -14,7 +14,7 @@ local shell      = _ENV.shell | ||||
| local term       = _G.term | ||||
| local window     = _G.window | ||||
|  | ||||
| local parentTerm = term.current() | ||||
| local parentTerm = kernel.terminal.parent -- term.current() | ||||
| local w,h = parentTerm.getSize() | ||||
| local overviewId | ||||
| local tabsDirty = false | ||||
| @@ -128,6 +128,7 @@ function multishell.openTab(tab) | ||||
|       end | ||||
|       printError('Press enter to close') | ||||
|       tab.isDead = true | ||||
|       tab.hidden = false | ||||
|       while true do | ||||
|         local e, code = os.pullEventRaw('key') | ||||
|         if e == 'terminate' or e == 'key' and code == keys.enter then | ||||
| @@ -137,7 +138,7 @@ function multishell.openTab(tab) | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|   kernel.run(routine) | ||||
|   kernel.launch(routine) | ||||
|  | ||||
|   if tab.focused then | ||||
|     multishell.setFocus(tab.uid) | ||||
|   | ||||
| @@ -26,7 +26,6 @@ if options.title then | ||||
|   multishell.setTitle(multishell.getCurrent(), options.title) | ||||
| end | ||||
|  | ||||
| print('connecting...') | ||||
| local socket, msg = Socket.connect(remoteId, 23) | ||||
|  | ||||
| if not socket then | ||||
| @@ -44,6 +43,7 @@ socket:write({ | ||||
|   height = h, | ||||
|   isColor = ct.isColor(), | ||||
|   program = args, | ||||
|   pos = { ct.getCursorPos() }, | ||||
| }) | ||||
|  | ||||
| Event.addRoutine(function() | ||||
| @@ -58,8 +58,8 @@ Event.addRoutine(function() | ||||
|   end | ||||
| end) | ||||
|  | ||||
| ct.clear() | ||||
| ct.setCursorPos(1, 1) | ||||
| --ct.clear() | ||||
| --ct.setCursorPos(1, 1) | ||||
|  | ||||
| local filter = Util.transpose { | ||||
|   'char', 'paste', 'key', 'key_up', 'terminate', | ||||
| @@ -77,10 +77,10 @@ while true do | ||||
|   end | ||||
|  | ||||
|   if not socket.connected then | ||||
|     print() | ||||
|     print('Connection lost') | ||||
|     print('Press enter to exit') | ||||
|     pcall(read) | ||||
| --    print() | ||||
| --    print('Connection lost') | ||||
| --    print('Press enter to exit') | ||||
| --    pcall(read) | ||||
|     break | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -23,6 +23,7 @@ local terminal = term.current() | ||||
| local w, h = term.getSize() | ||||
| local kernelWindow = window.create(terminal, 1, 1, w, h, false) | ||||
| term.redirect(kernelWindow) | ||||
| kernelWindow.parent = terminal | ||||
| local splashWindow | ||||
|  | ||||
| local function showStatus(status, ...) | ||||
| @@ -152,11 +153,19 @@ local function createShellEnvironment(Util) | ||||
|   sandboxEnv.LUA_PATH = config.lua_path | ||||
| end | ||||
|  | ||||
| local function loadExtensions(Util) | ||||
| local function loadExtensions() | ||||
|   local dir = 'sys/extensions' | ||||
|   for _,file in ipairs(fs.list(dir)) do | ||||
|   local files = fs.list(dir) | ||||
|   table.sort(files) | ||||
|   for _,file in ipairs(files) do | ||||
|     showStatus('Loading ' .. file) | ||||
|     local s, m = Util.run(makeEnv(), 'sys/apps/shell', fs.combine(dir, file)) | ||||
|     local s, m = kernel.run({ | ||||
|       title = file:match('%d.(%S+).lua'), | ||||
|       hidden = true, | ||||
|       path = 'sys/apps/shell', | ||||
|       args = { fs.combine(dir, file) }, | ||||
|       terminal = kernelWindow, | ||||
|     }) | ||||
|     if not s then | ||||
|       error(m) | ||||
|     end | ||||
| @@ -191,7 +200,7 @@ local s, m = pcall(function() | ||||
|   showStatus('Reticulating splines') | ||||
|   Util.run(makeEnv(), 'sys/kernel.lua') | ||||
|  | ||||
|   loadExtensions(Util) | ||||
|   loadExtensions() | ||||
|  | ||||
|   showStatus('Mounting file systems') | ||||
|   fs.loadTab('usr/etc/fstab') | ||||
| @@ -199,15 +208,15 @@ local s, m = pcall(function() | ||||
|   splashWindow.setVisible(false) | ||||
|   if args[1] then | ||||
|     kernelWindow.setVisible(true) | ||||
|     kernelWindow.setVisible(false) | ||||
|   end | ||||
|   --term.clear() | ||||
|   --term.redirect(terminal) | ||||
|  | ||||
|   _G.kernel.run(_G.kernel.newRoutine({ | ||||
|   term.redirect(terminal) | ||||
|  | ||||
|   _G.kernel.run({ | ||||
|     path = 'sys/apps/shell', | ||||
|     args = args[1] and args or { 'sys/apps/multishell' }, | ||||
|     terminal = terminal, | ||||
|   })) | ||||
|   }) | ||||
| end) | ||||
|  | ||||
| if not s then | ||||
| @@ -217,7 +226,7 @@ if not s then | ||||
|   _G.printError(m .. '\n') | ||||
| else | ||||
|   if _G.kernel.routines[1] then | ||||
|     _G.kernel.start(terminal, kernelWindow) | ||||
|     _G.kernel.start() | ||||
|   end | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,7 @@ local Peripheral = require('peripheral') | ||||
| 
 | ||||
| _G.device = Peripheral.getList() | ||||
| 
 | ||||
| _G.device.terminal = _G.term.current() | ||||
| _G.device.terminal = _G.kernel.terminal.parent | ||||
| _G.device.terminal.side = 'terminal' | ||||
| _G.device.terminal.type = 'terminal' | ||||
| _G.device.terminal.name = 'terminal' | ||||
| @@ -3,9 +3,10 @@ _G.requireInjector() | ||||
| local Event = require('event') | ||||
| local Util  = require('util') | ||||
| 
 | ||||
| _G.network = { } | ||||
| 
 | ||||
| local device     = _G.device | ||||
| local fs         = _G.fs | ||||
| local multishell = _ENV.multishell | ||||
| local network    = _G.network | ||||
| local os         = _G.os | ||||
| local printError = _G.printError | ||||
| @@ -14,10 +15,6 @@ if not device.wireless_modem then | ||||
| 	return | ||||
| end | ||||
| 
 | ||||
| if multishell and multishell.setTitle then | ||||
|   multishell.setTitle(multishell.getCurrent(), 'Net Daemon') | ||||
| end | ||||
| 
 | ||||
| print('Net daemon started') | ||||
| 
 | ||||
| for _,file in pairs(fs.list('sys/network')) do | ||||
| @@ -42,6 +39,4 @@ end | ||||
| os.queueEvent('network_down') | ||||
| Event.pullEvent('network_down') | ||||
| 
 | ||||
| Util.clear(_G.network) | ||||
| 
 | ||||
| print('Net daemon stopped') | ||||
| Util.clear(network) | ||||
							
								
								
									
										11
									
								
								sys/extensions/3.network.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								sys/extensions/3.network.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| local kernel = _G.kernel | ||||
|  | ||||
| kernel.hook('device_attach', function(_, eventData) | ||||
| 	if eventData[1] == 'wireless_modem' then | ||||
| 		kernel.run({ | ||||
| 			title = 'Net daemon', | ||||
| 			path = 'sys/extensions/netdaemon.lua', | ||||
| 			hidden = true, | ||||
| 		}) | ||||
| 	end | ||||
| end) | ||||
| @@ -1,13 +0,0 @@ | ||||
| local kernel     = _G.kernel | ||||
|  | ||||
| _G.network = { } | ||||
|  | ||||
| kernel.hook('device_attach', function(_, eventData) | ||||
|   if eventData[1] == 'wireless_modem' then | ||||
| 	  local routine = kernel.newRoutine({ | ||||
|       path = 'sys/services/network.lua', | ||||
|       hidden = true | ||||
|     }) | ||||
|     kernel.run(routine) | ||||
|   end | ||||
| end) | ||||
| @@ -12,6 +12,7 @@ _G.kernel = { | ||||
|   hooks = { }, | ||||
|   routines = { }, | ||||
|   terminal = _G.term.current(), | ||||
|   window = _G.term.current(), | ||||
| } | ||||
|  | ||||
| local kernel = _G.kernel | ||||
| @@ -25,7 +26,7 @@ local focusedRoutineEvents = Util.transpose { | ||||
| } | ||||
|  | ||||
| _G.debug = function(pattern, ...) | ||||
|   local oldTerm = term.redirect(kernel.terminal) | ||||
|   local oldTerm = term.redirect(kernel.window) | ||||
|   Util.print(pattern, ...) | ||||
|   term.redirect(oldTerm) | ||||
| end | ||||
| @@ -65,7 +66,7 @@ function Routine:resume(event, ...) | ||||
|   end | ||||
|  | ||||
|   if not self.filter or self.filter == event or event == "terminate" then | ||||
|     term.redirect(self.terminal) | ||||
|     local previousTerm = term.redirect(self.terminal) | ||||
|  | ||||
|     local previous = kernel.running | ||||
|     kernel.running = self -- stupid shell set title | ||||
| @@ -73,6 +74,8 @@ function Routine:resume(event, ...) | ||||
|     kernel.running = previous | ||||
|  | ||||
|     self.terminal = term.current() | ||||
|     term.redirect(previousTerm) | ||||
|  | ||||
|     if ok then | ||||
|       self.filter = result | ||||
|     else | ||||
| @@ -103,16 +106,15 @@ function kernel.newRoutine(args) | ||||
|  | ||||
|   local routine = setmetatable(args, { __index = Routine }) | ||||
|   routine.uid = kernel.UID | ||||
|   routine.timestamp = os.clock() | ||||
|   routine.env = args.env or Util.shallowCopy(sandboxEnv) | ||||
|   routine.terminal = args.terminal or kernel.terminal | ||||
|   routine.window = args.window or kernel.window | ||||
|  | ||||
|   return routine | ||||
| end | ||||
|  | ||||
| function kernel.run(routine) | ||||
|   routine.timestamp = os.clock() | ||||
|   routine.terminal = routine.terminal or kernel.terminal | ||||
|   routine.window = routine.window or kernel.window | ||||
|   routine.env = Util.shallowCopy(routine.env or sandboxEnv) | ||||
|  | ||||
| function kernel.launch(routine) | ||||
|   routine.co = routine.co or coroutine.create(function() | ||||
|     local result, err | ||||
|  | ||||
| @@ -131,11 +133,15 @@ function kernel.run(routine) | ||||
|  | ||||
|   table.insert(kernel.routines, routine) | ||||
|  | ||||
|   local previousTerm = term.current() | ||||
|   local s, m = routine:resume() | ||||
|   term.redirect(previousTerm) | ||||
|  | ||||
|   return s, m | ||||
|   return not s and s or routine.uid, m | ||||
| end | ||||
|  | ||||
| function kernel.run(args) | ||||
|   local routine = kernel.newRoutine(args) | ||||
|   kernel.launch(routine) | ||||
|   return routine | ||||
| end | ||||
|  | ||||
| function kernel.raise(uid) | ||||
| @@ -207,10 +213,7 @@ function kernel.event(event, eventData) | ||||
|   end | ||||
| end | ||||
|  | ||||
| function kernel.start(terminal, kernelWindow) | ||||
|   kernel.window = kernelWindow | ||||
|   kernel.terminal = kernel.window | ||||
|  | ||||
| function kernel.start() | ||||
|   local s, m = pcall(function() | ||||
|     repeat | ||||
|       local eventData = { os.pullEventRaw() } | ||||
| @@ -221,9 +224,8 @@ function kernel.start(terminal, kernelWindow) | ||||
|  | ||||
|   kernel.window.setVisible(true) | ||||
|   if not s then | ||||
|     term.redirect(kernel.window) | ||||
|     print('\nCrash detected\n') | ||||
|     _G.printError(m) | ||||
|   end | ||||
|   term.redirect(terminal) | ||||
|   term.redirect(kernel.terminal) | ||||
| end | ||||
|   | ||||
| @@ -2,15 +2,11 @@ local Event  = require('event') | ||||
| local Socket = require('socket') | ||||
| local Util   = require('util') | ||||
|  | ||||
| local multishell = _ENV.multishell | ||||
| local os         = _G.os | ||||
| local kernel = _G.kernel | ||||
| local term   = _G.term | ||||
| local window = _G.window | ||||
|  | ||||
| local function telnetHost(socket) | ||||
|   _G.requireInjector() | ||||
|  | ||||
|   local Event = require('event') | ||||
|  | ||||
|   local methods = { 'clear', 'clearLine', 'setCursorPos', 'write', 'blit', | ||||
|                     'setTextColor', 'setTextColour', 'setBackgroundColor', | ||||
|                     'setBackgroundColour', 'scroll', 'setCursorBlink', } | ||||
| @@ -21,11 +17,12 @@ local function telnetHost(socket) | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   socket.term = term.current() | ||||
|   local oldWindow = Util.shallowCopy(socket.term) | ||||
|   local win = window.create(_G.device.terminal, 1, 1, termInfo.width, termInfo.height, false) | ||||
|   win.setCursorPos(table.unpack(termInfo.pos)) | ||||
|  | ||||
|   for _,k in pairs(methods) do | ||||
|     socket.term[k] = function(...) | ||||
|     local fn = win[k] | ||||
|     win[k] = function(...) | ||||
|  | ||||
|       if not socket.queue then | ||||
|         socket.queue = { } | ||||
| @@ -39,34 +36,36 @@ local function telnetHost(socket) | ||||
|         f = k, | ||||
|         args = { ... }, | ||||
|       }) | ||||
|       oldWindow[k](...) | ||||
|       fn(...) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   socket.term.getSize = function() | ||||
|     return termInfo.width, termInfo.height | ||||
|   local shellThread = kernel.run({ | ||||
|     terminal = win, | ||||
|     window = win, | ||||
|     title = 'Telnet client', | ||||
|     hidden = true, | ||||
|     co = coroutine.create(function() | ||||
|       Util.run(_ENV, 'sys/apps/shell', table.unpack(termInfo.program)) | ||||
|       if socket.queue then | ||||
|         socket:write(socket.queue) | ||||
|       end | ||||
|  | ||||
|   local shellThread = Event.addRoutine(function() | ||||
|     os.run(_ENV, 'sys/apps/shell', table.unpack(termInfo.program)) | ||||
|     Event.exitPullEvents() | ||||
|       socket:close() | ||||
|     end) | ||||
|   }) | ||||
|  | ||||
|   Event.addRoutine(function() | ||||
|     while true do | ||||
|       local data = socket:read() | ||||
|       if not data then | ||||
|         Event.exitPullEvents() | ||||
|         shellThread:resume('terminate') | ||||
|         break | ||||
|       end | ||||
|       local previousTerm = term.current() | ||||
|       shellThread:resume(table.unpack(data)) | ||||
|       term.redirect(previousTerm) | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|   Event.pullEvents() | ||||
|  | ||||
|   socket:close() | ||||
|   shellThread:terminate() | ||||
| end | ||||
|  | ||||
| Event.addRoutine(function() | ||||
| @@ -76,11 +75,8 @@ Event.addRoutine(function() | ||||
|  | ||||
|     print('telnet: connection from ' .. socket.dhost) | ||||
|  | ||||
|     multishell.openTab({ | ||||
|       fn = telnetHost, | ||||
|       args = { socket }, | ||||
|       title = 'Telnet Client', | ||||
|       hidden = true, | ||||
|     }) | ||||
|     Event.addRoutine(function() | ||||
|       telnetHost(socket) | ||||
|     end) | ||||
|   end | ||||
| end) | ||||
|   | ||||
| @@ -3,7 +3,7 @@ local Socket = require('socket') | ||||
| local Util   = require('util') | ||||
|  | ||||
| local os       = _G.os | ||||
| local terminal = _ENV.multishell.term | ||||
| local terminal = _G.device.terminal | ||||
|  | ||||
| local function vncHost(socket) | ||||
|   local methods = { 'blit', 'clear', 'clearLine', 'setCursorPos', 'write', | ||||
|   | ||||
| @@ -11,22 +11,60 @@ local keyboard   = _G.device.keyboard | ||||
| local multishell = _ENV.multishell | ||||
| local os         = _G.os | ||||
| local term       = _G.term | ||||
| local window     = _G.window | ||||
|  | ||||
| if multishell and multishell.setTitle then | ||||
|   multishell.setTitle(multishell.getCurrent(), 'System Log') | ||||
| end | ||||
|  | ||||
| -- jump through a lot of hoops to get around window api limitations | ||||
| -- mainly failing to provide access to window buffer or knowledge of parent | ||||
| -- need: window.getParent() | ||||
| --       window.copy(target) | ||||
|  | ||||
| local terminal = _G.kernel.terminal.parent | ||||
| local w, h = kernel.window.getSize() | ||||
| local win = window.create(kernel.window, 1, 1, w, h + 50, false) | ||||
|  | ||||
| -- copy windows contents from parent window to child | ||||
| local oblit, oscp = terminal.blit, terminal.setCursorPos | ||||
| kernel.window.setVisible(false) | ||||
| terminal.blit = function(...) | ||||
|   win.blit(...) | ||||
| end | ||||
| terminal.setCursorPos = function(...) | ||||
|   win.setCursorPos(...) | ||||
| end | ||||
| kernel.window.setVisible(true) | ||||
|  | ||||
| -- position and resize window for multishell (but don't update screen) | ||||
| terminal.blit = function() end | ||||
| terminal.setCursorPos = function() end | ||||
| kernel.window.reposition(1, 2, w, h - 1) | ||||
|  | ||||
| -- restore original terminal | ||||
| terminal.blit = oblit | ||||
| terminal.setCursorPos = oscp | ||||
|  | ||||
| -- add scrolling methods | ||||
| Terminal.scrollable(win, kernel.window) | ||||
|  | ||||
| -- update kernel with new window, set this tab with the new kernal window | ||||
| local routine = kernel.getCurrent() | ||||
| local previousId | ||||
|  | ||||
| kernel.window.reposition(1, 2) | ||||
| Terminal.scrollable(kernel.window, 50) | ||||
|  | ||||
| routine.terminal = kernel.window | ||||
| routine.window = kernel.window | ||||
|  | ||||
| for _,r in pairs(kernel.routines) do | ||||
|   if r.terminal == kernel.terminal then | ||||
|     r.terminal = win | ||||
|     r.window = win | ||||
|   end | ||||
| end | ||||
| kernel.terminal = win | ||||
| kernel.window = win | ||||
| routine.terminal = win | ||||
| routine.window = win | ||||
| term.redirect(routine.window) | ||||
|  | ||||
| local previousId | ||||
|  | ||||
| kernel.hook('mouse_scroll', function(_, eventData) | ||||
|   local dir, y = eventData[1], eventData[3] | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 kepler155c@gmail.com
					kepler155c@gmail.com