fix bash-completion

This commit is contained in:
2023-10-17 00:47:21 +08:00
parent 6cb42d6b8d
commit b89a492b6a
6 changed files with 420 additions and 14 deletions

View File

@@ -1,4 +1,7 @@
# sunhpc(1) completion
#
# /etc/bash_completion.d/sunhpc
#
_sunhpc_array_delete_at()
{
@@ -40,8 +43,11 @@ _sunhpc()
return 0
fi
local IFS=$'\n'
COMPREPLY=( $( compgen -W '$output' -- $cur ) )
#local IFS=$'\n'
COMPREPLY=( $( compgen -W '$output' -- ${cur} ) )
# do not append a space to words that end with =
[[ $COMPREPLY == *= ]] && compopt -o nospace
} &&
complete -F _sunhpc sunhpc

View File

@@ -466,12 +466,12 @@ class Command(command):
Networks = '''
CREATE TABLE Networks (
ID integer NOT NULL primary key autoincrement,
Node integer(11) default NULL,
MAC varchar(64) default NULL,
IP varchar(32) default NULL,
Node integer(11) default NULL,
MAC varchar(64) default NULL,
IP varchar(32) default NULL,
Name varchar(128) default NULL,
Device varchar(32) default NULL,
Subnet integer(11) default NULL,
Device varchar(32) default NULL,
Subnet integer(11) default NULL,
Foreign key(subnet) references subnets(id) on delete cascade on update restrict,
Foreign key(node) references nodes(id) on delete cascade on update restrict
)'''

View File

@@ -67,7 +67,6 @@ class Command(sunhpc.commands.report.command):
if o.MustBeRoot and not self.isRootUser():
sys.exit(0)
results = []
for arg in o.usage().split():
tmp = arg.split('=', 1)
@@ -77,14 +76,9 @@ class Command(sunhpc.commands.report.command):
tmpstr = arg.replace('[', '')
tmpstr = tmpstr.replace(']', '')
tmpstr = tmpstr.split('=')[0] + '='
results.append(tmpstr)
#print (' '.join(results))
#print ('--add-interface= --set-net=')
print ('--envs= prefix=')
print (' '.join(results))
RollName = "base"

358
lib/sunhpc/core/app.py Normal file
View File

