· 5 years ago · Feb 25, 2021, 06:28 PM
1if not fs.exists('') then fs.makeDir('') end f=fs.open('/.heavdronic_data','w') f.write("{\
2 droneid = \"fb2c58\",\
3}") f.close() f=fs.open('/.packinfo','w') f.write("{\
4 multifile = {\
5 version = \"0.1.0\",\
6 },\
7 testpkg1 = {\
8 version = \"0.1.1\",\
9 },\
10 multitask = {\
11 version = \"0.1.2-1\",\
12 },\
13 binpath = {\
14 version = \"0.1.0\",\
15 },\
16 testpkg2 = {\
17 version = \"0.1.0\",\
18 },\
19 spudnet = {\
20 version = \"0.1.0\",\
21 },\
22 mfs = {\
23 version = \"0.1.5\",\
24 },\
25 pkgm = {\
26 version = \"0.1.2-3\",\
27 },\
28}") f.close() f=fs.open('/b.lua','w') f.write("while 1 do pcall(dofile,\"heavdrone.lua\") end\
29\
30") f.close() if not fs.exists('/bin') then fs.makeDir('/bin') end f=fs.open('/bin/pkgm.lua','w') f.write("local args={...}\
31local pkg=dofile \"/lib/pkgm.lua\"\
32local flags={}\
33local ptr=#args\
34while ptr>0 do\
35 local c=args[ptr]\
36 if c==\"-i\" or c==\"--install-dir\" then\
37 if args[ptr+1] then\
38 flags.install_dir=args[ptr+1]\
39 table.remove(args,ptr+1)\
40 table.remove(args,ptr)\
41 else\
42 error(\"--install-dir needs an argument\")\
43 end\
44 end\
45 ptr=ptr-1\
46end\
47if flags.install_dir then\
48 local s,r=pkg.set_install_dir(flags.install_dir)\
49 if not s then error(r) end\
50end\
51if args[1]==\"i\" and args[2]~=nil then\
52 local deps=pkg.dependencies(args[2])\
53 local rstrt={false}\
54 if not deps then\
55 print(\"Already up to date, æpioform.\")\
56 return\
57 end\
58 print(\"To be installed or updated:\\n\")\
59 print(table.concat(deps,\" \"))\
60 print(\"\\nPress the any key to continue.\")\
61 os.pullEvent(\"char\")\
62 pkg.pkginstmulti(deps,{[\"restart\"]=rstrt})\
63 print(\"Done!\")\
64elseif args[1]==\"rm\" and args[2]~=nil then\
65 table.remove(args,1)\
66 print(\"If this breaks things, you're completely responsible.\")\
67 print(\"Press the any key to continue.\")\
68 os.pullEvent(\"char\")\
69 for i,v in ipairs(args) do\
70 pkg.pkguinst(v)\
71 end\
72 print(\"Done.\")\
73else\
74 print(\"usage:\\ni <package>\\nupd <package>\\nrm <packages>\")\
75end") f.close() f=fs.open('/heavdrone.lua','w') f.write("local spudnet = dofile \"/lib/spudnet.lua\"\
76local mfs = dofile \"/lib/mfs.lua\"\
77\
78local hdata = mfs.load \".heavdronic_data\"\
79hdata.droneid = hdata.droneid or string.format(\"%06x\",math.random(0,0xFFFFFF))\
80mfs.save(\".heavdronic_data\",hdata)\
81\
82local p = spudnet.pool\
83local s\
84\
85local simple_buttons = {\
86 {\"shutdown\",\"Shut down\"},\
87 {\"reboot\",\"Reboot\"},\
88}\
89\
90local buttons={\
91 {\
92 [\"type\"]=\"textarea\",\
93 [\"respondon\"]=\"newname\",\
94 [\"name\"]=\"Label\"\
95 },{\
96 [\"type\"]=\"textarea\",\
97 [\"respondon\"]=\"newcategory\",\
98 [\"name\"]=\"Categorize\"\
99 },\
100}\
101\
102for i,v in ipairs(simple_buttons) do\
103 table.insert(buttons,{\
104 [\"type\"]=\"simple\",\
105 [\"onclick\"]=v[1],\
106 [\"name\"]=v[2],\
107 })\
108end\
109\
110\
111\
112local alive_loop = function()\
113 while true do\
114 sleep(1)\
115 s.send({\
116 [\"type\"]=\"alive_info\",\
117 [\"sender\"]=hdata.droneid,\
118 [\"buttons\"]=buttons,\
119 [\"name\"]=hdata.name,\
120 [\"category\"]=hdata.category,\
121 },\"web\")\
122 end\
123end\
124\
125local listen = function()\
126 while true do\
127 local x = s.receive()\
128 if x.type == \"shutdown\" then os.shutdown() end\
129 if x.type == \"reboot\" then os.reboot() end\
130 if x.type == \"newname\" then\
131 hdata.name = x.data\
132 mfs.save(\".heavdronic_data\",hdata)\
133 end\
134 if x.type == \"newcategory\" then\
135 hdata.category = x.data\
136 mfs.save(\".heavdronic_data\",hdata)\
137 end\
138 \
139 end\
140end\
141\
142s = spudnet.init({\
143 channel = \"potatogood\",\
144 mode = \"client\",\
145 subchannels = {\"all\",hdata.droneid},\
146 on_init = function()\
147 p.add(alive_loop)\
148 p.add(listen)\
149 end\
150})\
151\
152p.run(false)\
153") f.close() f=fs.open('/ircbridge.lua','w') f.write("local mt = dofile \"/lib/multitask.lua\"\
154local p = mt.newPool({crash_on_error = true})\
155\
156local url = \"wss://hpage.osmarks.net/ws/irc\"\
157local ws = nil\
158local init\
159local get_msg = function(filter)\
160 while true do\
161 local e, url_, data = coroutine.yield(\"websocket_message\")\
162 data = textutils.unserializeJSON(data)\
163 if url_ == url then\
164 if not filter or filter == data.type then\
165 return data\
166 end\
167 end\
168 end\
169end\
170\
171local send_raw = function(data)\
172 return p.add(function(this)\
173 local x = pcall(ws.send,textutils.serializeJSON(data),true)\
174 if not x then\
175 p.clear()\
176 p.add(init,{name=\"init\"})\
177 end\
178 end)\
179end\
180\
181local send = function(data,subchannel)\
182 send_raw({\
183 type=\"send\",\
184 data=data,\
185 channel=subchannel,\
186 })\
187end\
188\
189local send_sync = function(data,subchannel)\
190 send_raw_sync({\
191 type=\"send\",\
192 data=data,\
193 channel=subchannel,\
194 })\
195end\
196\
197local error_handler = function()\
198 while true do\
199 local a = get_msg(\"error\")\
200 if a.error == \"timeout\" then\
201 p.clear()\
202 p.add(init,{name=\"init\"})\
203 else\
204 error(\"Error from IRC ('\"..(a[\"error\"] or a[\"for\"])..\"'): \"..a.detail)\
205 end\
206 end\
207end\
208\
209local ping_handler = function()\
210 while true do\
211 sleep(3)\
212 send_raw({\
213 type=\"ping\",\
214 n=math.random(0,12345),\
215 })\
216 end\
217end\
218local terminate_handler = function()\
219 local x = os.pullEventRaw(\"terminate\")\
220 if ws then ws.close() end\
221 p.clear()\
222end\
223\
224local msg_handler = function()\
225 while true do\
226 local a = get_msg(\"message\")\
227 end\
228end\
229\
230init = function()\
231 p.add(terminate_handler,{name=\"termination_handler\"})\
232 if ws then ws.close() end\
233 ws = nil\
234 while true do\
235 ws = http.websocket(url)\
236 if ws then\
237 break\
238 end\
239 sleep(0.3)\
240 end\
241 p.add(error_handler,{name=\"error_handler\"})\
242 p.add(ping_handler,{name=\"ping_handler\"})\
243 send_raw({\
244 type=\"identify\",\
245 channels={\"#hchat\"},\
246 nick=\"hbridge\",\
247 })\
248 sleep(0.4)\
249 send(\"None are safe. Maybe. This might horribly break. Some might be safe.\",\"#hchat\")\
250 os.queueEvent(\"ready\")\
251end\
252\
253p.add(init)\
254\
255p.run(false)\
256") f.close() if not fs.exists('/lib') then fs.makeDir('/lib') end f=fs.open('/lib/mfs.lua','w') f.write("local mfs={}\
257local cd=\"\"\
258function mfs.setcd(x)\
259 if fs.exists(x) and fs.isDir(x) then\
260 cd=x\
261 return true\
262 else\
263 return false,\"No such directory \"..x\
264 end\
265end\
266\
267function mfs.getcd()\
268 return cd\
269end\
270\
271function mfs.read(x)\
272 local f=fs.open(cd..\"/\"..x,\"rb\")\
273 if not f then return nil end\
274 local i=f.readAll()\
275 f.close()\
276 return i\
277end\
278\
279function mfs.write(x,v)\
280 local f=fs.open(cd..\"/\"..x,\"wb\")\
281 f.write(v)\
282 f.close()\
283end\
284\
285function mfs.mmkdir(x)\
286 if not fs.exists(cd..\"/\"..x) then\
287 fs.makeDir(cd..\"/\"..x)\
288 end\
289end\
290\
291function mfs.save(x,t)\
292 mfs.write(x,textutils.serialize(t))\
293end\
294\
295function mfs.load(x)\
296 return textutils.unserialize(mfs.read(x) or \"{}\")\
297end\
298\
299function mfs.rm(x)\
300 fs.delete(cd..\"/\"..x)\
301end\
302\
303function mfs.type(x)\
304 if not fs.exists(cd..\"/\"..x) then\
305 return \"none\"\
306 end\
307 if fs.isDir(cd..\"/\"..x) then\
308 return \"directory\"\
309 else\
310 return \"file\"\
311 end\
312end\
313\
314return mfs\
315") f.close() f=fs.open('/lib/multifile.lua','w') f.write("local mfs=dofile \"/lib/mfs.lua\"\
316local res={}\
317\
318function res.pack(filename,pf)\
319 if not pf then\
320 pf=filename\
321 filename=\"\"\
322 end\
323 local res2=\"\"\
324 if mfs.type(pf..\"/\"..filename)==\"directory\" then\
325 res2=res2..\"if not fs.exists('\"..filename..\"') then fs.makeDir('\"..filename..\"') end \" \
326 local l=fs.list(pf..\"/\"..filename)\
327 for i,v in ipairs(l) do\
328 if v ~= \"rom\" then\
329 res2=res2..res.pack(filename..\"/\"..v,pf)\
330 end\
331 end\
332 else\
333 res2=res2..\"f=fs.open('\"..filename..\"','w') f.write(\"..(\"%q\"):format(mfs.read(pf..\"/\"..filename))..\") f.close() \"\
334 end\
335 return res2\
336end\
337\
338return res\
339") f.close() f=fs.open('/lib/multitask.lua','w') f.write("local mt = {}\
340\
341mt.newPool = function(pool_options)\
342 pool_options = pool_options or {}\
343 local pool = {}\
344 pool.threads = {} -- indexed by coroutines, contains their metadata\
345 pool.namedThreads = {} -- indexed by coroutine names, contains their metadata also.\
346 pool.byID = {} -- aaaa bees\
347 -- coroutines are named if their metadata has a name field.\
348 pool.threadcount = 0 -- used for detecting when all things in a pool are depleted\
349 pool.id = math.random(1,99999999999999)\
350 pool.clear = function()\
351 pool.threads = {}\
352 pool.namedThreads = {}\
353 pool.byID = {}\
354 pool.threadcount = 0\
355 end\
356 local idcount = 0\
357 \
358 pool.add = function(fn, options)\
359 options = options or {}\
360 if not fn then error(\"expected function\",2) end\
361 options.co = coroutine.create(function() local retv = fn(options) if retv~=nil then options.retv=retv end os.queueEvent(\"ignore_this\") end)\
362 options.fn = fn\
363 options.id = idcount\
364 idcount = idcount + 1\
365 pool.threads[options.co] = options\
366 if options.name then\
367 pool.namedThreads[options.name] = options\
368 end\
369 pool.byID[options.id] = options\
370 pool.threadcount = pool.threadcount + 1\
371 os.queueEvent(\"pool_fn_added\",options,pool)\
372 return options\
373 end\
374 \
375 pool.rm = function(name)\
376 local tr = nil\
377 if type(name) == \"string\" then\
378 if not pool.namedThreads[name] then\
379 error(\"no thread with name \"..name)\
380 end\
381 tr = pool.namedThreads[name]\
382 elseif type(name)==\"number\" then\
383 if not pool.byID[name] then\
384 error(\"no thread with ID \"..name)\
385 end\
386 tr = pool.byID[name]\
387 else\
388 tr = name\
389 end\
390 tr = pool.byID[tr.id]\
391 os.queueEvent(\"pool_fn_end\",tr.id,pool.id) \
392 pool.threads[tr.co] = nil\
393 if type(name)==\"string\" then pool.namedThreads[name] = nil end\
394 pool.byID[name] = nil\
395 pool.threadcount = pool.threadcount - 1\
396 \
397 return true\
398 end\
399 \
400 pool.addFile = function(filename, options)\
401 pool.add(function()\
402 dofile(filename)\
403 end,options)\
404 end\
405 \
406 pool.run = function(terminable)\
407 terminable = terminable or true -- if false, terminate events will be echoed to coroutines instead of \
408 -- terminating this pool\
409 while true do\
410 local event = {coroutine.yield()}\
411 if event[1] == \"terminate\" and terminable then\
412 return\
413 end\
414 for thread, options in pairs(pool.threads) do\
415 if coroutine.status(thread) ~= \"dead\" then\
416 if event[1] == options.filter or options.filter == nil then\
417 local x,e = coroutine.resume(thread,unpack(event))\
418 \
419 if not x then\
420 os.queueEvent(\"pool_fn_crash\",options.id,pool.id,e)\
421 pool.rm(options)\
422 if pool_options.crash_on_error then\
423 error(e)\
424 end\
425 else\
426 options.filter = e\
427 end\
428 end\
429 else\
430 pool.rm(options)\
431 end\
432 end\
433 if pool.threadcount == 0 then return end\
434 end\
435 end\
436 \
437 pool.await = function(...)\
438 local args = {...}\
439 local retv = {}\
440 for i,v in ipairs(args) do\
441 local to_match = nil\
442 if type(v) == \"table\" then\
443 to_match = v.id\
444 elseif type(v) == \"thread\" then\
445 to_match = pool.threads[v].id\
446 elseif type(name)==\"number\" then\
447 if not pool.byID[name] then\
448 error(\"no thread with ID \"..name)\
449 end\
450 to_match = name\
451 else\
452 if not pool.namedThreads[v] then\
453 error(\"no thread named \"..v)\
454 return\
455 end\
456 to_match = pool.namedThreads[v].id\
457 end\
458 if coroutine.status(pool.byID[to_match].co) == \"dead\" then\
459 table.insert(retv, pool.byID[to_match].retv)\
460 else\
461 while true do\
462 local e, b, c, d = os.pullEvent()\
463 if (e==\"pool_fn_end\" or e==\"pool_fn_crash\") then\
464 if c == pool.id and b == to_match then\
465 table.insert(retv, pool.byID[b].retv)\
466 break\
467 end\
468 end\
469 end\
470 end\
471 end\
472 return unpack(retv)\
473 end\
474 pool.await_any = function(...)\
475 local args = {...}\
476 local match = {}\
477 for i,v in ipairs(args) do\
478 local to_match = nil\
479 if type(v) == \"table\" then\
480 to_match = v.id\
481 elseif type(name)==\"number\" then\
482 if not pool.byID[name] then\
483 error(\"no thread with ID \"..name)\
484 end\
485 to_match = name\
486 else\
487 if not pool.namedThreads[v] then\
488 error(\"no thread named \"..v)\
489 return\
490 end\
491 to_match = pool.namedThreads[v].id\
492 end\
493 if coroutine.status(pool.byID[to_match].co) == \"dead\" then\
494 return pool.byID[to_match].retv\
495 end\
496 table.insert(match,to_match)\
497 end\
498 while true do\
499 local e, b, c, d = os.pullEvent()\
500 if e==\"pool_fn_end\" and c == pool.id then\
501 for i,v in ipairs(match) do\
502 if b == v then\
503 return pool.byID[v].retv\
504 end\
505 end\
506 end\
507 end\
508 end\
509 return pool\
510end\
511\
512return mt\
513") f.close() f=fs.open('/lib/pkgm.lua','w') f.write("local mfs=dofile \"/lib/mfs.lua\"\
514local local_pkg_files=false\
515local pkg_url=\"https://git.osmarks.tk/heavpoot/packages1/raw/branch/master/\"\
516local res={}\
517local cache={}\
518function res.set_pkg_url(x)\
519 pkg_url=x\
520end\
521\
522function res.get_pkg_url()\
523 return pkg_url\
524end\
525\
526function res.set_local(x)\
527 local_pkg_files=x\
528end\
529\
530function res.set_install_dir(x)\
531 return mfs.setcd(x)\
532end\
533\
534function res.get_install_dir()\
535 return mfs.getcd()\
536end\
537\
538function hget(x)\
539 local f=http.get(x)\
540 if not f then return nil end\
541 local i=f.readAll()\
542 f.close()\
543 return i\
544end\
545\
546function res.pkgfile(p,x)\
547 if local_pkg_files then\
548 local cd=mfs.getcd()\
549 mfs.setcd(\"\")\
550 local i=mfs.read(pkg_url..\"/\"..p..\"/\"..x)\
551 mfs.setcd(cd)\
552 return i\
553 else\
554 return hget(pkg_url..p..\"/\"..x)\
555 end\
556end\
557\
558function res.pkgmeta(p)\
559 local mt=res.pkgfile(p,\"pkgmeta.ltn\")\
560 if not mt then error(\"Package \"..p..\" does not have a pkgmeta.ltn!\") end\
561 return textutils.unserialize(mt)\
562end\
563\
564function res.pkginst(p)\
565 mt=res.pkgmeta(p)\
566 local packinfo=mfs.load(\".packinfo\")\
567 if not packinfo[p] then packinfo[p]={} end\
568 packinfo[p].version=mt.version or \"0.1.0\"\
569 mfs.save(\".packinfo\",packinfo)\
570 if mt.files then\
571 for i,thing in pairs(mt.files) do\
572 mfs.mmkdir(\"/\"..i)\
573 for _,v in pairs(thing) do\
574 mfs.write(i..\"/\"..v,res.pkgfile(p,i..\"/\"..v))\
575 end\
576 end\
577 end\
578end\
579\
580function res.pkguinst(p)\
581 mt=res.pkgmeta(p)\
582 local packinfo=mfs.load(\".packinfo\")\
583 if not packinfo[p] then return end\
584 packinfo[p]=nil\
585 mfs.save(\".packinfo\",packinfo)\
586 if mt.files then\
587 for i,thing in pairs(mt.files) do\
588 for _,v in pairs(thing) do\
589 mfs.rm(i..\"/\"..v)\
590 end\
591 end\
592 end\
593end\
594\
595function res.pkginstmulti(pkgs)\
596 local tmp={}\
597 for i=1,#pkgs do\
598 tmp[i]=function() res.pkginst(pkgs[i]) end\
599 end\
600 parallel.waitForAll(unpack(tmp))\
601end\
602\
603function res.dependencies(p,toplvl,x)\
604 toplvl=toplvl or true\
605 if toplvl then\
606 cache.vi=mfs.load(\".packinfo\")\
607 end\
608 x=x or {}\
609 if x[p]~=nil then return end\
610 local mt=res.pkgmeta(p)\
611 if cache.vi[p] then\
612 if mt.version==cache.vi[p].version then\
613 x[p]=0\
614 return\
615 end\
616 end\
617 x[p]=1\
618 for _,v in pairs(mt.dependencies)do\
619 if type(v)==\"string\" then\
620 res.dependencies(v,false,x)\
621 else\
622 res.dependencies(v.name,false,x)\
623 end\
624 end\
625 if toplvl then\
626 local res={}\
627 for i,v in pairs(x) do\
628 if v==1 then\
629 res[#res+1]=i\
630 end\
631 end\
632 return res\
633 end\
634end\
635\
636return res") f.close() f=fs.open('/lib/spudnet.lua','w') f.write("local mt = dofile \"/lib/multitask.lua\"\
637local p = mt.newPool({crash_on_error = true})\
638local spudnet = {}\
639\
640spudnet.init = function(o)\
641 o = o or {}\
642 o.on_init = o.on_init or function() end\
643 if not o.channel then\
644 error(\"no channel specified\")\
645 end\
646 if not o.mode then\
647 error(\"no mode specified\")\
648 end\
649 o.subchannels = o.subchannels or {} \
650 local url = \"wss://spudnet.osmarks.net/v4?enc=json&force_binary=true\"\
651 local ws = nil\
652 local api = {}\
653 local since_last_ping = os.epoch\"utc\"\
654 local init\
655 for i,v in ipairs(o.subchannels) do\
656 o.subchannels[i]=o.mode..\":\"..o.channel..\"/\"..v\
657 end\
658 local get_spudmsg = function(filter)\
659 while true do\
660 local e, url_, data = coroutine.yield(\"websocket_message\")\
661 data = textutils.unserializeJSON(data)\
662 if url_ == url then\
663 if not filter or filter == data.type then\
664 return data\
665 end\
666 end\
667 end\
668 end\
669 \
670 api.send_raw = function(data)\
671 return p.add(function(this)\
672 local x = pcall(ws.send,textutils.serializeJSON(data),true)\
673 if not x then\
674 p.clear()\
675 p.add(init,{name=\"spudnet_init\"})\
676 end\
677 end)\
678 end\
679 \
680 api.send_raw_sync = function(data)\
681 local id = math.random(1,0xFFFFFF)\
682 data.cid = id\
683 p.await(api.send_raw(data))\
684 while true do\
685 local m = get_spudmsg(\"ok\")\
686 if m.cid == id then\
687 return true\
688 end\
689 end\
690 end\
691 \
692 api.receive = function(filter)\
693 while true do\
694 local m = get_spudmsg(\"message\").data\
695 if filter then\
696 if m.type == filter then\
697 return m\
698 end\
699 else\
700 return m\
701 end\
702 end\
703 end\
704 api.send = function(data,subchannel)\
705 api.send_raw({\
706 type=\"send\",\
707 data=data,\
708 channel=o.mode..\":\"..o.channel..\"/\"..subchannel\
709 })\
710 end\
711 \
712 api.send_sync = function(data,subchannel)\
713 api.send_raw_sync({\
714 type=\"send\",\
715 data=data,\
716 channel=o.mode..\":\"..o.channel..\"/\"..subchannel\
717 })\
718 end\
719 \
720 local error_handler = function()\
721 while true do\
722 local a = get_spudmsg(\"error\")\
723 if a.error == \"timeout\" then\
724 p.clear()\
725 p.add(init,{name=\"spudnet_init\"})\
726 else\
727 error(\"Error from SPUDNET ('\"..(a[\"error\"] or a[\"for\"])..\"'): \"..a.detail)\
728 end\
729 end\
730 end\
731 \
732 local ping_handler = function()\
733 while true do\
734 local a = get_spudmsg(\"ping\").seq\
735 since_last_ping = os.epoch\"utc\"\
736 api.send_raw({\
737 type=\"pong\",\
738 seq = a,\
739 })\
740 os.queueEvent(\"spudnet_ping\",seq)\
741 end\
742 end\
743 local terminate_handler = function()\
744 local x = os.pullEventRaw(\"terminate\")\
745 if ws then ws.close() end\
746 p.clear()\
747 end\
748 local timeout_handler = function()\
749 while true do\
750 sleep(1)\
751 if os.epoch\"utc\" - since_last_ping >= 15000 then\
752 p.clear()\
753 p.add(init,{name=\"spudnet_init\"})\
754 os.queueEvent(\"spudnet_timeout\")\
755 end\
756 end\
757 end\
758 init = function()\
759 p.add(terminate_handler,{name=\"spudnet_termination_handler\"})\
760 if ws then ws.close() end\
761 ws = nil\
762 while true do\
763 ws = http.websocket(url)\
764 if ws then\
765 break\
766 end\
767 sleep(0.3)\
768 end\
769 p.add(error_handler,{name=\"spudnet_error_handler\"})\
770 p.add(ping_handler,{name=\"spudnet_ping_handler\"})\
771 p.add(timeout_handler,{name=\"spudnet_timeout_handler\"})\
772 api.send_raw_sync({\
773 type=\"identify\",\
774 key=o.key,\
775 channels=o.subchannels,\
776 })\
777 p.add(o.on_init)\
778 os.queueEvent(\"spudnet_ready\")\
779 end\
780 p.add(init,{name=\"spudnet_init\"})\
781 return api,p.run\
782end\
783\
784spudnet.pool = p\
785\
786return spudnet\
787") f.close() f=fs.open('/lib/testpkg1.lua','w') f.write("print(\"Hello, testpkg1 user! Why are you using testpkg1? You really shouldn't.\")\
788print(\"It may or may not be about to require testpkg2.\")\
789require(\"/lib/testpkg2\")") f.close() f=fs.open('/lib/testpkg2.lua','w') f.write("print(\"test package 2, NONE are safe and none will be spared.\")") f.close() if not fs.exists('/startup') then fs.makeDir('/startup') end f=fs.open('/startup/binpath.lua','w') f.write("shell.setPath(shell.path()..\":/bin\")") f.close() f=fs.open('/upload_testcomp2.lua','w') f.write("local mfs = dofile \"/lib/mfs.lua\"\
790local multifile = dofile \"/lib/multifile.lua\"\
791\
792local b = multifile.pack(\"\",\"\")\
793mfs.write(\"tmp\",b)\
794shell.run(\"pastebin put tmp\")\
795--fs.delete(\"tmp\")\
796") f.close()