mirror of
https://github.com/goonstation/goonstation-2016.git
synced 2026-05-19 15:09:01 +01:00
dc4217b498
this is all very alpha please don't hate me too much if i fucked it up
1400 lines
42 KiB
Plaintext
1400 lines
42 KiB
Plaintext
//CONTENTS:
|
|
//ls List directory
|
|
//cd Change current directory
|
|
//rm Remove files/folders
|
|
//cp Copy files
|
|
//mv Move files
|
|
//cat Print from files (Records or text)
|
|
//ln Create links
|
|
//mkdir Create directories
|
|
//chmod Change file/folder permissions
|
|
//chown Change file/folder owner/group (Sysop only)
|
|
//su Ascend to sysop status!!
|
|
//mount Mount (mountable) device drivers (Sysop only)
|
|
//grep Regexes and stuff. idk. nerds
|
|
//scnt Rescan device drivers (Sysop only)
|
|
//getopt POSIX getopt: -- rearrange arguments for easier processing and validate options
|
|
//date Time manipulation utility.
|
|
//tar Archiving utility
|
|
|
|
//List directory
|
|
/datum/computer/file/mainframe_program/utility/ls
|
|
name = "ls"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/descriptive = 0
|
|
|
|
if (initparams)
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (initlist.len && initlist[1] == "-l")
|
|
initparams = jointext(initlist - initlist[1], "")
|
|
descriptive = 1
|
|
|
|
var/current = read_user_field("curpath")
|
|
if (!initparams)
|
|
initparams = current
|
|
if(!initparams)
|
|
initparams = "/"
|
|
|
|
else if (!dd_hasprefix(initparams, "/"))
|
|
initparams = "[current]" + (current == "/" ? null : "/") + initparams
|
|
|
|
var/datum/computer/folder/listfolder = signal_program(1, list("command"=DWAINE_COMMAND_FGET,"path"=initparams))
|
|
|
|
if (istype(listfolder))
|
|
var/message
|
|
for(var/datum/computer/P in listfolder.contents)
|
|
if (!check_read_permission(P, useracc))
|
|
continue
|
|
|
|
if (descriptive)
|
|
if (!P.metadata)
|
|
P.metadata = list()
|
|
|
|
var/is_folder = istype(P, /datum/computer/folder)
|
|
message += "\[[add_zero("[is_folder ? "--" : P.size]", 2)]] [add_zero( (P.metadata && ("group" in P.metadata) && isnum(text2num(P.metadata["group"])) ? "[P.metadata["group"]]" : "ANY"), 3)][print_file_permissions(P)] [is_folder ? "DIR" : "[copytext(P:extension,1,4)]"]"
|
|
message += " [add_lspace((!P.metadata || isnull(P.metadata["owner"]) ? "Nobody" : P.metadata["owner"]), 16)] [P.name]|n"
|
|
else
|
|
if (dd_hasprefix(P.name, "_"))
|
|
continue
|
|
message += "[P.name]|n"
|
|
|
|
if(!message)
|
|
message = " No files.|n"
|
|
|
|
message_user("Contents of [initparams]|n" + message,"multiline")
|
|
|
|
else
|
|
if (descriptive && istype(listfolder, /datum/computer/file))
|
|
var/datum/computer/file/P = listfolder
|
|
var/message = "\[[add_zero("[P.size]", 2)]] "
|
|
message += add_zero((P.metadata && P.metadata.Find("group") && isnum(text2num(P.metadata["group"])) ? "[P.metadata["group"]]" : "ANY"), 3)
|
|
message += "[print_file_permissions(P)] [copytext(P.extension,1,4)]"
|
|
message += " [add_lspace(( (!P.metadata || !P.metadata.Find("owner") || isnull(P.metadata["owner"])) ? "Nobody" : P.metadata["owner"]), 16)] [P.name]|n"
|
|
message_user(message, "multiline")
|
|
else
|
|
message_user("Error: Invalid resource or directory.")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
proc/print_file_permissions(var/datum/computer/cdatum)
|
|
if (!cdatum)
|
|
return
|
|
|
|
. = ""
|
|
|
|
var/permissions
|
|
if (cdatum.metadata && cdatum.metadata.Find("permission"))
|
|
permissions = cdatum.metadata["permission"]
|
|
|
|
if (!isnum(permissions))
|
|
. = "srwsrwsrw"
|
|
else
|
|
. += "[permissions & COMP_DOWNER ? "s" : "-"][permissions & COMP_ROWNER ? "r" : "-"][permissions & COMP_WOWNER ? "w" : "-"]"
|
|
. += "[permissions & COMP_DGROUP ? "s" : "-"][permissions & COMP_RGROUP ? "r" : "-"][permissions & COMP_WGROUP ? "w" : "-"]"
|
|
. += "[permissions & COMP_DOTHER ? "s" : "-"][permissions & COMP_ROTHER ? "r" : "-"][permissions & COMP_WOTHER ? "w" : "-"]"
|
|
|
|
//return dat
|
|
|
|
//Change current directory.
|
|
/datum/computer/file/mainframe_program/utility/cd
|
|
name = "cd"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
if (!initparams)
|
|
/*
|
|
message_user("Error: No path specified.")
|
|
mainframe_prog_exit
|
|
return
|
|
*/
|
|
initparams = "/home/usr[read_user_field("name")]"
|
|
|
|
var/current = read_user_field("curpath")
|
|
|
|
if (!dd_hasprefix(initparams, "/"))
|
|
initparams = "[current]" + (current == "/" ? null : "/") + initparams
|
|
|
|
var/datum/computer/folder/checkfolder = signal_program(1, list("command"=DWAINE_COMMAND_FGET,"path"=initparams))
|
|
if (!istype(checkfolder))
|
|
message_user("Error: Invalid path.")
|
|
else
|
|
initparams = trim_path(initparams)
|
|
if (initparams != "/" && copytext(initparams, length(initparams)) == "/")
|
|
initparams = copytext(initparams, 1, length(initparams))
|
|
write_user_field("curpath", initparams)
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
proc/trim_path(var/filepath)
|
|
var/list/filelist = splittext(filepath, "/")
|
|
var/list/newfilelist = list()
|
|
for (var/x = 1, x <= filelist.len, x++)
|
|
switch(filelist[x])
|
|
if("..")
|
|
if (newfilelist.len)
|
|
newfilelist.len--
|
|
if(".")
|
|
continue
|
|
else
|
|
newfilelist += filelist[x]
|
|
|
|
if (!newfilelist.len)
|
|
newfilelist += "/"
|
|
|
|
return jointext(newfilelist, "/")
|
|
|
|
//Delete files/directories
|
|
/datum/computer/file/mainframe_program/utility/rm
|
|
name = "rm"
|
|
size = 1
|
|
var/tmp/target_path = null //For interactive mode
|
|
var/tmp/recursive = 0 //Can remove directories
|
|
var/tmp/silent = 0 //Do not report errors
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
recursive = 0
|
|
silent = 0
|
|
var/set_interactive = 0
|
|
|
|
if (initparams)
|
|
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (initlist.len)
|
|
var/argstring = initlist[1]
|
|
if (dd_hasprefix(argstring, "-"))
|
|
initlist -= initlist[1]
|
|
initparams = jointext(initlist, " ")
|
|
|
|
var/x = 2
|
|
while (x <= length(argstring))
|
|
var/checkchar = copytext(argstring, x, x+1)
|
|
x++
|
|
switch(lowertext(checkchar))
|
|
if ("r")
|
|
recursive = 1
|
|
if ("i")
|
|
if (silent) continue
|
|
set_interactive = 1
|
|
if ("f")
|
|
set_interactive = 0
|
|
silent = 1
|
|
else
|
|
break
|
|
|
|
if (!initparams)
|
|
message_user("Error: No name or path specified.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/current = read_user_field("curpath")
|
|
|
|
if (!dd_hasprefix(initparams, "/"))
|
|
initparams = "[current]" + (current == "/" ? null : "/") + initparams
|
|
|
|
var/datum/computer/checkdatum = signal_program(1, list("command"=DWAINE_COMMAND_FGET,"path"=initparams))
|
|
if (!istype(checkdatum))
|
|
message_user("Error: Invalid path.")
|
|
else
|
|
if (istype(checkdatum, /datum/computer/folder) && !recursive)
|
|
message_user("Error: Cannot remove target (Is a directory).")
|
|
else
|
|
if (set_interactive)
|
|
target_path = initparams
|
|
message_user("Remove target '[checkdatum.name]'?")
|
|
return
|
|
|
|
if (signal_program(1, list("command"=DWAINE_COMMAND_FKILL,"path"=initparams)) != ESIG_SUCCESS)
|
|
message_user("Error: Cannot remove target.")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
input_text(var/text)
|
|
if(..() || !useracc)
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
if (!target_path)
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/list/command_list = parse_string(text)
|
|
var/command = lowertext(command_list[1])
|
|
|
|
if (command == "yes" || command == "y")
|
|
var/datum/computer/checkdatum = signal_program(1, list("command"=DWAINE_COMMAND_FGET,"path"=target_path))
|
|
if (!istype(checkdatum))
|
|
message_user("Error: Unable to locate target.")
|
|
else
|
|
if (istype(checkdatum, /datum/computer/folder) && !recursive)
|
|
message_user("Error: Cannot remove target (Is a directory).")
|
|
else
|
|
if (signal_program(1, list("command"=DWAINE_COMMAND_FKILL,"path"=target_path)) != ESIG_SUCCESS)
|
|
message_user("Error: Cannot remove target.")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
message_user(var/msg, var/render=null)
|
|
if (silent)
|
|
return null
|
|
|
|
return ..()
|
|
|
|
//Copy files
|
|
/datum/computer/file/mainframe_program/utility/cp
|
|
name = "cp"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (!initparams || initlist.len < 2)
|
|
message_user("Error: Filepaths of target and destination must be specified.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/current = read_user_field("curpath")
|
|
if (!dd_hasprefix(initlist[1], "/"))
|
|
initlist[1] = "[current]" + (current == "/" ? null : "/") + initlist[1]
|
|
if (!dd_hasprefix(initlist[2], "/"))
|
|
initlist[2] = "[current]" + (current == "/" ? null : "/") + initlist[2]
|
|
|
|
var/datum/computer/file/prototype = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"=initlist[1]))
|
|
if (!istype(prototype))
|
|
message_user("Error: Invalid target path.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/dest_check = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"=initlist[2]))
|
|
|
|
var/adjust_name = null
|
|
if (dest_check != ESIG_NOFILE)
|
|
if (istype(dest_check, /datum/computer/folder) && !get_computer_datum(prototype.name, dest_check))
|
|
adjust_name = prototype.name
|
|
else
|
|
message_user("Error: Invalid destination path (Path already taken?).")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/prefixroot = dd_hasprefix(initlist[2], "/")
|
|
var/list/copypath = splittext(initlist[2], "/")
|
|
var/copyname = null
|
|
if (adjust_name)
|
|
copypath += adjust_name
|
|
if (copypath.len)
|
|
copyname = copytext(copypath[copypath.len], 1, 16)
|
|
copypath.len--
|
|
|
|
if (copypath.len)
|
|
initlist[2] = jointext(copypath, "/")
|
|
if (prefixroot && !dd_hasprefix(initlist[2], "/"))
|
|
initlist[2] = "/" + initlist[2]
|
|
else
|
|
initlist[2] = "/"
|
|
|
|
var/datum/computer/file/copy = prototype.copy_file()
|
|
copy.name = copyname
|
|
copy.metadata["owner"] = read_user_field("name")
|
|
copy.metadata["permission"] = COMP_ALLACC
|
|
if (signal_program(1, list("command"=DWAINE_COMMAND_FWRITE,"path"=initlist[2]), copy) != ESIG_SUCCESS)
|
|
//qdel(copy)
|
|
copy.dispose()
|
|
message_user("Error: Could not copy file.")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
//Move files
|
|
/datum/computer/file/mainframe_program/utility/mv
|
|
name = "mv"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (!initparams || initlist.len < 2)
|
|
message_user("Error: Filepaths of target and new location must be specified.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/current = read_user_field("curpath")
|
|
if (!dd_hasprefix(initlist[1], "/"))
|
|
initlist[1] = "[current]" + (current == "/" ? null : "/") + initlist[1]
|
|
if (!dd_hasprefix(initlist[2], "/"))
|
|
initlist[2] = "[current]" + (current == "/" ? null : "/") + initlist[2]
|
|
|
|
var/datum/computer/file/prototype = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"=initlist[1]))
|
|
if (!istype(prototype))
|
|
message_user("Error: Invalid target path.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/dest_check = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"=initlist[2]))
|
|
|
|
var/adjust_name = null
|
|
if (dest_check != ESIG_NOFILE)
|
|
if (istype(dest_check, /datum/computer/folder) && !get_computer_datum(prototype.name, dest_check))
|
|
adjust_name = prototype.name
|
|
else
|
|
message_user("Error: Invalid destination path (Path already taken?).")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/prefixroot = dd_hasprefix(initlist[2], "/")
|
|
var/list/copypath = splittext(initlist[2], "/")
|
|
var/copyname = null
|
|
if (adjust_name)
|
|
copypath += adjust_name
|
|
if (copypath.len)
|
|
copyname = copytext(copypath[copypath.len], 1, 16)
|
|
copypath.len--
|
|
|
|
if (copypath.len)
|
|
initlist[2] = jointext(copypath, "/")
|
|
if (prefixroot && !dd_hasprefix(initlist[2], "/"))
|
|
initlist[2] = "/" + initlist[2]
|
|
else
|
|
initlist[2] = "/"
|
|
|
|
var/datum/computer/file/copy = prototype.copy_file()
|
|
copy.name = copyname
|
|
copy.metadata["owner"] = read_user_field("name")
|
|
copy.metadata["permission"] = COMP_ALLACC
|
|
if (signal_program(1, list("command"=DWAINE_COMMAND_FWRITE,"path"=initlist[2]), copy) != ESIG_SUCCESS)
|
|
//qdel(copy)
|
|
copy.dispose()
|
|
message_user("Error: Could not move file.")
|
|
else
|
|
signal_program(1, list("command"=DWAINE_COMMAND_FKILL,"path"=initlist[1]))
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
//Concatenate...stuff
|
|
/datum/computer/file/mainframe_program/utility/cat
|
|
name = "cat"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (!initlist.len || !initparams)
|
|
message_user("Error: No filepath(s) specified.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/bulkmessage = ""
|
|
while (initlist.len)
|
|
if (!initlist[1]) break
|
|
var/current = read_user_field("curpath")
|
|
|
|
if (!dd_hasprefix(initlist[1], "/"))
|
|
initlist[1] = "[current]" + (current == "/" ? null : "/") + initlist[1]
|
|
|
|
var/datum/computer/file/currfile = signal_program(1, list("command"=DWAINE_COMMAND_FGET,"path"=initlist[1]))
|
|
initlist -= initlist[1]
|
|
if (!istype(currfile))
|
|
break
|
|
|
|
var/toAdd = currfile.asText()
|
|
if (toAdd)
|
|
bulkmessage += toAdd
|
|
|
|
/*
|
|
if (istype(currfile, /datum/computer/file/record))
|
|
for (var/x in currfile:fields)
|
|
bulkmessage += "[x]"
|
|
if (isnull(currfile:fields[x]))
|
|
bulkmessage += "|n"
|
|
else
|
|
bulkmessage += ": [currfile:fields[x]]|n"
|
|
|
|
else if (istype(currfile, /datum/computer/file/text))
|
|
bulkmessage += currfile:data + "|n"
|
|
else
|
|
//message_user("Error: Unknown filetype for '[currfile.name]'")
|
|
bulkmessage += corruptText(pick("Error: Unknown filetype for '[currfile.name]'", "Imagine four balls on the edge of a cliff. Time works the same way.","Packet five loss packet six echo loss packet nine loss packet ten loss gain signal."),60)
|
|
break
|
|
*/
|
|
continue
|
|
|
|
if (bulkmessage)
|
|
message_user(copytext(bulkmessage, 1, MAX_MESSAGE_LEN),"multiline")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
//Link folders
|
|
/datum/computer/file/mainframe_program/utility/ln
|
|
name = "ln"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (!initparams || initlist.len < 2)
|
|
message_user("Error: Must specify target and link paths.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/current = read_user_field("curpath")
|
|
if (!dd_hasprefix(initlist[1], "/"))
|
|
initlist[1] = "[current]" + (current == "/" ? null : "/") + initlist[1]
|
|
if (!dd_hasprefix(initlist[2], "/"))
|
|
initlist[2] = "[current]" + (current == "/" ? null : "/") + initlist[2]
|
|
|
|
var/datum/computer/folder/target_folder = signal_program(1, list("command"=DWAINE_COMMAND_FGET,"path"=initlist[1]))
|
|
var/link_check = signal_program(1, list("command"=DWAINE_COMMAND_FGET,"path"=initlist[2]))
|
|
|
|
if (!istype(target_folder))
|
|
message_user("Error: Invalid target path.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
if (link_check != ESIG_NOFILE)
|
|
message_user("Error: Invalid link path (Path already taken?).")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/prefixroot = dd_hasprefix(initlist[2], "/")
|
|
var/list/linkpath = splittext(initlist[2], "/")
|
|
var/linkname = null
|
|
if (linkpath.len)
|
|
linkname = copytext(linkpath[linkpath.len], 1, 16)
|
|
linkpath.len--
|
|
|
|
if (linkpath.len)
|
|
initlist[2] = jointext(linkpath, "/")
|
|
if (prefixroot && !dd_hasprefix(initlist[2], "/"))
|
|
initlist[2] = "/" + initlist[2]
|
|
else
|
|
initlist[2] = "/"
|
|
|
|
var/datum/computer/folder/link/symlink = new /datum/computer/folder/link(target_folder)
|
|
symlink.name = linkname
|
|
symlink.metadata["owner"] = read_user_field("name")
|
|
symlink.metadata["permission"] = COMP_ALLACC & ~(COMP_WOTHER|COMP_DOTHER)
|
|
if (signal_program(1, list("command"=DWAINE_COMMAND_FWRITE,"path"=initlist[2]), symlink) != ESIG_SUCCESS)
|
|
//qdel(symlink)
|
|
symlink.dispose()
|
|
message_user("Error: Could not create link.")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
//Make a directory. Woah!!
|
|
/datum/computer/file/mainframe_program/utility/mkdir
|
|
name = "mkdir"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..() || !useracc)
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (!initlist.len || !initparams)
|
|
message_user("Error: No filepath(s) specified.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
initlist.len = min(initlist.len, 4)
|
|
|
|
var/create_full = 0
|
|
if (initlist[1] == "-p")
|
|
initlist -= initlist[1]
|
|
create_full = 1
|
|
|
|
while (initlist.len)
|
|
if (!initlist[1]) break
|
|
var/current = read_user_field("curpath")
|
|
|
|
var/prefixroot = dd_hasprefix(initlist[1], "/")
|
|
if (!prefixroot)
|
|
initlist[1] = "[current]" + (current == "/" ? null : "/") + initlist[1]
|
|
|
|
var/list/dirpath = splittext(initlist[1], "/")
|
|
var/dirname = null
|
|
if (dirpath.len)
|
|
dirname = copytext(dirpath[dirpath.len], 1, 16)
|
|
dirpath.len--
|
|
|
|
if (dirpath.len)
|
|
initlist[1] = jointext(dirpath, "/")
|
|
if (prefixroot && !dd_hasprefix(initlist[1], "/"))
|
|
initlist[1] = "/" + initlist[1]
|
|
|
|
if (!initlist[1])
|
|
initlist[1] = "/"
|
|
|
|
//boutput(world, "The Path: \"[initlist[1]]\"")
|
|
var/datum/computer/folder/new_folder = new /datum/computer/folder( )
|
|
new_folder.name = dirname
|
|
new_folder.metadata["owner"] = read_user_field("name")
|
|
new_folder.metadata["permission"] = COMP_ALLACC & ~(COMP_WOTHER|COMP_DOTHER)
|
|
if (signal_program(1, list("command"=DWAINE_COMMAND_FWRITE,"path"=initlist[1],"mkdir"=create_full), new_folder) != ESIG_SUCCESS)
|
|
//qdel(new_folder)
|
|
new_folder.dispose()
|
|
|
|
initlist -= initlist[1]
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
//Change file permissions.
|
|
/datum/computer/file/mainframe_program/utility/chmod
|
|
name = "chmod"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..() || !useracc)
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (!initparams || initlist.len < 2)
|
|
message_user("Error: Must specify permission value and target path.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/newpermissions = text2num(initlist[1])
|
|
if (!isnum(newpermissions))
|
|
message_user("Error: Invalid permission value.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
newpermissions = process_permissions(newpermissions)
|
|
if (newpermissions < 0)
|
|
message_user("Error: Invalid permission value.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/current = read_user_field("curpath")
|
|
if (!dd_hasprefix(initlist[2], "/"))
|
|
initlist[2] = "[current]" + (current == "/" ? null : "/") + initlist[2]
|
|
|
|
var/outcome = signal_program(1, list("command"=DWAINE_COMMAND_FMODE,"path"=initlist[2], "permission"=newpermissions))
|
|
switch(outcome)
|
|
if (ESIG_NOFILE, ESIG_NOTARGET)
|
|
message_user("Error: Invalid target path.")
|
|
|
|
if (ESIG_GENERIC)
|
|
message_user("Error: Access denied.")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
proc/process_permissions(var/permissions)
|
|
if (permissions < 0 || permissions > 888)
|
|
return -1
|
|
|
|
var/otherperm = permissions % 10
|
|
permissions /= 10
|
|
var/groupperm = permissions % 10
|
|
permissions /= 10
|
|
var/ownerperm = permissions % 10
|
|
|
|
. = 0
|
|
if (otherperm & 4)
|
|
. |= COMP_ROTHER
|
|
if (otherperm & 2)
|
|
. |= COMP_WOTHER
|
|
if (otherperm & 1)
|
|
. |= COMP_DOTHER
|
|
|
|
if (groupperm & 4)
|
|
. |= COMP_RGROUP
|
|
if (groupperm & 2)
|
|
. |= COMP_WGROUP
|
|
if (groupperm & 1)
|
|
. |= COMP_DGROUP
|
|
|
|
if (ownerperm & 4)
|
|
. |= COMP_ROWNER
|
|
if (ownerperm & 2)
|
|
. |= COMP_WOWNER
|
|
if (ownerperm & 1)
|
|
. |= COMP_DOWNER
|
|
|
|
//return newpermissions
|
|
|
|
//Change file owner/group information
|
|
/datum/computer/file/mainframe_program/utility/chown
|
|
name = "chown"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..() || !useracc)
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
. = read_user_field("group")
|
|
if ((. > src.metadata["group"]) && (. != 0)) //User isn't sysop.
|
|
message_user("Error: Access denied.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (!initparams || initlist.len < 2)
|
|
message_user("Error: Must specify owner/group value(s) and target path.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/newowner = null
|
|
var/newgroup = null
|
|
|
|
var/list/newlist = splittext(initlist[1], ":") //New owner/group values should given in form owner:group
|
|
if (!newlist.len || newlist.len > 2)
|
|
message_user("Error: Input values should be of form \[owner]:\[group]")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
if (newlist.len == 2)
|
|
newgroup = text2num(newlist[2])
|
|
if (isnull(newgroup))
|
|
message_user("Error: Invalid group ID.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
newowner = copytext(ckeyEx(newlist[1]), 1, 16)
|
|
|
|
var/current = read_user_field("curpath")
|
|
if (!dd_hasprefix(initlist[2], "/"))
|
|
initlist[2] = "[current]" + (current == "/" ? null : "/") + initlist[2]
|
|
|
|
var/outcome = signal_program(1, list("command"=DWAINE_COMMAND_FOWNER,"path"=initlist[2], "owner"=newowner, "group"=newgroup))
|
|
switch(outcome)
|
|
if (ESIG_NOFILE, ESIG_NOTARGET)
|
|
message_user("Error: Invalid target path.")
|
|
|
|
if (ESIG_GENERIC)
|
|
message_user("Error: Access denied.")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
//Ascend to sysop status.
|
|
/datum/computer/file/mainframe_program/utility/su
|
|
name = "su"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..() || (read_user_field("group") == 0))
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
message_user("Please enter *authorized* card and \"term_login\"")
|
|
return
|
|
|
|
receive_progsignal(var/sendid, var/list/data, var/datum/computer/file/file)
|
|
if (..() || (data["command"] != DWAINE_COMMAND_RECVFILE) || !istype(file, /datum/computer/file/record))
|
|
return ESIG_GENERIC
|
|
|
|
if (!src.useracc)
|
|
return ESIG_NOUSR
|
|
|
|
var/datum/computer/file/record/usdat = file
|
|
if (!usdat.fields["registered"] || !usdat.fields["assignment"])
|
|
return ESIG_GENERIC
|
|
|
|
var/list/accessList = splittext(usdat.fields["access"] + ";", ";")
|
|
if ("[access_dwaine_superuser]" in accessList)
|
|
if(signal_program(1, list("command"=DWAINE_COMMAND_UGROUP, "group"=0)) == ESIG_SUCCESS)
|
|
message_user("You are now authorized.")
|
|
else
|
|
message_user("Error: Unable to authorize.")
|
|
else
|
|
message_user("Error: Insufficient credentials.")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
input_text(var/text) //We're only going to see this if they are at a login prompt and type something else. Assumedly that is because they want to exit (Or had a typo)
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
//Mount eligible device drivers
|
|
/datum/computer/file/mainframe_program/utility/mount
|
|
name = "mount"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
. = read_user_field("group")
|
|
if ((. > src.metadata["group"]) && (. != 0))
|
|
message_user("Error: Access denied.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (!initparams || initlist.len < 2)
|
|
message_user("Error: Must specify device file and mount point names.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/driver_id = initlist[1]
|
|
if (!driver_id)
|
|
message_user("Error: Invalid device file id.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/mountname = copytext(initlist[2], 1, 16)
|
|
if (!mountname || is_name_invalid(mountname))
|
|
message_user("Error: Invalid mountpoint name.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
if (signal_program(1, list("command"=DWAINE_COMMAND_MOUNT, "id"=driver_id, "link"=mountname)) != ESIG_SUCCESS)
|
|
message_user("Error: Could not mount filesystem.")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
//Grep. Sorta. Look, I'm not going to redo the regex library for High Nerd Marquesas
|
|
/datum/computer/file/mainframe_program/utility/grep
|
|
name = "grep"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/list/initlist = splittext(initparams, " ")
|
|
if (initlist.len > 1)
|
|
var/case_sensitive = 1
|
|
var/print_only_match = 0
|
|
|
|
if (copytext(initlist[1], 1, 2) == "-")
|
|
switch (copytext(initlist[1], 2, 4))
|
|
if ("i")
|
|
case_sensitive = 0
|
|
|
|
if ("o")
|
|
print_only_match = 1
|
|
|
|
if ("io","oi")
|
|
print_only_match = 1
|
|
case_sensitive = 0
|
|
|
|
initlist.Cut(1,2)
|
|
if (initlist.len < 2)
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/pattern = copytext(initlist[1], 1, 20)
|
|
if (!case_sensitive)
|
|
pattern = lowertext(pattern)
|
|
|
|
. = usr
|
|
usr = null
|
|
var/regex/R = new (pattern)
|
|
usr = .
|
|
if (!istype(R))
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
. = ""
|
|
var/current = read_user_field("curpath")
|
|
for (var/i = 2, i <= initlist.len, i++)
|
|
if (!dd_hasprefix(initlist[i], "/"))
|
|
initlist[i] = "[current]" + (. == "/" ? null : "/") + initlist[i]
|
|
|
|
var/datum/computer/file/to_check = signal_program(1, list("command"=DWAINE_COMMAND_FGET,"path"=initlist[i]))
|
|
if (!istype(to_check))
|
|
break
|
|
|
|
|
|
//WIP
|
|
if (istype(to_check, /datum/computer/file/record))
|
|
for (var/textLine in to_check:fields)
|
|
if (!R)
|
|
R = new (pattern)
|
|
|
|
if (R.Find(case_sensitive ? "[textLine][to_check:fields[textLine]]" : lowertext("[textLine][to_check:fields[textLine]]")))
|
|
if (print_only_match)
|
|
. += copytext(textLine, R.match, R.index) + "|n"
|
|
|
|
else
|
|
. += "[textLine][to_check:fields[textLine]]|n"
|
|
R = null
|
|
|
|
else
|
|
var/to_check_text = to_check.asText()
|
|
var/findOffset = 1
|
|
while (findOffset != 0)
|
|
if (R.Find(case_sensitive ? to_check_text : lowertext(to_check_text), findOffset))
|
|
if (print_only_match)
|
|
. += copytext(to_check_text, R.match, R.index) + "|n"
|
|
else
|
|
. += copytext(to_check_text, R.match, findtext(to_check_text, "|n", R.match)) + "|n"
|
|
findOffset = findtext(to_check_text, "|n", R.match) + 2
|
|
|
|
if (.)
|
|
message_user(., "multiline")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
//Force a rescan for network devices.
|
|
/datum/computer/file/mainframe_program/utility/scnt
|
|
name = "scnt"
|
|
size = 1
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
if(initparams)
|
|
var/list/initlist = splittext(initparams," ")
|
|
if (initlist.len)
|
|
for (var/x in initlist)
|
|
x = ckey(x)
|
|
if (length(x) != 8 || !ishex(x))
|
|
message_user("Error: Invalid net ID format")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
src.master.reconnect_device(x)
|
|
|
|
message_user("Now scanning for device(s).")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
. = read_user_field("group")
|
|
if ((. > src.metadata["group"]) && (. != 0))
|
|
message_user("Error: Access denied.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
if (signal_program(1, list("command"=DWAINE_COMMAND_DSCAN)) == ESIG_SUCCESS)
|
|
message_user("Now scanning for devices -- This may take a few seconds.")
|
|
else
|
|
message_user("Scan already in progress -- Please be patient.")
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
// Getopt, process command line options into a digestible form.
|
|
// Does not process longopts.
|
|
// Programs currently using this will workaround by using invoke(), until $() is implemented.
|
|
/datum/computer/file/mainframe_program/utility/getopt
|
|
name = "getopt"
|
|
size = 1
|
|
var/err = null
|
|
|
|
proc/message_reply_and_user(var/message)
|
|
var/list/data = list("command"=DWAINE_COMMAND_REPLY, "data" = message, "sender_tag" = "getopt")
|
|
if (useracc)
|
|
data["term"] = useracc.user_id
|
|
var/sig = signal_program(parent_task.progid, data)
|
|
if (sig != ESIG_USR4)
|
|
message_user(message)
|
|
|
|
proc/invoke(var/str)
|
|
err = null
|
|
var/list/unaff = list()
|
|
var/list/strlist = bash_explode(str)
|
|
if (!strlist.len)
|
|
err = "getopt: requires at least one parameter"
|
|
return err
|
|
var/list/opts = list()
|
|
var/def = strlist[1]
|
|
var/def_len = length(def)
|
|
var/cc = null
|
|
// Parse getopt option definition: /([a-zA-Z]:?)+/i
|
|
for (var/i = 1, i <= def_len, i++)
|
|
var/pc = chs(def, i)
|
|
var/asc = text2ascii(pc)
|
|
if (pc == ":")
|
|
if (!cc)
|
|
err = "getopt: unexpected : in definition following no option"
|
|
return err
|
|
opts[cc] = ""
|
|
cc = null
|
|
else if ((65 <= asc && asc <= 90) || (97 <= asc && 122 >= asc))
|
|
cc = pc
|
|
opts[cc] = 0
|
|
else
|
|
err = "getopt: unexpected [pc] in definition"
|
|
return err
|
|
cc = null
|
|
|
|
// Parse $@, the list of parameters provided to the original command
|
|
for (var/i = 2, i <= strlist.len, i++)
|
|
// -- resets parameters, eg. for: command -p -- something; something is not a parameter of -p
|
|
if (strlist[i] == "--")
|
|
cc = null
|
|
continue
|
|
var/sc = chs(strlist[i], 1)
|
|
if (sc == "-")
|
|
if (cc && istext(opts[cc]))
|
|
err = "getopt: -[cc] expecting parameter, found [strlist[i]]"
|
|
return err // expecting parameter
|
|
def = strlist[i]
|
|
def_len = length(def)
|
|
for (var/j = 2, j <= def_len, j++)
|
|
cc = chs(def, j)
|
|
if (!(cc in opts))
|
|
err = "getopt: unexpected option -[cc]"
|
|
return err // unexpected option
|
|
if (opts[cc] == "" && j != def_len)
|
|
err = "getopt: -[cc] expecting parameter in [def]"
|
|
return err // expecting parameter
|
|
else if (isnum(opts[cc]))
|
|
opts[cc] = 1
|
|
else
|
|
if (!cc)
|
|
unaff += strlist[i]
|
|
continue
|
|
else if (isnum(opts[cc]))
|
|
err = "getopt: unexpected parameter for -[cc]"
|
|
return err // unexpected parameter
|
|
else
|
|
opts[cc] = strlist[i]
|
|
cc = null
|
|
|
|
if (cc)
|
|
if (opts[cc] == "")
|
|
err = "getopt: -[cc] expecting parameter, found EOL"
|
|
return err // expecting parameter
|
|
|
|
var/list/ret = list()
|
|
for (var/opt in opts)
|
|
if (opts[opt] == 1)
|
|
ret[opt] = 1
|
|
else if (istext(opts[opt]) && opts[opt] != "")
|
|
ret[opt] = opts[opt]
|
|
|
|
return list(ret, unaff)
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
if (initparams)
|
|
if (!initparams)
|
|
message_user("Expected arguments.")
|
|
mainframe_prog_exit
|
|
return
|
|
var/list/params = bash_explode(initparams)
|
|
if (!params)
|
|
message_user("Invalid input: [initparams]")
|
|
mainframe_prog_exit
|
|
return
|
|
var/list/all = invoke(initparams)
|
|
if (!istype(all))
|
|
message_user(err)
|
|
mainframe_prog_exit
|
|
return
|
|
var/list/opts = all[1]
|
|
var/list/unaff = all[2]
|
|
var/printed = ""
|
|
for (var/opt in opts)
|
|
printed += "-[opt] "
|
|
if (istext(opts[opt]))
|
|
printed += "[opts[opt]] "
|
|
printed += "--"
|
|
for (var/elem in unaff)
|
|
printed += " [elem]"
|
|
message_reply_and_user(printed)
|
|
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
/proc/optparse(var/data)
|
|
var/list/L = bash_explode(data)
|
|
var/list/OD = list()
|
|
var/i = 1
|
|
var/cc = null
|
|
while (i <= L.len && L[i] != "--")
|
|
if (ascii2text(text2ascii(L[i], 1)) != "-")
|
|
if (!cc)
|
|
return null
|
|
OD[cc] = L[i]
|
|
cc = null
|
|
else
|
|
if (length(L[i]) != 2)
|
|
return null
|
|
if (cc)
|
|
OD[cc] = 1
|
|
cc = ascii2text(text2ascii(L[i], 2))
|
|
i++
|
|
if (cc)
|
|
OD[cc] = 1
|
|
if (i > L.len)
|
|
return null
|
|
var/list/U = list()
|
|
i++
|
|
while (i <= L.len)
|
|
U += L[i]
|
|
i++
|
|
return list(OD, U)
|
|
|
|
/proc/abspath(var/path, var/curpath)
|
|
if (chs(path, 1) == "/")
|
|
return path
|
|
return "[curpath]/[path]"
|
|
|
|
//
|
|
/datum/computer/file/mainframe_program/utility/date
|
|
name = "date"
|
|
size = 1
|
|
var/opt_data
|
|
|
|
proc/message_reply_and_user(var/message)
|
|
var/list/data = list("command"=DWAINE_COMMAND_REPLY, "data" = message, "sender_tag" = "date")
|
|
if (useracc)
|
|
data["term"] = useracc.user_id
|
|
var/sig = signal_program(parent_task.progid, data)
|
|
if (sig != ESIG_USR4)
|
|
message_user(message)
|
|
|
|
proc/usage()
|
|
message_user("Date and time utility. Without parameters, outputs current Spacetime Stamp.")
|
|
message_user("Format specifiers: %h hour, %m minute, %s second, %t one-tenth of a second.")
|
|
message_user("Usage:")
|
|
message_user("[name] \[-t FORMAT\]")
|
|
|
|
receive_progsignal(var/sendid, var/list/data, var/datum/computer/file/file)
|
|
. = ..()
|
|
if (!.)
|
|
if (data["command"] == DWAINE_COMMAND_REPLY)
|
|
if (data["sender_tag"] == "getopt")
|
|
opt_data = data["data"]
|
|
return ESIG_USR4
|
|
else
|
|
return ESIG_GENERIC
|
|
else if (data["command"] == DWAINE_COMMAND_MSG_TERM)
|
|
message_user(data["data"])
|
|
else
|
|
return ESIG_GENERIC
|
|
return ESIG_SUCCESS
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
if (!initparams)
|
|
initparams = ""
|
|
opt_data = null
|
|
var/status = signal_program(1, list("command"=DWAINE_COMMAND_TSPAWN, "passusr" = 1, "path" = "/bin/getopt", "args" = "ht: [initparams]"))
|
|
if (status == ESIG_NOTARGET)
|
|
message_user("getopt: command not found")
|
|
mainframe_prog_exit
|
|
return
|
|
if (!opt_data)
|
|
message_user("date: No response from getopt.")
|
|
mainframe_prog_exit
|
|
return
|
|
if (copytext(opt_data, 1, 7) == "getopt")
|
|
message_user(opt_data)
|
|
mainframe_prog_exit
|
|
return
|
|
var/list/OU = optparse(opt_data)
|
|
if (!OU)
|
|
message_user("date: Error parsing options: [opt_data]")
|
|
usage()
|
|
mainframe_prog_exit
|
|
return
|
|
var/list/opts = OU[1]
|
|
if (opts["h"])
|
|
usage()
|
|
mainframe_prog_exit
|
|
return
|
|
if (!opts["t"])
|
|
message_reply_and_user("[ticker.round_elapsed_ticks]")
|
|
mainframe_prog_exit
|
|
return
|
|
else
|
|
var/format = opts["t"]
|
|
var/t = ticker.round_elapsed_ticks % 10
|
|
format = replacetext(format, "%t", "[t]")
|
|
var/s = round(ticker.round_elapsed_ticks / 10) % 60
|
|
format = replacetext(format, "%s", "[s]")
|
|
var/m = round(ticker.round_elapsed_ticks / 600) % 60
|
|
format = replacetext(format, "%m", "[m]")
|
|
var/h = round(ticker.round_elapsed_ticks / 36000)
|
|
format = replacetext(format, "%h", "[h]")
|
|
message_reply_and_user(format)
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
// Archiving utility. Used for sending multiple files in one packet. By sending an archive.
|
|
/datum/computer/file/mainframe_program/utility/tar
|
|
name = "tar"
|
|
size = 3
|
|
var/opt_data
|
|
|
|
proc/message_reply_and_user(var/message)
|
|
var/list/data = list("command"=DWAINE_COMMAND_REPLY, "data" = message, "sender_tag" = "tar")
|
|
if (useracc)
|
|
data["term"] = useracc.user_id
|
|
var/sig = signal_program(parent_task.progid, data)
|
|
if (sig != ESIG_USR4)
|
|
message_user(message)
|
|
|
|
proc/usage()
|
|
message_user("Usage:")
|
|
message_user("[name] -x \[-kqv\] -f ARCHIVE \[PATH\]")
|
|
message_user("[name] -c \[-v\] (-t|-f ARCHIVE) FILE ...")
|
|
message_user("[name] -l -f ARCHIVE")
|
|
|
|
proc/recursive_list(var/datum/computer/F, cpath = "", depth = 0)
|
|
if (depth >= 8)
|
|
message_user("tar: Stack overflow.")
|
|
return null
|
|
message_reply_and_user("[cpath][F.name]")
|
|
if (istype(F, /datum/computer/folder))
|
|
var/datum/computer/folder/FO = F
|
|
var/lpath = "[cpath][FO.name]/"
|
|
for (var/datum/computer/C in FO.contents)
|
|
recursive_list(C, lpath, depth + 1)
|
|
|
|
proc/recursive_extract(var/datum/computer/C, var/datum/computer/folder/F, target, var/list/opts, cpath = "", depth = 0)
|
|
if (depth >= 8)
|
|
if (!opts["q"])
|
|
message_user("tar: Stack overflow.")
|
|
return null
|
|
var/datum/computer/T = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="[target][C.name]"))
|
|
if (opts["v"])
|
|
message_reply_and_user("[cpath][C.name]")
|
|
if (istype(C, /datum/computer/folder))
|
|
if (istype(T))
|
|
if (opts["k"])
|
|
if (!opts["q"])
|
|
message_user("[target][C.name] already exists, skipping")
|
|
else
|
|
if (!opts["q"])
|
|
message_user("tar: [target][C.name] already exists, cannot overwrite folder - skipping.")
|
|
else
|
|
if (signal_program(1, list("command"=DWAINE_COMMAND_TSPAWN, "passusr" = 1, "path"="/bin/mkdir", "args"="[target][C.name]")) == ESIG_NOTARGET && !opts["q"])
|
|
message_user("mkdir: command not found")
|
|
T = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="[target][C.name]"))
|
|
var/datum/computer/folder/FO = C
|
|
if (!istype(T) && !opts["q"])
|
|
message_user("tar: Failed to create directory [C.name]")
|
|
var/dtarget = "[target][C.name]/"
|
|
var/dcpath = "[cpath][C.name]/"
|
|
for (var/datum/computer/C2 in FO.contents)
|
|
recursive_extract(C2, T, dtarget, opts, dcpath, depth + 1)
|
|
else if (istype(C, /datum/computer/file))
|
|
if (istype(T) && opts["k"])
|
|
if (!opts["q"])
|
|
message_user("[target][C.name] already exists, skipping")
|
|
else if ((istype(T) && !opts["k"]) || !istype(T))
|
|
var/outcome = signal_program(1, list("command" = DWAINE_COMMAND_FWRITE, "path" = "[target]", "mkdir" = 1, "replace" = 1), C)
|
|
if (!opts["q"])
|
|
if (outcome == ESIG_NOWRITE)
|
|
message_user("[target][C.name]: permission denied")
|
|
else if (outcome == ESIG_GENERIC)
|
|
message_user("Error extracting [target][C.name]")
|
|
else if (outcome == ESIG_NOTARGET)
|
|
message_user("Bad path: [target] for file [C.name]")
|
|
else
|
|
if (!opts["q"])
|
|
message_user("tar: Unknown data type: [C.name]")
|
|
|
|
proc/deep_copy(var/datum/computer/C, var/list/opts, var/cpath = "", var/depth = 0)
|
|
if (depth >= 8)
|
|
if (!opts["q"])
|
|
message_user("tar: Stack overflow.")
|
|
return null
|
|
if (istype(C, /datum/computer/file/archive))
|
|
if (!opts["q"])
|
|
message_user("tar: Cannot handle file [cpath][C]")
|
|
return null
|
|
if (istype(C, /datum/computer/folder))
|
|
var/datum/computer/folder/F = new()
|
|
for (var/datum/computer/C2 in C:contents)
|
|
var/dcpath = "[cpath][C.name]/"
|
|
var/datum/computer/NC = deep_copy(C2, opts, dcpath, depth + 1)
|
|
if (istype(NC))
|
|
F.add_file(NC)
|
|
return F
|
|
else if (istype(C, /datum/computer/file))
|
|
if (opts["v"])
|
|
message_reply_and_user("[cpath][C.name]")
|
|
return C:copy_file()
|
|
else
|
|
if (!opts["q"])
|
|
message_user("tar: Unknown data type: [C.name]")
|
|
return null
|
|
|
|
receive_progsignal(var/sendid, var/list/data, var/datum/computer/file/file)
|
|
. = ..()
|
|
if (!.)
|
|
if (data["command"] == DWAINE_COMMAND_REPLY)
|
|
if (data["sender_tag"] == "getopt")
|
|
opt_data = data["data"]
|
|
return ESIG_USR4
|
|
else
|
|
return ESIG_GENERIC
|
|
else if (data["command"] == DWAINE_COMMAND_MSG_TERM)
|
|
message_user(data["data"])
|
|
else
|
|
return ESIG_GENERIC
|
|
return ESIG_SUCCESS
|
|
|
|
proc/temp_file_name()
|
|
var/filename = "tmp"
|
|
for (var/i = 0, i < 12, i++)
|
|
filename += "[num2hex(rand(0, 15), 1)]"
|
|
return filename
|
|
|
|
initialize(var/initparams)
|
|
if (..())
|
|
mainframe_prog_exit
|
|
return
|
|
if (initparams)
|
|
if (!initparams)
|
|
message_user("tar: Expected arguments.")
|
|
mainframe_prog_exit
|
|
return
|
|
opt_data = null
|
|
var/status = signal_program(1, list("command"=DWAINE_COMMAND_TSPAWN, "passusr" = 1, "path" = "/bin/getopt", "args" = "cf:ltqvx [initparams]"))
|
|
if (status == ESIG_NOTARGET)
|
|
message_user("getopt: command not found")
|
|
mainframe_prog_exit
|
|
return
|
|
if (!opt_data)
|
|
message_user("tar: No response from getopt.")
|
|
mainframe_prog_exit
|
|
return
|
|
if (copytext(opt_data, 1, 7) == "getopt")
|
|
message_user(opt_data)
|
|
mainframe_prog_exit
|
|
return
|
|
var/list/OU = optparse(opt_data)
|
|
if (!OU)
|
|
message_user("tar: Error parsing options: [opt_data]")
|
|
mainframe_prog_exit
|
|
return
|
|
var/list/opts = OU[1]
|
|
var/list/unaff = OU[2]
|
|
if (!opts["f"] && !(opts["c"] && opts["t"]))
|
|
usage()
|
|
mainframe_prog_exit
|
|
return
|
|
if (opts["t"] && opts["f"])
|
|
message_user("tar: Cannot create both temporary and targeted file.")
|
|
mainframe_prog_exit
|
|
return
|
|
if (opts["q"] && opts["v"])
|
|
message_user("tar: Cannot run in quiet verbose mode.")
|
|
mainframe_prog_exit
|
|
return
|
|
var/commands = (opts["c"] ? 1 : 0) + (opts["x"] ? 1 : 0) + (opts["l"] ? 1 : 0)
|
|
if (commands != 1)
|
|
usage()
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
var/curpath = read_user_field("curpath")
|
|
var/arcfile
|
|
if (opts["f"])
|
|
arcfile = abspath(opts["f"], curpath)
|
|
else
|
|
arcfile = "/tmp/[temp_file_name()]"
|
|
|
|
if (opts["l"] || opts["x"])
|
|
var/datum/computer/file/archive/archive = signal_program(1, list("command"=DWAINE_COMMAND_FGET,"path"=arcfile))
|
|
if (!istype(archive))
|
|
message_user("tar: Cannot locate archive [opts["f"]]")
|
|
mainframe_prog_exit
|
|
return
|
|
if (!istype(archive))
|
|
message_user("tar: [opts["f"]] is not a valid archive.")
|
|
mainframe_prog_exit
|
|
return
|
|
|
|
if (opts["l"])
|
|
for (var/datum/computer/F in archive.contained_files)
|
|
recursive_list(F, "")
|
|
else if (opts["x"])
|
|
var/target = curpath
|
|
if (unaff.len)
|
|
target = abspath(unaff[1], curpath)
|
|
var/datum/computer/folder/F = signal_program(1, list("command"=DWAINE_COMMAND_FGET,"path"=target))
|
|
if (!istype(F))
|
|
message_user("tar: cannot read target directory [target]")
|
|
mainframe_prog_exit
|
|
return
|
|
if (copytext(target, length(target)) != "/")
|
|
target += "/"
|
|
for (var/datum/computer/C in archive.contained_files)
|
|
recursive_extract(C, F, target, opts, "")
|
|
else if (opts["c"])
|
|
if (!unaff.len)
|
|
message_user("tar: No files to add to archive.")
|
|
mainframe_prog_exit
|
|
return
|
|
var/datum/computer/file/archive/archive = new()
|
|
for (var/path in unaff)
|
|
var/datum/computer/C = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"=abspath(path, curpath)))
|
|
if (!istype(C))
|
|
message_user("tar: File [path] does not exist.")
|
|
mainframe_prog_exit
|
|
return
|
|
var/datum/computer/C2 = deep_copy(C, opts)
|
|
if (!istype(C2))
|
|
message_user("tar: Failed to replicate [path].")
|
|
mainframe_prog_exit
|
|
return
|
|
archive.add_file(C2)
|
|
var/list/arcparts = splittext(arcfile, "/")
|
|
archive.name = arcparts[arcparts.len]
|
|
arcparts.Cut(arcparts.len, 0)
|
|
var/arcbase = "/"
|
|
if (arcparts.len)
|
|
arcbase = "[jointext(arcparts, "/")]"
|
|
if (chs(arcbase, 1) != "/")
|
|
arcbase = "/[arcbase]"
|
|
var/outcome = signal_program(1, list("command"=DWAINE_COMMAND_FWRITE, "path"=arcbase, "mkdir"=1, "replace" = 1), archive)
|
|
if (outcome == ESIG_NOWRITE)
|
|
message_user("tar: Cannot write destination [opts["f"]]")
|
|
else if (outcome == ESIG_NOTARGET)
|
|
message_user("tar: Error creating path to archive.")
|
|
else if (outcome == ESIG_GENERIC)
|
|
message_user("tar: Error while creating archive.")
|
|
if (opts["t"])
|
|
message_reply_and_user(arcfile)
|
|
|
|
mainframe_prog_exit
|
|
return
|