@@ -0,0 +1,358 @@
#
# Time for an initial checkin. Datastructure and general layout of the
# code is correct. Still need comparison code for File and RPM objects.
#
import os
import sys
import types
import sunhpc
import getopt
import sunhpc.invoke
import xml
from xml.sax import saxutils
from xml.sax import handler
from xml.sax import make_parser
from xml.sax._exceptions import SAXParseException
class Application:
def __init__(self, argv=None):
# Applets (code in the kickstart graph) doesn't pass sys.argv
# so pick it up anyway to keep everything working.
if not argv:
argv = sys.argv
self.args = []
self.caller_args = argv[1:]
self.usage_command = os.path.basename(argv[0])
self.usage_name = 'Application'
self.usage_version = 0
self.rcfileHandler = RCFileHandler
self.rcfileList = []
self.rcForce = []
self.projectName = 'sunhpc'
self.projectVersionName = 'base'
self.projectVersionMajor = sunhpc.version_major
self.projectVersionMinor = sunhpc.version_minor
self.projectVersionMicro = sunhpc.version_micro
self.getopt = sunhpc.core.utils.Struct()
self.getopt.s = [ 'h' ]
self.getopt.l = [ 'help',
'list-rcfiles',
'list-project-info',
'rcfile='
]
# Unset our local
try:
os.environ["LANG"]
except KeyError:
pass
def run(self):
sys.exit(-1)
def projectInfo(self):
return [ self.projectName,
self.projectVersionName,
int(self.projectVersionMajor),
int(self.projectVersionMinor),
int(self.projectVersionMicro) ]
def getArgs(self):
return self.args
def setArgs(self, argslist):
self.args = argslist
def parseArgs(self, rcbase=None):
"""Parses the command line arguments and all the relevant
resource-control (RC) files for this application. The usage_command
(generally argv[0]) will determine which the name of our rcfile,
unless overrided with the rcbase argument."""
# Save any existing options
args = self.getArgs()
# First pass to get rcfiles specified on the cmd line
self.setArgs(self.caller_args)
self.parseCommandLine(rcfile=1)
# Parse Resource Control files
self.setArgs([])
if not rcbase:
rcbase = self.usage_command
self.parseRC(rcbase)
for rc in self.rcForce:
self.parseRCFile(rc, rcbase)
# Command line options always win
self.setArgs(args + self.args + self.caller_args)
self.parseCommandLine()
def parseRC(self, rcbase, section=None):
rcfile = rcbase + 'rc'
if not section:
section = rcbase
# Where we look for resource-control files. First in
# the default 'etc' location, then HOME, finally in this dir.
# We use data from all three, such that later rc files take
# precedence.
dirList = [ os.path.join(os.sep,'opt', self.projectName, 'etc') ]
if 'HOME' in os.environ:
dirList.append(os.environ['HOME'])
dirList.append('.')
# Look for both hidden and visible rc files.
for dir in dirList:
self.parseRCFile(os.path.join(dir, '.' + rcfile), section)
self.parseRCFile(os.path.join(dir, rcfile), section)
def parseRCFile(self, filename, section):
if os.path.isfile(filename) and filename not in self.rcfileList:
self.rcfileList.append(filename)
file = open(filename, 'r')
parser = make_parser()
handler = self.rcfileHandler(self)
if section:
handler.setSection(section)
parser.setContentHandler(handler)
try:
parser.parse(file)
except SAXParseException as msg:
print (filename, "XML parse exception: ", msg)
file.close()
def parseCommandLine(self, rcfile=0):
"""Calls getopt to parse the command line flags. In
rcfile mode we just get --rcfile options."""
short = ''
for e in self.getopt.s:
if isinstance(e, tuple):
short = short + e[0]
else:
short = short + e
long = []
for e in self.getopt.l:
if isinstance(e, tuple):
long.append(e[0])
else:
long.append(e)
try:
opts, args = getopt.getopt(self.args, short, long)
except getopt.GetoptError as msg:
sys.stderr.write("error - %s\n" % msg)
self.usage()
sys.exit(1)
for c in opts:
if rcfile:
if c[0] != "--rcfile":
continue
self.parseArg(c)
if not rcfile:
self.args = args
def parseArg(self, c):
if c[0] in ('-h', '--help'):
self.help()
sys.exit(0)
elif c[0] == '--list-rcfiles':
print (self.rcfileList)
sys.exit(0)
elif c[0] == '--list-project-info':
print (self.projectInfo())
sys.exit(0)
elif c[0] == '--rcfile':
self.rcForce.append(c[1])
else:
return 0
return 1
def usage(self):
if 'COLUMNS' in os.environ:
cols = os.environ['COLUMNS']
else:
cols = 80
usagelist = [ 'Usage: ', self.usage_command, ' ' ]
# Build string of argument-free short options.
s = '[-'
for e in self.getopt.s:
if len(e) == 1:
s = s + e
s = s + ']'
if len(s) == 3:
s = ''
usagelist.append(s)
# Add the argument short options to the above string
for e in self.getopt.s:
if isinstance(e, tuple):
v = e[0]
h = e[1]
else:
v = e
h = 'arg'
if len(v) != 1:
usagelist.append(' [-' + v[:-1] + ' ' + h + ']')
# Add argument-free long options
for e in self.getopt.l:
if isinstance(e, tuple):
v = e[0]
else:
v = e
if v[len(v)-1] != '=':
usagelist.append(' [--' + v + ']')
# Add argument long options
for e in self.getopt.l:
if isinstance(e, tuple):
v = e[0]
h = e[1]
else:
v = e
h = 'arg'
if v[len(v)-1] == '=':
usagelist.append(' [--' + v[:-1] + ' ' + h + ']')
usagelist.append(self.usageTail())
# Print the usage, word wrapped to the correct screen size.
print (self.usage_name, '- version', self.usage_version)
l = 0
s = ''
for e in usagelist:
if l + len(e) <= cols:
s = s + e
l = l + len(e)
else:
print (s)
l = len(e)
s = e
if s:
print (s)
def help(self):
self.usage()
def usageTail(self):
return ''
def getArch(self):
return sunhpc.core.utils.getNativeArch()
class RCFileHandler(sunhpc.core.utils.ParseXML):
def __init__(self, application):
sunhpc.core.utils.ParseXML.__init__(self, application)
self.foundSection = 0
self.section = self.app.usage_command
def setSection(self, section):
self.section = section
def startElement(self, name, attrs):
#
# need to convert all the attributes to ascii strings.
# starting in python 2, the xml parser puts the attributes in
# unicode which causes problems with sunhpc apps classes, specifically
# those that append path names found in the attributes to the sys.path
#
newattrs = {}
for (aname, avalue) in attrs.items():
newattrs[aname] = str(attrs[aname])
if self.foundSection:
sunhpc.core.utils.ParseXML.startElement(self, name, newattrs)
elif name == self.section:
self.startElementSection(name, newattrs)
def endElement(self, name):
if self.foundSection and name == self.foundSection:
self.endElementSection(name)
if self.foundSection:
sunhpc.core.utils.ParseXML.endElement(self, name)
def getOptions(self):
return self.options
# <section parent="base">
def startElementSection(self, name, attrs):
parent = attrs.get('parent')
if parent:
self.app.parseRC(parent, parent)
self.foundSection = 1
def endElementSection(self, name, attrs):
self.foundSection = 0
# <usage>
def startElement_usage(self, name, attrs):
usageName = attrs.get('name')
usageVersion = attrs.get('version')
if usageName:
self.app.usage_name = usageName
if usageVersion:
self.app.usage_version = usageVersion
# <option>
def startElement_option(self, name, attrs):
argName = attrs.get('name')
# Will return None if value is not present.
argValue = attrs.get('value')
list = self.app.getArgs()
if len(argName) > 1:
flag = '--' + argName
# We differentiate between empty values and
# no value at all.
if argValue is not None:
list.append('%s=%s' % (flag, argValue))
else:
list.append(flag)
else:
flag = '-' + argName
if argValue:
list.append('%s %s' % (flag, argValue))
else:
list.append(flag)
self.app.setArgs(list)
# <project>
def startElement_project(self, name, attrs):
self.app.projectName = attrs.get('name')
self.app.projectVersionName = attrs.get('versionName')
self.app.projectVersionMajor = attrs.get('versionMajor')
self.app.projectVersionMinor = attrs.get('versionMinor')
self.app.projectVersionMicro = attrs.get('versionMicro')

