crontab.c revision 78ae324cd873d8b8b4ee8b2ea86a4f932a9e4f3e
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <pwd.h>
#include <unistd.h>
#include <locale.h>
#include <nl_types.h>
#include <langinfo.h>
#include <libintl.h>
#include <security/pam_appl.h>
#include <limits.h>
#include <libzoneinfo.h>
#include "cron.h"
#include "getresponse.h"
#if defined(XPG4)
#else
#define _XPG_NOTDEFINED
#define VIPATH "vi"
#endif
#define BADCREATE \
"can't create your crontab file in the crontab directory."
#define BADOPEN "can't open your crontab file."
#define BADSHELL \
#define BADUSAGE \
"usage:\n" \
"\tcrontab [file]\n" \
"\tcrontab -e [username]\n" \
"\tcrontab -l [username]\n" \
"\tcrontab -r [username]"
#define INVALIDUSER "you are not a valid user (no entry in /etc/passwd)."
#define NOTALLOWED "you are not authorized to use cron. Sorry."
#define NOTROOT \
"you must be super-user to access another user's crontab file"
#define AUDITREJECT "The audit context for your shell has not been set."
#define EOLN "unexpected end of line."
#define UNEXPECT "unexpected character found in line."
#define OUTOFBOUND "number out of bounds."
#define ERRSFND "errors detected in input, no crontab file generated."
#define ED_ERROR \
" The editor indicates that an error occurred while you were\n"\
" editing the crontab data - usually a minor typing error.\n\n"
#define BADREAD "error reading your crontab file"
#define ED_PROMPT \
" Edit again, to ensure crontab information is intact (%s/%s)?\n"\
" ('%s' will discard edits.)"
#define NAMETOOLONG "login name too long"
#define BAD_TZ "Timezone unrecognized in: %s"
#define BAD_SHELL "Invalid shell specified: %s"
#define BAD_HOME "Unable to access directory: %s\t%s\n"
extern int per_errno;
extern int audit_crontab_modify(char *, char *, int);
extern int audit_crontab_delete(char *, int);
extern int audit_crontab_not_allowed(uid_t, char *);
int err;
int cursor;
char *cf;
char *tnam;
char line[CTLINESIZE];
static int next_field(int, int);
static void catch(int);
static void crabort(char *);
static void cerror(char *);
int
{
int c, r;
int rflag = 0;
int lflag = 0;
int eflag = 0;
int errflg = 0;
char *pp;
char *editor;
int stat_loc;
int ret;
char real_login[UNAMESIZE];
int tmpfd = -1;
int pam_error;
char *buf;
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
if (init_yes() < 0) {
exit(1);
}
switch (c) {
case 'e':
eflag++;
break;
case 'l':
lflag++;
break;
case 'r':
rflag++;
break;
case '?':
errflg++;
break;
}
errflg++;
>= sizeof (real_login))
else
} else
} else {
}
if (per_errno == 2)
else
}
/* Do account validation check */
if (pam_error != PAM_SUCCESS) {
}
if (pam_error != PAM_SUCCESS) {
"'%s' not allowed to execute cronjobs\n"), pp);
}
/* check for unaudited shell */
if (rflag) {
audit_crontab_delete(cf, r);
exit(0);
}
if (lflag) {
exit(0);
}
if (eflag) {
}
crabort("fchown of temporary file failed");
}
/*
* Fork off a child with user's permissions,
* to edit the crontab file
*/
crabort("fork failed");
if (pid == 0) { /* child process */
/* give up super-user privileges. */
crabort("can't create temporary file");
/*
* Copy user's crontab file to temporary file.
*/
crabort("write error on"
"temporary file");
}
}
}
}
crabort("write error on temporary file");
crabort("can't stat temporary file");
#ifdef _XPG_NOTDEFINED
#endif
#ifdef _XPG_NOTDEFINED
}
#endif
sleep(1);
while (1) {
/* sanity checks */
crabort("can't open temporary file");
crabort("can't stat temporary file");
crabort("temporary file empty");
"The crontab file was not"
" changed.\n"));
exit(1);
}
/*
* Some editors (like 'vi') can return
* a non-zero exit status even though
* everything is okay. Need to check.
*/
/* Interactive */
if (yes()) {
/* Edit again */
continue;
} else {
/* Dump changes */
exit(1);
}
} else {
/*
* Non-interactive, dump changes
*/
exit(1);
}
}
exit(0);
} /* while (1) */
}
/* fix for 1125555 - ignore common signals while waiting */
if ((stat_loc & 0xFF00) != 0)
exit(1);
/*
* unlink edtemp as 'ruid'. The file contents will be held
* since we open the file descriptor 'tmpfp' before calling
* unlink.
*/
exit(1);
} else
seteuid(0);
} else {
if (argc == 0)
== NULL)
else {
seteuid(0);
}
}
/*
* if (per_errno == 2)
* fprintf(stderr, gettext(WARNSHELL));
*/
return (0);
}
static void
{
int t;
/* cut trailing blanks */
*tnam_end = 0;
/* catch SIGINT, SIGHUP, SIGQUIT signals */
}
err = 0; /* if errors found, err set to 1 */
cursor = 0;
cursor++;
/* fix for 1039689 - treat blank line like a comment */
goto cont;
char *x;
sizeof (buf));
*x = NULL;
goto cont;
} else {
err = 1;
continue;
}
char *x;
sizeof (buf));
*x = NULL;
if (isvalid_shell(buf)) {
goto cont;
} else {
err = 1;
continue;
}
char *x;
sizeof (buf));
*x = NULL;
goto cont;
} else {
err = 1;
continue;
}
}
if (next_field(0, 59)) continue;
if (next_field(0, 23)) continue;
if (next_field(0, 06)) continue;
continue;
}
cont:
}
}
/* audit differences between old and new crontabs */
if (!err) {
/* make file tfp the new crontab */
}
} else {
}
}
static int
{
return (1);
}
cursor++;
return (1);
}
return (0);
}
while (TRUE) {
return (1);
}
num = 0;
do {
return (1);
}
return (1);
}
num2 = 0;
do {
return (1);
}
}
return (1);
}
return (1);
}
}
return (0);
}
static void
char *msg;
{
err = 1;
}
static void
catch(int x)
{
exit(1);
}
static void
char *msg;
{
int sverrno;
}
}
exit(1);
}