int main (int argc, char *argv[]) { mu_locker_t locker = 0; int err = 0; pid_t usergid = getgid (); pid_t mailgid = getegid (); /* Native Language Support */ MU_APP_INIT_NLS (); /* Drop permissions during argument parsing. */ if (setegid (usergid) < 0) return MU_DL_EX_ERROR; argp_err_exit_status = MU_DL_EX_ERROR; mu_argp_init (NULL, NULL); if (mu_app_init (&argp, dotlock_capa, dotlock_cfg_param, argc, argv, 0, NULL, NULL)) exit (1); if (force) { force *= 60; flags |= MU_LOCKER_TIME; } if (retries != 0) flags |= MU_LOCKER_RETRY; if ((err = mu_locker_create (&locker, file, flags))) { if (debug) mu_diag_funcall (MU_DIAG_ERROR, "mu_locker_create", NULL, err); return MU_DL_EX_ERROR; } if (force != 0) mu_locker_set_expire_time (locker, force); if (retries != 0) mu_locker_set_retries (locker, retries); if (setegid (mailgid) < 0) return MU_DL_EX_ERROR; if (unlock) err = mu_locker_remove_lock (locker); else err = mu_locker_lock (locker); setegid(usergid); mu_locker_destroy (&locker); if (debug && err) mu_error (unlock ? _("unlocking the file %s failed: %s") : _("locking the file %s failed: %s"), file, mu_strerror (err)); switch (err) { case 0: err = MU_DL_EX_OK; break; case EPERM: err = MU_DL_EX_PERM; break; case MU_ERR_LOCK_NOT_HELD: err = MU_DL_EX_NEXIST; break; case MU_ERR_LOCK_CONFLICT: err = MU_DL_EX_EXIST; break; default: err = MU_DL_EX_ERROR; break; } return err; }
/* Check and update the vacation database. Return 0 if the mail should be answered, 0 if it should not, and throw exception if an error occurs. */ static int check_db (mu_sieve_machine_t mach, mu_list_t tags, char *from) { mu_property_t prop; char *file; mu_sieve_value_t *arg; unsigned int days; int rc; mu_stream_t str; mu_locker_t locker; if (mu_sieve_tag_lookup (tags, "days", &arg)) { days = arg->v.number; if (days > DAYS_MAX) days = DAYS_MAX; } else days = DAYS_DEFAULT; file = mu_tilde_expansion ("~/.vacation", MU_HIERARCHY_DELIMITER, NULL); if (!file) { mu_sieve_error (mach, _("%lu: cannot build db file name"), (unsigned long) mu_sieve_get_message_num (mach)); mu_sieve_abort (mach); } rc = mu_locker_create (&locker, file, 0); if (rc) { mu_sieve_error (mach, _("%lu: cannot lock %s: %s"), (unsigned long) mu_sieve_get_message_num (mach), file, mu_strerror (rc)); free (file); mu_sieve_abort (mach); } rc = mu_file_stream_create (&str, file, MU_STREAM_RDWR|MU_STREAM_CREAT); if (rc) { mu_sieve_error (mach, "%lu: mu_file_stream_create(%s): %s", (unsigned long) mu_sieve_get_message_num (mach), file, mu_strerror (rc)); mu_locker_destroy (&locker); free (file); mu_sieve_abort (mach); } free (file); rc = mu_property_create_init (&prop, mu_assoc_property_init, str); if (rc) { mu_sieve_error (mach, "%lu: mu_property_create_init: %s", (unsigned long) mu_sieve_get_message_num (mach), mu_strerror (rc)); mu_locker_destroy (&locker); mu_sieve_abort (mach); } rc = mu_locker_lock (locker); if (rc) { mu_sieve_error (mach, "%lu: cannot lock vacation database: %s", (unsigned long) mu_sieve_get_message_num (mach), mu_strerror (rc)); mu_property_destroy (&prop); mu_sieve_abort (mach); } rc = test_and_update_prop (prop, from, time (NULL), days, mach); mu_property_destroy (&prop); mu_locker_unlock (locker); mu_locker_destroy (&locker); if (rc == -1) mu_sieve_abort (mach); return rc; }
int mu_locker_create (mu_locker_t *plocker, const char *fname, int flags) { unsigned type; mu_locker_t l; char *filename; int err = 0; if (plocker == NULL) return MU_ERR_OUT_PTR_NULL; if (fname == NULL) return EINVAL; if ((err = mu_unroll_symlink (fname, &filename))) { if (err == ENOENT) { /* Try the directory part. If it unrolls successfully (i.e. all its components exist), tuck the filename part back in the resulting path and use it as the lock filename. */ char *p, *new_name, *tmp = strdup (fname); if (!tmp) return ENOMEM; p = strrchr (tmp, '/'); if (!p) filename = tmp; else { *p = 0; err = mu_unroll_symlink (tmp, &filename); if (err) { free (tmp); return err; } new_name = mu_make_file_name_suf (filename, p + 1, NULL); free (tmp); free (filename); if (!new_name) return ENOMEM; filename = new_name; } } else return err; } l = calloc (1, sizeof (*l)); if (l == NULL) { free (filename); return ENOMEM; } l->file = filename; if (l->file == NULL) { free (l); return ENOMEM; } if (strcmp (filename, "/dev/null") == 0) l->flags = MU_LOCKER_NULL; else if (flags) l->flags = flags; else l->flags = mu_locker_default_flags; l->expire_time = mu_locker_expire_timeout; l->retries = mu_locker_retry_count; l->retry_sleep = mu_locker_retry_timeout; type = MU_LOCKER_TYPE (l); if (type >= MU_LOCKER_NTYPES) { free (l->file); return EINVAL; } /* Initialize locker-type-specific data */ err = locker_tab[type].init ? locker_tab[type].init (l) : 0; if (err) { mu_locker_destroy (&l); return err; } *plocker = l; return 0; }