home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / TOP / USR / SRC / vcron.t.Z / vcron.t / VCRON / vcron.c < prev   
C/C++ Source or Header  |  1988-11-15  |  8KB  |  312 lines

  1. /* $Source: /h0/usr/src/local/src/crond/crond.c,v $
  2.  * $Revision: 1.7 $
  3.  * $Log:    crond.c,v $
  4.  * Revision 1.7  88/04/20  20:00:00  ram
  5.  * adapted paul's UN*X version for OSK
  6.  *   got around the UN*X fork() by executing vcron with special 
  7.  *   argv[0]. Also moved crontab-owner recognition to group-entry.
  8.  *   Mailing of output with '-' as first character of command instead of
  9.  *   empty MAILTO. Usage of Sysinfo. Vcron now forks commands at the beginning
  10.  *   of a minute.
  11.  *
  12.  * Revision 1.6  87/05/02  17:33:16  paul
  13.  * baseline for mod.sources release
  14.  * 
  15.  * Revision 1.5  87/03/31  00:23:08  paul
  16.  * another GREAT idea from rs@mirror...
  17.  *   do all time calculations in int instead of double -- the double
  18.  *   stuff was for a previous kludge that turned out to be unneeded.
  19.  *   time.c went away as of this change, also.
  20.  * 
  21.  * Revision 1.4  87/02/12  18:20:29  paul
  22.  * fixed target_time scope misdesign, lots of fixes to sigchld stuff
  23.  * 
  24.  * Revision 1.3  87/02/10  18:26:38  paul
  25.  * POKECRON, time_d(), target_time, other massive changes
  26.  * 
  27.  * Revision 1.2  87/02/02  19:25:43  paul
  28.  * various
  29.  * 
  30.  * Revision 1.1  87/01/26  23:48:55  paul
  31.  * Initial revision
  32.  */
  33.  
  34. /* Copyright 1987 by Vixie Enterprises
  35.  * All rights reserved
  36.  *
  37.  * Distribute freely, except: don't sell it, don't remove my name from the
  38.  * source or documentation (don't take credit for my work), mark your changes
  39.  * (don't get me blamed for your possible bugs), don't alter or remove this
  40.  * notice.  Commercial redistribution is negotiable; contact me for details.
  41.  *
  42.  * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  43.  * I'll try to keep a version up to date.  I can be reached as follows:
  44.  * Paul Vixie, Vixie Enterprises, 329 Noe Street, San Francisco, CA, 94114,
  45.  * (415) 864-7013, {ucbvax!dual,ames,ucsfmis,lll-crg,sun}!ptsfa!vixie!paul.
  46.  */
  47.  
  48.  
  49. #define    MAIN_PROGRAM
  50.  
  51.  
  52. #include "cron.h"
  53.  
  54. #include <time.h>
  55. #include <signal.h>
  56. #include <types.h>
  57. # include <modes.h>
  58. # include <info.h>
  59.  
  60. extern int    fprintf(), exit(), sleep();
  61. extern time_t    time();
  62.  
  63. static int    dummy;
  64. static int    PokeCron;
  65. static int    Ticks_sec;
  66. char        *console = NULL;
  67. char        spooldir[MAX_FNAME];
  68.  
  69. void
  70. usage()
  71. {
  72.     exit (_errmsg (ERROR_EXIT, "usage:  %s [-x<=>debugflag[,...]] \n", PROGNAME));
  73. }
  74.  
  75.  
  76. void
  77. main(argc, argv)
  78.     int    argc;
  79.     char    *argv[];
  80. {
  81.     extern char    *_prgname(),*getenv(),**environ;
  82.     extern void    set_cron_uid(), parse_args(),
  83.             free_database(),
  84.             do_1th_child(),do_2nd_child();
  85.     extern user    *load_database();
  86.     extern long    cron(),getuid(),os9exec(),os9forkc(),_memmins;
  87.  
  88.     REG user    *database;
  89.     REG long    target_time;
  90.     int        i,handler ();
  91.  
  92.     _memmins = BUFSIZ;    /* make vcron smaller    */
  93.     PROGNAME = _prgname();    /* get name of Modul    */
  94.  
  95.     /*
  96.      * After getting the modulename, we are checking for argv[0][0],
  97.      * because of 'sub'crons. If we are a 'normal' Vcron we fork our-
  98.      * self again with argv[0][0] == '-'. That one is the real cron,
  99.      * parent == sysgo etc...
  100.      */
  101.  
  102.     switch( argv[0][0] ) {
  103.         case '*' :do_1th_child(argc,argv); exit(0);
  104.         case '?' :do_2nd_child(argc,argv); exit(0);
  105.         case '-' :break;
  106.         default: {
  107.             argv[0][0] = '-';
  108.             os9exec(os9forkc,PROGNAME,argv,environ,0,0,3);
  109.             sleep(1);
  110.             exit(0);
  111.         }
  112.     }
  113.  
  114.     if( (long) getuid() ) 
  115.         exit (_errmsg (1,"YOU are NOT allowed to start Vcron !\n"));
  116.  
  117.     intercept (handler);
  118.  
  119.     Ticks_sec = CLK_TCK;    /* how many ticks per second ? */
  120.  
  121.     /*
  122.      * get the spooldir. there are 2 ways to guess it:
  123.      * 1. entry 'CRONDIR' in Sysinfo
  124.      * 2. hardcoded to SPOOLDIR
  125.      */
  126.     if(!( info_str("CRONDIR",spooldir, MAX_FNAME))) 
  127.         strcpy( spooldir, SPOOLDIR);
  128.     strcat(spooldir, "/");
  129.  
  130.     /* if there is only one argument, it's the program name.  this means
  131.      * that debugging can't be on (it would require '-x'), thus test-mode
  132.      * can't be on, thus we should fork and exit, to be compatible with
  133.      * the real cron. Not so in OSK-Version.
  134.      */
  135.     (void) fprintf(stderr, "[%d] vcron started\n", getpid());
  136.  
  137.     parse_args(argc, argv);
  138.  
  139.     if (!console) console = CONSOLE;
  140.     if ( info_is_locked(POKECRON) )
  141.         exit (_errmsg (1,"Already locked: %s!\n",POKECRON));
  142.      if ( info_lock( POKECRON, 99) <0)
  143.         exit (_errmsg (1,"Cant't lock: %s!\n",POKECRON));
  144.      close (STDOUT);
  145.     close (STDERR);
  146.     if (access (console,02)) close (create (console,02,03));
  147.     open (console,S_IWRITE | S_IREAD);
  148.     dup (1);
  149.     /*open (console,S_IWRITE);*/
  150.     close (STDIN);
  151.     if (!strcmp (console,"/nil")) dup (1);
  152.     else open ("/nil",S_IREAD);
  153.     set_cron_uid();
  154.  
  155.     _sysdate(0, &i, &dummy, &dummy, &dummy);
  156.     sleep( 60 - ( i & 0xff));    /* synch to begining of minute */
  157.  
  158.     target_time = (long) time((time_t*)0);
  159.     PokeCron = 0;
  160.  
  161.     while (TRUE)
  162.     {
  163.         database = load_database();
  164.         target_time = cron(database, target_time);
  165.         free_database(database);
  166.     }
  167. }
  168.  
  169.  
  170. static long
  171. cron(db, target_time)
  172.     REG user    *db;
  173.     REG long    target_time;
  174. {
  175.     extern int    unlink();
  176.     extern void    cron_tick(), cron_sleep();
  177.  
  178.     /*
  179.      * The Variable PokeCron contains the last signal received (if any)
  180.      * if we got one, exit the loop to reload the database.
  181.      */
  182.     while (! PokeCron)
  183.     {
  184.         /* do this iteration
  185.          */
  186.         cron_tick(db, target_time);
  187.  
  188.         /* sleep 1 minute
  189.          */
  190.         target_time += 60;
  191.         cron_sleep(target_time);
  192.     }
  193.     PokeCron = 0;
  194. #if DEBUGGING
  195.     Debug(DSCH, "POKECRON Signal detected\n");
  196. #endif
  197.     return target_time;
  198. }
  199.  
  200.  
  201. static void
  202. cron_tick(db, target_time)
  203.     user    *db;
  204.     long    target_time;
  205. {
  206.     extern void        do_command();
  207.     extern struct tm    *localtime();
  208.     REG struct tm        *tm = localtime((time_t*) &target_time);
  209.     REG user        *u;
  210.     REG entry        *e;
  211.     REG int            minute, hour, dom, month, dow;
  212.  
  213.     minute = tm->tm_min -FIRST_MINUTE;
  214.     hour = tm->tm_hour -FIRST_HOUR;
  215.     dom = tm->tm_mday -FIRST_DOM;
  216.     month = tm->tm_mon +1 /* 0..11 -> 1..12 */ -FIRST_MONTH;
  217.     dow = tm->tm_wday -FIRST_DOW;
  218.  
  219. #if DEBUGGING
  220.     Debug(DSCH, "tick(%d,%d,%d,%d,%d)\n", minute, hour, dom, month, dow);
  221. #endif
  222.  
  223.     /* the dom/dow situation is odd.  '* * 1,15 * Sun' will run on the
  224.      * first and fifteenth AND every Sunday;  '* * * * Sun' will run *only*
  225.      * on Sundays;    '* * 1,15 * *' will run *only* the 1st and 15th.  this
  226.      * is why we keep 'e->dow_star' and 'e->dom_star'.
  227.      */
  228.     for (u = db;  u != NULL;  u = u->next)
  229.         for (e = u->crontab;  e != NULL;  e = e->next)
  230.             if (bit_test(e->minute, minute)
  231.              && bit_test(e->hour, hour)
  232.              && bit_test(e->month, month)
  233.              && ( (e->dom_star || e->dow_star)
  234.                   ? (bit_test(e->dow,dow) && bit_test(e->dom,dom))
  235.                   : (bit_test(e->dow,dow) || bit_test(e->dom,dom))
  236.                 )
  237.                )
  238.                 do_command(e->cmd, u);
  239. }
  240.  
  241. static void
  242. cron_sleep(target_time)
  243.     long    target_time;
  244. {
  245.     REG int    seconds_to_wait;
  246.  
  247.     seconds_to_wait = (int) (target_time - (long) time((time_t*)0));
  248. #if DEBUGGING
  249.     Debug(DSCH, "target_time=%ld, sec-to-wait=%d\n",
  250.         target_time, seconds_to_wait);
  251. #endif
  252.  
  253.     if (seconds_to_wait > 0)
  254.     {
  255. #if DEBUGGING
  256.         Debug(DSCH, "sleeping for %d seconds\n", seconds_to_wait);
  257. #endif
  258.     /* sleep for x seconds,  signal-proof :-) */
  259.     seconds_to_wait *= Ticks_sec;
  260.     while( seconds_to_wait = tsleep( (unsigned int) seconds_to_wait)) ;
  261.     }
  262. }
  263.  
  264.  
  265. static void
  266. parse_args(argc, argv)
  267.     int    argc;
  268.     char    *argv[];
  269. {
  270.     char *x;
  271.     int t;
  272.     
  273.     for (t=1;t<argc;++t)
  274.         if (*(x = argv[t]) == '-') {
  275.             ++x;
  276.             while (*x) {
  277.                 switch (*x) {
  278.                     case 'x':
  279.                         if (*(x+1) == '=') ++x;
  280.                         if (*x) ++x;
  281.                         if (!*x) x = "ext,sch,proc,pars,misc";
  282.                         if (!set_debug_flags(x))
  283.                             usage();
  284.                         else while (*x) ++x;
  285.                         break;
  286.                     case 'c':
  287.                         if (*(x+1) == '=') ++x;
  288.                         if (*x) ++x;
  289.                         console = x;
  290.                         while (*x) ++x;
  291.                         break;
  292.                     default:
  293.                         usage ();
  294.                 }
  295.             }
  296.         }
  297.         else usage ();
  298. }
  299.  
  300. handler (sig)
  301. REG int sig;
  302. {
  303.     if (sig == SIGINT || sig == SIGQUIT) {
  304.         info_unlock(POKECRON);
  305.         exit (1);
  306.     }
  307.     PokeCron = sig;
  308. #if DEBUGGING
  309.     Debug(DMISC, "Signal #%d received\n",sig);
  310. #endif
  311. }
  312.