1387 lines
54 KiB
Python
1387 lines
54 KiB
Python
import os
|
|
try:
|
|
from os import sep
|
|
except:
|
|
sep = os.getcwd()[0]
|
|
from time import localtime,struct_time
|
|
from sys import stdin,implementation,path
|
|
try:
|
|
from traceback import print_exception,format_exception
|
|
except:
|
|
from sys import print_exception as sysprexcept
|
|
print_exception = lambda err,value=None,tb=None: sysprexcept(err)
|
|
format_exception = lambda err,value=None,tb=None: [err]
|
|
if not sep+'lib' in path:
|
|
path.insert(1,sep+'lib')
|
|
path.append(f'{sep}apps{sep}PyBasic')
|
|
try:
|
|
from pydos_ui import Pydos_ui
|
|
except ImportError:
|
|
Pydos_ui = None
|
|
try:
|
|
from pydos_ui import input
|
|
except ImportError:
|
|
pass
|
|
try:
|
|
from rtc import RTC
|
|
clockavail = True
|
|
except ImportError:
|
|
clockavail = False
|
|
|
|
import gc
|
|
imp = "B"
|
|
if implementation.name.upper() == "MICROPYTHON":
|
|
from micropython import mem_info
|
|
readonly = False
|
|
imp = "M"
|
|
elif implementation.name.upper() == "CIRCUITPYTHON":
|
|
if not Pydos_ui:
|
|
from supervisor import runtime
|
|
|
|
from supervisor import reload
|
|
import storage
|
|
import microcontroller
|
|
import displayio
|
|
from adafruit_argv_file import argv_filename
|
|
readonly = storage.getmount("/").readonly
|
|
|
|
imp = "C"
|
|
|
|
gc.collect()
|
|
if 'threshold' in dir(gc):
|
|
gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
|
|
|
|
# The first string may contain wildcards
|
|
def _match(first, second):
|
|
|
|
# If we reach end of both strings, we are done
|
|
if len(first) == 0 and len(second) == 0:
|
|
return True
|
|
|
|
# Make sure that the characters after '*' are present
|
|
# in second string. Can't contain two consecutive '*'
|
|
if len(first) > 1 and first[0] == '*' and len(second) == 0:
|
|
return False
|
|
|
|
if (len(first) > 1 and first[0] == '?') or (len(first) != 0
|
|
and len(second) !=0 and first[0] == second[0]):
|
|
return _match(first[1:],second[1:])
|
|
|
|
if first[:1] == '*':
|
|
return _match(first[1:],second) or _match(first,second[1:])
|
|
|
|
return False
|
|
|
|
def calcWildCardLen(wldCLen,recursiveFail):
|
|
wldCLen += 1
|
|
if not recursiveFail and wldCLen < 115:
|
|
try:
|
|
(wldCLen,recursiveFail) = calcWildCardLen(wldCLen,recursiveFail)
|
|
except:
|
|
recursiveFail = True
|
|
|
|
return (wldCLen,recursiveFail)
|
|
|
|
def PyDOS():
|
|
|
|
global envVars
|
|
if "envVars" not in globals().keys():
|
|
envVars = {}
|
|
_VER = "1.54-fruitjam"
|
|
prmpVals = ['>','(',')','&','|','\x1b','\b','<','=',' ',_VER,'\n','$','']
|
|
|
|
print("Starting Py-DOS... Type 'help' for help.")
|
|
if readonly:
|
|
print("Warning: Py-DOS is running in read-only mode, some commands may not work.")
|
|
ans = 'N'
|
|
while ans[:1].upper() != "C" and ans[:1].upper() != "R":
|
|
ans = input("Press 'C' to continue or 'R' to restart in read-write mode: ")
|
|
if ans[:1].upper() == "R":
|
|
print("\nNote: You can not modify files using the CIRCUITPY drive from a")
|
|
print("connected host computer in read-write mode. After restarting,")
|
|
print("you can use the 'readonly' command in PyDOS to return to read-only mode.\n")
|
|
if input('Are you sure? (Y/N): ').upper() == 'Y':
|
|
boot_args_file = argv_filename("/boot.py")
|
|
with open(boot_args_file, "w") as f:
|
|
f.write('[false, "/code.py"]')
|
|
microcontroller.reset()
|
|
else:
|
|
break
|
|
elif ans[:1].upper() == "C":
|
|
break
|
|
else:
|
|
print("\nInvalid entry",ans[:1])
|
|
|
|
|
|
envVars["PATH"] = f'{sep};{sep}apps{sep}PyDOS;{sep}apps{sep}PyBasic'
|
|
envVars["PROMPT"] = "$P$G"
|
|
envVars["LIB"] = ";".join(path[1:])
|
|
envVars["DIRSEP"] = sep
|
|
if Pydos_ui:
|
|
(envVars["_scrHeight"],envVars["_scrWidth"]) = Pydos_ui.get_screensize()
|
|
else:
|
|
try:
|
|
envVars["_scrHeight"] = runtime.display.root_group[0].height
|
|
envVars["_scrWidth"] = runtime.display.root_group[0].width - 1
|
|
except:
|
|
envVars["_scrHeight"] = 24
|
|
envVars["_scrWidth"] = 89
|
|
scrWdth = int(envVars["_scrWidth"])
|
|
|
|
wldCLen = 0
|
|
recursiveFail = False
|
|
|
|
(wldCLen,recursiveFail) = calcWildCardLen(wldCLen,recursiveFail)
|
|
wldCAdj = int(1+.2*wldCLen)
|
|
if imp == "C":
|
|
wldCAdj += 5
|
|
wldCLen = max(1,wldCLen-wldCAdj)
|
|
|
|
if wldCLen < 60:
|
|
print("Wild card length set to: ",wldCLen)
|
|
gc.collect()
|
|
|
|
aFile = lambda dPth: bool(os.stat(dPth)[0]&(32768))
|
|
|
|
def setdate(newDate):
|
|
mdays = [0,31,29,31,30,31,30,31,31,30,31,30,31]
|
|
|
|
if newDate != "":
|
|
inDate = newDate.split('-')
|
|
|
|
if len(inDate) != 3:
|
|
print("Bad Date format")
|
|
elif int(inDate[0]) not in range(1,13):
|
|
print("Invalid month entered (1-12)")
|
|
elif int(inDate[1]) not in range(1,mdays[int(inDate[0])]+1):
|
|
print("invalid day entered (1-",mdays[int(inDate[0])],")")
|
|
elif int(inDate[2]) not in range(21,32):
|
|
print("invalid year entered (21-31)")
|
|
else:
|
|
RTC().datetime = struct_time((2000+int(inDate[2]),int(inDate[0]),int(inDate[1]), \
|
|
RTC().datetime[3],RTC().datetime[4],RTC().datetime[5],RTC().datetime[6],-1,-1))
|
|
|
|
def settime(newTime):
|
|
if newTime != "":
|
|
inTime = newTime.split(':')
|
|
|
|
if len(inTime) != 3:
|
|
print("Bad time format")
|
|
elif int(inTime[0]) not in range(0,25):
|
|
print("Invalid hour entered (0-24)")
|
|
elif int(inTime[1]) not in range(0,61):
|
|
print("invalid minute entered (0-60)")
|
|
elif int(inTime[2]) not in range(0,61):
|
|
print("invalid seconds entered (0-60)")
|
|
else:
|
|
RTC().datetime = struct_time((RTC().datetime[0],RTC().datetime[1],RTC().datetime[2], \
|
|
int(inTime[0]),int(inTime[1]),int(inTime[2]),RTC().datetime[6],-1,-1))
|
|
|
|
def anyKey():
|
|
print("Press any key to continue . . . ."[:scrWdth],end="")
|
|
if Pydos_ui:
|
|
while not Pydos_ui.serial_bytes_available():
|
|
pass
|
|
keyIn = Pydos_ui.read_keyboard(1)
|
|
else:
|
|
if imp == "C":
|
|
while not runtime.serial_bytes_available:
|
|
pass
|
|
keyIn = stdin.read(1)
|
|
print("")
|
|
return(keyIn)
|
|
|
|
def scrnPause(swPause,nLines,scrnLine,scrnEnd=None):
|
|
quit = False
|
|
i = 0
|
|
for sLine in scrnLine:
|
|
i += 1
|
|
if swPause and nLines >= int(envVars["_scrHeight"])-1:
|
|
key = anyKey()
|
|
nLines = 0
|
|
if key in "QqCc":
|
|
quit = True
|
|
break
|
|
if sLine is not None:
|
|
if scrnEnd is None or i<len(scrnLine):
|
|
print(sLine)
|
|
nLines += 1
|
|
else:
|
|
print(sLine,end="")
|
|
return (quit,nLines)
|
|
|
|
def exCmd(cFile,passedIn):
|
|
try:
|
|
with open(cFile) as cf:
|
|
if passedIn.find("'") > -1:
|
|
exec(f'passedIn = "{passedIn}"\n{cf.read()}')
|
|
else:
|
|
exec(f"passedIn = '{passedIn}'\n{cf.read()}")
|
|
except Exception as err:
|
|
print_exception(err,err, \
|
|
err.__traceback__ if hasattr(err,'__traceback__') else None)
|
|
envVars['lasterror'] = format_exception(err,err, \
|
|
err.__traceback__ if hasattr(err,'__traceback__') else None)
|
|
if supervisor.runtime.display.root_group != displayio.CIRCUITPYTHON_TERMINAL:
|
|
supervisor.runtime.display.root_group = displayio.CIRCUITPYTHON_TERMINAL
|
|
except KeyboardInterrupt:
|
|
print("^C")
|
|
if supervisor.runtime.display.root_group != displayio.CIRCUITPYTHON_TERMINAL:
|
|
supervisor.runtime.display.root_group = displayio.CIRCUITPYTHON_TERMINAL
|
|
|
|
return
|
|
|
|
def chkPath(tstPath):
|
|
validPath = True
|
|
simpPath = ""
|
|
|
|
if tstPath != []:
|
|
savDir = os.getcwd()
|
|
for path in tstPath:
|
|
if path[1:2] == ":":
|
|
path = path[2:]
|
|
if path == "":
|
|
os.chdir(sep)
|
|
elif os.getcwd() == sep and path == "..":
|
|
validPath = False
|
|
break
|
|
elif path == ".":
|
|
continue
|
|
elif path == ".." and len(os.getcwd().split(sep)) == 2:
|
|
os.chdir(sep)
|
|
elif path == "..":
|
|
os.chdir("..")
|
|
elif path in os.listdir() and not aFile(path):
|
|
os.chdir(path)
|
|
else:
|
|
validPath = False
|
|
break
|
|
|
|
if validPath:
|
|
simpPath = os.getcwd()
|
|
os.chdir(savDir)
|
|
|
|
return((validPath,simpPath))
|
|
|
|
def pFmt(dPath,trailsep=True):
|
|
if dPath == "":
|
|
return sep
|
|
elif dPath == sep:
|
|
return dPath
|
|
elif trailsep:
|
|
return dPath+(sep if dPath[-1]!=sep else "")
|
|
else:
|
|
return dPath[:(-1 if dPath[-1] == sep else None)]
|
|
|
|
def absolutePath(argPath,currDir):
|
|
|
|
if argPath[:1] == sep:
|
|
fullPath = argPath
|
|
elif currDir == sep:
|
|
fullPath = sep+argPath
|
|
else:
|
|
fullPath = currDir+sep+argPath
|
|
|
|
fullPath = pFmt(fullPath,False)
|
|
|
|
return(fullPath)
|
|
|
|
srtFnc = lambda v,dP: f"{str(os.stat(dP+v)[0]&(32768))[0]}{v.lower()}*{v}"
|
|
|
|
def dirLoop(tmpDir,lastDir,isFile,swPause,swWide,swRecur,prSum, \
|
|
nLines=0,nFiles=0,tFSize=0,nDirs=0):
|
|
|
|
wideCols = scrWdth//16
|
|
wideCount = 0
|
|
dirHeadPrntd = False
|
|
quit = False
|
|
|
|
if "*" in lastDir or "?" in lastDir or isFile:
|
|
dirPat = lastDir
|
|
lastDir = ""
|
|
else:
|
|
dirPat = None
|
|
|
|
dPath = pFmt(pFmt(tmpDir)+lastDir,False)
|
|
if dPath == sep+".":
|
|
dPath = sep
|
|
lastDir = ""
|
|
|
|
if dirPat is None:
|
|
(quit,nLines) = scrnPause(swPause,nLines,["","Directory of "+dPath.replace('/',('\\' if envVars.get('DIRSEP','/') == '\\' else '/'))])
|
|
dirHeadPrntd = True
|
|
nDirs += 2
|
|
if swWide:
|
|
if wideCols > 1:
|
|
(quit,nLines) = scrnPause(swPause,nLines, \
|
|
["[.] [..] "],"")
|
|
wideCount += 2
|
|
else:
|
|
(quit,nLines) = scrnPause(swPause,nLines,["[.]","[..]"],"")
|
|
wideCount = 1
|
|
else:
|
|
scrAdj1 = 52 - min(scrWdth,52)
|
|
(quit,nLines) = scrnPause(swPause,nLines, \
|
|
[f'.{" "*(23-scrAdj1)}<DIR>',f'..{" "*(22-scrAdj1)}<DIR>'])
|
|
|
|
for _dir in sorted([srtFnc(x,pFmt(dPath)) for x in os.listdir(dPath)]):
|
|
_dir = _dir.split('*')[1]
|
|
|
|
if (dirPat is None or _match(dirPat,_dir[:wldCLen])) and not quit:
|
|
dStat = os.stat(f"{pFmt(dPath)}{_dir}")
|
|
ForD = aFile(f"{pFmt(dPath)}{_dir}")
|
|
|
|
if not dirHeadPrntd:
|
|
(quit,nLines) = scrnPause(swPause,nLines,["","Directory of "+dPath.replace('/',('\\' if envVars.get('DIRSEP','/') == '\\' else '/'))])
|
|
if quit:
|
|
break
|
|
dirHeadPrntd = True
|
|
|
|
if not ForD:
|
|
fSize = 0
|
|
nDirs += 1
|
|
else:
|
|
fSize = str(dStat[6])
|
|
tFSize += int(fSize)
|
|
nFiles += 1
|
|
|
|
if swWide:
|
|
if wideCount >= wideCols:
|
|
wideCount = 0
|
|
print()
|
|
nLines += 1
|
|
wideCount += 1
|
|
if not ForD:
|
|
(quit,nLines) = scrnPause(swPause,nLines, \
|
|
[f'[{_dir[:13]}]{" "*(14-len(_dir[:13]))}'],"")
|
|
else:
|
|
(quit,nLines) = scrnPause(swPause,nLines, \
|
|
[_dir[:15]+" "*(16-len(_dir[:15]))],"")
|
|
else:
|
|
|
|
fTime = localtime(max(min(2145916800,dStat[9]),946684800))
|
|
if not ForD:
|
|
scrAdj1 = 52 - min(scrWdth,52)
|
|
scrAdj2 = min(13,65-min(scrWdth,65))
|
|
(quit,nLines) = scrnPause(swPause,nLines, \
|
|
[f'{_dir[:max(8,scrWdth-26)]}{" "*(24-len(_dir)-scrAdj1)}<DIR>{" "*(18-scrAdj2)}{fTime[1]:02}-{fTime[2]:02}-{fTime[0]:04} {fTime[3]:02}:{fTime[4]:02}'])
|
|
else:
|
|
scrAdj1 = 65 - min(scrWdth,65)
|
|
(quit,nLines) = scrnPause(swPause,nLines, \
|
|
[f'{_dir[:max(8,scrWdth-20-len(fSize))]}{" "*(36-len(_dir)+10-len(fSize)-scrAdj1)}{fSize} {fTime[1]:02}-{fTime[2]:02}-{fTime[0]:04} {fTime[3]:02}:{fTime[4]:02}'])
|
|
|
|
if quit:
|
|
break
|
|
|
|
if not quit:
|
|
if swWide:
|
|
if dirHeadPrntd:
|
|
print()
|
|
nLines += 1
|
|
|
|
if swRecur:
|
|
for _dir in sorted(os.listdir(dPath), key=str.upper):
|
|
dStat = pFmt(dPath)+_dir
|
|
if not aFile(dStat):
|
|
try:
|
|
(nLines,nFiles,tFSize,nDirs,quit) = \
|
|
dirLoop(dStat,(dirPat if dirPat is not None else ""), \
|
|
isFile,swPause,swWide,swRecur,False, \
|
|
nLines,nFiles,tFSize,nDirs)
|
|
except:
|
|
print("Recursion limit exceeded, Pystack too small")
|
|
quit = True
|
|
if quit:
|
|
break
|
|
|
|
if prSum and not quit:
|
|
try:
|
|
availDisk = os.statvfs(dPath)[1]*os.statvfs(dPath)[4]
|
|
except:
|
|
availDisk = 0
|
|
|
|
scrAdj1 = 65 - min(scrWdth,65)
|
|
(quit,nLines) = scrnPause(swPause,nLines, \
|
|
[(f'{" "*(4-len(str(nFiles)))} {nFiles} File(s){" "*(32-len(str(tFSize))-scrAdj1)} {tFSize} Bytes.')[:scrWdth], \
|
|
(f'{" "*(4-len(str(nDirs)))} {nDirs} Dir(s){" "*(33-len(str(availDisk))-scrAdj1)} {availDisk} Bytes free.')[:scrWdth],""],"")
|
|
|
|
return (nLines,nFiles,tFSize,nDirs,quit)
|
|
|
|
def prDir(dirPath,swBits):
|
|
if swBits & (swAllB-int('010110',2)):
|
|
print("Illegal switch, Command Format: DIR[/p][/w][/s] [path][file]")
|
|
return
|
|
|
|
savDir = os.getcwd()
|
|
fullPath = absolutePath(dirPath,savDir)
|
|
|
|
pathDirs = fullPath.split(sep)
|
|
lastDir = pathDirs.pop(-1)
|
|
|
|
(validPath, tmpDir) = chkPath(pathDirs)
|
|
|
|
if validPath:
|
|
|
|
os.chdir(tmpDir)
|
|
|
|
if tmpDir == sep:
|
|
pathDirs = [""]
|
|
else:
|
|
pathDirs = tmpDir.split(sep)
|
|
|
|
# Check for relative directory from possible mount point root
|
|
if len(pathDirs) == 2:
|
|
if lastDir == ".":
|
|
os.chdir(sep)
|
|
lastDir = tmpDir[1:]
|
|
elif lastDir == "..":
|
|
os.chdir(sep)
|
|
lastDir = ""
|
|
|
|
tmpDir = os.getcwd()
|
|
|
|
if lastDir in os.listdir() or lastDir in ".." or "*" in lastDir or "?" in lastDir or \
|
|
swBits & int('000010',2):
|
|
|
|
if lastDir in os.listdir():
|
|
if aFile(pFmt(lastDir,False)):
|
|
isFile = True
|
|
else:
|
|
isFile = False
|
|
else:
|
|
if lastDir in ".." or (tmpDir == sep and lastDir == ""):
|
|
isFile = False
|
|
else:
|
|
isFile = True
|
|
|
|
dirLoop(tmpDir,lastDir,isFile,bool(swBits&int('000100',2)),bool(swBits&int('010000',2)),bool(swBits&int('000010',2)),True)
|
|
else:
|
|
print("File",dirPath,"not found. (1)")
|
|
|
|
os.chdir(savDir)
|
|
else:
|
|
print("File",dirPath,"not found. (2)")
|
|
|
|
return
|
|
|
|
def filecpy(file1,file2):
|
|
gc.collect()
|
|
with open(file2, "wb") as fCopy:
|
|
with open(file1, 'rb') as fOrig:
|
|
for line in fOrig:
|
|
fCopy.write(line)
|
|
return
|
|
|
|
def delFiles(Dir,File,Recurs,removDirs):
|
|
for _dir in os.listdir(pFmt(Dir,False)):
|
|
if _match(File,_dir[:wldCLen]):
|
|
if File == "*" or File == "*.*" or _dir == _dir[:wldCLen]:
|
|
if aFile(Dir+_dir):
|
|
try:
|
|
os.remove(Dir+_dir)
|
|
print((Dir+_dir).replace('/',('\\' if envVars.get('DIRSEP','/') == '\\' else '/')),"deleted.")
|
|
except Exception as err:
|
|
print(f"Unable to delete: {Dir}{_dir}, Exception: {err}")
|
|
break
|
|
elif Recurs:
|
|
delFiles(Dir+_dir+sep,'*',Recurs,removDirs)
|
|
if removDirs:
|
|
if os.getcwd() == Dir+_dir:
|
|
os.chdir("..")
|
|
try:
|
|
os.rmdir(Dir+_dir)
|
|
except Exception as err:
|
|
print(f"Unable to remove: {Dir}{_dir}, Exception: {err}")
|
|
break
|
|
else:
|
|
print("Unable to delete: "+Dir+_dir+". Filename too long for wildcard operation.")
|
|
elif Recurs and not removDirs and not aFile(Dir+_dir):
|
|
delFiles(Dir+_dir+sep,File,Recurs,removDirs)
|
|
|
|
def setCondCmd(args,i,condResult):
|
|
condCmd = ""
|
|
foundElse = False
|
|
|
|
for _ in args[i:]:
|
|
|
|
if condResult:
|
|
if _.upper() == "ELSE":
|
|
break
|
|
condCmd += (_+" ")
|
|
else:
|
|
if foundElse:
|
|
condCmd += (_+" ")
|
|
else:
|
|
if _.upper() == "ELSE":
|
|
foundElse = True
|
|
|
|
return condCmd
|
|
|
|
def readBATFile(BATfile):
|
|
batIndex = [0]
|
|
batLabels = {}
|
|
batLineNo = 0
|
|
for batLine in BATfile:
|
|
batIndex.append(batIndex[batLineNo]+len(batLine))
|
|
batLineNo += 1
|
|
if batLine.strip()[:1] == ":" and len(batLine.strip().split(" ")[0]) > 1:
|
|
batLabels[batLine.strip().split(" ")[0][1:]] = [batLineNo,batIndex[batLineNo]]
|
|
BATfile.seek(0)
|
|
del batIndex,batLineNo
|
|
|
|
return batLabels
|
|
|
|
batEcho = True
|
|
cmd = ""
|
|
condCmd = ""
|
|
os.chdir(sep)
|
|
if "autoexec.bat" in ",".join(os.listdir()).lower().split(','):
|
|
activeBAT = True
|
|
BATfile = open(os.listdir()[(",".join(os.listdir()).lower().split(",")).index("autoexec.bat")])
|
|
batLabels = readBATFile(BATfile)
|
|
batLineNo = 0
|
|
batParams = []
|
|
else:
|
|
activeBAT = False
|
|
gc.collect()
|
|
|
|
while True:
|
|
scrWdth = int(envVars["_scrWidth"])
|
|
if condCmd != "":
|
|
cmdLine = condCmd
|
|
condCmd = ""
|
|
else:
|
|
if activeBAT:
|
|
cmdLine = BATfile.readline()
|
|
i=1
|
|
for param in batParams:
|
|
cmdLine = cmdLine.replace(f'%{i}',param)
|
|
i+=1
|
|
if i>9:
|
|
break
|
|
|
|
batLineNo += 1
|
|
if cmdLine == "":
|
|
activeBAT = False
|
|
batEcho = True
|
|
BATfile.close()
|
|
gc.collect()
|
|
elif batEcho and cmdLine[0] !="@":
|
|
print(cmdLine,end="")
|
|
elif cmdLine[0] == "@":
|
|
cmdLine = cmdLine[1:]
|
|
|
|
else:
|
|
prompt = "\n"
|
|
prmpLitrl = True
|
|
for prmpToken in envVars.get('PROMPT','$P$G').replace("$$","$."):
|
|
if prmpToken == '$':
|
|
prmpLitrl = False
|
|
continue
|
|
if prmpLitrl:
|
|
prompt += prmpToken
|
|
else:
|
|
prmpToken = prmpToken.upper()
|
|
prmpLitrl = True
|
|
if prmpToken == 'R':
|
|
if 'mem_free' in dir(gc):
|
|
prompt += str(gc.mem_free())
|
|
elif prmpToken == 'D':
|
|
prompt += f"{localtime()[1]:02}/{localtime()[2]:02}/{localtime()[0]:04}"
|
|
elif prmpToken == 'T':
|
|
prompt += f"{localtime()[3]:02}:{localtime()[4]:02}:{localtime()[5]:02}"
|
|
elif prmpToken == 'P':
|
|
prompt += os.getcwd().replace('/',('\\' if envVars.get('DIRSEP','/') == '\\' else '/'))
|
|
else:
|
|
prompt += prmpVals['GCFABEHLQSV_.'.find(prmpToken)]
|
|
cmdLine = input(prompt)
|
|
|
|
cmdLine = cmdLine.strip()
|
|
|
|
envFound = False
|
|
fndVar = ""
|
|
newCmdLine = ""
|
|
for _ in cmdLine:
|
|
if not envFound:
|
|
if _ == "%":
|
|
envFound = True
|
|
doublepct = True
|
|
else:
|
|
newCmdLine += _
|
|
else:
|
|
if _ == "%":
|
|
if doublepct:
|
|
newCmdLine += "%"
|
|
envFound = False
|
|
newCmdLine += str(envVars.get(fndVar,""))
|
|
fndVar = ""
|
|
else:
|
|
doublepct = False
|
|
fndVar += _
|
|
|
|
if envVars.get('DIRSEP','/') == '\\':
|
|
switches = []
|
|
switch = ""
|
|
nxt = False
|
|
cmdLine = newCmdLine[:1].replace('\\','/')
|
|
|
|
for _ in newCmdLine[1:]:
|
|
if nxt and _ not in " /":
|
|
switch += _.upper()
|
|
elif _ == '/':
|
|
nxt = True
|
|
if switch != "":
|
|
switches.append(switch)
|
|
switch = ""
|
|
elif nxt and _ == " ":
|
|
cmdLine += _
|
|
nxt = False
|
|
switches.append(switch)
|
|
switch = ""
|
|
elif _ == "\\":
|
|
cmdLine += sep
|
|
else:
|
|
cmdLine += _
|
|
if switch != "":
|
|
switches.append(switch)
|
|
else:
|
|
cmdLine = newCmdLine
|
|
|
|
args = cmdLine.split(" ")
|
|
|
|
quotedArg = False
|
|
if len(args) > 1:
|
|
i = 0
|
|
iEnd = len(args)
|
|
for _ in range(0, iEnd):
|
|
if args[i].strip() == "":
|
|
args.pop(i)
|
|
elif quotedArg:
|
|
if args[i].find('"') > -1 and args[i].find('"') != len(args[i])-1:
|
|
break
|
|
elif args[i][-1] == '"':
|
|
args[i-1] = f"{args[i-1]} {args.pop(i)[:-1]}"
|
|
quotedArg = False
|
|
else:
|
|
args[i-1] = f"{args[i-1]} {args.pop(i)}"
|
|
elif args[i][0] == '"':
|
|
if args[i][-1] != '"':
|
|
args[i] = args[i][1:]
|
|
i += 1
|
|
quotedArg = True
|
|
else:
|
|
args[i] = args[i][1:-1]
|
|
i += 1
|
|
else:
|
|
i += 1
|
|
|
|
if cmdLine != "" and cmdLine[0] != '/':
|
|
tmp = (args[0].upper()).split('/')
|
|
if envVars.get('DIRSEP','/') != '\\':
|
|
switches = tmp
|
|
cmd = tmp.pop(0)
|
|
else:
|
|
if envVars.get('DIRSEP','/') != '\\':
|
|
switches = []
|
|
cmd = args[0]
|
|
|
|
# Error=1, (S)Recur=2, (P)Pause=4, (Y)Conf=8, (W)Wide=16, (D)debug=32, (Q)uiet=64
|
|
# (V)erify=128
|
|
swBits = 0
|
|
swAllB = int('11111111',2)
|
|
for i in range(len(switches)):
|
|
swBits = swBits | (2**('SPYWDQV'.find(switches[i])+1))
|
|
|
|
if quotedArg:
|
|
print("Mismatched quotes.")
|
|
cmd = ""
|
|
|
|
if cmd in ["DELETE","DEL","TYPE","MORE","MKDIR","MD","RMDIR","RD","COPY", \
|
|
"CHDIR","CD","RENAME","REN","MOVE","DELTREE"]:
|
|
if len(args) > 1:
|
|
savDir = os.getcwd()
|
|
args[1] = absolutePath(args[1],savDir)
|
|
aPath = args[1].split(sep)
|
|
if cmd not in ["RMDIR","RD","CHDIR","CD","DELTREE"]:
|
|
newdir = aPath.pop(-1)
|
|
(validPath,tmpDir) = chkPath(aPath)
|
|
if cmd in ["DELETE","DEL","TYPE","MORE","MKDIR","MD"]:
|
|
tmpDir = pFmt(tmpDir)
|
|
else:
|
|
tmpDir = pFmt(tmpDir,False)
|
|
|
|
if cmd == "" or cmd == "REM":
|
|
continue
|
|
elif cmd == "HELP":
|
|
print("File Commands: DIR[/p][/w][/s], RENAME, DEL[/s], TYPE[/p], CD, MKDIR, RMDIR[/s], COPY[/y]")
|
|
print("Environment Commands: HELP, SET[/p][/a], PROMPT, PATH, READONLY")
|
|
print("Operating System Commands: EXIT, VER, MEM, DATE [mm-dd-yy], TIME [hh:mm:ss]")
|
|
print("Batch Commands: GOTO, IF, ECHO, PAUSE")
|
|
print("Command to execute a single Python command: PEXEC [command]")
|
|
print("Run a Python program: [path]program[.py]")
|
|
print("Run a DOS batch file: [path]program[.bat]")
|
|
elif cmd == "DIR":
|
|
if len(args) == 1:
|
|
prDir(os.getcwd()[(2 if os.getcwd()[1:2]==":" else 0):],swBits)
|
|
elif len(args) == 2:
|
|
prDir(args[1],swBits)
|
|
else:
|
|
print("Too many arguments. Command Format: DIR/p/w/s [path][file]")
|
|
|
|
elif cmd == "DATE":
|
|
if len(args) <=2:
|
|
if len(args) == 2:
|
|
if clockavail:
|
|
setdate(args[1])
|
|
else:
|
|
print("Real Time Clock (rtc) not available on board")
|
|
i = localtime()[6]*3
|
|
print(f'The current date is: {"MonTueWedThuFriSatSun"[i:i+3]} {localtime()[1]:02}/{localtime()[2]:02}/{localtime()[0]:04}')
|
|
else:
|
|
print("Too many arguments. Command Format: DATE [mm-dd-yy]")
|
|
|
|
elif cmd == "TIME":
|
|
if len(args) <= 2:
|
|
if len(args) == 2:
|
|
if clockavail:
|
|
settime(args[1])
|
|
else:
|
|
print("Real Time Clock (rtc) not available on board")
|
|
print(f'The current time is: {localtime()[3]%12}:{localtime()[4]:02}:{localtime()[5]:02} {["AM","PM"][localtime()[3]//12]}')
|
|
else:
|
|
print("Too many arguments. Command Format: TIME [hh:mm:ss]")
|
|
|
|
elif cmd == "MEM":
|
|
gc.collect()
|
|
print(f"\n{gc.mem_free()/1024:10.1f} Kb free conventional memory")
|
|
print(f"{gc.mem_alloc()/1024:10.1f} Kb used conventional memory")
|
|
if imp == "M":
|
|
if 'threshold' in dir(gc):
|
|
print(f"{gc.threshold()/1024:10.1f} Kb current threshold value")
|
|
|
|
if swBits & int('010000',2):
|
|
print(mem_info(1))
|
|
elif swBits:
|
|
print("Illegal switch, Command Format: mem[/d]")
|
|
|
|
elif cmd == "VER":
|
|
print(f"PyDOS [Version {_VER}]")
|
|
|
|
elif cmd == "ECHO":
|
|
if len(args) == 1:
|
|
print("Echo is "+("on." if batEcho else "off."))
|
|
else:
|
|
if args[1].upper() == 'ON':
|
|
batEcho = True
|
|
elif args[1].upper() == 'OFF':
|
|
batEcho = False
|
|
else:
|
|
print(cmdLine[5:])
|
|
|
|
elif cmd == "PAUSE":
|
|
anyKey()
|
|
|
|
elif cmd[0] == ":" and activeBAT:
|
|
if len(args[0]) <= 1 or len(args) != 1:
|
|
print("Invalid batch label")
|
|
condCmd = "exit"
|
|
|
|
elif cmd == "GOTO" and activeBAT:
|
|
if len(args) == 2:
|
|
try:
|
|
BATfile.seek(batLabels[args[1]][1])
|
|
except:
|
|
print("Invalid Goto label:",args[1])
|
|
condCmd = "exit"
|
|
|
|
batLineNo = batLabels.get(args[1],[batLineNo+1,0])[0]
|
|
else:
|
|
print("Invalid Goto label:",cmdLine)
|
|
condCmd = "exit"
|
|
|
|
elif cmd == "IF" and activeBAT:
|
|
condResult = False
|
|
|
|
if len(args) < 3:
|
|
print("Invalid command format:",cmdLine)
|
|
condCmd = "exit"
|
|
else:
|
|
i = 1
|
|
notlogic = False
|
|
if args[1].upper() == "NOT":
|
|
notlogic = True
|
|
i = 2
|
|
|
|
if args[i].strip().upper() == 'ERRORLEVEL':
|
|
i += 1
|
|
if len(args) > i and args[i].isdigit():
|
|
if str(envVars.get('errorlevel')).isdigit() and int(envVars.get('errorlevel')) == int(args[i]):
|
|
condResult = True
|
|
|
|
if notlogic:
|
|
condResult = not condResult
|
|
|
|
i += 1
|
|
condCmd = setCondCmd(args,i,condResult)
|
|
else:
|
|
print("Invalid conditional ERRORLEVEL:",cmdLine)
|
|
condCmd = "exit"
|
|
|
|
elif args[i].strip().upper() == 'EXIST':
|
|
i += 1
|
|
if len(args) > i:
|
|
savDir = os.getcwd()
|
|
args[i] = absolutePath(args[i],savDir)
|
|
|
|
aPath = args[i].split(sep)
|
|
newdir = aPath.pop(-1)
|
|
(validPath, tmpDir) = chkPath(aPath)
|
|
tmpDir = pFmt(tmpDir)
|
|
|
|
if validPath and newdir in os.listdir(pFmt(tmpDir,False)):
|
|
condResult = True
|
|
if notlogic:
|
|
condResult = not condResult
|
|
|
|
i += 1
|
|
condCmd = setCondCmd(args,i,condResult)
|
|
|
|
else:
|
|
print("Invalid conditional EXIST:",cmdLine)
|
|
condCmd = "exit"
|
|
else:
|
|
# string comparison
|
|
if len(args) > i:
|
|
string1 = args[i]
|
|
if "==" in args[i]:
|
|
string1 = args[i].split("==")[0]
|
|
if args[i][-1] != "=":
|
|
string2 = args[i].split("==")[-1]
|
|
else:
|
|
i += 1
|
|
if len(args) > i:
|
|
string2 = args[i]
|
|
else:
|
|
print("Invalid string conditional:",cmdLine)
|
|
condCmd = "exit"
|
|
elif len(args) > i+1:
|
|
i += 1
|
|
if "==" in args[i]:
|
|
if len(args[i]) > 2:
|
|
string2 = args[i].split("==")[-1]
|
|
else:
|
|
i+=1
|
|
if len(args) > i:
|
|
string2 = args[i]
|
|
else:
|
|
print("Invalid string conditional:",cmdLine)
|
|
condCmd = "exit"
|
|
else:
|
|
print("Invalid string conditional:",cmdLine)
|
|
condCmd = "exit"
|
|
else:
|
|
print("Invalid string conditional:",cmdLine)
|
|
condCmd = "exit"
|
|
|
|
|
|
if condCmd != "exit":
|
|
if string1 == string2:
|
|
condResult = True
|
|
if notlogic:
|
|
condResult = not condResult
|
|
|
|
i += 1
|
|
condCmd = setCondCmd(args,i,condResult)
|
|
else:
|
|
print("Invalid string conditional:",cmdLine)
|
|
condCmd = "exit"
|
|
|
|
elif cmd == "SET":
|
|
if len(args) == 1:
|
|
for _ in sorted(envVars):
|
|
print(f"{_}={envVars[_]}")
|
|
else:
|
|
args = cmdLine.split(" ")
|
|
args.pop(0)
|
|
envCmd = (" ".join(args)).split("=")
|
|
envCmdVar = envCmd.pop(0).strip()
|
|
|
|
if len(switches) <= 1:
|
|
if len(switches) == 0:
|
|
tmp = "=".join(envCmd).strip()
|
|
elif switches[0] == 'A':
|
|
# Replace all possible environment variables with their values
|
|
envCmd = "=".join(envCmd)
|
|
for _ in " %*()-+/":
|
|
envCmd = envCmd.replace(_," ")
|
|
envCmd = envCmd.split(" ")
|
|
|
|
for _ in envCmd:
|
|
if _[:1].isalpha() or _[:1] == "_":
|
|
cmdLine = cmdLine.replace(_.strip(),str(envVars.get(_,0)))
|
|
|
|
# Evaluate right sight of = after value substituion
|
|
args = cmdLine.split(" ")
|
|
args.pop(0)
|
|
envCmd = (" ".join(args)).split("=")
|
|
envCmdVar = envCmd.pop(0).strip()
|
|
try:
|
|
envVars[envCmdVar] = str(eval("=".join(envCmd).strip()))
|
|
except:
|
|
envVars[envCmdVar] = "0"
|
|
elif switches[0] == "P":
|
|
tmp = input("=".join(envCmd).strip()+" ")
|
|
else:
|
|
print("Illegal switch, Command Format: SET[/a|/p] [variable = [string|expression]]")
|
|
|
|
if len(switches) == 0 or switches[0] == "P":
|
|
if tmp != "":
|
|
envVars[envCmdVar] = tmp
|
|
elif envCmdVar == "_scrHeight" or envCmdVar == "_scrWidth":
|
|
if Pydos_ui:
|
|
(tHeight,tWidth) = Pydos_ui.get_screensize(envVars.get('_display'))
|
|
else:
|
|
tHeight = 29
|
|
tWidth = 79
|
|
if envCmdVar == "_scrWidth":
|
|
envVars[envCmdVar] = tWidth
|
|
else:
|
|
envVars[envCmdVar] = tHeight
|
|
elif envVars.get(envCmdVar) != None:
|
|
envVars.pop(envCmdVar)
|
|
|
|
scrWdth = int(envVars["_scrWidth"])
|
|
if envCmdVar == 'LIB':
|
|
path.clear()
|
|
path.extend(['']+envVars.get("LIB","").split(';'))
|
|
else:
|
|
print("Illegal switch, Command Format: SET[/a|/p] [variable = [string|expression]]")
|
|
|
|
elif cmd in ["PROMPT","PATH"]:
|
|
if len(args) == 1:
|
|
print(cmd+"="+envVars.get(cmd,""))
|
|
else:
|
|
envVars[cmd] = args[1]
|
|
|
|
elif cmd in ["RENAME","REN","MOVE"]:
|
|
# todo: allow source to be file and target directory?
|
|
# Wildcard renames
|
|
# renames across sd mount points
|
|
|
|
if len(args) == 3:
|
|
# Check that first argument has a valid path and exists
|
|
if validPath and newdir in os.listdir(tmpDir) and args[1][-1] != sep:
|
|
|
|
args[2] = absolutePath(args[2],savDir)
|
|
aPath2 = args[2].split(sep)
|
|
newdir2 = aPath2.pop(-1)
|
|
(validPath, tmpDir2) = chkPath(aPath2)
|
|
|
|
if newdir2 == '*':
|
|
newdir2 = newdir
|
|
# Second argument has valid path
|
|
if validPath and args[2][-1] != sep and '?' not in newdir2 and \
|
|
'*' not in newdir2 and newdir2 !="." and newdir2 != "..":
|
|
|
|
# second argument doesn't specify an existing target
|
|
if newdir2 not in os.listdir(tmpDir2):
|
|
currDRen = False
|
|
if not aFile(tmpDir+sep+newdir):
|
|
if tmpDir+sep+newdir == os.getcwd():
|
|
currDRen = True
|
|
os.rename(pFmt(tmpDir)+newdir,pFmt(tmpDir2)+newdir2)
|
|
if currDRen:
|
|
os.chdir(tmpDir2)
|
|
|
|
else:
|
|
print("Target file exists")
|
|
else:
|
|
print("Invalid target:",args[2])
|
|
else:
|
|
print("Invalid source:",args[1])
|
|
else:
|
|
print("Wrong number of arguments")
|
|
|
|
elif cmd in ["DELETE","DEL"]:
|
|
|
|
if len(args) == 2:
|
|
if validPath:
|
|
if not (swAllB-int('000010',2)) & swBits:
|
|
if "*" in newdir or "?" in newdir:
|
|
ans = "Y"
|
|
if newdir == "*" or newdir == "*.*":
|
|
ans = input(tmpDir+newdir+", Are you sure (y/n)? ").upper()
|
|
|
|
if ans == "Y":
|
|
delFiles(tmpDir,newdir,bool(swBits&int('000010',2)),False)
|
|
else:
|
|
if newdir in os.listdir(pFmt(tmpDir,False)):
|
|
if aFile(tmpDir+newdir):
|
|
os.remove(tmpDir+newdir)
|
|
print((tmpDir+newdir).replace('/',('\\' if envVars.get('DIRSEP','/') == '\\' else '/')),"deleted.")
|
|
else:
|
|
ans = input(tmpDir+newdir+sep+"*, Are you sure (y/n)? ").upper()
|
|
if ans == "Y":
|
|
delFiles(tmpDir+newdir+sep,'*',bool(swBits&int('000010',2)),False)
|
|
else:
|
|
if swBits & int('000010',2):
|
|
ans = input(tmpDir+newdir+sep+"*, Are you sure (y/n)? ").upper()
|
|
if ans == "Y":
|
|
delFiles(tmpDir,newdir,True,False)
|
|
else:
|
|
print(f"Unable to delete: {tmpDir}{newdir}. File not found.")
|
|
else:
|
|
print("Illegal switch, Command Format: DEL[/s] [path][file]")
|
|
else:
|
|
print(f"Unable to delete: {tmpDir}{newdir}. File not found.")
|
|
else:
|
|
print("Illegal Path.")
|
|
|
|
elif cmd in ["TYPE","MORE"]:
|
|
|
|
if len(args) == 2:
|
|
if validPath and newdir in os.listdir(pFmt(tmpDir,False)) and aFile(tmpDir+newdir):
|
|
if cmd == "MORE":
|
|
swBits = swBits | int('000100',2)
|
|
|
|
if not ((swAllB-int('000100',2)) & swBits):
|
|
swPause = bool(swBits & int('000100',2))
|
|
key = " "
|
|
with open(tmpDir+newdir, "rb") as f:
|
|
nLines = 0
|
|
for line in f:
|
|
istrt = 0
|
|
while istrt+scrWdth < len(line):
|
|
(quit,nLines) = scrnPause(swPause,nLines,[None])
|
|
try:
|
|
print(line[istrt:istrt+scrWdth].decode())
|
|
except:
|
|
print(chr(65534)*scrWdth)
|
|
nLines += 1
|
|
istrt += scrWdth
|
|
(quit,nLines) = scrnPause(swPause,nLines,[None])
|
|
if quit:
|
|
break
|
|
try:
|
|
print(line[istrt:len(line)].decode(),end="")
|
|
except:
|
|
print(chr(65534)*(len(line)-istrt))
|
|
nLines += 1
|
|
else:
|
|
print("Illegal switch, Command Format: TYPE[/p] [path][file]")
|
|
else:
|
|
print(f"Unable to display: {tmpDir}{newdir}. File not found.")
|
|
else:
|
|
print("Illegal Path.")
|
|
|
|
|
|
elif cmd in ["CHDIR","CD"]:
|
|
|
|
if len(args) == 1:
|
|
print(os.getcwd().replace('/',('\\' if envVars.get('DIRSEP','/') == '\\' else '/')))
|
|
else:
|
|
if validPath:
|
|
os.chdir(tmpDir)
|
|
else:
|
|
print("Unable to change to:",args[1])
|
|
|
|
elif cmd in ["MKDIR","MD"]:
|
|
if len(args) == 1:
|
|
print("Unable to make .")
|
|
elif len(args) > 2:
|
|
print("Too many arguments")
|
|
else:
|
|
if validPath:
|
|
if newdir not in os.listdir(pFmt(tmpDir,False)):
|
|
os.mkdir(tmpDir+newdir)
|
|
else:
|
|
print("Target name already exists")
|
|
else:
|
|
print("Invalid path")
|
|
|
|
elif cmd in ["RMDIR","RD","DELTREE"]:
|
|
if len(args) == 2 and validPath:
|
|
if cmd == "DELTREE":
|
|
swBits = int('000010',2)
|
|
|
|
if not (swBits & (swAllB-int('000010',2))):
|
|
if tmpDir != sep:
|
|
if swBits & int('000010',2):
|
|
ans = input(tmpDir+" Are you sure (y/n)? ").upper()
|
|
if ans == "Y":
|
|
delFiles(tmpDir+sep,'*',bool(swBits&int('000010',2)),True)
|
|
|
|
if os.listdir(tmpDir) == []:
|
|
if os.getcwd() == tmpDir:
|
|
os.chdir("..")
|
|
if len(tmpDir.split(sep)) > 2:
|
|
os.chdir(sep+tmpDir.split(sep)[1])
|
|
try:
|
|
os.rmdir(tmpDir)
|
|
except Exception as err:
|
|
print(f"Unable to remove: {tmpDir}, Exception: {err}")
|
|
try:
|
|
os.chdir(savDir)
|
|
except:
|
|
pass
|
|
else:
|
|
print("The directory is not empty")
|
|
else:
|
|
print("Can not remove root directory")
|
|
else:
|
|
print("Illegal switch, Command Format: RD[/s] path")
|
|
else:
|
|
print("Invalid path")
|
|
|
|
elif cmd == "COPY":
|
|
|
|
if (len(args) == 3 or len(args) == 2) and not swBits & (swAllB-int('00001000',2)):
|
|
if len(args) == 2:
|
|
args.append('.')
|
|
|
|
nFiles = 0
|
|
earlyError = False
|
|
trailingSlash = False
|
|
if args[1][-1] == sep:
|
|
print("The source file cannot be a directory")
|
|
earlyError = True
|
|
if args[2][-1] == sep:
|
|
trailingSlash = True
|
|
|
|
# Check that first argument has a valid path, exists and is not a directory file
|
|
if not earlyError and validPath and ("*" in newdir or "?" in newdir or \
|
|
(newdir in os.listdir(tmpDir) and aFile(pFmt(tmpDir)+newdir))):
|
|
|
|
sourcePath = tmpDir
|
|
if "*" in newdir or "?" in newdir:
|
|
wildCardOp = True
|
|
else:
|
|
wildCardOp = False
|
|
|
|
enteredArg = args[2]
|
|
args[2] = absolutePath(args[2],savDir)
|
|
aPath2 = args[2].split(sep)
|
|
newdir2 = aPath2.pop(-1)
|
|
(validPath, tmpDir) = chkPath(aPath2)
|
|
if newdir2 == "*":
|
|
newdir2 = "."
|
|
if "*" in newdir2 or "?" in newdir2:
|
|
validPath = False
|
|
|
|
# Second argument has valid path
|
|
if validPath:
|
|
gc.collect()
|
|
targetPath = tmpDir
|
|
|
|
if newdir2 in "..":
|
|
(validPath,tmpDir) = chkPath((pFmt(targetPath)+newdir2).split(sep))
|
|
aPath2 = tmpDir.split(sep)
|
|
newdir2 = aPath2.pop(-1)
|
|
targetPath = chkPath(aPath2)[1]
|
|
if not validPath:
|
|
print("Impossible Target Error:",args[2])
|
|
|
|
# Second argument specifies an existing target
|
|
if newdir2 in os.listdir(targetPath) or (targetPath == sep and newdir2 == ""):
|
|
|
|
# Second argument target is a file
|
|
if aFile(pFmt(targetPath)+newdir2):
|
|
if trailingSlash:
|
|
print("Cannot find the specified path: ",enteredArg)
|
|
elif wildCardOp:
|
|
print("Target must be directory for wildcard copy ",enteredArg)
|
|
|
|
elif sourcePath == targetPath and newdir == newdir2:
|
|
print("The file cannot be copied onto itself")
|
|
|
|
elif swBits & int('001000',2) or input("Overwrite "+args[2]+"? (y/n): ").upper() == "Y":
|
|
os.remove(pFmt(targetPath)+newdir2)
|
|
filecpy(pFmt(sourcePath)+newdir,pFmt(targetPath)+newdir2)
|
|
nFiles += 1
|
|
|
|
# Second argument target is a directory
|
|
else:
|
|
sourcePath = pFmt(sourcePath)
|
|
targetPath = pFmt(targetPath)
|
|
|
|
if wildCardOp:
|
|
ans = ""
|
|
for _dir in os.listdir(pFmt(sourcePath,False)):
|
|
if aFile(sourcePath+_dir) and _match(newdir,_dir[:wldCLen]):
|
|
print("copy",sourcePath+_dir,"to",pFmt(targetPath+newdir2)+_dir)
|
|
if _dir in os.listdir(targetPath+newdir2):
|
|
if sourcePath == pFmt(targetPath+newdir2):
|
|
print("The file cannot be copied onto itself")
|
|
break
|
|
else:
|
|
if ans != "A" and not swBits & int('001000',2):
|
|
ans = input("Overwrite "+pFmt(targetPath+newdir2)+_dir+"? (y/n/(q)uit/(a)ll): ").upper()
|
|
if ans == "Y" or ans == "A" or swBits & int('001000',2):
|
|
filecpy(sourcePath+_dir,pFmt(targetPath+newdir2)+_dir)
|
|
nFiles += 1
|
|
elif ans == "Q":
|
|
break
|
|
else:
|
|
filecpy(sourcePath+_dir,pFmt(targetPath+newdir2)+_dir)
|
|
nFiles += 1
|
|
gc.collect()
|
|
|
|
elif newdir in os.listdir(targetPath+newdir2):
|
|
if sourcePath == pFmt(targetPath+newdir2):
|
|
print("The file cannot be copied onto itself")
|
|
elif swBits & int('001000',2) or input("Overwrite "+pFmt(targetPath+newdir2)+newdir+"? (y/n): ").upper() == "Y":
|
|
os.remove(pFmt(targetPath+newdir2)+newdir)
|
|
filecpy(sourcePath+newdir,pFmt(targetPath+newdir2)+newdir)
|
|
nFiles += 1
|
|
|
|
else:
|
|
filecpy(sourcePath+newdir,pFmt(targetPath+newdir2)+newdir)
|
|
nFiles += 1
|
|
# Second argument is a new file
|
|
else:
|
|
if trailingSlash or wildCardOp:
|
|
if wildCardOp:
|
|
print("Target must be directory for wildcard copy ",enteredArg)
|
|
else:
|
|
print("Cannot find the specified path: ",enteredArg)
|
|
else:
|
|
filecpy(pFmt(sourcePath)+newdir,pFmt(targetPath)+newdir2)
|
|
nFiles += 1
|
|
|
|
print(" "*7,nFiles,"files(s) copied.")
|
|
else:
|
|
print("Invalid destination:",args[2])
|
|
else:
|
|
print("No such file:",args[1])
|
|
else:
|
|
if swBits & (swAllB-int('001000',2)):
|
|
print("Illegal switch, Command Format: COPY[/y] [path]file [path][file]")
|
|
else:
|
|
print("Wrong number of arguments")
|
|
|
|
elif cmd == "PEXEC":
|
|
if not (swAllB-int('1000000',2)) & swBits:
|
|
if len(args) == 1:
|
|
pcmd = input("=>> ")
|
|
else:
|
|
pcmd = " ".join(args[1:])
|
|
try:
|
|
exec(pcmd)
|
|
envVars['errorlevel'] = '0'
|
|
except Exception as err:
|
|
if not swBits & int('1000000',2):
|
|
print("*ERROR* Exception:",str(err))
|
|
envVars['errorlevel'] = '1'
|
|
del pcmd
|
|
else:
|
|
print("Illegal switch, Command Format: PEXEC[/q] python command")
|
|
|
|
elif cmd == "READONLY":
|
|
if imp != "C":
|
|
print("READONLY command is only available when running on CirucitPython.")
|
|
elif readonly:
|
|
print("The system is already set to read-only.")
|
|
else:
|
|
if input("Setting the system to read-only will cause the Fruit Jam to restart? (y/n): ").upper() == "Y":
|
|
boot_args_file = argv_filename("/boot.py")
|
|
with open(boot_args_file, "w") as f:
|
|
f.write('[true, "/code.py"]')
|
|
microcontroller.reset()
|
|
|
|
elif cmd == "EXIT":
|
|
if activeBAT:
|
|
if len(args) > 1:
|
|
envVars['errorlevel'] = args[1]
|
|
activeBAT = False
|
|
batEcho = True
|
|
BATfile.close()
|
|
else:
|
|
threadFound = True
|
|
try:
|
|
testthreadLock = threadLock
|
|
except:
|
|
threadFound = False
|
|
|
|
if threadFound:
|
|
import _thread
|
|
|
|
if threadLock.locked():
|
|
threadLock.release()
|
|
else:
|
|
threadLock.acquire()
|
|
|
|
break
|
|
|
|
else:
|
|
savDir = os.getcwd()
|
|
args[0] = absolutePath(args[0],savDir)
|
|
|
|
aPath = args[0].split(sep)
|
|
if 'xcopy' in aPath:
|
|
envVars["_switches"] = [i.upper() for i in aPath[aPath.index('xcopy')+1:]]
|
|
aPath = aPath[0:aPath.index('xcopy')+1]
|
|
newdir = aPath.pop(-1)
|
|
(validPath, tmpDir) = chkPath(aPath)
|
|
tmpDir = pFmt(tmpDir)
|
|
|
|
args = [('"'+i+'"' if i.find(" ") != -1 else i) for i in args]
|
|
if len(args) == 1:
|
|
passedIn = ""
|
|
batParams = []
|
|
elif len(args) > 1:
|
|
passedIn = " ".join(args[1:])
|
|
batParams = args[1:]
|
|
|
|
gc.collect()
|
|
batFound = ""
|
|
|
|
cmdFound = False
|
|
for tmpDir in [tmpDir]+(envVars.get('PATH',"").split(";") if envVars.get('PATH',"") != "" else []):
|
|
tmpDir = pFmt(tmpDir)
|
|
try:
|
|
curDLst = os.listdir(pFmt(tmpDir,False))
|
|
except:
|
|
curDLst = []
|
|
curDLst_LC = ",".join(curDLst).lower().split(",")
|
|
if ((newdir.split("."))[-1]).upper() == "PY":
|
|
if validPath and newdir in curDLst and aFile(tmpDir+newdir):
|
|
|
|
exCmd(tmpDir+newdir,passedIn)
|
|
cmdFound = True
|
|
break
|
|
elif ((newdir.split("."))[-1]).upper() == "BAT":
|
|
if validPath and newdir in curDLst and aFile(tmpDir+newdir):
|
|
batFound = newdir
|
|
break
|
|
elif validPath:
|
|
if newdir.lower()+".py" in curDLst_LC:
|
|
curDLst_indx = curDLst_LC.index(newdir.lower()+".py")
|
|
if aFile(tmpDir+curDLst[curDLst_indx]):
|
|
exCmd(tmpDir+curDLst[curDLst_indx],passedIn)
|
|
cmdFound = True
|
|
break
|
|
elif newdir.lower()+".bat" in curDLst_LC:
|
|
curDLst_indx = curDLst_LC.index(newdir.lower()+".bat")
|
|
if aFile(tmpDir+curDLst[curDLst_indx]):
|
|
batFound = curDLst[curDLst_indx]
|
|
break
|
|
|
|
if '_switches' in envVars.keys():
|
|
envVars.pop('_switches')
|
|
|
|
if batFound != "":
|
|
if activeBAT:
|
|
BATfile.close()
|
|
BATfile = open(tmpDir+batFound)
|
|
activeBAT = True
|
|
batEcho = True
|
|
batLabels = readBATFile(BATfile)
|
|
batLineNo = 0
|
|
elif not cmdFound:
|
|
print("Illegal command:",cmdLine.split(" ")[0])
|
|
|
|
gc.collect()
|
|
|
|
PyDOS()
|
|
reload()
|
|
|