mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-18 11:48:02 -04:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
36f93eae9e
26
LICENSE
Normal file
26
LICENSE
Normal file
@ -0,0 +1,26 @@
|
||||
Copyright (c) 2013-2014 Florian "Sangar" Nücke
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
All images / textures and localization strings (resources) are put in the
|
||||
public domain. More specicially, see CC0 1.0 Universal:
|
||||
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
25
LICENSE-jnlua
Normal file
25
LICENSE-jnlua
Normal file
@ -0,0 +1,25 @@
|
||||
OpenComputers uses the JNLua library, with a patch to allow memory limits:
|
||||
|
||||
http://code.google.com/p/jnlua/issues/detail?id=9
|
||||
|
||||
JNLua is copyrighted and licensed as follows:
|
||||
|
||||
Copyright (C) 2008,2012 Andre Naef
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
19
LICENSE-luaj
Normal file
19
LICENSE-luaj
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2007 LuaJ. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
22
LICENSE-mods
Normal file
22
LICENSE-mods
Normal file
@ -0,0 +1,22 @@
|
||||
OpenComputers uses APIs from a couple of other mods.
|
||||
|
||||
To support accepting energy from their respective power systems:
|
||||
- BuildCraft [1], license: Minecraft Mod Public License, see homepage.
|
||||
- Universal Electricity [3], license: Lesser General Public License [4].
|
||||
|
||||
To support bundled redstone input and output:
|
||||
- RedLogic [6], license: MIT License, see thread.
|
||||
- MineFactory Reloaded [7], license: custom, see thread.
|
||||
- Project: Red [9], license: Restricted Public Software License [10].
|
||||
|
||||
For providing a peripheral and reading their floppy disks:
|
||||
- ComputerCraft [8], copyright Daniel Ratcliffe.
|
||||
|
||||
[1] http://www.mod-buildcraft.com/
|
||||
[3] http://universalelectricity.com/
|
||||
[4] http://www.gnu.org/copyleft/lesser.html
|
||||
[6] http://www.minecraftforum.net/topic/1852277-162-redlogic-wip-replacement-for-rp2-wiringlogiccontrollighting/
|
||||
[7] http://www.minecraftforum.net/topic/2016680-162164-powercrystals-mods-minefactoryreloaded-powercrystalscore-and-netherores-updated/
|
||||
[8] http://www.computercraft.info/
|
||||
[9] http://projectredwiki.com/
|
||||
[10] https://github.com/MrTJP/ProjectRed/blob/master/LICENSE.md
|
207
LICENSE-typesafe
Normal file
207
LICENSE-typesafe
Normal file
@ -0,0 +1,207 @@
|
||||
OpenComputers uses the typesafe config library, it is copyrighted as follows:
|
||||
|
||||
Copyright (C) 2011-2012 Typesafe Inc. <http://typesafe.com>
|
||||
|
||||
It is licensed as follows:
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -1,11 +1,13 @@
|
||||
package li.cil.oc.api.fs;
|
||||
|
||||
import li.cil.oc.api.Persistable;
|
||||
|
||||
/**
|
||||
* Used by file system components to get and set the file system's label.
|
||||
*
|
||||
* @see li.cil.oc.api.FileSystem#asManagedEnvironment(FileSystem, Label)
|
||||
*/
|
||||
public interface Label {
|
||||
public interface Label extends Persistable {
|
||||
/**
|
||||
* Get the current value of this label.
|
||||
* <p/>
|
||||
|
@ -37,5 +37,5 @@
|
||||
@cpw.mods.fml.common.API(
|
||||
owner = "OpenComputers|Core",
|
||||
provides = "OpenComputersAPI",
|
||||
apiVersion = "1.3.0")
|
||||
apiVersion = "1.4.0")
|
||||
package li.cil.oc.api;
|
@ -489,7 +489,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def installedMemory = 96 * 1024
|
||||
override def installedMemory = 128 * 1024
|
||||
|
||||
override def tier = 0
|
||||
|
||||
|
@ -28,7 +28,7 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
|
||||
@Callback(doc = """function():boolean -- Returns whether the screen is currently on.""")
|
||||
def isOn(computer: Context, args: Arguments): Array[AnyRef] = result(origin.isOn)
|
||||
|
||||
@Callback(doc = """function():boolean -- Turns off the screen. Returns true if it was on.""")
|
||||
@Callback(doc = """function():boolean -- Turns the screen on. Returns true if it was off.""")
|
||||
def turnOn(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||
if (!origin.isOn) {
|
||||
origin.turnOn()
|
||||
@ -37,7 +37,7 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
|
||||
else result(false, origin.isOn)
|
||||
}
|
||||
|
||||
@Callback(doc = """function():boolean -- Turns the screen on. Returns true if it was off.""")
|
||||
@Callback(doc = """function():boolean -- Turns off the screen. Returns true if it was on.""")
|
||||
def turnOff(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||
if (origin.isOn) {
|
||||
origin.turnOff()
|
||||
|
@ -20,13 +20,15 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@Callback(direct = true)
|
||||
def getLabel(context: Context, args: Arguments): Array[AnyRef] = label match {
|
||||
case value: Label => result(label.getLabel)
|
||||
case _ => null
|
||||
def getLabel(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
label match {
|
||||
case value: Label => result(label.getLabel)
|
||||
case _ => null
|
||||
}
|
||||
}
|
||||
|
||||
@Callback
|
||||
def setLabel(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def setLabel(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
if (label == null) throw new Exception("filesystem does not support labeling")
|
||||
if (args.checkAny(0) == null) label.setLabel(null)
|
||||
else label.setLabel(args.checkString(0))
|
||||
@ -34,12 +36,12 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def isReadOnly(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def isReadOnly(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.isReadOnly)
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def spaceTotal(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def spaceTotal(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
val space = fileSystem.spaceTotal
|
||||
if (space < 0)
|
||||
Array("unlimited")
|
||||
@ -48,32 +50,32 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def spaceUsed(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def spaceUsed(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.spaceUsed)
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def exists(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def exists(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.exists(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def size(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def size(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.size(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def isDirectory(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def isDirectory(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.isDirectory(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def lastModified(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def lastModified(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.lastModified(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback
|
||||
def list(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def list(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
Option(fileSystem.list(clean(args.checkString(0)))) match {
|
||||
case Some(list) => Array(list)
|
||||
case _ => null
|
||||
@ -81,26 +83,26 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
|
||||
@Callback
|
||||
def makeDirectory(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def makeDirectory(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
def recurse(path: String): Boolean = !fileSystem.exists(path) && (fileSystem.makeDirectory(path) ||
|
||||
(recurse(path.split("/").dropRight(1).mkString("/")) && fileSystem.makeDirectory(path)))
|
||||
result(recurse(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback
|
||||
def remove(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def remove(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
def recurse(parent: String): Boolean = (!fileSystem.isDirectory(parent) ||
|
||||
fileSystem.list(parent).forall(child => recurse(parent + "/" + child))) && fileSystem.delete(parent)
|
||||
result(recurse(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback
|
||||
def rename(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def rename(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.rename(clean(args.checkString(0)), clean(args.checkString(1))))
|
||||
}
|
||||
|
||||
@Callback
|
||||
def close(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
@Callback(direct = true)
|
||||
def close(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
val handle = args.checkInteger(0)
|
||||
Option(fileSystem.getHandle(handle)) match {
|
||||
case Some(file) =>
|
||||
@ -113,8 +115,8 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
null
|
||||
}
|
||||
|
||||
@Callback
|
||||
def open(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
@Callback(direct = true, limit = 4)
|
||||
def open(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
if (owners.get(context.node.address).fold(false)(_.size >= Settings.get.maxHandles)) {
|
||||
throw new IOException("too many open handles")
|
||||
}
|
||||
@ -127,8 +129,8 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
result(handle)
|
||||
}
|
||||
|
||||
@Callback
|
||||
def read(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
@Callback(direct = true, limit = 4)
|
||||
def read(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
val handle = args.checkInteger(0)
|
||||
val n = math.min(Settings.get.maxReadBuffer, math.max(0, args.checkInteger(1)))
|
||||
checkOwner(context.node.address, handle)
|
||||
@ -158,8 +160,8 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
}
|
||||
|
||||
@Callback
|
||||
def seek(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
@Callback(direct = true, limit = 4)
|
||||
def seek(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
val handle = args.checkInteger(0)
|
||||
val whence = args.checkString(1)
|
||||
val offset = args.checkInteger(2)
|
||||
@ -178,7 +180,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
|
||||
@Callback
|
||||
def write(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def write(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
val handle = args.checkInteger(0)
|
||||
val value = args.checkByteArray(1)
|
||||
if (!node.tryChangeBuffer(-Settings.get.hddWriteCost * value.length)) {
|
||||
@ -243,6 +245,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
})
|
||||
|
||||
label.load(nbt.getCompoundTag("label"))
|
||||
fileSystem.load(nbt.getCompoundTag("fs"))
|
||||
}
|
||||
|
||||
@ -262,6 +265,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
nbt.setTag("owners", ownersNbt)
|
||||
|
||||
nbt.setNewCompoundTag("label", label.save)
|
||||
nbt.setNewCompoundTag("fs", fileSystem.save)
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,15 @@ trait Architecture {
|
||||
*/
|
||||
def init(): Boolean
|
||||
|
||||
/**
|
||||
* Called when the owning machine was connected to the component network.
|
||||
*
|
||||
* This can be useful for connecting custom file systems (read only memory)
|
||||
* in case init() was called from the machine's load() method (where it was
|
||||
* not yet connected to the network).
|
||||
*/
|
||||
def onConnect()
|
||||
|
||||
/**
|
||||
* Called when a computer stopped. Used to clean up any handles, memory and
|
||||
* so on. For example, for Lua this destroys the Lua state.
|
||||
|
@ -0,0 +1,34 @@
|
||||
package li.cil.oc.server.component.machine
|
||||
|
||||
import li.cil.oc.api.FileSystem
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import li.cil.oc.{Settings, OpenComputers}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
abstract class LuaArchitecture(val machine: Machine) extends Architecture {
|
||||
val rom = Option(FileSystem.asManagedEnvironment(FileSystem.
|
||||
fromClass(OpenComputers.getClass, Settings.resourceDomain, "lua/rom"), "rom"))
|
||||
|
||||
override def init() = {
|
||||
if (machine.node.network != null) {
|
||||
rom.foreach(fs => machine.node.connect(fs.node))
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
override def onConnect() {
|
||||
rom.foreach(fs => machine.node.connect(fs.node))
|
||||
}
|
||||
|
||||
override def close() {
|
||||
rom.foreach(_.node.remove())
|
||||
}
|
||||
|
||||
override def load(nbt: NBTTagCompound) {
|
||||
rom.foreach(fs => fs.load(nbt.getCompoundTag("rom")))
|
||||
}
|
||||
|
||||
override def save(nbt: NBTTagCompound) {
|
||||
rom.foreach(fs => nbt.setNewCompoundTag("rom", fs.save))
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ import org.luaj.vm3.lib.jse.JsePlatform
|
||||
import scala.Some
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
|
||||
class LuaJLuaArchitecture(machine: Machine) extends Architecture {
|
||||
class LuaJLuaArchitecture(machine: Machine) extends LuaArchitecture(machine) {
|
||||
private var lua: Globals = _
|
||||
|
||||
private var thread: LuaThread = _
|
||||
@ -132,6 +132,8 @@ class LuaJLuaArchitecture(machine: Machine) extends Architecture {
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def init() = {
|
||||
super.init()
|
||||
|
||||
lua = JsePlatform.debugGlobals()
|
||||
lua.set("package", LuaValue.NIL)
|
||||
lua.set("io", LuaValue.NIL)
|
||||
@ -251,13 +253,13 @@ class LuaJLuaArchitecture(machine: Machine) extends Architecture {
|
||||
computer.set("pushSignal", (args: Varargs) => LuaValue.valueOf(machine.signal(args.checkjstring(1), toSimpleJavaObjects(args, 2): _*)))
|
||||
|
||||
// And its ROM address.
|
||||
computer.set("romAddress", (_: Varargs) => machine.rom.fold(LuaValue.NIL)(rom => Option(rom.node.address) match {
|
||||
computer.set("romAddress", (_: Varargs) => rom.fold(LuaValue.NIL)(fs => Option(fs.node.address) match {
|
||||
case Some(address) => LuaValue.valueOf(address)
|
||||
case _ => LuaValue.NIL
|
||||
}))
|
||||
|
||||
// And it's /tmp address...
|
||||
computer.set("tmpAddress", (_: Varargs) => machine.tmp.fold(LuaValue.NIL)(tmp => Option(tmp.node.address) match {
|
||||
computer.set("tmpAddress", (_: Varargs) => machine.tmp.fold(LuaValue.NIL)(fs => Option(fs.node.address) match {
|
||||
case Some(address) => LuaValue.valueOf(address)
|
||||
case _ => LuaValue.NIL
|
||||
}))
|
||||
@ -375,6 +377,8 @@ class LuaJLuaArchitecture(machine: Machine) extends Architecture {
|
||||
}
|
||||
|
||||
override def close() = {
|
||||
super.close()
|
||||
|
||||
lua = null
|
||||
thread = null
|
||||
synchronizedCall = null
|
||||
@ -385,11 +389,11 @@ class LuaJLuaArchitecture(machine: Machine) extends Architecture {
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def load(nbt: NBTTagCompound) {
|
||||
super.load(nbt)
|
||||
|
||||
if (machine.isRunning) {
|
||||
machine.stop()
|
||||
machine.start()
|
||||
}
|
||||
}
|
||||
|
||||
override def save(nbt: NBTTagCompound) {}
|
||||
}
|
||||
|
@ -24,9 +24,6 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
withConnector(if (isRobot) Settings.get.bufferRobot + 30 * Settings.get.bufferPerLevel else Settings.get.bufferComputer).
|
||||
create()
|
||||
|
||||
val rom = Option(FileSystem.asManagedEnvironment(FileSystem.
|
||||
fromClass(OpenComputers.getClass, Settings.resourceDomain, "lua/rom"), "rom"))
|
||||
|
||||
val tmp = if (Settings.get.tmpSize > 0) {
|
||||
Option(FileSystem.asManagedEnvironment(FileSystem.
|
||||
fromMemory(Settings.get.tmpSize * 1024), "tmpfs"))
|
||||
@ -208,7 +205,7 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
Option(node.network.node(address)) match {
|
||||
case Some(component: server.network.Component) if component.canBeSeenFrom(node) || component == node =>
|
||||
val direct = component.isDirect(method)
|
||||
if (direct) callCounts.synchronized {
|
||||
if (direct && architecture.isInitialized) callCounts.synchronized {
|
||||
val limit = component.limit(method)
|
||||
val counts = callCounts.getOrElseUpdate(component.address, mutable.Map.empty[String, Int])
|
||||
val count = counts.getOrElseUpdate(method, 0)
|
||||
@ -424,8 +421,8 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
override def onConnect(node: Node) {
|
||||
if (node == this.node) {
|
||||
components += this.node.address -> this.node.name
|
||||
rom.foreach(rom => node.connect(rom.node))
|
||||
tmp.foreach(tmp => node.connect(tmp.node))
|
||||
architecture.onConnect()
|
||||
}
|
||||
else {
|
||||
node match {
|
||||
@ -439,8 +436,7 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
|
||||
override def onDisconnect(node: Node) {
|
||||
if (node == this.node) {
|
||||
stop()
|
||||
rom.foreach(_.node.remove())
|
||||
close()
|
||||
tmp.foreach(_.node.remove())
|
||||
}
|
||||
else {
|
||||
@ -522,7 +518,6 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
components ++= nbt.getTagList("components").iterator[NBTTagCompound].map(c =>
|
||||
c.getString("address") -> c.getString("name"))
|
||||
|
||||
rom.foreach(rom => rom.load(nbt.getCompoundTag("rom")))
|
||||
tmp.foreach(tmp => tmp.load(nbt.getCompoundTag("tmp")))
|
||||
|
||||
if (state.size > 0 && state.top != Machine.State.Stopped && init()) {
|
||||
@ -587,7 +582,6 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
}
|
||||
nbt.setTag("components", componentsNbt)
|
||||
|
||||
rom.foreach(rom => nbt.setNewCompoundTag("rom", rom.save))
|
||||
tmp.foreach(tmp => nbt.setNewCompoundTag("tmp", tmp.save))
|
||||
|
||||
if (state.top != Machine.State.Stopped) {
|
||||
@ -637,7 +631,6 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
||||
// Connect the ROM and `/tmp` node to our owner. We're not in a network in
|
||||
// case we're loading, which is why we have to check it here.
|
||||
if (node.network != null) {
|
||||
rom.foreach(rom => node.connect(rom.node))
|
||||
tmp.foreach(tmp => node.connect(tmp.node))
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ import scala.Some
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
import scala.collection.mutable
|
||||
|
||||
class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
||||
class NativeLuaArchitecture(machine: Machine) extends LuaArchitecture(machine) {
|
||||
private var lua: LuaState = null
|
||||
|
||||
private var kernelMemory = 0
|
||||
@ -179,6 +179,8 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def init(): Boolean = {
|
||||
super.init()
|
||||
|
||||
// Creates a new state with all base libraries and the persistence library
|
||||
// loaded into it. This means the state has much more power than it
|
||||
// rightfully should have, so we sandbox it a bit in the following.
|
||||
@ -321,7 +323,7 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
||||
|
||||
// And its ROM address.
|
||||
lua.pushScalaFunction(lua => {
|
||||
machine.rom.foreach(rom => Option(rom.node.address) match {
|
||||
rom.foreach(fs => Option(fs.node.address) match {
|
||||
case None => lua.pushNil()
|
||||
case Some(address) => lua.pushString(address)
|
||||
})
|
||||
@ -331,7 +333,7 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
||||
|
||||
// And it's /tmp address...
|
||||
lua.pushScalaFunction(lua => {
|
||||
machine.tmp.foreach(tmp => Option(tmp.node.address) match {
|
||||
machine.tmp.foreach(fs => Option(fs.node.address) match {
|
||||
case None => lua.pushNil()
|
||||
case Some(address) => lua.pushString(address)
|
||||
})
|
||||
@ -563,6 +565,8 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
||||
}
|
||||
|
||||
override def close() {
|
||||
super.close()
|
||||
|
||||
if (lua != null) {
|
||||
lua.setTotalMemory(Integer.MAX_VALUE)
|
||||
lua.close()
|
||||
@ -574,6 +578,8 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def load(nbt: NBTTagCompound) {
|
||||
super.load(nbt)
|
||||
|
||||
// Unlimit memory use while unpersisting.
|
||||
lua.setTotalMemory(Integer.MAX_VALUE)
|
||||
|
||||
@ -609,6 +615,8 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
||||
}
|
||||
|
||||
override def save(nbt: NBTTagCompound) {
|
||||
super.save(nbt)
|
||||
|
||||
// Unlimit memory while persisting.
|
||||
lua.setTotalMemory(Integer.MAX_VALUE)
|
||||
|
||||
|
@ -121,24 +121,22 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Sett
|
||||
val block = Block.blocksList(blockId)
|
||||
val canActivate = block != null && Settings.get.allowActivateBlocks
|
||||
val shouldActivate = canActivate && (!isSneaking || (item == null || item.shouldPassSneakingClickToBlock(world, x, y, z)))
|
||||
if (shouldActivate && block.onBlockActivated(world, x, y, z, this, side, hitX, hitY, hitZ)) {
|
||||
return ActivationType.BlockActivated
|
||||
}
|
||||
val result =
|
||||
if (shouldActivate && block.onBlockActivated(world, x, y, z, this, side, hitX, hitY, hitZ))
|
||||
ActivationType.BlockActivated
|
||||
else if (tryPlaceBlockWhileHandlingFunnySpecialCases(stack, x, y, z, side, hitX, hitY, hitZ))
|
||||
ActivationType.ItemPlaced
|
||||
else if (tryUseItem(stack, duration))
|
||||
ActivationType.ItemUsed
|
||||
else
|
||||
ActivationType.None
|
||||
|
||||
if (stack != null) {
|
||||
val didPlace = tryPlaceBlockWhileHandlingFunnySpecialCases(stack, x, y, z, side, hitX, hitY, hitZ)
|
||||
if (stack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(this, stack)
|
||||
if (stack.stackSize <= 0) inventory.setInventorySlotContents(0, null)
|
||||
if (didPlace) {
|
||||
return ActivationType.ItemPlaced
|
||||
}
|
||||
|
||||
if (tryUseItem(stack, duration)) {
|
||||
return ActivationType.ItemUsed
|
||||
}
|
||||
}
|
||||
|
||||
ActivationType.None
|
||||
result
|
||||
}
|
||||
|
||||
def useEquippedItem(duration: Double) = {
|
||||
@ -324,14 +322,16 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Sett
|
||||
}
|
||||
|
||||
private def tryPlaceBlockWhileHandlingFunnySpecialCases(stack: ItemStack, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float) = {
|
||||
val fakeEyeHeight = if (rotationPitch < 0 && isSomeKindOfPiston(stack)) 1.82 else 0
|
||||
setPosition(posX, posY - fakeEyeHeight, posZ)
|
||||
val didPlace = stack.tryPlaceItemIntoWorld(this, world, x, y, z, side, hitX, hitY, hitZ)
|
||||
setPosition(posX, posY + fakeEyeHeight, posZ)
|
||||
if (didPlace) {
|
||||
robot.addXp(Settings.get.robotActionXp)
|
||||
stack != null && stack.stackSize > 0 && {
|
||||
val fakeEyeHeight = if (rotationPitch < 0 && isSomeKindOfPiston(stack)) 1.82 else 0
|
||||
setPosition(posX, posY - fakeEyeHeight, posZ)
|
||||
val didPlace = stack.tryPlaceItemIntoWorld(this, world, x, y, z, side, hitX, hitY, hitZ)
|
||||
setPosition(posX, posY + fakeEyeHeight, posZ)
|
||||
if (didPlace) {
|
||||
robot.addXp(Settings.get.robotActionXp)
|
||||
}
|
||||
didPlace
|
||||
}
|
||||
didPlace
|
||||
}
|
||||
|
||||
private def isSomeKindOfPiston(stack: ItemStack) =
|
||||
|
@ -72,17 +72,32 @@ object FileSystem extends Item {
|
||||
override def setLabel(value: String) {
|
||||
media.setLabel(stack, value)
|
||||
}
|
||||
|
||||
override def load(nbt: NBTTagCompound) {}
|
||||
|
||||
override def save(nbt: NBTTagCompound) {}
|
||||
}
|
||||
|
||||
private class ItemLabel(val stack: ItemStack) extends Label {
|
||||
override def getLabel =
|
||||
if (dataTag(stack).hasKey(Settings.namespace + "fs.label"))
|
||||
dataTag(stack).getString(Settings.namespace + "fs.label")
|
||||
else null
|
||||
var label: Option[String] = None
|
||||
|
||||
override def getLabel = label.orNull
|
||||
|
||||
override def setLabel(value: String) {
|
||||
dataTag(stack).setString(Settings.namespace + "fs.label",
|
||||
if (value.length > 16) value.substring(0, 16) else value)
|
||||
label = Option(if (value != null && value.length > 16) value.substring(0, 16) else value)
|
||||
}
|
||||
|
||||
override def load(nbt: NBTTagCompound) {
|
||||
if (dataTag(stack).hasKey(Settings.namespace + "fs.label")) {
|
||||
label = Option(dataTag(stack).getString(Settings.namespace + "fs.label"))
|
||||
}
|
||||
}
|
||||
|
||||
override def save(nbt: NBTTagCompound) {
|
||||
label match {
|
||||
case Some(value) => dataTag(stack).setString(Settings.namespace + "fs.label", value)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import li.cil.oc.api.fs.Label
|
||||
import li.cil.oc.server.component
|
||||
import li.cil.oc.{Settings, api}
|
||||
import net.minecraftforge.common.DimensionManager
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
object FileSystem extends api.detail.FileSystemAPI {
|
||||
override def fromClass(clazz: Class[_], domain: String, root: String): api.fs.FileSystem = {
|
||||
@ -84,6 +85,10 @@ object FileSystem extends api.detail.FileSystemAPI {
|
||||
def setLabel(value: String) = throw new IllegalArgumentException("label is read only")
|
||||
|
||||
def getLabel = label
|
||||
|
||||
override def load(nbt: NBTTagCompound) {}
|
||||
|
||||
override def save(nbt: NBTTagCompound) {}
|
||||
}
|
||||
|
||||
private class ReadOnlyFileSystem(protected val root: io.File)
|
||||
|
@ -1,12 +1,12 @@
|
||||
local event = require("event")
|
||||
local fs = require("filesystem")
|
||||
local shell = require("shell")
|
||||
local process = require("process")
|
||||
|
||||
local proxy = ...
|
||||
|
||||
-- Install symlinks if they don't already exist.
|
||||
local links = {}
|
||||
local fsroot = fs.path(shell.running())
|
||||
local fsroot = fs.path(process.running())
|
||||
local function inject(path)
|
||||
for file in fs.list(fs.concat(fsroot, path)) do
|
||||
local source = fs.concat(fsroot, path, file)
|
||||
|
@ -6,7 +6,7 @@ local internet = require("internet")
|
||||
local shell = require("shell")
|
||||
|
||||
if not component.isAvailable("internet") then
|
||||
io.write("This program requires an internet card to run.")
|
||||
io.stderr:write("This program requires an internet card to run.")
|
||||
return
|
||||
end
|
||||
|
||||
@ -16,7 +16,7 @@ local args, options = shell.parse(...)
|
||||
local function get(pasteId, filename)
|
||||
local f, reason = io.open(filename, "w")
|
||||
if not f then
|
||||
io.write("Failed opening file for writing: ", reason)
|
||||
io.stderr:write("Failed opening file for writing: ", reason)
|
||||
return
|
||||
end
|
||||
|
||||
@ -35,9 +35,10 @@ local function get(pasteId, filename)
|
||||
f:close()
|
||||
io.write("Saved data to ", filename, "\n")
|
||||
else
|
||||
io.write("failed.\n")
|
||||
f:close()
|
||||
fs.remove(filename)
|
||||
io.write("HTTP request failed: ", response, "\n")
|
||||
io.stderr:write("HTTP request failed: ", response, "\n")
|
||||
end
|
||||
end
|
||||
|
||||
@ -61,7 +62,7 @@ function run(pasteId, ...)
|
||||
|
||||
local success, reason = shell.execute(tmpFile, nil, ...)
|
||||
if not success then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
end
|
||||
fs.remove(tmpFile)
|
||||
end
|
||||
@ -73,14 +74,14 @@ function put(path)
|
||||
if configFile then
|
||||
local result, reason = pcall(configFile)
|
||||
if not result then
|
||||
io.write("Failed loading config: ", reason)
|
||||
io.stderr:write("Failed loading config: ", reason)
|
||||
end
|
||||
end
|
||||
config.key = config.key or "fd92bd40a84c127eeb6804b146793c97"
|
||||
local file, reason = io.open(path, "r")
|
||||
|
||||
if not file then
|
||||
io.write("Failed opening file for reading: ", reason)
|
||||
io.stderr:write("Failed opening file for reading: ", reason)
|
||||
return
|
||||
end
|
||||
|
||||
@ -112,7 +113,8 @@ function put(path)
|
||||
io.write('Run "pastebin get ', pasteId, '" to download anywhere.')
|
||||
end
|
||||
else
|
||||
io.write("failed: ", response)
|
||||
io.write("failed.\n")
|
||||
io.stderr:write(response)
|
||||
end
|
||||
end
|
||||
|
||||
@ -127,7 +129,7 @@ elseif command == "get" then
|
||||
local path = shell.resolve(args[3])
|
||||
if fs.exists(path) then
|
||||
if not options.f or not os.remove(path) then
|
||||
io.write("file already exists")
|
||||
io.stderr:write("file already exists")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
@ -5,7 +5,7 @@ local shell = require("shell")
|
||||
local text = require("text")
|
||||
|
||||
if not component.isAvailable("internet") then
|
||||
io.write("This program requires an internet card to run.")
|
||||
io.stderr:write("This program requires an internet card to run.")
|
||||
return
|
||||
end
|
||||
|
||||
@ -33,21 +33,21 @@ if not filename then
|
||||
end
|
||||
filename = text.trim(filename)
|
||||
if filename == "" then
|
||||
io.write("could not infer filename, please specify one")
|
||||
io.stderr:write("could not infer filename, please specify one")
|
||||
return
|
||||
end
|
||||
filename = shell.resolve(filename)
|
||||
|
||||
if fs.exists(filename) then
|
||||
if not options.f or not os.remove(filename) then
|
||||
io.write("file already exists")
|
||||
io.stderr:write("file already exists")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local f, reason = io.open(filename, "wb")
|
||||
if not f then
|
||||
io.write("Failed opening file for writing: ", reason)
|
||||
io.stderr:write("failed opening file for writing: ", reason)
|
||||
return
|
||||
end
|
||||
|
||||
@ -68,7 +68,10 @@ if result then
|
||||
io.write("Saved data to ", filename, "\n")
|
||||
end
|
||||
else
|
||||
if not options.q then
|
||||
io.write("failed.\n")
|
||||
end
|
||||
f:close()
|
||||
fs.remove(filename)
|
||||
io.write("HTTP request failed: ", response, "\n")
|
||||
io.stderr:write("HTTP request failed: ", response, "\n")
|
||||
end
|
@ -1,12 +1,12 @@
|
||||
local event = require("event")
|
||||
local fs = require("filesystem")
|
||||
local shell = require("shell")
|
||||
local process = require("process")
|
||||
|
||||
local proxy = ...
|
||||
|
||||
-- Install symlinks if they don't already exist.
|
||||
local links = {}
|
||||
local fsroot = fs.path(shell.running())
|
||||
local fsroot = fs.path(process.running())
|
||||
local function inject(path)
|
||||
for file in fs.list(fs.concat(fsroot, path)) do
|
||||
local source = fs.concat(fsroot, path, file)
|
||||
|
@ -5,7 +5,8 @@ local shell = require("shell")
|
||||
local sides = require("sides")
|
||||
|
||||
if not computer.isRobot() then
|
||||
error("can only run on robots", 0)
|
||||
io.stderr:write("can only run on robots")
|
||||
return
|
||||
end
|
||||
|
||||
local args, options = shell.parse(...)
|
||||
@ -17,7 +18,8 @@ end
|
||||
|
||||
local size = tonumber(args[1])
|
||||
if not size then
|
||||
error("invalid size", 0)
|
||||
io.stderr:write("invalid size")
|
||||
return
|
||||
end
|
||||
|
||||
local r = component.computer
|
||||
|
@ -50,12 +50,27 @@ end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local running = setmetatable({}, {__mode="k"})
|
||||
|
||||
local function findProcess(co)
|
||||
co = co or coroutine.running()
|
||||
for _, process in pairs(running) do
|
||||
for _, instance in pairs(process.instances) do
|
||||
if instance == co then
|
||||
return process
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
--[[ This is the global environment we make available to userland programs. ]]
|
||||
-- You'll notice that we do a lot of wrapping of native functions and adding
|
||||
-- parameter checks in those wrappers. This is to avoid errors from the host
|
||||
-- side that would push error objects - which are userdata and cannot be
|
||||
-- persisted.
|
||||
local sandbox
|
||||
local sandbox, libprocess
|
||||
sandbox = {
|
||||
assert = assert,
|
||||
dofile = nil, -- in boot/*_base.lua
|
||||
@ -70,10 +85,7 @@ sandbox = {
|
||||
if not allowBytecode() then
|
||||
mode = "t"
|
||||
end
|
||||
pcall(function()
|
||||
local _, penv = sandbox.require("shell").running()
|
||||
env = env or penv
|
||||
end)
|
||||
env = env or select(2, libprocess.running())
|
||||
return load(ld, source, mode, env or sandbox)
|
||||
end,
|
||||
loadfile = nil, -- in boot/*_base.lua
|
||||
@ -96,9 +108,7 @@ sandbox = {
|
||||
coroutine = {
|
||||
create = function(f)
|
||||
local co = coroutine.create(f)
|
||||
pcall(function()
|
||||
sandbox.require("shell").register(co)
|
||||
end)
|
||||
table.insert(findProcess().instances, co)
|
||||
return co
|
||||
end,
|
||||
resume = function(co, ...) -- custom resume part for bubbling sysyields
|
||||
@ -257,7 +267,7 @@ sandbox = {
|
||||
sandbox._G = sandbox
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Start of non-standard stuff made available via package.preload.
|
||||
-- Start of non-standard stuff.
|
||||
|
||||
local libcomponent
|
||||
libcomponent = {
|
||||
@ -359,6 +369,51 @@ local libcomputer = {
|
||||
end
|
||||
}
|
||||
|
||||
libprocess = {
|
||||
load = function(path, env, init, name)
|
||||
checkArg(1, path, "string")
|
||||
checkArg(2, env, "table", "nil")
|
||||
checkArg(3, init, "function", "nil")
|
||||
checkArg(4, name, "string", "nil")
|
||||
|
||||
local process = findProcess()
|
||||
if process then
|
||||
env = env or process.env
|
||||
end
|
||||
env = setmetatable({}, {__index=env or sandbox})
|
||||
local code, reason = sandbox.loadfile(path, "t", env)
|
||||
if not code then
|
||||
return nil, reason
|
||||
end
|
||||
|
||||
local thread = coroutine.create(function(...)
|
||||
if init then
|
||||
init()
|
||||
end
|
||||
return code(...)
|
||||
end)
|
||||
running[thread] = {
|
||||
path = path,
|
||||
command = name,
|
||||
env = env,
|
||||
parent = process,
|
||||
instances = setmetatable({thread}, {__mode="v"})
|
||||
}
|
||||
return thread
|
||||
end,
|
||||
running = function(level)
|
||||
level = level or 1
|
||||
local process = findProcess()
|
||||
while level > 1 and process do
|
||||
process = process.parent
|
||||
level = level - 1
|
||||
end
|
||||
if process then
|
||||
return process.path, process.env, process.command
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
local libunicode = {
|
||||
char = function(...)
|
||||
local args = table.pack(...)
|
||||
@ -396,107 +451,103 @@ local libunicode = {
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local function main()
|
||||
local args
|
||||
local function bootstrap()
|
||||
-- Minimalistic hard-coded pure async proxy for our ROM.
|
||||
local rom = {}
|
||||
function rom.invoke(method, ...)
|
||||
return invoke(true, computer.romAddress(), method, ...)
|
||||
end
|
||||
function rom.open(file) return rom.invoke("open", file) end
|
||||
function rom.read(handle) return rom.invoke("read", handle, math.huge) end
|
||||
function rom.close(handle) return rom.invoke("close", handle) end
|
||||
function rom.inits(file) return ipairs(rom.invoke("list", "boot")) end
|
||||
function rom.isDirectory(path) return rom.invoke("isDirectory", path) end
|
||||
|
||||
-- Custom low-level loadfile/dofile implementation reading from our ROM.
|
||||
local function loadfile(file)
|
||||
local handle, reason = rom.open(file)
|
||||
if not handle then
|
||||
error(reason)
|
||||
end
|
||||
if handle then
|
||||
local buffer = ""
|
||||
repeat
|
||||
local data, reason = rom.read(handle)
|
||||
if not data and reason then
|
||||
error(reason)
|
||||
end
|
||||
buffer = buffer .. (data or "")
|
||||
until not data
|
||||
rom.close(handle)
|
||||
return load(buffer, "=" .. file, "t", sandbox)
|
||||
end
|
||||
end
|
||||
local function dofile(file)
|
||||
local program, reason = loadfile(file)
|
||||
if program then
|
||||
local result = table.pack(pcall(program))
|
||||
if result[1] then
|
||||
return table.unpack(result, 2, result.n)
|
||||
else
|
||||
error(result[2])
|
||||
end
|
||||
else
|
||||
error(reason)
|
||||
end
|
||||
end
|
||||
|
||||
-- Make all calls in the bootstrapper direct to speed up booting. This is
|
||||
-- safe because all invokes are rom fs related - or should be, anyway.
|
||||
local realInvoke = invoke
|
||||
invoke = function(_, ...) return realInvoke(true, ...) end
|
||||
|
||||
-- Load file system related libraries we need to load other stuff moree
|
||||
-- comfortably. This is basically wrapper stuff for the file streams
|
||||
-- provided by the filesystem components.
|
||||
local buffer = loadfile("/lib/buffer.lua")
|
||||
local fs = loadfile("/lib/filesystem.lua")
|
||||
local io = loadfile("/lib/io.lua")
|
||||
local package = dofile("/lib/package.lua")
|
||||
|
||||
-- Initialize the package module with some of our own APIs.
|
||||
package.preload["buffer"] = buffer
|
||||
package.preload["component"] = function() return libcomponent end
|
||||
package.preload["computer"] = function() return libcomputer end
|
||||
package.preload["filesystem"] = fs
|
||||
package.preload["io"] = io
|
||||
package.preload["unicode"] = function() return libunicode end
|
||||
|
||||
-- Inject the package and io modules into the global namespace, as in Lua.
|
||||
sandbox.package = package
|
||||
sandbox.io = sandbox.require("io")
|
||||
|
||||
-- Mount the ROM and temporary file systems to allow working on the file
|
||||
-- system module from this point on.
|
||||
sandbox.require("filesystem").mount(computer.romAddress(), "/")
|
||||
if computer.tmpAddress() then
|
||||
sandbox.require("filesystem").mount(computer.tmpAddress(), "/tmp")
|
||||
end
|
||||
|
||||
-- Run library startup scripts. These mostly initialize event handlers.
|
||||
local scripts = {}
|
||||
for _, file in rom.inits() do
|
||||
local path = "boot/" .. file
|
||||
if not rom.isDirectory(path) then
|
||||
table.insert(scripts, path)
|
||||
end
|
||||
end
|
||||
table.sort(scripts)
|
||||
for i = 1, #scripts do
|
||||
dofile(scripts[i])
|
||||
end
|
||||
|
||||
-- Step out of the fast lane, all the basic stuff should now be loaded.
|
||||
invoke = realInvoke
|
||||
|
||||
-- Yield once to get a memory baseline.
|
||||
coroutine.yield()
|
||||
|
||||
return coroutine.create(function() dofile("/init.lua") end)
|
||||
local function bootstrap()
|
||||
-- Minimalistic hard-coded pure async proxy for our ROM.
|
||||
local rom = {}
|
||||
function rom.invoke(method, ...)
|
||||
return invoke(true, computer.romAddress(), method, ...)
|
||||
end
|
||||
local co, args = bootstrap(), {n=0}
|
||||
function rom.open(file) return rom.invoke("open", file) end
|
||||
function rom.read(handle) return rom.invoke("read", handle, math.huge) end
|
||||
function rom.close(handle) return rom.invoke("close", handle) end
|
||||
function rom.inits(file) return ipairs(rom.invoke("list", "boot")) end
|
||||
function rom.isDirectory(path) return rom.invoke("isDirectory", path) end
|
||||
|
||||
-- Custom low-level loadfile/dofile implementation reading from our ROM.
|
||||
local function loadfile(file)
|
||||
local handle, reason = rom.open(file)
|
||||
if not handle then
|
||||
error(reason)
|
||||
end
|
||||
local buffer = ""
|
||||
repeat
|
||||
local data, reason = rom.read(handle)
|
||||
if not data and reason then
|
||||
error(reason)
|
||||
end
|
||||
buffer = buffer .. (data or "")
|
||||
until not data
|
||||
rom.close(handle)
|
||||
return load(buffer, "=" .. file, "t", sandbox)
|
||||
end
|
||||
local function dofile(file)
|
||||
local program, reason = loadfile(file)
|
||||
if program then
|
||||
local result = table.pack(pcall(program))
|
||||
if result[1] then
|
||||
return table.unpack(result, 2, result.n)
|
||||
else
|
||||
error(result[2])
|
||||
end
|
||||
else
|
||||
error(reason)
|
||||
end
|
||||
end
|
||||
|
||||
-- Load file system related libraries we need to load other stuff moree
|
||||
-- comfortably. This is basically wrapper stuff for the file streams
|
||||
-- provided by the filesystem components.
|
||||
local package = dofile("/lib/package.lua")
|
||||
|
||||
-- Initialize the package module with some of our own APIs.
|
||||
package.preload["buffer"] = loadfile("/lib/buffer.lua")
|
||||
package.preload["component"] = function() return libcomponent end
|
||||
package.preload["computer"] = function() return libcomputer end
|
||||
package.preload["filesystem"] = loadfile("/lib/filesystem.lua")
|
||||
package.preload["io"] = loadfile("/lib/io.lua")
|
||||
package.preload["process"] = function() return libprocess end
|
||||
package.preload["unicode"] = function() return libunicode end
|
||||
|
||||
-- Inject the package and io modules into the global namespace, as in Lua.
|
||||
sandbox.package = package
|
||||
sandbox.io = sandbox.require("io")
|
||||
|
||||
-- Mount the ROM and temporary file systems to allow working on the file
|
||||
-- system module from this point on.
|
||||
sandbox.require("filesystem").mount(computer.romAddress(), "/")
|
||||
if computer.tmpAddress() then
|
||||
sandbox.require("filesystem").mount(computer.tmpAddress(), "/tmp")
|
||||
end
|
||||
|
||||
-- Run library startup scripts. These mostly initialize event handlers.
|
||||
local scripts = {}
|
||||
for _, file in rom.inits() do
|
||||
local path = "boot/" .. file
|
||||
if not rom.isDirectory(path) then
|
||||
table.insert(scripts, path)
|
||||
end
|
||||
end
|
||||
table.sort(scripts)
|
||||
for i = 1, #scripts do
|
||||
dofile(scripts[i])
|
||||
end
|
||||
|
||||
return coroutine.create(function() dofile("/init.lua") end), {n=0}
|
||||
end
|
||||
|
||||
local function main()
|
||||
-- Make all calls in the bootstrapper direct to speed up booting.
|
||||
local realInvoke = invoke
|
||||
invoke = function(_, ...) return realInvoke(true, ...) end
|
||||
|
||||
local co, args = bootstrap()
|
||||
|
||||
-- Step out of the fast lane, all the basic stuff should now be loaded.
|
||||
invoke = realInvoke
|
||||
|
||||
-- Yield once to get a memory baseline.
|
||||
coroutine.yield()
|
||||
|
||||
while true do
|
||||
deadline = computer.realTime() + timeout -- timeout global is set by host
|
||||
debug.sethook(co, checkDeadline, "", hookInterval)
|
||||
|
@ -11,7 +11,7 @@ elseif #args == 1 then
|
||||
if value then
|
||||
io.write(value)
|
||||
else
|
||||
io.write("no such alias")
|
||||
io.stderr:write("no such alias")
|
||||
end
|
||||
else
|
||||
shell.setAlias(args[1], args[2])
|
||||
|
@ -12,7 +12,7 @@ else
|
||||
for i = 1, #args do
|
||||
local file, reason = io.open(shell.resolve(args[i]))
|
||||
if not file then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
return
|
||||
end
|
||||
repeat
|
||||
|
@ -6,6 +6,6 @@ if #args == 0 then
|
||||
else
|
||||
local result, reason = shell.setWorkingDirectory(shell.resolve(args[1]))
|
||||
if not result then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
end
|
||||
end
|
||||
|
@ -14,9 +14,10 @@ if fs.isDirectory(to) then
|
||||
to = to .. "/" .. fs.name(from)
|
||||
end
|
||||
if fs.exists(to) and not options.f then
|
||||
error("target file exists")
|
||||
io.stderr:write("target file exists")
|
||||
return
|
||||
end
|
||||
local result, reason = fs.copy(from, to)
|
||||
if not result then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
end
|
@ -12,7 +12,7 @@ else
|
||||
for i = 1, #args do
|
||||
local proxy, path = fs.get(args[i])
|
||||
if not proxy then
|
||||
io.write(args[i], ": no such file or directory\n")
|
||||
io.stderr:write(args[i], ": no such file or directory\n")
|
||||
else
|
||||
mounts[path] = proxy
|
||||
end
|
||||
|
@ -22,7 +22,7 @@ local filename = shell.resolve(args[1])
|
||||
local readonly = options.r or fs.get(filename) == nil or fs.get(filename).isReadOnly()
|
||||
|
||||
if fs.isDirectory(filename) or readonly and not fs.exists(filename) then
|
||||
io.write("file not found")
|
||||
io.stderr:write("file not found")
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -15,15 +15,15 @@ else
|
||||
proxy, reaons = fs.get(args[1])
|
||||
end
|
||||
if not proxy then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
return
|
||||
end
|
||||
|
||||
if #args < 2 then
|
||||
io.write(proxy.getLabel() or "no label")
|
||||
io.stderr:write(proxy.getLabel() or "no label")
|
||||
else
|
||||
local result, reason = proxy.setLabel(args[2])
|
||||
if not result then
|
||||
io.write(reason or "could not set label")
|
||||
io.stderr:write(reason or "could not set label")
|
||||
end
|
||||
end
|
@ -18,5 +18,5 @@ end
|
||||
|
||||
local result, reason = fs.link(target, linkpath)
|
||||
if not result then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
end
|
@ -46,7 +46,7 @@ while term.isAvailable() do
|
||||
if type(result[2]) == "table" and result[2].reason == "terminated" then
|
||||
os.exit(result[2].code)
|
||||
end
|
||||
io.write(tostring(result[2]), "\n")
|
||||
io.stderr:write(tostring(result[2]), "\n")
|
||||
else
|
||||
for i = 2, result.n do
|
||||
io.write(text.serialize(result[i], true), "\t")
|
||||
@ -56,6 +56,6 @@ while term.isAvailable() do
|
||||
end
|
||||
end
|
||||
else
|
||||
io.write(reason, "\n")
|
||||
io.stderr:write(reason, "\n")
|
||||
end
|
||||
end
|
||||
|
@ -16,4 +16,4 @@ for path in string.gmatch(os.getenv("MANPATH"), "[^:]+") do
|
||||
os.exit()
|
||||
end
|
||||
end
|
||||
io.write("No manual entry for " .. topic)
|
||||
io.stderr:write("No manual entry for " .. topic)
|
@ -18,6 +18,6 @@ for i = 1, #args do
|
||||
reason = "unknown reason"
|
||||
end
|
||||
end
|
||||
io.write(path, ": ", reason, "\n")
|
||||
io.stderr:write(path, ": ", reason, "\n")
|
||||
end
|
||||
end
|
||||
|
@ -12,7 +12,7 @@ end
|
||||
|
||||
local file, reason = io.open(shell.resolve(args[1]))
|
||||
if not file then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -18,11 +18,11 @@ end
|
||||
|
||||
local proxy, reason = fs.proxy(args[1])
|
||||
if not proxy then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
return
|
||||
end
|
||||
|
||||
local result, reason = fs.mount(proxy, shell.resolve(args[2]))
|
||||
if not result then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
end
|
@ -15,11 +15,11 @@ if fs.isDirectory(to) then
|
||||
end
|
||||
if fs.exists(to) then
|
||||
if not options.f then
|
||||
io.write("target file exists")
|
||||
io.stderr:write("target file exists")
|
||||
end
|
||||
fs.remove(to)
|
||||
end
|
||||
local result, reason = os.rename(from, to)
|
||||
if not result then
|
||||
io.write(reason or "unknown error")
|
||||
io.stderr:write(reason or "unknown error")
|
||||
end
|
||||
|
@ -13,7 +13,7 @@ local componentType = args[1]
|
||||
if #args > 1 then
|
||||
local address = args[2]
|
||||
if not component.get(address) then
|
||||
io.write("no component with this address")
|
||||
io.stderr:write("no component with this address")
|
||||
return
|
||||
else
|
||||
component.setPrimary(componentType, address)
|
||||
@ -23,5 +23,5 @@ end
|
||||
if component.isAvailable(componentType) then
|
||||
io.write(component.getPrimary(componentType).address)
|
||||
else
|
||||
io.write("no primary component for this type")
|
||||
io.stderr:write("no primary component for this type")
|
||||
end
|
||||
|
@ -3,6 +3,10 @@ local component = require("component")
|
||||
local shell = require("shell")
|
||||
local sides = require("sides")
|
||||
|
||||
if not component.isAvailable("redstone") then
|
||||
io.stderr:write("This program requires a redstone card or redstone I/O block.")
|
||||
return
|
||||
end
|
||||
local rs = component.redstone
|
||||
|
||||
local args, options = shell.parse(...)
|
||||
@ -17,7 +21,8 @@ end
|
||||
|
||||
local side = sides[args[1]]
|
||||
if not side then
|
||||
error("Invalid side.")
|
||||
io.stderr:write("invalid side")
|
||||
return
|
||||
end
|
||||
if type(side) == "string" then
|
||||
side = sides[side]
|
||||
@ -25,11 +30,13 @@ end
|
||||
|
||||
if options.b then
|
||||
if not rs.setBundledOutput then
|
||||
error("Bundled redstone not available.")
|
||||
io.stderr:write("bundled redstone not available")
|
||||
return
|
||||
end
|
||||
local color = colors[args[2]]
|
||||
if not color then
|
||||
error("Invalid color.")
|
||||
io.stderr:write("invalid color")
|
||||
return
|
||||
end
|
||||
if type(color) == "string" then
|
||||
color = colors[color]
|
||||
|
@ -17,12 +17,13 @@ end
|
||||
local w = tonumber(args[1])
|
||||
local h = tonumber(args[2])
|
||||
if not w or not h then
|
||||
io.write("invalid width or height")
|
||||
io.stderr:write("invalid width or height")
|
||||
return
|
||||
end
|
||||
|
||||
local result, reason = component.gpu.setResolution(w, h)
|
||||
if not result then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
return
|
||||
end
|
||||
term.clear()
|
@ -9,6 +9,6 @@ end
|
||||
for i = 1, #args do
|
||||
local path = shell.resolve(args[i])
|
||||
if not os.remove(path) then
|
||||
io.write(path, ": no such file, or permission denied\n")
|
||||
io.stderr:write(path, ": no such file, or permission denied\n")
|
||||
end
|
||||
end
|
||||
|
@ -2,7 +2,7 @@ local args = {...}
|
||||
|
||||
if #args < 1 then
|
||||
for k,v in pairs(os.getenv()) do
|
||||
io.write(k..'='..v..'\n')
|
||||
io.write(k, "='", string.gsub(v, "'", [['"'"']]), "'\n")
|
||||
end
|
||||
else
|
||||
local count = 0
|
||||
|
@ -1,6 +1,7 @@
|
||||
local component = require("component")
|
||||
local computer = require("computer")
|
||||
local event = require("event")
|
||||
local process = require("process")
|
||||
local shell = require("shell")
|
||||
local term = require("term")
|
||||
local text = require("text")
|
||||
@ -8,8 +9,8 @@ local text = require("text")
|
||||
local args, options = shell.parse(...)
|
||||
local history = {}
|
||||
|
||||
if options.v or not shell.running(2) then
|
||||
print(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)")
|
||||
if options.v or not process.running(2) then
|
||||
io.write(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)\n")
|
||||
end
|
||||
|
||||
while true do
|
||||
@ -19,7 +20,7 @@ while true do
|
||||
end
|
||||
term.clear()
|
||||
if options.v then
|
||||
print(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)")
|
||||
io.write(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)\n")
|
||||
end
|
||||
end
|
||||
while term.isAvailable() do
|
||||
@ -28,7 +29,7 @@ while true do
|
||||
component.gpu.setForeground(foreground)
|
||||
local command = term.read(history)
|
||||
if not command then
|
||||
print("exit")
|
||||
io.write("exit\n")
|
||||
return -- eof
|
||||
end
|
||||
while #history > 10 do
|
||||
@ -40,10 +41,10 @@ while true do
|
||||
elseif command ~= "" then
|
||||
local result, reason = os.execute(command)
|
||||
if not result then
|
||||
print(reason)
|
||||
io.stderr:write(reason .. "\n")
|
||||
elseif term.getCursor() > 1 then
|
||||
print()
|
||||
io.write("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -21,16 +21,16 @@ else
|
||||
if proxy then
|
||||
proxy = reason -- = path
|
||||
if proxy ~= path then
|
||||
io.write("not a mount point")
|
||||
io.stderr:write("not a mount point")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
if not proxy then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
return
|
||||
end
|
||||
|
||||
if not fs.umount(proxy) then
|
||||
io.write("nothing to unmount here")
|
||||
io.stderr:write("nothing to unmount here")
|
||||
end
|
@ -8,7 +8,7 @@ end
|
||||
|
||||
local result = shell.getAlias(args[1])
|
||||
if not result then
|
||||
io.write("no such alias")
|
||||
io.stderr:write("no such alias")
|
||||
else
|
||||
shell.setAlias(args[1], nil)
|
||||
io.write("alias removed: ", args[1], " -> ", result)
|
||||
|
@ -1,9 +1,9 @@
|
||||
local args = {...}
|
||||
|
||||
if #args < 1 then
|
||||
print "You have to specify which arguments to unset!"
|
||||
print("Usage: unset <varname>[ <varname2> [...]]")
|
||||
else
|
||||
for _, k in ipairs(args) do
|
||||
os.setenv(k, nil)
|
||||
end
|
||||
end
|
||||
end
|
@ -9,5 +9,5 @@ end
|
||||
|
||||
local result, reason = computer.addUser(args[1])
|
||||
if not result then
|
||||
io.write(reason)
|
||||
io.stderr:write(reason)
|
||||
end
|
@ -8,5 +8,5 @@ if #args < 1 then
|
||||
end
|
||||
|
||||
if not computer.removeUser(args[1]) then
|
||||
io.write("no such user")
|
||||
io.stderr:write("no such user")
|
||||
end
|
@ -16,6 +16,6 @@ for i = 1, #args do
|
||||
if result then
|
||||
io.write(result, "\n")
|
||||
else
|
||||
io.write(args[i], ": ", reason, "\n")
|
||||
io.stderr:write(args[i], ": ", reason, "\n")
|
||||
end
|
||||
end
|
@ -3,6 +3,7 @@ local term = require("term")
|
||||
|
||||
local stdinStream = {handle="stdin"}
|
||||
local stdoutStream = {handle="stdout"}
|
||||
local stderrStream = {handle="stderr"}
|
||||
local stdinHistory = {}
|
||||
|
||||
local function badFileDescriptor()
|
||||
@ -13,6 +14,7 @@ function stdinStream:close()
|
||||
return nil, "cannot close standard file"
|
||||
end
|
||||
stdoutStream.close = stdinStream.close
|
||||
stderrStream.close = stdinStream.close
|
||||
|
||||
function stdinStream:read(n)
|
||||
local result = term.read(stdinHistory)
|
||||
@ -27,16 +29,32 @@ function stdoutStream:write(str)
|
||||
return self
|
||||
end
|
||||
|
||||
function stderrStream:write(str)
|
||||
local component = require("component")
|
||||
if component.isAvailable("gpu") and component.gpu.getDepth() > 1 then
|
||||
local foreground = component.gpu.getForeground()
|
||||
component.gpu.setForeground(0xFF0000)
|
||||
term.write(str, true)
|
||||
component.gpu.setForeground(foreground)
|
||||
else
|
||||
term.write(str, true)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
stdinStream.seek = badFileDescriptor
|
||||
stdinStream.write = badFileDescriptor
|
||||
stdoutStream.read = badFileDescriptor
|
||||
stdoutStream.seek = badFileDescriptor
|
||||
stderrStream.read = badFileDescriptor
|
||||
stderrStream.seek = badFileDescriptor
|
||||
|
||||
io.stdin = buffer.new("r", stdinStream)
|
||||
io.stdout = buffer.new("w", stdoutStream)
|
||||
io.stderr = io.stdout
|
||||
io.stderr = buffer.new("w", stderrStream)
|
||||
|
||||
io.stdout:setvbuf("no")
|
||||
io.stderr:setvbuf("no")
|
||||
|
||||
io.input(io.stdin)
|
||||
io.output(io.stdout)
|
@ -3,7 +3,7 @@ local unicode = require("unicode")
|
||||
|
||||
local filesystem, fileStream = {}, {}
|
||||
local isAutorunEnabled = true
|
||||
local mtab = {children={}, links={}}
|
||||
local mtab = {name="", children={}, links={}}
|
||||
|
||||
local function segments(path)
|
||||
path = path:gsub("\\", "/")
|
||||
@ -258,7 +258,7 @@ function filesystem.exists(path)
|
||||
if not vrest or vnode.links[vrest] then -- virtual directory or symbolic link
|
||||
return true
|
||||
end
|
||||
if node.fs then
|
||||
if node and node.fs then
|
||||
return node.fs.exists(rest)
|
||||
end
|
||||
return false
|
||||
@ -472,18 +472,9 @@ function filesystem.open(path, mode)
|
||||
|
||||
local stream = {fs = node.fs, handle = handle}
|
||||
|
||||
-- stream:close does a syscall, which yields, and that's not possible in
|
||||
-- the __gc metamethod. So we start a timer to do the yield/cleanup.
|
||||
local function cleanup(self)
|
||||
if not self.handle then return end
|
||||
-- save non-gc'ed values as upvalues
|
||||
local fs = self.fs
|
||||
local handle = self.handle
|
||||
local function close()
|
||||
fs.close(handle)
|
||||
end
|
||||
-- Required locally because this is a bootstrapped file.
|
||||
require("event").timer(0, close)
|
||||
pcall(self.fs.close, self.handle)
|
||||
end
|
||||
local metatable = {__index = fileStream,
|
||||
__gc = cleanup,
|
||||
|
@ -8,7 +8,6 @@ local loaded = {
|
||||
["_G"] = _G,
|
||||
["bit32"] = bit32,
|
||||
["coroutine"] = coroutine,
|
||||
["io"] = io,
|
||||
["math"] = math,
|
||||
["os"] = os,
|
||||
["package"] = package,
|
||||
@ -29,13 +28,14 @@ function package.searchpath(name, path, sep, rep)
|
||||
rep = rep or '/'
|
||||
sep, rep = '%' .. sep, rep
|
||||
name = string.gsub(name, sep, rep)
|
||||
local fs = require("filesystem")
|
||||
local errorFiles = {}
|
||||
for subPath in string.gmatch(path, "([^;]+)") do
|
||||
subPath = string.gsub(subPath, "?", name)
|
||||
if loaded.shell then
|
||||
subPath = require("shell").resolve(subPath)
|
||||
if subPath:sub(1, 1) ~= "/" and os.getenv then
|
||||
subPath = fs.concat(os.getenv("PWD") or "/", subPath)
|
||||
end
|
||||
if require("filesystem").exists(subPath) then
|
||||
if fs.exists(subPath) then
|
||||
local file = io.open(subPath, "r")
|
||||
if file then
|
||||
file:close()
|
||||
@ -80,8 +80,11 @@ function require(module)
|
||||
loading[module] = true
|
||||
local loader, value, errorMsg = nil, nil, {"module '" .. module .. "' not found:"}
|
||||
for i = 1, #package.searchers do
|
||||
local f, extra = package.searchers[i](module)
|
||||
if f and type(f) ~= "string" then
|
||||
-- the pcall is mostly for out of memory errors
|
||||
local ok, f, extra = pcall(package.searchers[i], module)
|
||||
if not ok then
|
||||
table.insert(errorMsg, "\t" .. f)
|
||||
elseif f and type(f) ~= "string" then
|
||||
loader = f
|
||||
value = extra
|
||||
break
|
||||
|
@ -5,23 +5,13 @@ local text = require("text")
|
||||
|
||||
local shell = {}
|
||||
local aliases = {}
|
||||
local running = setmetatable({}, {__mode="k"})
|
||||
local isLoading = false
|
||||
|
||||
local function findProcess(co)
|
||||
co = co or coroutine.running()
|
||||
for _, process in pairs(running) do
|
||||
for _, instance in pairs(process.instances) do
|
||||
if instance == co then
|
||||
return process
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function findFile(name, ext)
|
||||
checkArg(1, name, "string")
|
||||
local function findIn(dir)
|
||||
if dir:sub(1, 1) ~= "/" then
|
||||
dir = shell.resolve(dir)
|
||||
end
|
||||
dir = fs.concat(fs.concat(dir, name), "..")
|
||||
name = fs.name(name)
|
||||
local list = fs.list(dir)
|
||||
@ -475,52 +465,11 @@ function shell.execute(command, env, ...)
|
||||
end
|
||||
|
||||
function shell.load(path, env, init, name)
|
||||
checkArg(1, path, "string")
|
||||
checkArg(2, env, "table", "nil")
|
||||
checkArg(3, init, "function", "nil")
|
||||
checkArg(4, name, "string", "nil")
|
||||
local filename, reason = shell.resolve(path, "lua")
|
||||
if not filename then
|
||||
local path, reason = shell.resolve(path, "lua")
|
||||
if not path then
|
||||
return nil, reason
|
||||
end
|
||||
|
||||
local process = findProcess()
|
||||
if process then
|
||||
env = env or process.env
|
||||
end
|
||||
env = setmetatable({}, {__index=env or _ENV})
|
||||
local code, reason = loadfile(filename, "t", env)
|
||||
if not code then
|
||||
return nil, reason
|
||||
end
|
||||
|
||||
isLoading = true
|
||||
local thread = coroutine.create(function(...)
|
||||
if init then
|
||||
init()
|
||||
end
|
||||
return code(...)
|
||||
end)
|
||||
isLoading = false
|
||||
running[thread] = {
|
||||
path = filename,
|
||||
command = name,
|
||||
env = env,
|
||||
parent = process,
|
||||
instances = setmetatable({thread}, {__mode="v"})
|
||||
}
|
||||
return thread
|
||||
end
|
||||
|
||||
function shell.register(thread) -- called from coroutine.create
|
||||
checkArg(1, thread, "thread")
|
||||
if findProcess(thread) then
|
||||
return false -- already attached somewhere
|
||||
end
|
||||
if not isLoading then
|
||||
table.insert(findProcess().instances, thread)
|
||||
end
|
||||
return true
|
||||
return require("process").load(path, env, init, name)
|
||||
end
|
||||
|
||||
function shell.parse(...)
|
||||
@ -540,16 +489,8 @@ function shell.parse(...)
|
||||
return args, options
|
||||
end
|
||||
|
||||
function shell.running(level)
|
||||
level = level or 1
|
||||
local process = findProcess()
|
||||
while level > 1 and process do
|
||||
process = process.parent
|
||||
level = level - 1
|
||||
end
|
||||
if process then
|
||||
return process.path, process.env, process.command
|
||||
end
|
||||
function shell.running(level) -- deprecated
|
||||
return require("process").running(level)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -588,7 +588,7 @@ opencomputers {
|
||||
# allocations regardless of the amount of RAM installed in the computer it
|
||||
# runs on. As a side effect this pretty much determines the read
|
||||
# performance of file systems.
|
||||
maxReadBuffer: 8192
|
||||
maxReadBuffer: 2048
|
||||
}
|
||||
|
||||
# Internet settings, security related.
|
||||
|
Loading…
x
Reference in New Issue
Block a user