.RB [ -s ]
.br
.B crontab
-.BR -h\ [
+.BR -n\ [
.IR "hostname " ]
+.br
+.B crontab
+.BR -c
.SH DESCRIPTION
.I Crontab
is the program used to install, remove or list the tables
occurs - see the documentation of MLS_LEVEL in
.BR crontab(5)\.
.TP
-.B "\-h"
+.B "\-n"
This option is only relevant if
.BR cron (8)
was started with the \fB-c\fP option, to enable clustering support. It is
used to set which host in the cluster should run the jobs specified in the
crontab files in the directory
-.I /var/spool/cron
-or to display the current setting. If a hostname is supplied, then the host
-whose hostname, as returned by
-.BR gethostname(2)\,
-will be selected to run these cron jobs subseqently. If there is no host
-in the cluster matching that hostname, or you explicitly specify an empty
-hostname, then these jobs will not be run at all. As a special case,
-specifying "localhost" will select the host on which
-.BR crontab(1)
-is being run. Using this option has no effect on
+.I /var/spool/cron\.
+If a hostname is supplied, then the host whose hostname as returned by
+.BR gethostname(2)
+matches this will be selected to run these cron jobs subseqently. If there
+is no host in the cluster matching that hostname, or you explicitly specify
+an empty hostname, then these jobs will not be run at all. If the hostname
+is omitted, the name of the local host as returned by
+.BR gethostname(2)
+is assumed. Using this option has no effect on
.I /etc/crontab
and the files in the
.I /etc/cron.d
-directory, which are always run, and considered host-specific.
-If no hostname is supplied, the name of the currently-selected host is
-displayed. Only root may set the hostname, but any user permitted to run
-cron may display it. For more details about clustering support, see
+directory, which are always run, and considered host-specific. For more
+details about clustering support, see
.BR cron (8)\.
+.TP
+.B "\-c"
+This option is only relevant if
+.BR cron (8)
+was started with the \fB-c\fP option, to enable clustering support. It is
+used to query which host in the cluster is currently set to run the jobs
+specified in the crontab files in the directory
+.I /var/spool/cron
+, as set using the \fB-n\fP option.
.SH "SEE ALSO"
.BR crontab (5), cron (8)
.SH FILES
#define NHEADER_LINES 0
-enum opt_t {opt_unknown, opt_list, opt_delete, opt_edit, opt_replace, opt_host};
+enum opt_t {opt_unknown, opt_list, opt_delete, opt_edit, opt_replace, opt_hostset, opt_hostget};
#if DEBUGGING
-static char *Options[] = {"???", "list", "delete", "edit", "replace", "host"};
+static char *Options[] = {"???", "list", "delete", "edit", "replace", "hostset", "hostget"};
# ifdef WITH_SELINUX
-static char *getoptargs = "u:lerishx:";
+static char *getoptargs = "u:lerisncx:";
# else
-static char *getoptargs = "u:lerihx:";
+static char *getoptargs = "u:lerincx:";
# endif
#else
# ifdef WITH_SELINUX
-static char *getoptargs = "u:lerish";
+static char *getoptargs = "u:lerisnc";
# else
-static char *getoptargs = "u:lerih";
+static char *getoptargs = "u:lerinc";
# endif
#endif
static char *selinux_context = 0;
static FILE *NewCrontab;
static int CheckErrorCount;
static int PromptOnDelete;
-static int HostSet;
+static int HostSpecified;
static enum opt_t Option;
static struct passwd *pw;
static void list_cmd(void),
edit_cmd(void),
poke_daemon(void),
check_error(const char *), parse_args(int c, char *v[]), die(int);
-static int replace_cmd(void), host_cmd(void);
+static int replace_cmd(void), hostset_cmd(void), hostget_cmd(void);
static char *host_specific_filename(char *filename, int prefix);
static char *tmp_path(void);
fprintf(stderr, "%s: usage error: %s\n", ProgramName, msg);
fprintf(stderr, "usage:\t%s [-u user] file\n", ProgramName);
fprintf(stderr, "\t%s [-u user] [ -e | -l | -r ]\n", ProgramName);
- fprintf(stderr, "\t%s -h [ hostname ]\n", ProgramName);
+ fprintf(stderr, "\t%s -n [ hostname ]\n", ProgramName);
+ fprintf(stderr, "\t%s -c\n", ProgramName);
fprintf(stderr, "\t\t(default operation is replace, per 1003.2)\n");
fprintf(stderr, "\t-e\t(edit user's crontab)\n");
fprintf(stderr, "\t-l\t(list user's crontab)\n");
fprintf(stderr, "\t-r\t(delete user's crontab)\n");
fprintf(stderr, "\t-i\t(prompt before deleting user's crontab)\n");
- fprintf(stderr, "\t-h\t(get or set host in cluster to run users' crontabs)\n");
+ fprintf(stderr, "\t-n\t(set host in cluster to run users' crontabs)\n");
+ fprintf(stderr, "\t-c\t(get host in cluster to run users' crontabs)\n");
#ifdef WITH_SELINUX
fprintf(stderr, "\t-s\t(selinux context)\n");
#endif
if (replace_cmd() < 0)
exitstatus = ERROR_EXIT;
break;
- case opt_host:
- if (host_cmd() < 0)
+ case opt_hostset:
+ if (hostset_cmd() < 0)
+ exitstatus = ERROR_EXIT;
+ break;
+ case opt_hostget:
+ if (hostget_cmd() < 0)
exitstatus = ERROR_EXIT;
break;
default:
Filename[0] = '\0';
Option = opt_unknown;
PromptOnDelete = 0;
- HostSet = 0;
+ HostSpecified = 0;
while (-1 != (argch = getopt(argc, argv, getoptargs))) {
switch (argch) {
#if DEBUGGING
break;
#endif
case 'u':
- if (Option == opt_host) {
- fprintf(stderr,
- "cannot use -u with -h\n");
- exit(ERROR_EXIT);
- }
if (MY_UID(pw) != ROOT_UID) {
fprintf(stderr, "must be privileged to use -u\n");
exit(ERROR_EXIT);
exit(ERROR_EXIT);
}
+ if (Option == opt_hostset || Option == opt_hostget) {
+ fprintf(stderr,
+ "cannot use -u with -n or -c\n");
+ exit(ERROR_EXIT);
+ }
+
if (!(pw = getpwnam(optarg))) {
fprintf(stderr, "%s: user `%s' unknown\n",
ProgramName, optarg);
}
break;
#endif
- case 'h':
+ case 'n':
+ if (MY_UID(pw) != ROOT_UID) {
+ fprintf(stderr,
+ "must be privileged to set host with -n\n");
+ exit(ERROR_EXIT);
+ }
+ if (Option != opt_unknown)
+ usage("only one operation permitted");
+ if (strcmp(User, RealUser) != 0) {
+ fprintf(stderr,
+ "cannot use -u with -n or -c\n");
+ exit(ERROR_EXIT);
+ }
+ Option = opt_hostset;
+ break;
+ case 'c':
if (Option != opt_unknown)
usage("only one operation permitted");
if (strcmp(User, RealUser) != 0) {
fprintf(stderr,
- "cannot use -u with -h\n");
+ "cannot use -u with -n or -c\n");
exit(ERROR_EXIT);
}
- Option = opt_host;
+ Option = opt_hostget;
break;
default:
usage("unrecognized option");
endpwent();
- if (Option == opt_host && argv[optind] != NULL) {
- if (MY_UID(pw) != ROOT_UID) {
- fprintf(stderr,
- "must be privileged to set host with -h\n");
- exit(ERROR_EXIT);
- }
-
- HostSet = 1;
+ if (Option == opt_hostset && argv[optind] != NULL) {
+ HostSpecified = 1;
if (strlen(argv[optind]) >= sizeof Host)
usage("hostname too long");
(void) strcpy(Host, argv[optind]);
return (error);
}
-static int host_cmd(void) {
+static int hostset_cmd(void) {
char n[MAX_FNAME];
- FILE *f, *tmp;
+ FILE *tmp;
int fd;
int error = 0;
char *safename;
-
- if (!HostSet) {
-
- if (!glue_strings(n, sizeof n, SPOOL_DIR, CRON_HOSTNAME, '/')) {
- fprintf(stderr, "path too long\n");
- return (-2);
- }
-
- if (!(f = fopen(n, "r"))) {
- if (errno == ENOENT)
- fprintf(stderr, "File %s not found\n", n);
- else
- perror(n);
- return (-2);
- }
-
- if (get_string(Host, sizeof Host, f, "\n") == EOF) {
- fprintf(stderr, "Error reading from %s\n", n);
- fclose(f);
- return (-2);
- }
-
- fclose(f);
-
- printf("%s\n", Host);
- fflush(stdout);
-
- log_it(RealUser, Pid, "GET HOST", Host, 0);
- return (0);
- }
-
- if (strcmp(Host, "localhost") == 0) {
+
+ if (!HostSpecified)
gethostname(Host, sizeof Host);
- }
-
+
safename = host_specific_filename("tmp.XXXXXXXXXX", 1);
if (!safename || !glue_strings(TempFilename, sizeof TempFilename, SPOOL_DIR,
- safename, '/')) {
+ safename, '/')) {
TempFilename[0] = '\0';
fprintf(stderr, "path too long\n");
return (-2);
poke_daemon();
-done:
+ done:
(void) signal(SIGHUP, SIG_DFL);
(void) signal(SIGINT, SIG_DFL);
(void) signal(SIGQUIT, SIG_DFL);
return (error);
}
+static int hostget_cmd(void) {
+ char n[MAX_FNAME];
+ FILE *f;
+
+ if (!glue_strings(n, sizeof n, SPOOL_DIR, CRON_HOSTNAME, '/')) {
+ fprintf(stderr, "path too long\n");
+ return (-2);
+ }
+
+ if (!(f = fopen(n, "r"))) {
+ if (errno == ENOENT)
+ fprintf(stderr, "File %s not found\n", n);
+ else
+ perror(n);
+ return (-2);
+ }
+
+ if (get_string(Host, sizeof Host, f, "\n") == EOF) {
+ fprintf(stderr, "Error reading from %s\n", n);
+ fclose(f);
+ return (-2);
+ }
+
+ fclose(f);
+
+ printf("%s\n", Host);
+ fflush(stdout);
+
+ log_it(RealUser, Pid, "GET HOST", Host, 0);
+ return (0);
+}
+
static void poke_daemon(void) {
if (utime(SPOOL_DIR, NULL) < OK) {
fprintf(stderr, "crontab: can't update mtime on spooldir\n");