at.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1996-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*
* at -- bundle request and send to AT_SERVICE
*/
static const char usage[] =
"[-?\n@(#)$Id: at (AT&T Research) 2000-05-09 $\n]"
"[+NAME?\f?\f - run commands at specified time(s)]"
"[+DESCRIPTION?\b\f?\f\b is the command interface to the \bat\b daemon."
" It submits commands to be executed at a future time, lists"
" queue status, and controls the daemon.]"
"[+?Options that refer to specific jobs interpret the operands as job ids,"
" otherwise if the \b--time\b option is not specified then the operands"
" are interpreted as the start time. If \atime\a is not specified then"
" the command is scheduled to be executed immediately, subject to the"
" queue constraints.]"
"[+?If \b--time\b is specified then the first non-option argument is the"
" command to be executed, otherwise the command to be executed is read"
" from the standard input. The command job id is written to the standard"
" output after the command has been successfully submitted to the"
" daemon.]"
"[a:access?Check queue access and exit.]"
"[f:file?\afile\a is a script to be run at the specified time.]:[file]"
"[h:label|heading?Set the job label to \astring\a.]:[string]"
"[i:info?List queue information and exit.]"
"[l:list?List queue jobs and exit.]"
"[m:mail?Send mail when the command completes.]"
"[n!:exec?Execute the command. \b--noexec\b shows what would be done but"
" does not execute.]"
"[p:status?List detailed queue status.]"
"[q:queue?Send request to \aqueue\a. Standard queues are:]:[queue]{"
" [+a?The \bat\b(1) queue.]"
" [+b?The \bbatch\b(1) queue.]"
" [+c?The \bcron\b(1) queue.]"
"}"
"[r:remove?Remove command named by the \ajob\a ... operands from the queue.]"
"[s:service?Connect to the \bcs\b(1) service \apath\a.]:"
"[t:time|date?Schedule the command to be run at \atime\a. Most common"
" date formats are accepted. The keyword \bevery\b can be combined"
" with date parts to specify repeat executions, e.g.,"
" \bevery Monday\b.]:[time:=now]"
"[u:user?List the per user queue information. Requires sufficient privilege"
" to view the status of other users.]"
"[A:admin?Enable administrative actions. Requires sufficient privilege.]"
"[D:debug?Enable \bat\b daemon debug tracing to \afile\a at debug level"
" \alevel\a. Higher levels produce more output. Requires sufficient"
" privilege.]:[[level]][file]]]"
"[L:log?Write the log file path name on the standard output and exit. The log"
" file is renamed with a \b.old\b suffix at the beginning of each month"
" and a new log file started.]"
"[Q:quit?Terminate the \bat\b daemon. Requires sufficient privilege.]"
"[U:update?Causes the \bat\b daemon to do a schedule update and re-read"
" the queue definition file if it has changed from the last time"
" it was read. If \aqueuedef\a is specified then it is interpreted as"
" a queue definition file line. See \bQUEUE DEFINITIONS\b below."
" Requires sufficient privilege.]:?[queuedef]"
"[+QUEUE DEFINITIONS?(\aNOTE\a: the \bnroff\b(1) style syntax is taken from"
" one queue per line. Lines starting with \b#\b are comments. The format"
" of a definition line is: \aname\a.[\anumber\a\battribute\b]]..., where"
" \aname\a is a single letter queue name and \anumber\a applies to the"
" following single character \battribute\b. If \anumber\a is omitted"
" then it defaults to \b1\b. The default queues are: \ba.4j1n2u\b,"
" \bb.2j2n90w2u\b, \bc.h8j2u60w\b. Per-queue user access may be"
" specified by appending a space separated user names after the queue"
" attributes. If the first list element is \b+\b then the list"
" specifies users allowed to use the queue; othewise it specifies users"
" denied access to the queue. If no user list is specified then queue"
" access is controlled by the global files described in"
" \bQUEUE ACCESS\b below. The attributes are:]{"
" [+h?The job environment is initialized to contain at least the"
" \bHOME\b, \bLOGNAME\b, \bUSER\b, \bPATH\b and"
" \bSHELL\b of the submitting user. The jobs are also"
" run in the user \bHOME\b directory.]"
" [+j?The total number of running jobs for all queues is limited"
" to \anumber\a.]"
" [+l?No new jobs will be run until the load average is smaller"
" than \anumber\a. This only works on systems where the"
" load average is easily determined.]"
" [+n?The default \bnice\b(1) priority is set to \anumber\a.]"
" [+u?The per-user running job limit is set to \anumber\a.]"
" [+w?At least \anumber\a seconds will elapse before the"
" next job from the queue is run.]"
" }"
"[+QUEUE ACCESS?The user \broot\b may submit jobs to all queues. If a queue"
" definition does not specify a user access list then the queue access"
" is controlled by the default access files in this order:]{"
" job access is granted to all users.]"
" access is granted only to user names listed in this"
" file, one name per line.]"
" access is denied to user names listed in this file,"
" one name per line.]"
" [+(4)?Otherwise access is denied to all users but \broot\b.]"
" }"
"\n"
"\n[ job ... | time ... ]\n"
"\n"
"[+FILES]{"
"}"
"[+SEE ALSO?\bbatch\b(1), \bcrontab\b(1), \bnice\b(1), \bsh\b(1)]"
;
#include "at.h"
#include <fs3d.h>
#define ACCESS (1<<0)
int
{
register int c;
register char* s;
char* e;
char* t;
int n;
int skip;
int flags = 0;
int interval = 1;
char* file = 0;
char* label = 0;
char* queue = 0;
char* service = AT_SERVICE;
char* date = 0;
char* every = 0;
char* trace = 0;
char* update = 0;
static char que[2];
s = *argv;
else if (t = strchr(++s, '_'))
s = t + 1;
if (*s == 'b')
{
date = "now";
}
else
for (;;)
{
{
case 'a':
continue;
case 'f':
continue;
case 'h':
continue;
case 'i':
continue;
case 'l':
continue;
case 'm':
continue;
case 'n':
continue;
case 'p':
continue;
case 'q':
continue;
case 'r':
continue;
case 's':
continue;
case 't':
continue;
case 'u':
continue;
case 'v':
continue;
case 'A':
continue;
case 'D':
continue;
case 'L':
continue;
case 'Q':
continue;
case 'U':
continue;
case ':':
continue;
case '?':
continue;
}
break;
}
if (error_info.errors)
if (queue)
{
case ACCESS:
break;
case INFO:
break;
case LIST:
break;
case LOG:
break;
case QUIT:
flags |= CS_OPEN_TEST;
break;
case REMOVE:
break;
case STATUS:
break;
case TRACE:
break;
case UPDATE:
break;
case USER:
break;
case VERSION:
break;
default:
s = pathshell();
{
if (date)
else
for (s = *argv;;)
{
for (n = ' '; c = *s++; n = c)
if (!isspace(c) || n != (c = ' '))
if (!(s = *++argv))
break;
if (n != ' ')
}
s += 3;
if (strneq(s, "cron ", n = 5) || strneq(s, "each ", n = 5) || strneq(s, "every ", n = 6) || strneq(s, "repeat ", n = 7))
{
every = s + n;
t = s;
*t++ = '+';
*t++ = '0';
while (*t != ' ')
*t++ = ' ';
{
while (*t && *t != ' ')
*t++ = ' ';
}
else if (isdigit(*t))
{
if (!isalpha(*e))
interval = 1;
else
while (*t && *t != ' ')
*t++ = ' ';
}
while (*every == ' ')
every++;
}
if (*t)
if (s = label)
{
while ((c = *s++) && !isspace(c))
if (isalnum(c))
}
if (s = every)
}
break;
}
{
if (s = *argv++)
{
while (s = *argv++)
}
else
}
else
{
if (s = *argv++)
{
s = "*";
while (s = *argv++)
}
}
s[6] = '\n';
{
if (n < 0)
}
else
{
{
if (every)
}
}
return 0;
}