# 2.11BSD#431 - /usr/src/usr.sbin/cron/database.c

##### Functions

    find_user         X
    link_user         X
    load_database     X
    unlink_user       X

##### Macros

    TMAX              X

       1: /* Copyright 1988,1990,1993,1994 by Paul Vixie
       2:  * All rights reserved
       3:  *
       4:  * Distribute freely, except: don't remove my name from the source or
       5:  * documentation (don't take credit for my work), mark your changes (don't
       6:  * get me blamed for your possible bugs), don't alter or remove this
       7:  * notice.  May be sold if buildable source is provided to buyer.  No
       8:  * warrantee of any kind, express or implied, is included with this
       9:  * software; use at your own risk, responsibility for damages (if any) to
      10:  * anyone resulting from the use of this software rests entirely with the
      11:  * user.
      12:  *
      13:  * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
      14:  * I'll try to keep a version up to date.  I can be reached as follows:
      15:  * Paul Vixie          <paul@vix.com>          uunet!decwrl!vixie!paul
      16:  */
      17:
      18: #if !defined(lint) && !defined(LINT)
      19: static char rcsid[] = "$Id: database.c,v 2.8 1994/01/15 20:43:43 vixie Exp $";
      20: #endif
      21:
      22: /* vix 26jan87 [RCS has the log]
      23:  */
      24:
      25:
      26: #include "cron.h"
      27: #include <fcntl.h>
      28: #include <sys/stat.h>
      29: #include <sys/file.h>
      30:
      31:
      32: #define TMAX(a,b) ((a)>(b)?(a):(b))
      33:
      34:
      35: static  void        process_crontab __P((char *, char *, char *,
      36:                          struct stat *,
      37:                          cron_db *, cron_db *));
      38:
      39:
      40: void
      41: load_database(old_db)
      42:     cron_db     *old_db;
      43: {
      44:     DIR     *dir;
      45:     struct stat statbuf;
      46:     struct stat syscron_stat;
      47:     register DIR_T   *dp;
      48:     cron_db     new_db;
      49:     user        *u, *nu;
      50:
      51:     Debug(DLOAD, ("[%d] load_database()\n", getpid()))
      52:
      53:     /* before we start loading any data, do a stat on SPOOL_DIR
      54: 	 * so that if anything changes as of this moment (i.e., before we've
      55: 	 * cached any of the database), we'll see the changes next time.
      56: 	 */
      57:     if (stat(SPOOL_DIR, &statbuf) < OK) {
      58:         log_it("CRON", getpid(), "STAT FAILED", SPOOL_DIR);
      59:         (void) exit(ERROR_EXIT);
      60:     }
      61:
      62:     /* track system crontab file
      63: 	 */
      64:     if (stat(SYSCRONTAB, &syscron_stat) < OK)
      65:         syscron_stat.st_mtime = 0;
      66:
      67:     /* if spooldir's mtime has not changed, we don't need to fiddle with
      68: 	 * the database.
      69: 	 *
      70: 	 * Note that old_db->mtime is initialized to 0 in main(), and
      71: 	 * so is guaranteed to be different than the stat() mtime the first
      72: 	 * time this function is called.
      73: 	 */
      74:     if (old_db->mtime == TMAX(statbuf.st_mtime, syscron_stat.st_mtime)) {
      75:         Debug(DLOAD, ("[%d] spool dir mtime unch, no load needed.\n",
      76:                   getpid()))
      77:         return;
      78:     }
      79:
      80:     /* something's different.  make a new database, moving unchanged
      81: 	 * elements from the old database, reloading elements that have
      82: 	 * actually changed.  Whatever is left in the old database when
      83: 	 * we're done is chaff -- crontabs that disappeared.
      84: 	 */
      85:     new_db.mtime = TMAX(statbuf.st_mtime, syscron_stat.st_mtime);
      86:     new_db.head = new_db.tail = NULL;
      87:
      88:     if (syscron_stat.st_mtime) {
      89:         process_crontab("root", "*system*",
      90:                 SYSCRONTAB, &syscron_stat,
      91:                 &new_db, old_db);
      92:     }
      93:
      94:     /* we used to keep this dir open all the time, for the sake of
      95: 	 * efficiency.  however, we need to close it in every fork, and
      96: 	 * we fork a lot more often than the mtime of the dir changes.
      97: 	 */
      98:     if (!(dir = opendir(SPOOL_DIR))) {
      99:         log_it("CRON", getpid(), "OPENDIR FAILED", SPOOL_DIR);
     100:         (void) exit(ERROR_EXIT);
     101:     }
     102:
     103:     while (NULL != (dp = readdir(dir))) {
     104:         char    fname[MAXNAMLEN+1],
     105:             tabname[MAXNAMLEN+1];
     106:
     107:         /* avoid file names beginning with ".".  this is good
     108: 		 * because we would otherwise waste two guaranteed calls
     109: 		 * to getpwnam() for . and .., and also because user names
     110: 		 * starting with a period are just too nasty to consider.
     111: 		 */
     112:         if (dp->d_name[0] == '.')
     113:             continue;
     114:
     115:         (void) strcpy(fname, dp->d_name);
     116:         sprintf(tabname, CRON_TAB(fname));
     117:
     118:         process_crontab(fname, fname, tabname,
     119:                 &statbuf, &new_db, old_db);
     120:     }
     121:     closedir(dir);
     122:
     123:     /* if we don't do this, then when our children eventually call
     124: 	 * getpwnam() in do_command.c's child_process to verify MAILTO=,
     125: 	 * they will screw us up (and v-v).
     126: 	 */
     127:     endpwent();
     128:
     129:     /* whatever's left in the old database is now junk.
     130: 	 */
     131:     Debug(DLOAD, ("unlinking old database:\n"))
     132:     for (u = old_db->head;  u != NULL;  u = nu) {
     133:         Debug(DLOAD, ("\t%s\n", u->name))
     134:         nu = u->next;
     135:         unlink_user(old_db, u);
     136:         free_user(u);
     137:     }
     138:
     139:     /* overwrite the database control block with the new one.
     140: 	 */
     141:     *old_db = new_db;
     142:     Debug(DLOAD, ("load_database is done\n"))
     143: }
     144:
     145:
     146: void
     147: link_user(db, u)
     148:     register cron_db    *db;
     149:     register user   *u;
     150: {
     151:     if (db->head == NULL)
     152:         db->head = u;
     153:     if (db->tail)
     154:         db->tail->next = u;
     155:     u->prev = db->tail;
     156:     u->next = NULL;
     157:     db->tail = u;
     158: }
     159:
     160:
     161: void
     162: unlink_user(db, u)
     163:     register cron_db    *db;
     164:     register user   *u;
     165: {
     166:     if (u->prev == NULL)
     167:         db->head = u->next;
     168:     else
     169:         u->prev->next = u->next;
     170:
     171:     if (u->next == NULL)
     172:         db->tail = u->prev;
     173:     else
     174:         u->next->prev = u->prev;
     175: }
     176:
     177:
     178: user *
     179: find_user(db, name)
     180:     cron_db *db;
     181:     register char   *name;
     182: {
     183:     char    *env_get();
     184:     register user   *u;
     185:
     186:     for (u = db->head;  u != NULL;  u = u->next)
     187:         if (!strcmp(u->name, name))
     188:             break;
     189:     return u;
     190: }
     191:
     192:
     193: static void
     194: process_crontab(uname, fname, tabname, statbuf, new_db, old_db)
     195:     char        *uname;
     196:     char        *fname;
     197:     char        *tabname;
     198:     struct stat *statbuf;
     199:     cron_db     *new_db;
     200:     cron_db     *old_db;
     201: {
     202:     struct passwd   *pw = NULL;
     203:     int     crontab_fd = OK - 1;
     204:     register user       *u;
     205:
     206:     if (strcmp(fname, "*system*") && !(pw = getpwnam(uname))) {
     207:         /* file doesn't have a user in passwd file.
     208: 		 */
     209:         log_it(fname, getpid(), "ORPHAN", "no passwd entry");
     210:         goto next_crontab;
     211:     }
     212:
     213:     if ((crontab_fd = open(tabname, O_RDONLY, 0)) < OK) {
     214:         /* crontab not accessible?
     215: 		 */
     216:         log_it(fname, getpid(), "CAN'T OPEN", tabname);
     217:         goto next_crontab;
     218:     }
     219:
     220:     if (fstat(crontab_fd, statbuf) < OK) {
     221:         log_it(fname, getpid(), "FSTAT FAILED", tabname);
     222:         goto next_crontab;
     223:     }
     224:
     225:     Debug(DLOAD, ("\t%s:", fname))
     226:     u = find_user(old_db, fname);
     227:     if (u != NULL) {
     228:         /* if crontab has not changed since we last read it
     229: 		 * in, then we can just use our existing entry.
     230: 		 */
     231:         if (u->mtime == statbuf->st_mtime) {
     232:             Debug(DLOAD, (" [no change, using old data]"))
     233:             unlink_user(old_db, u);
     234:             link_user(new_db, u);
     235:             goto next_crontab;
     236:         }
     237:
     238:         /* before we fall through to the code that will reload
     239: 		 * the user, let's deallocate and unlink the user in
     240: 		 * the old database.  This is more a point of memory
     241: 		 * efficiency than anything else, since all leftover
     242: 		 * users will be deleted from the old database when
     243: 		 * we finish with the crontab...
     244: 		 */
     245:         Debug(DLOAD, (" [delete old data]"))
     246:         unlink_user(old_db, u);
     247:         free_user(u);
     248:         log_it(fname, getpid(), "RELOAD", tabname);
     249:     }
     250:     u = load_user(crontab_fd, pw, fname);
     251:     if (u != NULL) {
     252:         u->mtime = statbuf->st_mtime;
     253:         link_user(new_db, u);
     254:     }
     255:
     256: next_crontab:
     257:     if (crontab_fd >= OK) {
     258:         Debug(DLOAD, (" [done]\n"))
     259:         close(crontab_fd);
     260:     }
     261: }

#### Defined functions

find_user defined in line 178; used 1 times

- in line 226

link_user defined in line 146; used 2 times

- in line 234, 253

load_database defined in line 40; never used
process_crontab defined in line 193; used 2 times

- in line 89, 118

unlink_user defined in line 161; used 3 times

- in line 135, 233, 246

#### Defined variables

rcsid defined in line 19; never used

#### Defined macros

TMAX defined in line 32; used 2 times

- in line 74, 85

Last modified: 1999-06-13 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1708 |