exit(EXIT_FAILURE);
}
-static ssize_t unsubscribe(int subreadfd, int subwritefd, const char *address)
-{
- off_t suboff = find_subscriber(subreadfd, address);
- struct stat st;
- char *inmap;
- size_t len = strlen(address) + 1; /* + 1 for the '\n' */
- ssize_t writeres = 0, written = 0;
-
- if(suboff == -1)
- return -1; /* Did not find subscriber */
-
- if(fstat(subreadfd, &st) < 0) {
- log_error(LOG_ARGS, "Could not stat subreadfd");
- return -1;
- }
-
- if((inmap = mmap(0, st.st_size, PROT_READ, MAP_SHARED,
- subreadfd, 0)) == MAP_FAILED) {
- log_error(LOG_ARGS, "Could not mmap subreadfd");
- return -1;
- }
-
- if(suboff > 0) {
- writeres = dprintf(subwritefd, "%.*s", (int)suboff, inmap);
- if(writeres < 0)
- return -1;
- }
- written += writeres;
-
- writeres = dprintf(subwritefd, "%.*s", (int)(st.st_size - len - suboff),
- inmap + len + suboff);
- if(writeres < 0)
- return -1;
-
- written += writeres;
-
- munmap(inmap, st.st_size);
-
- return written;
-}
static void print_help(const char *prg)
{
exit(EXIT_FAILURE);
}
-static void unsubscribe_type(struct mlmmj_list *list,
- char *address,
- enum subtype typesub, enum subreason reasonsub) {
- const char *subdir;
- char *sublockname;
- char *subwritename;
- int subread, subwrite, sublockfd;
- int groupwritable = 0;
- int unsubres;
- struct stat st;
- DIR *subddir;
- struct dirent *dp;
- off_t suboff;
- int subdirfd;
-
- subdirfd = open_subscriber_directory(list, typesub, &subdir);
- if (fstat(subdirfd, &st) == 0) {
- if(st.st_mode & S_IWGRP) {
- groupwritable = S_IRGRP|S_IWGRP;
- umask(S_IWOTH);
- }
- }
-
- if((subddir = fdopendir(subdirfd)) == NULL) {
- log_error(LOG_ARGS, "Could not opendir(%s/%s)",
- list->dir, subdir);
- exit(EXIT_FAILURE);
- }
-
- while((dp = readdir(subddir)) != NULL) {
- if(!strcmp(dp->d_name, "."))
- continue;
- if(!strcmp(dp->d_name, ".."))
- continue;
-
- subread = openat(subdirfd, dp->d_name, O_RDWR|O_EXLOCK);
- if(subread == -1)
- continue;
-
- suboff = find_subscriber(subread, address);
- if(suboff == -1) {
- close(subread);
- continue;
- }
-
- /* create a .name.lock file and aquire the lock */
- myasprintf(&sublockname, ".%s.lock", dp->d_name);
- sublockfd = open(sublockname, O_RDWR | O_CREAT | O_EXLOCK,
- S_IRUSR | S_IWUSR);
- if (sublockfd < 0) {
- log_error(LOG_ARGS, "Error opening lock file %s/%s/%s",
- list->dir, subdir, sublockname);
- myfree(sublockname);
- continue;
- }
-
- myasprintf(&subwritename, "%s.new", dp->d_name);
- subwrite = openat(subdirfd, subwritename, O_RDWR | O_CREAT | O_TRUNC | O_EXLOCK,
- S_IRUSR | S_IWUSR | groupwritable);
- if(subwrite == -1){
- log_error(LOG_ARGS, "Could not open '%s/%s/%s'",
- list->dir, subdir, subwritename);
- close(subread);
- close(sublockfd);
- myfree(subwritename);
- myfree(sublockname);
- continue;
- }
-
- unsubres = unsubscribe(subread, subwrite, address);
- if(unsubres < 0) {
- close(subread);
- close(subwrite);
- close(sublockfd);
- unlink(subwritename);
- myfree(subwritename);
- myfree(sublockname);
- continue;
- }
-
- if(unsubres > 0) {
- if(renameat(subdirfd, subwritename, subdirfd, dp->d_name) < 0) {
- log_error(LOG_ARGS,
- "Could not rename '%s' to '%s'",
- subwritename, dp->d_name);
- close(subread);
- close(subwrite);
- myfree(subwritename);
- continue;
- }
- } else { /* unsubres == 0, no subscribers left */
- unlinkat(subdirfd, subwritename, 0);
- }
-
- close(subread);
- close(subwrite);
- close(sublockfd);
- myfree(subwritename);
- unlinkat(subdirfd, sublockname, 0);
- myfree(sublockname);
-
- }
-
- closedir(subddir);
-}
-
int main(int argc, char **argv)
{
int opt;
generate_unsubconfirm(&list, address, typesub, reasonsub);
if (typesub == SUB_ALL) {
- unsubscribe_type(&list, address, SUB_NORMAL, reasonsub);
- unsubscribe_type(&list, address, SUB_DIGEST, reasonsub);
- unsubscribe_type(&list, address, SUB_NOMAIL, reasonsub);
+ unsubscribe(&list, address, SUB_NORMAL, reasonsub);
+ unsubscribe(&list, address, SUB_DIGEST, reasonsub);
+ unsubscribe(&list, address, SUB_NOMAIL, reasonsub);
} else {
- unsubscribe_type(&list, address, typesub, reasonsub);
+ unsubscribe(&list, address, typesub, reasonsub);
}
if(confirmunsub) {
return (loweraddress);
}
+static ssize_t
+real_unsubscribe(int subreadfd, int subwritefd, const char *address)
+{
+ off_t suboff = find_subscriber(subreadfd, address);
+ struct stat st;
+ char *inmap;
+ size_t len = strlen(address) + 1; /* + 1 for the '\n' */
+ ssize_t writeres = 0, written = 0;
+
+ if(suboff == -1)
+ return -1; /* Did not find subscriber */
+
+ if(fstat(subreadfd, &st) < 0) {
+ log_error(LOG_ARGS, "Could not stat subreadfd");
+ return -1;
+ }
+
+ if((inmap = mmap(0, st.st_size, PROT_READ, MAP_SHARED,
+ subreadfd, 0)) == MAP_FAILED) {
+ log_error(LOG_ARGS, "Could not mmap subreadfd");
+ return -1;
+ }
+
+ if(suboff > 0) {
+ writeres = dprintf(subwritefd, "%.*s", (int)suboff, inmap);
+ if(writeres < 0)
+ return -1;
+ }
+ written += writeres;
+
+ writeres = dprintf(subwritefd, "%.*s", (int)(st.st_size - len - suboff),
+ inmap + len + suboff);
+ if(writeres < 0)
+ return -1;
+
+ written += writeres;
+
+ munmap(inmap, st.st_size);
+
+ return written;
+}
+void
+unsubscribe(struct mlmmj_list *list, const char *address, enum subtype typesub,
+ enum subreason reasonsub)
+{
+
+ const char *subdir;
+ char *sublockname;
+ char *subwritename;
+ int subread, subwrite, sublockfd;
+ int groupwritable = 0;
+ int unsubres;
+ struct stat st;
+ DIR *subddir;
+ struct dirent *dp;
+ off_t suboff;
+ int subdirfd;
+
+ subdirfd = open_subscriber_directory(list, typesub, &subdir);
+ if (fstat(subdirfd, &st) == 0) {
+ if(st.st_mode & S_IWGRP) {
+ groupwritable = S_IRGRP|S_IWGRP;
+ umask(S_IWOTH);
+ }
+ }
+
+ if((subddir = fdopendir(subdirfd)) == NULL) {
+ log_error(LOG_ARGS, "Could not opendir(%s/%s)",
+ list->dir, subdir);
+ exit(EXIT_FAILURE);
+ }
+
+ while((dp = readdir(subddir)) != NULL) {
+ if(!strcmp(dp->d_name, "."))
+ continue;
+ if(!strcmp(dp->d_name, ".."))
+ continue;
+
+ subread = openat(subdirfd, dp->d_name, O_RDWR|O_EXLOCK);
+ if(subread == -1)
+ continue;
+
+ suboff = find_subscriber(subread, address);
+ if(suboff == -1) {
+ close(subread);
+ continue;
+ }
+
+ /* create a .name.lock file and aquire the lock */
+ myasprintf(&sublockname, ".%s.lock", dp->d_name);
+ sublockfd = open(sublockname, O_RDWR | O_CREAT | O_EXLOCK,
+ S_IRUSR | S_IWUSR);
+ if (sublockfd < 0) {
+ log_error(LOG_ARGS, "Error opening lock file %s/%s/%s",
+ list->dir, subdir, sublockname);
+ myfree(sublockname);
+ continue;
+ }
+
+ myasprintf(&subwritename, "%s.new", dp->d_name);
+ subwrite = openat(subdirfd, subwritename, O_RDWR | O_CREAT | O_TRUNC | O_EXLOCK,
+ S_IRUSR | S_IWUSR | groupwritable);
+ if(subwrite == -1){
+ log_error(LOG_ARGS, "Could not open '%s/%s/%s'",
+ list->dir, subdir, subwritename);
+ close(subread);
+ close(sublockfd);
+ myfree(subwritename);
+ myfree(sublockname);
+ continue;
+ }
+
+ unsubres = real_unsubscribe(subread, subwrite, address);
+ if(unsubres < 0) {
+ close(subread);
+ close(subwrite);
+ close(sublockfd);
+ unlink(subwritename);
+ myfree(subwritename);
+ myfree(sublockname);
+ continue;
+ }
+
+ if(unsubres > 0) {
+ if(renameat(subdirfd, subwritename, subdirfd, dp->d_name) < 0) {
+ log_error(LOG_ARGS,
+ "Could not rename '%s' to '%s'",
+ subwritename, dp->d_name);
+ close(subread);
+ close(subwrite);
+ myfree(subwritename);
+ continue;
+ }
+ } else { /* unsubres == 0, no subscribers left */
+ unlinkat(subdirfd, subwritename, 0);
+ }
+
+ close(subread);
+ close(subwrite);
+ close(sublockfd);
+ myfree(subwritename);
+ unlinkat(subdirfd, sublockname, 0);
+ myfree(sublockname);
+
+ }
+
+ closedir(subddir);
+}