crontab (alpha version)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

 Here is the first version of a crontab for our Nokia N... (I don't
know on which model alarmd is). I think it can parse all crontab
input however I expect you to let me know if there is a problem.
Of course, don't complain if it destroys all you Nokia, job and life,
I tried it but you never can be sure with this things!

 You should first run it as root to init the directory and files :

      crontab init

 Then as a user you can do crontab -e or crontab -l as usual.

                                          Olivier.
-------------- next part --------------
#! /usr/bin/env python

# mimicks the *NIX crontab
# it uses the alarmd of the Nokia N... to reduce the energy cost
#
# (c) 2008 Olivier Ricou <olivier at ricou.eu.org>
# Licence: BSDlike
#
# depends: pyalarmd, cf http://home.cfl.rr.com/genecash/nokia/

import sys,os,datetime,time,pyalarmd

# The crontab has 6 fields. The 5 first can have int value
#
# # m h dom mon dow command
#
# # run five minutes after midnight, every day
# 5 0 * * *       $HOME/bin/daily.job >> $HOME/tmp/out 2>&1
# # run at 2:15pm on the first of every month
# 15 14 1 * *     $HOME/bin/monthly
# # run at 10 pm on weekdays, annoy Joe
# 0 22 * * 1-5    mail -s "It's 10pm" joe%Joe,%%Where are your kids?%
# 23 0-23/2 * * * echo "run 23 minutes after midn, 2am, 4am ..., everyday"
# 5 4 * * sun     echo "run at 5 after 4 every sunday"

# the alarmd has only one value for recurrence hence we cannot set an
# alarm every first of month since monthes have different length. 
# Therefore the trick is to run crontab.py every night and reparse the crontabs

one_day = 24 * 60
flag =(pyalarmd.ALARM_EVENT_NO_DIALOG | pyalarmd.ALARM_EVENT_NO_SNOOZE | pyalarmd.ALARM_EVENT_ACTDEAD)

today = datetime.datetime.now()
tomorrow = today + datetime.timedelta(days=1)
now = time.mktime(today.timetuple()) # Epoch seconds
now24 = time.mktime(tomorrow.timetuple()) # Epoch seconds

def parse_crontab_and_set_alarms(dir,user):
  file = open("%s/%s" % (dir,user),'r')
  comment = " # crontab of %s" % user
  for al in pyalarmd.alarm_query(0,sys.maxint):
    try:
      if (pyalarmd.get_alarm(al)['exec_name'].find(comment) >= 0):
        pyalarmd.cancel_alarm(al)
    except:
      pass
  for line in file.readlines():
    recurrence = 0
    recurrence_count = 1
    alarms = []
    line = line.strip()
    if (line == '' or line[0] == '#'):
      continue
    t = line.split()
    # minutes
    try:
      minute = int(t[0])
    except:
      try:
        recurrence = int(t[0].split('/')[1])
        t[0] = t[0].split('/')[0]
      except: # / is optional
        recurrence = 1
      if (t[0] == '*'): 
        minute = 0
        recurrence_count = 60 / recurrence
      else: # then the only possibility is x-y
        try:
          minute = int(t[0].split('-')[0])
          end = int(t[0].split('-')[1])
          recurrence_count = int((end - minute) % 60 / recurrence) + 1
        except:
          print "syntax error in minutes:\n %s" % line
          sys.exit(1)
    # hours
    try:
      hour = int(t[1])
      rec = 0
      rec_count = 1
    except:
      try:
        rec = int(t[1].split('/')[1])
        t[1] = t[1].split('/')[0]
      except: # / is optional
        rec = 1
      if (t[1] == '*'): 
        hour = 0
        rec_count = 24 / rec
      else: # then the only possibility is x-y
        try:
          hour = int(t[1].split('-')[0])
          end = int(t[1].split('-')[1])
          rec_count = int((end - hour) % 24 / rec ) + 1
        except:
          print "syntax error in hours:\n %s" % line
          sys.exit(1)
    if (recurrence > 0): # for each hour we set up an alarm
      for h in range(rec_count):
        a = []
        start = datetime.datetime(today.year, today.month, today.day, hour+h*rec, minute, 0)
        a.append(start)
        a.append(recurrence)
        a.append(recurrence_count)
        alarms.append(a)
        start += datetime.timedelta(days=1)
        a = []
        a.append(start)
        a.append(recurrence)
        a.append(recurrence_count)
        alarms.append(a)
    else:
      start_time = datetime.datetime(today.year, today.month, today.day, hour, minute, 0)
      a = []
      a.append(start_time)
      a.append(rec * 60)
      a.append(rec_count)
      alarms.append(a)
      start_time += datetime.timedelta(days=1)
      a = []
      a.append(start_time)
      a.append(rec * 60)
      a.append(rec_count)
      alarms.append(a)
    #
    # Now all we do is to remove alarm from alarms
    #
    # day of the month
    if not (t[2] == '*'):
      try:
        dom = int(t[2])
        for a in alarms:
          if (a[0].day != dom):
            alarms.remove(a)
      except:
        try:
          rec = int(t[2].split('/')[1])
          t[2] = t[2].split('/')[0]
        except: # / is optional
          rec = 1
        try:
          start = int(t[2].split('-')[0])
          end = int(t[2].split('-')[1])
          for a in alarms:
            if (today.day > end or tomorrow.day < start or (a[0].day -start) % rec != 0):
              alarms.remove(a)
        except:
          if (t[2] == '*'):
            for a in alarms:
              if (a[0].day % rec != 0):
                alarms.remove(a)
          else:
            print "syntax error in day:\n %s" % line
            sys.exit(1)
    # month
    if not (t[3] == '*'):
      try:
        month = int(t[3])
        for a in alarms:
          if (a[0].month != month):
            alarms.remove(a)
      except:
        try:
          rec = int(t[3].split('/')[1])
          t[3] = t[3].split('/')[0]
        except: # / is optional
          rec = 1
        try:
          start = int(t[3].split('-')[0])
          end = int(t[3].split('-')[1])
          for a in alarms:
            if (today.month > end or tomorrow.month < start or (a[0].month -start) % rec != 0):
              alarms.remove(a)
        except:
          if (t[3] == '*'):
            for a in alarms:
              if (a[0].month % rec != 0):
                alarms.remove(a)
          else:
            print "syntax error in month:\n %s" % line
            sys.exit(1)
    # day of the week
    if not (t[4] == '*'):
      try:
        dow = int(t[4])
        for a in alarms:
          if (a[0].weekday() != dow):
            alarms.remove(a)
      except:
        try:
          rec = int(t[4].split('/')[1])
          t[4] = t[4].split('/')[0]
        except: # / is optional
          rec = 1
        try:
          start = int(t[4].split('-')[0])
          end = int(t[4].split('-')[1])
          for a in alarms:
            if (today.weekday() > end or tomorrow.weekday() < start or (a[0].weekday() -start) % rec != 0):
              alarms.remove(a)
        except:
          if (t[4] == '*'):
            for a in alarms:
              if (a[0].weekday % rec != 0):
                alarms.remove(a)
          else:
            print "syntax error in weekday (use only figure):\n %s" % line
            sys.exit(1)
    # command
    cmd = ""
    for i in t[5:]:
      cmd += i+" "
    cmd += comment
    #
    # Let put the alarms in the queue
    #
    for a in alarms:
      pyalarmd.add_alarm(time.mktime(a[0].timetuple()),a[1], a[2],0, None, \
                         None,None,None,None,None,None,None, cmd, flag)


