From 16758a425265afaf6d4ba2636fdafbdb5b26b708 Mon Sep 17 00:00:00 2001 From: Matthew Chapman Date: Fri, 23 Apr 1999 15:01:35 +0000 Subject: 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) --- source3/rpcclient/cmd_atsvc.c | 327 ++++++++++++++++++++++++++++++++++++++++++ source3/rpcclient/display.c | 166 +++++++++++++++++++++ source3/rpcclient/rpcclient.c | 1 + 3 files changed, 494 insertions(+) create mode 100644 source3/rpcclient/cmd_atsvc.c (limited to 'source3') diff --git a/source3/rpcclient/cmd_atsvc.c b/source3/rpcclient/cmd_atsvc.c new file mode 100644 index 0000000000..a7b771e48e --- /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 831378ab96..e5c65fdec8 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 870555e6e2..20cc3ad49b 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, " Registry Enumeration (keys, values)"}, {"regdeletekey",cmd_reg_delete_key, " Registry Key Delete"}, {"regcreatekey",cmd_reg_create_key, " [keyclass] Registry Key Create"}, -- cgit