from traceback import format_tb
if USE_DB: import pg
from time import time, sleep, mktime, localtime
-from popen2 import popen2
+from subprocess import Popen, PIPE
from LATClient import LATClient, LATClientException
from SerialClient import SerialClient, SerialClientException
from VendingMachine import VendingMachine, VendingException
from SnackConfig import get_snack#, get_snacks
import socket
from posix import geteuid
-from LDAPConnector import get_uid, set_card_id
+from LDAPConnector import get_uid,get_uname, set_card_id
CREDITS="""
This vending machine software brought to you by:
def scroll_options(username, mk, welcome = False):
if welcome:
- # Balance checking: crap code, [DAA]'s fault
- # Updated 2011 to handle new dispense [MRD]
- raw_acct = os.popen('dispense acct %s' % username)
- acct = raw_acct.read()
+ # Balance checking
+ acct, unused = Popen(['dispense', 'acct', username], close_fds=True, stdout=PIPE).communicate()
# this is fucking appalling
balance = acct[acct.find("$")+1:acct.find("(")].strip()
- raw_acct.close()
msg = [(center('WELCOME'), False, TEXT_SPEED),
(center(username), False, TEXT_SPEED),
# Get coke contents
cokes = []
for i in range(0, 7):
- cmd = 'dispense iteminfo coke:%i' % i
- raw = os.popen(cmd)
- info = raw.read()
- raw.close()
+ args = ('dispense', 'iteminfo', 'coke:%i' % i)
+ info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate()
m = re.match("\s*[a-z]+:\d+\s+(\d+)\.(\d\d)\s+([^\n]+)", info)
cents = int(m.group(1))*100 + int(m.group(2))
cokes.append('%i %i %s' % (i, cents, m.group(3)));
msg.append((choices, False, None))
mk.set_messages(msg)
-def get_pin(uid):
- try:
- info = pwd.getpwuid(uid)
- except KeyError:
- logging.info('getting pin for uid %d: user not in password file'%uid)
- return None
- if info.pw_dir == None: return False
- pinfile = os.path.join(info.pw_dir, '.pin')
- try:
- s = os.stat(pinfile)
- except OSError:
- logging.info('getting pin for uid %d: .pin not found in home directory'%uid)
- return None
- if s.st_mode & 077:
- logging.info('getting pin for uid %d: .pin has wrong permissions. Fixing.'%uid)
- os.chmod(pinfile, 0600)
- try:
- f = file(pinfile)
- except IOError:
- logging.info('getting pin for uid %d: I cannot read pin file'%uid)
- return None
- pinstr = f.readline()
- f.close()
- if not re.search('^'+'[0-9]'*PIN_LENGTH+'$', pinstr):
- logging.info('getting pin for uid %d: %s not a good pin'%(uid,repr(pinstr)))
- return None
- return int(pinstr)
+_pin_uid = 0
+_pin_uname = 'root'
+_pin_pin = '----'
+
+def _check_pin(uid, pin):
+ global _pin_uid
+ global _pin_uname
+ global _pin_pin
+ print "_check_pin('",uid,"',---)"
+ if uid != _pin_uid:
+ try:
+ info = pwd.getpwuid(uid)
+ except KeyError:
+ logging.info('getting pin for uid %d: user not in password file'%uid)
+ return None
+ if info.pw_dir == None: return False
+ pinfile = os.path.join(info.pw_dir, '.pin')
+ try:
+ s = os.stat(pinfile)
+ except OSError:
+ logging.info('getting pin for uid %d: .pin not found in home directory'%uid)
+ return None
+ if s.st_mode & 077:
+ logging.info('getting pin for uid %d: .pin has wrong permissions. Fixing.'%uid)
+ os.chmod(pinfile, 0600)
+ try:
+ f = file(pinfile)
+ except IOError:
+ logging.info('getting pin for uid %d: I cannot read pin file'%uid)
+ return None
+ pinstr = f.readline()
+ f.close()
+ if not re.search('^'+'[0-9]'*PIN_LENGTH+'$', pinstr):
+ logging.info('getting pin for uid %d: %s not a good pin'%(uid,repr(pinstr)))
+ return None
+ _pin_uid = uid
+ _pin_pin = pinstr
+ _pin_uname = info.pw_name
+ else:
+ pinstr = _pin_pin
+ if pin == int(pinstr):
+ logging.info("Pin correct for %d",uid)
+ else:
+ logging.info("Pin incorrect for %d",uid)
+ return pin == int(pinstr)
+
+def acct_is_disabled(name=None):
+ global _pin_uname
+ if name == None:
+ name = _pin_uname
+ acct, unused = Popen(['dispense', 'acct', _pin_uname], close_fds=True, stdout=PIPE).communicate()
+ # this is fucking appalling
+ flags = acct[acct.find("(")+1:acct.find(")")].strip()
+ if 'disabled' in flags:
+ return True
+ if 'internal' in flags:
+ return True
+ return False
def has_good_pin(uid):
- return get_pin(uid) != None
+ return _check_pin(uid, None) != None
def verify_user_pin(uid, pin, skip_pin_check=False):
- if skip_pin_check or get_pin(uid) == pin:
+ if skip_pin_check or _check_pin(uid, pin) == True:
info = pwd.getpwuid(uid)
if skip_pin_check:
+ if acct_is_disabled(info.pw_name):
+ logging.info('refused mifare for disabled acct uid %d (%s)'%(uid,info.pw_name))
+ return '-disabled-'
logging.info('accepted mifare for uid %d (%s)'%(uid,info.pw_name))
else:
logging.info('accepted pin for uid %d (%s)'%(uid,info.pw_name))
ClockIdler(v),
StringIdler(v),
TrainIdler(v),
+ # "Hello World" in brainfuck
+ StringIdler(v, text=">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++."),
]
disabled = [
]
price, shortname, name = get_snack( '--' )
dollarprice = "$%.2f" % ( price / 100.0 )
v.display(vstatus.cur_selection+' - %s'%dollarprice)
- exitcode = os.system('dispense -u "%s" give \>snacksales %d "%s"'%(vstatus.username, price, name)) >> 8
+# exitcode = os.system('dispense -u "%s" give \>snacksales %d "%s"'%(vstatus.username, price, name)) >> 8
# exitcode = os.system('dispense -u "%s" give \>sales\:snack %d "%s"'%(vstatus.username, price, name)) >> 8
-# exitcode = os.system('dispense -u "%s" snack:%s'%(vstatus.username, vstatus.cur_selection)) >> 8
+ exitcode = os.system('dispense -u "%s" snack:%s'%(vstatus.username, vstatus.cur_selection)) >> 8
if (exitcode == 0):
# magic dispense syslog service
syslog.syslog(syslog.LOG_INFO | syslog.LOG_LOCAL4, "vended %s (slot %s) for %s" % (name, vstatus.cur_selection, vstatus.username))
- v.vend(vstatus.cur_selection)
- v.display('THANK YOU')
+ (worked, code, string) = v.vend(vstatus.cur_selection)
+ if worked:
+ v.display('THANK YOU')
+ else:
+ print "Vend Failed:", code, string
+ v.display('VEND FAIL')
elif (exitcode == 5): # RV_BALANCE
v.display('NO MONEY?')
elif (exitcode == 4): # RV_ARGUMENTS (zero give causes arguments)
def price_check(v, vstatus):
if vstatus.cur_selection[1] == '8':
- v.display(center('SEE COKE'))
+ args = ('dispense', 'iteminfo', 'coke:' + vstatus.cur_selection[0])
+ info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate()
+ dollarprice = re.match("\s*[a-z]+:\d+\s+(\d+\.\d\d)\s+([^\n]+)", info).group(1)
else:
# first see if it's a named slot
try:
except:
price, shortname, name = get_snack( '--' )
dollarprice = "$%.2f" % ( price / 100.0 )
- v.display(vstatus.cur_selection+' - %s'%dollarprice)
+ v.display(vstatus.cur_selection+' - %s'%dollarprice)
def handle_getting_pin_key(state, event, params, v, vstatus):
reset_idler(v, vstatus, 3)
return
+
+ if acct_is_disabled():
+ logging.info('user '+vstatus.cur_user+' is disabled')
+ vstatus.mk.set_messages(
+ [(' '*11+'ACCOUNT DISABLED'+' '*11, False, 3)])
+ vstatus.cur_user = ''
+ vstatus.cur_pin = ''
+
+ reset_idler(v, vstatus, 3)
+ return
vstatus.cur_pin = ''
try:
vstatus.cur_user = get_uid(card_id)
logging.info('Mapped card id to uid %s'%vstatus.cur_user)
- vstatus.username = verify_user_pin(int(vstatus.cur_user), None, True)
+ vstatus.username = get_uname(vstatus.cur_user)
+ if acct_is_disabled(vstatus.username):
+ vstatus.username = '-disabled-'
except ValueError:
vstatus.username = None
- if vstatus.username:
+ if vstatus.username == '-disabled-':
+ v.beep(40, False)
+ vstatus.mk.set_messages(
+ [(center('ACCT DISABLED'), False, 1.0),
+ (center('SORRY'), False, 0.5)])
+ vstatus.cur_user = ''
+ vstatus.cur_pin = ''
+ vstatus.username = None
+
+ reset_idler(v, vstatus, 2)
+ return
+ elif vstatus.username:
v.beep(0, False)
vstatus.cur_selection = ''
vstatus.change_state(STATE_GET_SELECTION)