dir = "/var/spool/cron/crontab"
user = os.getlogin()
if (len(sys.argv) == 1):  # we parse all the crontabs
  for u in os.listdir(dir):
    parse_crontab_and_set_alarms(dir,u)
else:
  if (sys.argv[1] == "init"):  # should be run by root
    if (user != "root"):
      print "init should be run by root"
      sys.exit(1)
    # first we init the dir and files
    os.system("/bin/mkdir -p %s" % dir)
    for u in os.popen("ls -1 /home/").readlines():
      u = u.strip()
      os.system("/bin/touch %s/%s" % (dir,u))
      os.system("/bin/chown %s %s/%s" % (u,dir,u))
    os.system("/bin/touch %s/root" % dir)
    # then we put crontab.py in the alarmd queue (it should be run every day)
    # we cancel the former alarm to put a new one which allows:
    #   - to have a new time to parse the crontabs 
    #   - to move this program in another directory
    for al in pyalarmd.alarm_query(0,sys.maxint):
      try:
        if (pyalarmd.get_alarm(al)['exec_name'].find(sys.argv[0].split('/')[-1]) >= 0):
          pyalarmd.cancel_alarm(al)
      except:
        pass
    pyalarmd.add_alarm(now,one_day,-1,0,0,None,None,None,None,None, \
                       None,None,None,os.path.abspath(sys.argv[0]),flag)
  elif (sys.argv[1] == "-e"):  # we edit the user crontab and parse it
    if not os.path.isfile("%s/%s" % (dir,user)):
      print "your crontab should be created by root, run as root:\n %s init" \
            % sys.argv[0]
      sys.exit(1)
    editor = os.getenv("EDITOR")
    if (editor == None):
      editor = "vi"
    os.system("%s %s/%s" % (editor,dir,user))
    parse_crontab_and_set_alarms(dir,user)
  elif (sys.argv[1] == "-l"):  # we list the user crontab
    os.system("/bin/cat %s/%s" % (dir,user))
  else:
    print "usage: %s [-e|-l|init]" % sys.argv[0]
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://lists.maemo.org/pipermail/maemo-users/attachments/20080403/90365d8a/attachment-0001.pgp 


[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Big List of Linux Books]    

  Powered by Linux