diff options
| author | mbartlett21 <29034492+mbartlett21@users.noreply.github.com> | 2026-05-03 18:53:07 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-05-03 09:53:07 +0100 |
| commit | c23112c3a0bbf1d07f03b3c07fe96b5b4c5271f1 (patch) | |
| tree | 7e14fca560a2e729f90e97282f9eea60769064da /miscutils | |
| parent | 750a5e863cc04584ba50722d8b003e279cd67d24 (diff) | |
| download | busybox-w32-c23112c3a0bbf1d07f03b3c07fe96b5b4c5271f1.tar.gz busybox-w32-c23112c3a0bbf1d07f03b3c07fe96b5b4c5271f1.tar.bz2 busybox-w32-c23112c3a0bbf1d07f03b3c07fe96b5b4c5271f1.zip | |
Add crond and crontab (#561)
* Enable crontab
* Enable crond
* Allow sendmail to be used in crond
This also adds another option to the mingw_popen_fd function to capture
stderr as well. And also added the options to support WNOHANG as well
as an unused status in mingw_wait3
* Check current uid when running crond
* Only show tail for mailto jobs
* Use system drive for cron
* crond: add missing feature check
* crond: use spawn_detach for background operation
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/crond.c | 183 | ||||
| -rw-r--r-- | miscutils/crontab.c | 29 |
2 files changed, 204 insertions, 8 deletions
diff --git a/miscutils/crond.c b/miscutils/crond.c index 6a384fdfb..bbb312882 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | //config:config CROND | 11 | //config:config CROND |
| 12 | //config: bool "crond (15 kb)" | 12 | //config: bool "crond (15 kb)" |
| 13 | //config: default y | 13 | //config: default y |
| 14 | //config: select FEATURE_SYSLOG | 14 | //config: depends on FEATURE_SYSLOG || PLATFORM_MINGW32 |
| 15 | //config: help | 15 | //config: help |
| 16 | //config: Crond is a background daemon that parses individual crontab | 16 | //config: Crond is a background daemon that parses individual crontab |
| 17 | //config: files and executes commands on behalf of the users in question. | 17 | //config: files and executes commands on behalf of the users in question. |
| @@ -77,7 +77,12 @@ | |||
| 77 | 77 | ||
| 78 | #include "libbb.h" | 78 | #include "libbb.h" |
| 79 | #include "common_bufsiz.h" | 79 | #include "common_bufsiz.h" |
| 80 | #if ENABLE_PLATFORM_MINGW32 | ||
| 81 | #include <unistd.h> | ||
| 82 | #include "BB_VER.h" | ||
| 83 | #else | ||
| 80 | #include <syslog.h> | 84 | #include <syslog.h> |
| 85 | #endif | ||
| 81 | 86 | ||
| 82 | #if 0 | 87 | #if 0 |
| 83 | /* If libc tracks and reuses setenv()-allocated memory, ok to set this to 0 */ | 88 | /* If libc tracks and reuses setenv()-allocated memory, ok to set this to 0 */ |
| @@ -123,6 +128,9 @@ typedef struct CronLine { | |||
| 123 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL | 128 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL |
| 124 | int cl_empty_mail_size; /* size of mail header only, 0 if no mailfile */ | 129 | int cl_empty_mail_size; /* size of mail header only, 0 if no mailfile */ |
| 125 | char *cl_mailto; /* whom to mail results, may be NULL */ | 130 | char *cl_mailto; /* whom to mail results, may be NULL */ |
| 131 | #if ENABLE_PLATFORM_MINGW32 | ||
| 132 | int randomint; /* appended to the file rather than the child's pid */ | ||
| 133 | #endif | ||
| 126 | #endif | 134 | #endif |
| 127 | char *cl_shell; | 135 | char *cl_shell; |
| 128 | char *cl_path; | 136 | char *cl_path; |
| @@ -153,6 +161,9 @@ struct globals { | |||
| 153 | time_t crontab_dir_mtime; | 161 | time_t crontab_dir_mtime; |
| 154 | const char *log_filename; | 162 | const char *log_filename; |
| 155 | const char *crontab_dir_name; /* = CRONTABS; */ | 163 | const char *crontab_dir_name; /* = CRONTABS; */ |
| 164 | #if ENABLE_PLATFORM_MINGW32 | ||
| 165 | const char *crondir_name; /* = CRON_DIR; */ | ||
| 166 | #endif | ||
| 156 | CronFile *cron_files; | 167 | CronFile *cron_files; |
| 157 | char *default_shell; | 168 | char *default_shell; |
| 158 | #if SETENV_LEAKS | 169 | #if SETENV_LEAKS |
| @@ -163,6 +174,8 @@ struct globals { | |||
| 163 | #endif | 174 | #endif |
| 164 | } FIX_ALIASING; | 175 | } FIX_ALIASING; |
| 165 | #define G (*(struct globals*)bb_common_bufsiz1) | 176 | #define G (*(struct globals*)bb_common_bufsiz1) |
| 177 | |||
| 178 | /* crondir_name and crontab_dir_name are initialised outside this in mingw */ | ||
| 166 | #define INIT_G() do { \ | 179 | #define INIT_G() do { \ |
| 167 | setup_common_bufsiz(); \ | 180 | setup_common_bufsiz(); \ |
| 168 | G.log_level = 8; \ | 181 | G.log_level = 8; \ |
| @@ -424,20 +437,39 @@ static void load_crontab(const char *fileName) | |||
| 424 | char *shell = NULL; | 437 | char *shell = NULL; |
| 425 | char *path = NULL; | 438 | char *path = NULL; |
| 426 | 439 | ||
| 440 | #if ENABLE_PLATFORM_MINGW32 | ||
| 441 | struct passwd *p; | ||
| 442 | #endif | ||
| 443 | |||
| 427 | delete_cronfile(fileName); | 444 | delete_cronfile(fileName); |
| 428 | 445 | ||
| 429 | if (!getpwnam(fileName)) { | 446 | if (!( |
| 447 | #if ENABLE_PLATFORM_MINGW32 | ||
| 448 | p = | ||
| 449 | #endif | ||
| 450 | getpwnam(fileName))) { | ||
| 430 | log7("ignoring file '%s' (no such user)", fileName); | 451 | log7("ignoring file '%s' (no such user)", fileName); |
| 431 | return; | 452 | return; |
| 432 | } | 453 | } |
| 433 | 454 | ||
| 455 | #if ENABLE_PLATFORM_MINGW32 | ||
| 456 | if (p->pw_uid != getuid()) { | ||
| 457 | log7("ignoring file '%s' (not current user)", fileName); | ||
| 458 | return; | ||
| 459 | } | ||
| 460 | #endif | ||
| 461 | |||
| 434 | parser = config_open(fileName); | 462 | parser = config_open(fileName); |
| 435 | if (!parser) | 463 | if (!parser) |
| 436 | return; | 464 | return; |
| 437 | 465 | ||
| 438 | maxLines = (strcmp(fileName, "root") == 0) ? 65535 : MAXLINES; | 466 | maxLines = (strcmp(fileName, "root") == 0) ? 65535 : MAXLINES; |
| 439 | 467 | ||
| 440 | if (fstat(fileno(parser->fp), &sbuf) == 0 && sbuf.st_uid == DAEMON_UID) { | 468 | if (fstat(fileno(parser->fp), &sbuf) == 0 |
| 469 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 470 | && sbuf.st_uid == DAEMON_UID | ||
| 471 | #endif | ||
| 472 | ) { | ||
| 441 | CronFile *file = xzalloc(sizeof(CronFile)); | 473 | CronFile *file = xzalloc(sizeof(CronFile)); |
| 442 | CronLine **pline; | 474 | CronLine **pline; |
| 443 | int n; | 475 | int n; |
| @@ -680,6 +712,7 @@ static void set_env_vars(struct passwd *pas, const char *shell, const char *path | |||
| 680 | #endif | 712 | #endif |
| 681 | } | 713 | } |
| 682 | 714 | ||
| 715 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 683 | static void change_user(struct passwd *pas) | 716 | static void change_user(struct passwd *pas) |
| 684 | { | 717 | { |
| 685 | /* careful: we're after vfork! */ | 718 | /* careful: we're after vfork! */ |
| @@ -688,6 +721,7 @@ static void change_user(struct passwd *pas) | |||
| 688 | xchdir(CRON_DIR); | 721 | xchdir(CRON_DIR); |
| 689 | } | 722 | } |
| 690 | } | 723 | } |
| 724 | #endif | ||
| 691 | 725 | ||
| 692 | // TODO: sendmail should be _run-time_ option, not compile-time! | 726 | // TODO: sendmail should be _run-time_ option, not compile-time! |
| 693 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL | 727 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL |
| @@ -697,8 +731,16 @@ fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail) | |||
| 697 | { | 731 | { |
| 698 | struct passwd *pas; | 732 | struct passwd *pas; |
| 699 | const char *shell, *prog; | 733 | const char *shell, *prog; |
| 734 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 700 | smallint sv_logmode; | 735 | smallint sv_logmode; |
| 736 | #endif | ||
| 701 | pid_t pid; | 737 | pid_t pid; |
| 738 | #if ENABLE_PLATFORM_MINGW32 | ||
| 739 | char *args[4]; | ||
| 740 | char *cl_cmd_quoted; | ||
| 741 | char *shell_arg; | ||
| 742 | int fdpipe; | ||
| 743 | #endif | ||
| 702 | 744 | ||
| 703 | /* prepare things before vfork */ | 745 | /* prepare things before vfork */ |
| 704 | pas = getpwnam(user); | 746 | pas = getpwnam(user); |
| @@ -712,6 +754,37 @@ fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail) | |||
| 712 | 754 | ||
| 713 | set_env_vars(pas, shell, NULL); /* don't use crontab's PATH for sendmail */ | 755 | set_env_vars(pas, shell, NULL); /* don't use crontab's PATH for sendmail */ |
| 714 | 756 | ||
| 757 | #if ENABLE_PLATFORM_MINGW32 | ||
| 758 | args[0] = (char *)prog; | ||
| 759 | if (run_sendmail) { | ||
| 760 | /* mailFd >= 0 */ | ||
| 761 | /* Using the fd as input doesn't appear to work with external programs */ | ||
| 762 | shell_arg = (char *)"sh -c \""SENDMAIL" "SENDMAIL_ARGS"\""; | ||
| 763 | if ((fdpipe = mingw_popen_fd("sh", shell_arg, "w", -1, &pid)) == -1) | ||
| 764 | bb_perror_msg("can't execute '%s'", "sh"); | ||
| 765 | |||
| 766 | bb_copyfd_eof(mailFd, fdpipe); | ||
| 767 | close(fdpipe); | ||
| 768 | } else if (mailFd >= 0) { | ||
| 769 | /* run and pipe stdout and stderr */ | ||
| 770 | cl_cmd_quoted = quote_arg(line->cl_cmd); | ||
| 771 | shell_arg = xasprintf("sh -c %s", cl_cmd_quoted); | ||
| 772 | |||
| 773 | if ((fdpipe = mingw_popen_fd("sh", shell_arg, "W", mailFd, &pid)) == -1) | ||
| 774 | bb_perror_msg("can't execute '%s'", "sh"); | ||
| 775 | |||
| 776 | close(fdpipe); | ||
| 777 | free(shell_arg); | ||
| 778 | free(cl_cmd_quoted); | ||
| 779 | } else { | ||
| 780 | /* no redirection = we can just spawn it */ | ||
| 781 | args[1] = (char *)"-c"; | ||
| 782 | args[2] = line->cl_cmd; | ||
| 783 | args[3] = NULL; | ||
| 784 | pid = !(option_mask32 & OPT_f) ? | ||
| 785 | mingw_spawn_detach(args) : mingw_spawn(args); | ||
| 786 | } | ||
| 787 | #else | ||
| 715 | sv_logmode = logmode; | 788 | sv_logmode = logmode; |
| 716 | pid = vfork(); | 789 | pid = vfork(); |
| 717 | if (pid == 0) { | 790 | if (pid == 0) { |
| @@ -737,6 +810,7 @@ fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail) | |||
| 737 | bb_error_msg_and_die("can't execute '%s' for user %s", prog, user); | 810 | bb_error_msg_and_die("can't execute '%s' for user %s", prog, user); |
| 738 | } | 811 | } |
| 739 | logmode = sv_logmode; | 812 | logmode = sv_logmode; |
| 813 | #endif | ||
| 740 | 814 | ||
| 741 | if (pid < 0) { | 815 | if (pid < 0) { |
| 742 | bb_simple_perror_msg("vfork"); | 816 | bb_simple_perror_msg("vfork"); |
| @@ -758,13 +832,20 @@ static pid_t start_one_job(const char *user, CronLine *line) | |||
| 758 | { | 832 | { |
| 759 | char mailFile[128]; | 833 | char mailFile[128]; |
| 760 | int mailFd = -1; | 834 | int mailFd = -1; |
| 761 | 835 | #if ENABLE_PLATFORM_MINGW32 | |
| 836 | line->randomint = 0; | ||
| 837 | #endif | ||
| 762 | line->cl_pid = 0; | 838 | line->cl_pid = 0; |
| 763 | line->cl_empty_mail_size = 0; | 839 | line->cl_empty_mail_size = 0; |
| 764 | 840 | ||
| 765 | if (line->cl_mailto) { | 841 | if (line->cl_mailto) { |
| 766 | /* Open mail file (owner is root so nobody can screw with it) */ | 842 | /* Open mail file (owner is root so nobody can screw with it) */ |
| 843 | #if ENABLE_PLATFORM_MINGW32 | ||
| 844 | MINGW_SPECIAL(open_read_close)("/dev/urandom", (char *)(&line->randomint), sizeof(int)); | ||
| 845 | snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d.%u", G.crondir_name, user, getpid(), line->randomint); | ||
| 846 | #else | ||
| 767 | snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", CRON_DIR, user, getpid()); | 847 | snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", CRON_DIR, user, getpid()); |
| 848 | #endif | ||
| 768 | mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600); | 849 | mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600); |
| 769 | 850 | ||
| 770 | if (mailFd >= 0) { | 851 | if (mailFd >= 0) { |
| @@ -782,10 +863,13 @@ static pid_t start_one_job(const char *user, CronLine *line) | |||
| 782 | if (line->cl_pid <= 0) { | 863 | if (line->cl_pid <= 0) { |
| 783 | unlink(mailFile); | 864 | unlink(mailFile); |
| 784 | } else { | 865 | } else { |
| 866 | /* on Windows open files can't be renamed */ | ||
| 867 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 785 | /* rename mail-file based on pid of process */ | 868 | /* rename mail-file based on pid of process */ |
| 786 | char *mailFile2 = xasprintf("%s/cron.%s.%d", CRON_DIR, user, (int)line->cl_pid); | 869 | char *mailFile2 = xasprintf("%s/cron.%s.%d", CRON_DIR, user, (int)line->cl_pid); |
| 787 | rename(mailFile, mailFile2); // TODO: xrename? | 870 | rename(mailFile, mailFile2); // TODO: xrename? |
| 788 | free(mailFile2); | 871 | free(mailFile2); |
| 872 | #endif | ||
| 789 | } | 873 | } |
| 790 | } | 874 | } |
| 791 | 875 | ||
| @@ -817,25 +901,45 @@ static void process_finished_job(const char *user, CronLine *line) | |||
| 817 | * End of primary job - check for mail file. | 901 | * End of primary job - check for mail file. |
| 818 | * If size has changed and the file is still valid, we send it. | 902 | * If size has changed and the file is still valid, we send it. |
| 819 | */ | 903 | */ |
| 904 | #if ENABLE_PLATFORM_MINGW32 | ||
| 905 | /* on Windows, the files are all just named with the pid of the parent and a random id */ | ||
| 906 | snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d.%u", G.crondir_name, user, getpid(), line->randomint); | ||
| 907 | #else | ||
| 820 | snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", CRON_DIR, user, (int)pid); | 908 | snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", CRON_DIR, user, (int)pid); |
| 821 | mailFd = open(mailFile, O_RDONLY); | 909 | #endif |
| 910 | mailFd = open(mailFile, O_RDONLY | ||
| 911 | #if ENABLE_PLATFORM_MINGW32 | ||
| 912 | | O_BINARY | _O_NOINHERIT | ||
| 913 | #endif | ||
| 914 | ); | ||
| 915 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 822 | unlink(mailFile); | 916 | unlink(mailFile); |
| 917 | #endif | ||
| 823 | if (mailFd < 0) { | 918 | if (mailFd < 0) { |
| 824 | return; | 919 | return; |
| 825 | } | 920 | } |
| 826 | 921 | ||
| 827 | if (fstat(mailFd, &sbuf) < 0 | 922 | if (fstat(mailFd, &sbuf) < 0 |
| 923 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 828 | || sbuf.st_uid != DAEMON_UID | 924 | || sbuf.st_uid != DAEMON_UID |
| 829 | || sbuf.st_nlink != 0 | 925 | || sbuf.st_nlink != 0 |
| 926 | #endif | ||
| 830 | || sbuf.st_size == line->cl_empty_mail_size | 927 | || sbuf.st_size == line->cl_empty_mail_size |
| 831 | || !S_ISREG(sbuf.st_mode) | 928 | || !S_ISREG(sbuf.st_mode) |
| 832 | ) { | 929 | ) { |
| 833 | close(mailFd); | 930 | close(mailFd); |
| 931 | #if ENABLE_PLATFORM_MINGW32 | ||
| 932 | unlink(mailFile); | ||
| 933 | #endif | ||
| 834 | return; | 934 | return; |
| 835 | } | 935 | } |
| 836 | line->cl_empty_mail_size = 0; | 936 | line->cl_empty_mail_size = 0; |
| 837 | /* if (line->cl_mailto) - always true if cl_empty_mail_size was nonzero */ | 937 | /* if (line->cl_mailto) - always true if cl_empty_mail_size was nonzero */ |
| 838 | line->cl_pid = fork_job(user, mailFd, line, /*sendmail?*/ 1); | 938 | line->cl_pid = fork_job(user, mailFd, line, /*sendmail?*/ 1); |
| 939 | #if ENABLE_PLATFORM_MINGW32 | ||
| 940 | /* delay until here, when we have the mailFd closed again */ | ||
| 941 | unlink(mailFile); | ||
| 942 | #endif | ||
| 839 | } | 943 | } |
| 840 | 944 | ||
| 841 | #else /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */ | 945 | #else /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */ |
| @@ -845,6 +949,9 @@ static pid_t start_one_job(const char *user, CronLine *line) | |||
| 845 | const char *shell; | 949 | const char *shell; |
| 846 | struct passwd *pas; | 950 | struct passwd *pas; |
| 847 | pid_t pid; | 951 | pid_t pid; |
| 952 | #if ENABLE_PLATFORM_MINGW32 | ||
| 953 | char *args[4]; | ||
| 954 | #endif | ||
| 848 | 955 | ||
| 849 | pas = getpwnam(user); | 956 | pas = getpwnam(user); |
| 850 | if (!pas) { | 957 | if (!pas) { |
| @@ -856,6 +963,16 @@ static pid_t start_one_job(const char *user, CronLine *line) | |||
| 856 | shell = line->cl_shell ? line->cl_shell : G.default_shell; | 963 | shell = line->cl_shell ? line->cl_shell : G.default_shell; |
| 857 | set_env_vars(pas, shell, line->cl_path); | 964 | set_env_vars(pas, shell, line->cl_path); |
| 858 | 965 | ||
| 966 | #if ENABLE_PLATFORM_MINGW32 | ||
| 967 | args[0] = (char *)shell; | ||
| 968 | args[1] = (char *)"-c"; | ||
| 969 | args[2] = line->cl_cmd; | ||
| 970 | args[3] = NULL; | ||
| 971 | pid = !(option_mask32 & OPT_f) ? | ||
| 972 | mingw_spawn_detach(args) : mingw_spawn(args); | ||
| 973 | if (pid < 0) | ||
| 974 | bb_error_msg("can't execute '%s' for user %s", shell, user); | ||
| 975 | #else | ||
| 859 | /* Fork as the user in question and run program */ | 976 | /* Fork as the user in question and run program */ |
| 860 | pid = vfork(); | 977 | pid = vfork(); |
| 861 | if (pid == 0) { | 978 | if (pid == 0) { |
| @@ -868,6 +985,7 @@ static pid_t start_one_job(const char *user, CronLine *line) | |||
| 868 | execl(shell, shell, "-c", line->cl_cmd, (char *) NULL); | 985 | execl(shell, shell, "-c", line->cl_cmd, (char *) NULL); |
| 869 | bb_error_msg_and_die("can't execute '%s' for user %s", shell, user); | 986 | bb_error_msg_and_die("can't execute '%s' for user %s", shell, user); |
| 870 | } | 987 | } |
| 988 | #endif | ||
| 871 | if (pid < 0) { | 989 | if (pid < 0) { |
| 872 | bb_simple_perror_msg("vfork"); | 990 | bb_simple_perror_msg("vfork"); |
| 873 | err: | 991 | err: |
| @@ -956,8 +1074,14 @@ static void start_jobs(int wants_start) | |||
| 956 | continue; | 1074 | continue; |
| 957 | 1075 | ||
| 958 | pid = start_one_job(file->cf_username, line); | 1076 | pid = start_one_job(file->cf_username, line); |
| 959 | log8("USER %s pid %3d cmd %s", | 1077 | #if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_CROND_CALL_SENDMAIL |
| 960 | file->cf_username, (int)pid, line->cl_cmd); | 1078 | if (line->cl_mailto) |
| 1079 | log8("USER %s pid %3d tail %u cmd %s", | ||
| 1080 | file->cf_username, (int)pid, line->randomint, line->cl_cmd); | ||
| 1081 | else | ||
| 1082 | #endif | ||
| 1083 | log8("USER %s pid %3d cmd %s", | ||
| 1084 | file->cf_username, (int)pid, line->cl_cmd); | ||
| 961 | if (pid < 0) { | 1085 | if (pid < 0) { |
| 962 | file->cf_wants_starting = 1; | 1086 | file->cf_wants_starting = 1; |
| 963 | } | 1087 | } |
| @@ -1025,6 +1149,29 @@ static void reopen_logfile_to_stderr(void) | |||
| 1025 | } | 1149 | } |
| 1026 | } | 1150 | } |
| 1027 | 1151 | ||
| 1152 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1153 | /* see similar function in networking/httpd.c */ | ||
| 1154 | static void mingw_daemonize(char **argv) | ||
| 1155 | { | ||
| 1156 | char **new_argv; | ||
| 1157 | int fd; | ||
| 1158 | |||
| 1159 | new_argv = grow_argv(argv + 1, 3); | ||
| 1160 | new_argv[0] = (char *)bb_busybox_exec_path; | ||
| 1161 | new_argv[1] = (char *)"--busybox"; | ||
| 1162 | // don't daemonise in main(), we explicitly detach below | ||
| 1163 | new_argv[2] = (char *)"-crond"; | ||
| 1164 | |||
| 1165 | fd = xopen(bb_dev_null, O_RDWR); | ||
| 1166 | xdup2(fd, 0); | ||
| 1167 | xdup2(fd, 1); | ||
| 1168 | xdup2(fd, 2); | ||
| 1169 | close(fd); | ||
| 1170 | |||
| 1171 | exit(mingw_spawn_detach(new_argv) == -1 ? EXIT_FAILURE : EXIT_SUCCESS); | ||
| 1172 | } | ||
| 1173 | #endif | ||
| 1174 | |||
| 1028 | int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1175 | int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 1029 | int crond_main(int argc UNUSED_PARAM, char **argv) | 1176 | int crond_main(int argc UNUSED_PARAM, char **argv) |
| 1030 | { | 1177 | { |
| @@ -1035,6 +1182,12 @@ int crond_main(int argc UNUSED_PARAM, char **argv) | |||
| 1035 | 1182 | ||
| 1036 | INIT_G(); | 1183 | INIT_G(); |
| 1037 | 1184 | ||
| 1185 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1186 | /* crontab dirname should be different */ | ||
| 1187 | G.crontab_dir_name = concat_path_file(get_system_drive(), CRONTABS); | ||
| 1188 | G.crondir_name = concat_path_file(get_system_drive(), CRON_DIR); | ||
| 1189 | #endif | ||
| 1190 | |||
| 1038 | opts = getopt32(argv, "^" | 1191 | opts = getopt32(argv, "^" |
| 1039 | "l:L:fbSc:" IF_FEATURE_CROND_D("d:") | 1192 | "l:L:fbSc:" IF_FEATURE_CROND_D("d:") |
| 1040 | "\0" | 1193 | "\0" |
| @@ -1048,17 +1201,30 @@ int crond_main(int argc UNUSED_PARAM, char **argv) | |||
| 1048 | ); | 1201 | ); |
| 1049 | /* both -d N and -l N set the same variable: G.log_level */ | 1202 | /* both -d N and -l N set the same variable: G.log_level */ |
| 1050 | 1203 | ||
| 1204 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1205 | if (!(opts & OPT_d) && G.log_filename == NULL) { | ||
| 1206 | bb_error_msg_and_die("syslog isn't supported on Windows"); | ||
| 1207 | } | ||
| 1208 | #endif | ||
| 1209 | |||
| 1051 | if (!(opts & OPT_f)) { | 1210 | if (!(opts & OPT_f)) { |
| 1052 | /* close stdin, stdout, stderr. | 1211 | /* close stdin, stdout, stderr. |
| 1053 | * close unused descriptors - don't need them. */ | 1212 | * close unused descriptors - don't need them. */ |
| 1213 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1214 | if (argv[0][0] != '-') | ||
| 1215 | mingw_daemonize(argv); | ||
| 1216 | #else | ||
| 1054 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); | 1217 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); |
| 1218 | #endif | ||
| 1055 | } | 1219 | } |
| 1056 | 1220 | ||
| 1221 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 1057 | if (!(opts & OPT_d) && G.log_filename == NULL) { | 1222 | if (!(opts & OPT_d) && G.log_filename == NULL) { |
| 1058 | /* logging to syslog */ | 1223 | /* logging to syslog */ |
| 1059 | openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON); | 1224 | openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON); |
| 1060 | logmode = LOGMODE_SYSLOG; | 1225 | logmode = LOGMODE_SYSLOG; |
| 1061 | } | 1226 | } |
| 1227 | #endif | ||
| 1062 | 1228 | ||
| 1063 | //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */ | 1229 | //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */ |
| 1064 | 1230 | ||
| @@ -1069,6 +1235,9 @@ int crond_main(int argc UNUSED_PARAM, char **argv) | |||
| 1069 | G.default_shell = xstrdup(get_shell_name()); | 1235 | G.default_shell = xstrdup(get_shell_name()); |
| 1070 | 1236 | ||
| 1071 | log8("crond (busybox "BB_VER") started, log level %d", G.log_level); | 1237 | log8("crond (busybox "BB_VER") started, log level %d", G.log_level); |
| 1238 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1239 | log5("crond pid %3d", getpid()); | ||
| 1240 | #endif | ||
| 1072 | rescan_crontab_dir(); | 1241 | rescan_crontab_dir(); |
| 1073 | write_pidfile_std_path_and_ext("crond"); | 1242 | write_pidfile_std_path_and_ext("crond"); |
| 1074 | #if ENABLE_FEATURE_CROND_SPECIAL_TIMES | 1243 | #if ENABLE_FEATURE_CROND_SPECIAL_TIMES |
diff --git a/miscutils/crontab.c b/miscutils/crontab.c index 1111f4d54..e59b1e49b 100644 --- a/miscutils/crontab.c +++ b/miscutils/crontab.c | |||
| @@ -44,6 +44,10 @@ static void edit_file(const struct passwd *pas, const char *file) | |||
| 44 | { | 44 | { |
| 45 | const char *ptr; | 45 | const char *ptr; |
| 46 | pid_t pid; | 46 | pid_t pid; |
| 47 | #if ENABLE_PLATFORM_MINGW32 | ||
| 48 | char *args[3]; | ||
| 49 | (void) pas; | ||
| 50 | #else | ||
| 47 | 51 | ||
| 48 | pid = xvfork(); | 52 | pid = xvfork(); |
| 49 | if (pid) { /* parent */ | 53 | if (pid) { /* parent */ |
| @@ -57,6 +61,7 @@ static void edit_file(const struct passwd *pas, const char *file) | |||
| 57 | setup_environment(pas->pw_shell, | 61 | setup_environment(pas->pw_shell, |
| 58 | SETUP_ENV_CHANGEENV | SETUP_ENV_TO_TMP | SETUP_ENV_CHDIR, | 62 | SETUP_ENV_CHANGEENV | SETUP_ENV_TO_TMP | SETUP_ENV_CHDIR, |
| 59 | pas); | 63 | pas); |
| 64 | #endif | ||
| 60 | ptr = getenv("VISUAL"); | 65 | ptr = getenv("VISUAL"); |
| 61 | if (!ptr) { | 66 | if (!ptr) { |
| 62 | ptr = getenv("EDITOR"); | 67 | ptr = getenv("EDITOR"); |
| @@ -64,7 +69,18 @@ static void edit_file(const struct passwd *pas, const char *file) | |||
| 64 | ptr = "vi"; | 69 | ptr = "vi"; |
| 65 | } | 70 | } |
| 66 | 71 | ||
| 72 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 67 | BB_EXECLP(ptr, ptr, file, NULL); | 73 | BB_EXECLP(ptr, ptr, file, NULL); |
| 74 | #else | ||
| 75 | args[0] = (char *)ptr; | ||
| 76 | args[1] = (char *)file; | ||
| 77 | args[2] = NULL; | ||
| 78 | pid = mingw_spawn(args); | ||
| 79 | if (pid == -1) | ||
| 80 | bb_perror_msg_and_die("can't execute '%s'", ptr); | ||
| 81 | wait4pid(pid); | ||
| 82 | return; | ||
| 83 | #endif | ||
| 68 | bb_perror_msg_and_die("can't execute '%s'", ptr); | 84 | bb_perror_msg_and_die("can't execute '%s'", ptr); |
| 69 | } | 85 | } |
| 70 | 86 | ||
| @@ -99,16 +115,22 @@ int crontab_main(int argc UNUSED_PARAM, char **argv) | |||
| 99 | OPT_ler = OPT_l + OPT_e + OPT_r, | 115 | OPT_ler = OPT_l + OPT_e + OPT_r, |
| 100 | }; | 116 | }; |
| 101 | 117 | ||
| 118 | #if ENABLE_PLATFORM_MINGW32 | ||
| 119 | crontab_dir = concat_path_file(get_system_drive(), CRONTABS); | ||
| 120 | #endif | ||
| 121 | |||
| 102 | opt_ler = getopt32(argv, "^" "u:c:lerd" "\0" "?1:dr"/*max one arg; -d implies -r*/, | 122 | opt_ler = getopt32(argv, "^" "u:c:lerd" "\0" "?1:dr"/*max one arg; -d implies -r*/, |
| 103 | &user_name, &crontab_dir | 123 | &user_name, &crontab_dir |
| 104 | ); | 124 | ); |
| 105 | argv += optind; | 125 | argv += optind; |
| 106 | 126 | ||
| 127 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 107 | if (sanitize_env_if_suid()) { /* Clears dangerous stuff, sets PATH */ | 128 | if (sanitize_env_if_suid()) { /* Clears dangerous stuff, sets PATH */ |
| 108 | /* Run by non-root */ | 129 | /* Run by non-root */ |
| 109 | if (opt_ler & (OPT_u|OPT_c)) | 130 | if (opt_ler & (OPT_u|OPT_c)) |
| 110 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | 131 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); |
| 111 | } | 132 | } |
| 133 | #endif | ||
| 112 | 134 | ||
| 113 | if (opt_ler & OPT_u) { | 135 | if (opt_ler & OPT_u) { |
| 114 | pas = xgetpwnam(user_name); | 136 | pas = xgetpwnam(user_name); |
| @@ -184,8 +206,13 @@ int crontab_main(int argc UNUSED_PARAM, char **argv) | |||
| 184 | bb_error_msg("can't create %s/%s", | 206 | bb_error_msg("can't create %s/%s", |
| 185 | crontab_dir, new_fname); | 207 | crontab_dir, new_fname); |
| 186 | } | 208 | } |
| 187 | if (tmp_fname) | 209 | if (tmp_fname) { |
| 210 | #if ENABLE_PLATFORM_MINGW32 | ||
| 211 | /* can't delete open files on Windows */ | ||
| 212 | close(src_fd); | ||
| 213 | #endif | ||
| 188 | unlink(tmp_fname); | 214 | unlink(tmp_fname); |
| 215 | } | ||
| 189 | /*free(tmp_fname);*/ | 216 | /*free(tmp_fname);*/ |
| 190 | /*free(new_fname);*/ | 217 | /*free(new_fname);*/ |
| 191 | } /* switch */ | 218 | } /* switch */ |