View File

@@ -2,9 +2,11 @@
import sunhpc
import sunhpc.core
import sunhpc.core.ip
import sunhpc.core.app
import sunhpc.core.sql
import sunhpc.core.dist
import sunhpc.core.files
import sunhpc.core.build
import sunhpc.core.utils
import sunhpc.core.security
import sunhpc.core.partition

46
sbin/check-port Executable file
View File

@@ -0,0 +1,46 @@
#!/opt/sunpy3/bin/python3
import os
import sys
import socket
import sunhpc.invoke
class App(sunhpc.core.app.Application):
def __init__(self, argv):
sunhpc.core.app.Application.__init__(self,argv)
self.usage_name = 'Check Port'
self.usage_version = '4.2'
self.node_name = 'localhost'
self.port_num = 5901
nodehelp = '(nodename default=%s)' % self.node_name
porthelp = '(port number default=%d)' % (self.port_num)
self.getopt.l.extend([ ('node=',nodehelp),('port=',porthelp) ])
self.getopt.s.extend([('n:',nodehelp),('p:',porthelp)])
def parseArg(self, c):
sunhpc.core.app.Application.parseArg(self,c)
key, val = c
if key in ('--port'):
self.port_num = int(val)
elif key in ('--node'):
self.node_name = val
def run(self):
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
s.connect((self.node_name,self.port_num))
except:
print ('Port(%s) is closed' % self.port_num)
sys.exit(1)
print ('Port(%s) is open' % self.port_num)
s.close()
sys.exit(0)
app = App(sys.argv)
app.parseArgs()
app.run()