###########################################################
#                                                         #
# magma.py -- compute things using system calls to MAGMA  #
#                                                         #
# Original author: William Stein, 10/10/2003              #
# Released under GPL, etc.                                #
#                                                         #
###########################################################

import os, string  

MAGMA='/usr/local/bin/magma'

BAD=['system', 'open', 'getcurrentdirectory', 'getuid', 'isintrinsic',\
     'file', 'pipe', 'memory', 'editor', 'outputfile', \
     'load', 'save', 'attach', 'read', 'write', 'alarm', '%', 'sethelp',\
     'put']

MAXTIME="20"
MAXMEMORY="100000000"
MAXLEN = 10000

def strip(cmd):
    cmd0 = cmd.lower()
    ans=""
    for x in cmd.lower():
        if ord(x) >= ord("a") and ord(x) <= ord("z"):
            ans=ans+x
    return ans

def magma(cmd):
    s=strip(cmd)
    for word in BAD:
        if s.find(word) != -1:
            return "WARNING: MAGMA command contains unsafe command "+\
                   "'%s', so it will not be executed."%word
    for word in BAD:
        if cmd.replace("%o","").find(word) != -1:
            return "WARNING: MAGMA command contains unsafe command "+\
                   "'%s', so it will not be executed."%word
    mtime=MAXTIME
    cmd="SetIgnorePrompt(true);\n"+cmd
    cmd="Alarm(%s);"%mtime+cmd
    cmd="SetMemoryLimit(%s);\n;"%MAXMEMORY+cmd
    cmd=cmd+';\nquit;'

    process = os.popen3(MAGMA)
    process[0].write(cmd)
    process[0].close()
    out=process[1].read()
    err=process[2].read()
    n0=out.find("Type ?")
    n1=out.find("quit.")+5
    out=out[:n0]+"   -------------------------------------\n"+out[n1:]
    if len(out) > MAXLEN:
        out = out[:MAXLEN]
        out = out + "\n ** WARNING: Output too long, hence truncated."
    if err!="":
        out=out+"\nErrors: "+err
    if out.find("Alarm clock") != -1:
        out = "** WARNING: Computation time exceeded %s seconds, so computation was terminated after %s seconds. **\n\n"%(MAXTIME,MAXTIME) + "\n"+out
    if out.find("User memory limit") != -1:
        out = "** WARNING: Computation used more memory than allowed. **\n\n" + out
    return out



