/* * Jsafecat - Store messages in maildir directories, skip empty ones. * (C)opyleft 2006-2008 by Frank DENIS (Jedi/Sector One). * Public domain. */ #include #include #include #include #include #include #include #define MINIMUM_SIZE 10 static int preline = 0; void usage(void) { puts("\nUsage: jsafecat [--preline] \n"); exit(EXIT_FAILURE); } char *get_filename(void) { char hostname[256] = "hostname"; char *filename; size_t sizeof_filename = PATH_MAX; struct timeval tp; if (gettimeofday(&tp, NULL) != 0) { return NULL; } if ((filename = malloc(sizeof_filename)) == NULL) { return NULL; } (void) gethostname(hostname, sizeof hostname); snprintf(filename, sizeof_filename, "%ld.M%ldP%lu.%s", tp.tv_sec, tp.tv_usec, (unsigned long) getpid(), hostname); return filename; } int cat_stdin_into_file(const char *file) { FILE *fp; int c; const char *ev; size_t size = (size_t) 0U; if ((fp = fopen(file, "wb")) == NULL) { perror("fopen()"); return -1; } if (preline != 0) { if ((ev = getenv("UFLINE")) != NULL) { fputs(ev, fp); } if ((ev = getenv("RPLINE")) != NULL) { fputs(ev, fp); } if ((ev = getenv("DTLINE")) != NULL) { fputs(ev, fp); } } while ((c = getchar()) != EOF) { fputc(c, fp); size++; } if (fclose(fp) != 0) { perror("fclose()"); return -1; } if (size < MINIMUM_SIZE) { unlink(file); return 1; } return 0; } int main(int argc, char *argv[]) { const char *filename; char *tmp_filename, *new_filename; size_t sizeof_tmp_filename, sizeof_new_filename; const char *tmp_dir, *new_dir; size_t strlen_filename; int ret; if (argc < 3) { usage(); } else if (argc == 4 && strcmp(argv[1], "--preline") == 0) { preline++; argv++; } else if (argc > 4) { usage(); } if ((filename = get_filename()) == NULL) { perror("get_filename()"); return 1; } tmp_dir = argv[1]; new_dir = argv[2]; strlen_filename = strlen(filename); sizeof_tmp_filename = strlen(tmp_dir) + 1U + strlen(filename) + 1U; sizeof_new_filename = strlen(new_dir) + 1U + strlen(filename) + 1U; if ((tmp_filename = malloc(sizeof_tmp_filename)) == NULL || (new_filename = malloc(sizeof_new_filename)) == NULL) { perror("malloc()"); return 1; } snprintf(tmp_filename, sizeof_tmp_filename, "%s/%s", tmp_dir, filename); snprintf(new_filename, sizeof_new_filename, "%s/%s", new_dir, filename); ret = cat_stdin_into_file(tmp_filename); if (ret < 0) { perror("cat_stdin_into_file()"); return 2; } if (ret > 0) { return 0; } if (rename(tmp_filename, new_filename) != 0) { perror("rename()"); return 4; } return 0; }