summaryrefslogtreecommitdiffstats
path: root/source3
diff options
context:
space:
mode:
authorMatthew Chapman <matty@samba.org>1999-04-23 15:01:35 +0000
committerMatthew Chapman <matty@samba.org>1999-04-23 15:01:35 +0000
commit16758a425265afaf6d4ba2636fdafbdb5b26b708 (patch)
treeedffd5716e09ab8eb157b6e6970ff5621bbed5c3 /source3
parent2bc0641b88bb770812fbfbcfa8cf63b60eb49e45 (diff)
downloadsamba-16758a425265afaf6d4ba2636fdafbdb5b26b708.tar.gz
samba-16758a425265afaf6d4ba2636fdafbdb5b26b708.tar.xz
samba-16758a425265afaf6d4ba2636fdafbdb5b26b708.zip
New rpcclient command "at" for NT scheduler control, a slightly improved
version of the NT command. at { time [/INTERACTIVE] [{/EVERY|/NEXT}:5,Sun,...] command | [/DEL] [jobid] } Examples (options used in abbreviated form): at ; Shows all jobs at 1 ; Detail on job 1 at /D ; Deletes all jobs at /D 1 ; Deletes job 1 at 11:11:11AM /I /N:1 d:\humour\silly.exe ; First of next month at 9:00AM /E:M,T,W,Th,F net send MATTY Hi ; Each weekday at 11:00PM /E c:\winnt\backup.exe ; Every day (This used to be commit cf8c476d2eec24c150877b6bb8af7f7875cc1840)
Diffstat (limited to 'source3')
-rw-r--r--source3/rpcclient/cmd_atsvc.c327
-rw-r--r--source3/rpcclient/display.c166
-rw-r--r--source3/rpcclient/rpcclient.c1
3 files changed, 494 insertions, 0 deletions
diff --git a/source3/rpcclient/cmd_atsvc.c b/source3/rpcclient/cmd_atsvc.c
new file mode 100644
index 00000000000..a7b771e48e4
--- /dev/null
+++ b/source3/rpcclient/cmd_atsvc.c
@@ -0,0 +1,327 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.1.
+ MSRPC client: scheduler service
+ Copyright (C) Matthew Chapman 1999
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1999
+ Copyright (C) Andrew Tridgell 1994-1999
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+#define DEBUG_TESTING
+
+extern struct cli_state *smb_cli;
+extern FILE* out_hnd;
+
+
+/****************************************************************************
+checks for a /OPTION:param style option
+****************************************************************************/
+static BOOL checkopt(char *input, char *optname, char **params)
+{
+ char *inend;
+ int i, len;
+
+ if (*input++ != '/')
+ return False;
+
+ for (inend = input; *inend != 0 && *inend != ':'; inend++);
+
+ if (params != NULL)
+ {
+ *inend = 0;
+ *params = inend;
+ }
+
+ while(input < inend)
+ {
+ if (toupper(*input++) != *optname++)
+ return False;
+ }
+
+ return True;
+}
+
+char *daynames[] = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
+char *daynames_short[] = {"M", "T", "W", "Th", "F", "S", "Su"};
+
+/****************************************************************************
+parses a list of days of the week and month
+****************************************************************************/
+static BOOL at_parse_days(char *str, uint32 *monthdays, uint8 *weekdays)
+{
+ char *tok;
+ char *nexttok = str;
+ int day;
+
+ do {
+ tok = nexttok;
+
+ if ((nexttok = strchr(tok, ',')) != NULL)
+ {
+ *nexttok++ = 0;
+ }
+
+ if (isdigit(*tok))
+ {
+ day = strtol(tok, NULL, 10);
+ if (day == 0 || day > 31)
+ {
+ printf("\tInvalid day of month.\n\n");
+ return False;
+ }
+
+ *monthdays |= (1 << (day-1));
+ }
+ else
+ {
+ if (strlen(tok) < 3)
+ {
+ for (day = 0; day < 7; day++)
+ {
+ if (!strcasecmp(tok, daynames_short[day]))
+ break;
+ }
+ }
+ else
+ {
+ for (day = 0; day < 7; day++)
+ {
+ if (!strncasecmp(tok, daynames[day], 3))
+ break;
+ }
+ }
+
+ if (day < 7)
+ {
+ *weekdays |= (1 << day);
+ }
+ else
+ {
+ printf("\tInvalid day of week\n\n");
+ return False;
+ }
+ }
+
+ } while (nexttok != NULL);
+
+ return True;
+}
+
+
+/****************************************************************************
+scheduler add job
+****************************************************************************/
+void cmd_at(struct client_info *info)
+{
+ uint16 nt_pipe_fnum;
+ fstring temp;
+ fstring dest_wks;
+ BOOL add = False;
+ BOOL del = False;
+ char *p;
+
+ uint32 jobid = -1;
+ unsigned int hours, minutes, seconds = 0;
+ uint32 monthdays = 0;
+ uint8 weekdays = 0;
+ uint8 flags = JOB_NONINTERACTIVE;
+ fstring command;
+
+ while (next_token(NULL, temp, NULL, sizeof(temp)))
+ {
+ if (checkopt(temp, "DELETE", NULL))
+ {
+ del = True;
+ continue;
+ }
+ else if (checkopt(temp, "YES", NULL))
+ {
+ /* Compatibility */
+ continue;
+ }
+
+ jobid = strtol(temp, &p, 10);
+ if (*p == 0) /* Entirely numeric field */
+ continue;
+
+ if ((p == temp) || (sscanf(temp, "%d:%d:%d",
+ &hours, &minutes, &seconds) < 2))
+ {
+ printf("at { time [/INTERACTIVE] [{/EVERY|/NEXT}:5,Sun,...] command | [/DEL] [jobid] }\n\n");
+ return;
+ }
+
+ p = strchr(temp, 0);
+
+ if (!strcasecmp(p-2, "AM"))
+ {
+ hours = (hours == 12) ? 0 : hours;
+ }
+
+ if (!strcasecmp(p-2, "PM"))
+ {
+ hours = (hours == 12) ? 12 : hours + 12;
+ }
+
+ if (hours > 23 || minutes > 59 || seconds > 59)
+ {
+ printf("\tInvalid time.\n\n");
+ return;
+ }
+
+ add = True;
+ command[0] = 0;
+ p = NULL;
+
+ if (!next_token(NULL, temp, NULL, sizeof(temp)))
+ break;
+
+ if (checkopt(temp, "INTERACTIVE", NULL))
+ {
+ flags &= ~JOB_NONINTERACTIVE;
+
+ if (!next_token(NULL, temp, NULL, sizeof(temp)))
+ break;
+ }
+
+ if (checkopt(temp, "EVERY", &p))
+ {
+ flags |= JOB_PERIODIC;
+ }
+ else
+ {
+ checkopt(temp, "NEXT", &p);
+ }
+
+ if (p != NULL)
+ {
+ if (*p == ':')
+ {
+ if (!at_parse_days(p, &monthdays, &weekdays))
+ return;
+ }
+ else
+ {
+ weekdays = 0x7F;
+ }
+
+ if (!next_token(NULL, temp, NULL, sizeof(temp)))
+ break;
+ }
+
+ while (True)
+ {
+ fstrcat(command, temp);
+
+ if (!next_token(NULL, temp, NULL, sizeof(temp)))
+ break;
+
+ fstrcat(command, " ");
+ }
+
+ break;
+ }
+
+ if (add && !command[0])
+ {
+ printf("\tNo command specified.\n\n");
+ return;
+ }
+
+ fstrcpy(dest_wks, "\\\\");
+ fstrcat(dest_wks, info->dest_host);
+ strupper(dest_wks);
+
+ /* open scheduler session. */
+ if (!cli_nt_session_open(smb_cli, PIPE_ATSVC, &nt_pipe_fnum))
+ return;
+
+ if (add) /* add job */
+ {
+ AT_JOB_INFO job;
+
+ job.time = ((((hours * 60) + minutes) * 60) + seconds) * 1000;
+ job.monthdays = monthdays;
+ job.weekdays = weekdays;
+ job.flags = flags;
+ job.ptr_command = 1;
+
+ display_at_job_info(out_hnd, ACTION_HEADER , &job, command);
+ display_at_job_info(out_hnd, ACTION_ENUMERATE, &job, command);
+ display_at_job_info(out_hnd, ACTION_FOOTER , &job, command);
+
+ if (at_add_job(smb_cli, nt_pipe_fnum, dest_wks, &job,
+ command, &jobid))
+ {
+ fprintf(out_hnd, "\tJob ID: %d\n\n", jobid);
+ }
+ }
+ else if (del) /* delete */
+ {
+ if (jobid == -1)
+ {
+ fprintf(out_hnd, "\tDeleting all jobs.\n\n");
+ at_del_job(smb_cli, nt_pipe_fnum, dest_wks,
+ 0, 0xffffffff);
+ }
+ else
+ {
+ fprintf(out_hnd, "\tDeleting job %d.\n\n", jobid);
+ at_del_job(smb_cli, nt_pipe_fnum, dest_wks,
+ jobid, jobid);
+ }
+
+ }
+ else if (jobid == -1) /* enumerate */
+ {
+ AT_ENUM_INFO jobs[AT_MAX_JOBS];
+ fstring commands[AT_MAX_JOBS];
+ uint32 num_jobs;
+
+ if (at_enum_jobs(smb_cli, nt_pipe_fnum, dest_wks, &num_jobs,
+ jobs, commands))
+ {
+ display_at_enum_info(out_hnd, ACTION_HEADER , num_jobs, jobs, commands);
+ display_at_enum_info(out_hnd, ACTION_ENUMERATE, num_jobs, jobs, commands);
+ display_at_enum_info(out_hnd, ACTION_FOOTER , num_jobs, jobs, commands);
+ }
+ }
+ else /* job info */
+ {
+ AT_JOB_INFO job;
+
+ if (at_query_job(smb_cli, nt_pipe_fnum, dest_wks, jobid, &job, command))
+ {
+ display_at_job_info(out_hnd, ACTION_HEADER , &job, command);
+ display_at_job_info(out_hnd, ACTION_ENUMERATE, &job, command);
+ display_at_job_info(out_hnd, ACTION_FOOTER , &job, command);
+ }
+ }
+
+ /* close the session */
+ cli_nt_session_close(smb_cli, nt_pipe_fnum);
+}
diff --git a/source3/rpcclient/display.c b/source3/rpcclient/display.c
index 831378ab964..e5c65fdec8d 100644
--- a/source3/rpcclient/display.c
+++ b/source3/rpcclient/display.c
@@ -1662,6 +1662,172 @@ void display_svc_info(FILE *out_hnd, enum action_type action, ENUM_SRVC_STATUS *
}
}
+static char *get_at_time_str(uint32 time)
+{
+ static fstring timestr;
+ unsigned int hours, minutes, seconds;
+
+ hours = time / 1000;
+ seconds = hours % 60;
+ hours /= 60;
+ minutes = hours % 60;
+ hours /= 60;
+
+ slprintf(timestr, sizeof(timestr)-1, "%2d:%02d:%02d",
+ hours, minutes, seconds);
+
+ return timestr;
+}
+
+extern char *daynames_short[];
+
+static char *get_at_days_str(uint32 monthdays, uint8 weekdays, uint8 flags)
+{
+ static fstring days;
+ fstring numstr;
+ int day, bit;
+ BOOL first = True;
+
+ if (monthdays == 0 && weekdays == 0)
+ return "Once";
+
+ if (flags & JOB_PERIODIC)
+ {
+ if (IS_BITS_SET_ALL(weekdays, 0x7F))
+ return "Every Day";
+
+ fstrcpy(days, "Every ");
+ }
+ else
+ {
+ fstrcpy(days, "Next ");
+ }
+
+ for (day = 1, bit = 1; day < 32; day++, bit <<= 1)
+ {
+ if (monthdays & bit)
+ {
+ if (first)
+ first = False;
+ else
+ fstrcat(days, ",");
+
+ slprintf(numstr, sizeof(numstr)-1, "%d", day);
+ fstrcat(days, numstr);
+ }
+ }
+
+ for (day = 0, bit = 1; day < 7; day++, bit <<= 1)
+ {
+ if (weekdays & bit)
+ {
+ if (first)
+ first = False;
+ else
+ fstrcat(days, ",");
+
+ fstrcat(days, daynames_short[day]);
+ }
+ }
+
+ return days;
+}
+
+/****************************************************************************
+ display scheduled jobs
+ ****************************************************************************/
+void display_at_enum_info(FILE *out_hnd, enum action_type action,
+ uint32 num_jobs, AT_ENUM_INFO *jobs, fstring *commands)
+{
+ switch (action)
+ {
+ case ACTION_HEADER:
+ {
+ if (num_jobs == 0)
+ {
+ fprintf(out_hnd, "\tNo Jobs.\n");
+ }
+ else
+ {
+ fprintf(out_hnd, "\tJobs:\n");
+ fprintf(out_hnd, "\t-----\n");
+ }
+ break;
+ }
+ case ACTION_ENUMERATE:
+ {
+ int i;
+
+ for (i = 0; i < num_jobs; i++)
+ {
+ AT_JOB_INFO *job = &jobs[i].info;
+
+ fprintf(out_hnd, "\t%d\t%s\t%s\t%s\n",
+ jobs[i].jobid,
+ get_at_time_str(job->time),
+ get_at_days_str(job->monthdays,
+ job->weekdays,
+ job->flags),
+ commands[i]);
+ }
+
+ break;
+ }
+ case ACTION_FOOTER:
+ {
+ fprintf(out_hnd, "\n");
+ break;
+ }
+ }
+}
+
+/****************************************************************************
+ display information about a scheduled job
+ ****************************************************************************/
+void display_at_job_info(FILE *out_hnd, enum action_type action,
+ AT_JOB_INFO *job, fstring command)
+{
+ switch (action)
+ {
+ case ACTION_HEADER:
+ {
+ fprintf(out_hnd, "\tJob Information:\n");
+ fprintf(out_hnd, "\t----------------\n");
+ break;
+ }
+ case ACTION_ENUMERATE:
+ {
+ fprintf(out_hnd, "\tTime: %s\n",
+ get_at_time_str(job->time));
+
+ fprintf(out_hnd, "\tSchedule: %s\n",
+ get_at_days_str(job->monthdays, job->weekdays,
+ job->flags));
+
+ fprintf(out_hnd, "\tStatus: %s",
+ (job->flags & JOB_EXEC_ERR) ? "Failed" : "OK");
+
+ if (job->flags & JOB_RUNS_TODAY)
+ {
+ fprintf(out_hnd, ", Runs Today");
+ }
+
+ fprintf(out_hnd, "\n\tInteractive: %s\n",
+ (job->flags & JOB_NONINTERACTIVE) ? "No"
+ : "Yes");
+
+ fprintf(out_hnd, "\tCommand: %s\n", command);
+ break;
+ }
+ case ACTION_FOOTER:
+ {
+ fprintf(out_hnd, "\n");
+ break;
+ }
+ }
+}
+
+
#if COPY_THIS_TEMPLATE
/****************************************************************************
display structure
diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c
index 870555e6e2d..20cc3ad49b1 100644
--- a/source3/rpcclient/rpcclient.c
+++ b/source3/rpcclient/rpcclient.c
@@ -106,6 +106,7 @@ struct
} commands[] =
{
{"svcenum", cmd_svc_enum, "[-i] Lists Services Manager"},
+ {"at", cmd_at, "Scheduler control (at /? for syntax)"},
{"regenum", cmd_reg_enum, "<keyname> Registry Enumeration (keys, values)"},
{"regdeletekey",cmd_reg_delete_key, "<keyname> Registry Key Delete"},
{"regcreatekey",cmd_reg_create_key, "<keyname> [keyclass] Registry Key Create"},