Home | History | Annotate | Download | only in cron
      1    523    basabi /*
      2  11115  Nobutomo  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
      3    523    basabi  * Use is subject to license terms.
      4    523    basabi  */
      5    523    basabi 
      6      0    stevel /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
      7      0    stevel /*	  All Rights Reserved  	*/
      8      0    stevel 
      9      0    stevel 
     10      0    stevel /*
     11      0    stevel  * Copyright (c) 1983 Regents of the University of California.
     12      0    stevel  * All rights reserved.  The Berkeley software License Agreement
     13      0    stevel  * specifies the terms and conditions for redistribution.
     14      0    stevel  */
     15      0    stevel 
     16      0    stevel /*
     17      0    stevel  *	synopsis: atrm [-f] [-i] [-a] [[job #] [user] ...]
     18      0    stevel  *
     19      0    stevel  *
     20      0    stevel  *	Remove "at" jobs.
     21      0    stevel  */
     22      0    stevel 
     23      0    stevel #include <stdio.h>
     24      0    stevel #include <pwd.h>
     25      0    stevel #include <ctype.h>
     26      0    stevel #include <sys/types.h>
     27      0    stevel #include <dirent.h>
     28      0    stevel #include <sys/file.h>
     29      0    stevel #include <sys/stat.h>
     30      0    stevel #include <errno.h>
     31      0    stevel #include <unistd.h>
     32      0    stevel #include <locale.h>
     33    523    basabi #include <strings.h>
     34   4774  as145665 #include <stdlib.h>
     35   4774  as145665 #include <libintl.h>
     36      0    stevel #include "cron.h"
     37   4774  as145665 #include "getresponse.h"
     38      0    stevel 
     39      0    stevel extern time_t	num();
     40      0    stevel extern char	*errmsg();
     41   4774  as145665 extern void	audit_at_delete(char *, char *, int);
     42      0    stevel 
     43    523    basabi #define	SUPERUSER	0			/* is user super-user? */
     44    523    basabi #define	CANTCD		"can't change directory to the at directory"
     45    523    basabi #define	NOREADDIR	"can't read the at directory"
     46      0    stevel 
     47      0    stevel uid_t user;					/* person requesting removal */
     48      0    stevel int fflag = 0;					/* suppress announcements? */
     49      0    stevel int iflag = 0;					/* run interactively? */
     50      0    stevel 
     51      0    stevel char login[UNAMESIZE];
     52      0    stevel char login_authchk[UNAMESIZE]; /* used for authorization checks */
     53      0    stevel 
     54    523    basabi #define	INVALIDUSER	"you are not a valid user (no entry in /etc/passwd)"
     55    523    basabi #define	NOTALLOWED	"you are not authorized to use at.  Sorry."
     56      0    stevel #define	NAMETOOLONG	"login name too long"
     57      0    stevel 
     58    523    basabi static void usage(void);
     59    523    basabi static void atabortperror(char *msg);
     60    523    basabi static void atabort(char *msg);
     61    523    basabi static void atperror(char *msg);
     62    523    basabi static void atperror2(char *msg, char *name);
     63    523    basabi static void aterror(char *msg);
     64    523    basabi static void powner(char *file);
     65      0    stevel 
     66   4774  as145665 int	getjoblist(struct dirent ***, struct stat ***, int (*)());
     67   4774  as145665 int	removentry(char *, struct stat *, uid_t);
     68   4774  as145665 
     69    523    basabi int
     70    523    basabi main(int argc, char **argv)
     71      0    stevel {
     72      0    stevel 	int i;				/* for loop index */
     73      0    stevel 	int numjobs;			/* # of jobs in spooling area */
     74      0    stevel 	int allflag = 0;		/* remove all jobs belonging to user? */
     75      0    stevel 	int jobexists;			/* does a requested job exist? */
     76      0    stevel 	char *pp;
     77      0    stevel 	struct dirent **namelist;	/* names of jobs in spooling area */
     78      0    stevel 	struct stat **statlist;
     79      0    stevel 	struct passwd *pwd;
     80      0    stevel 
     81      0    stevel 	/*
     82      0    stevel 	 * If job number, user name, or "-" is not specified, just print
     83      0    stevel 	 * usage info and exit.
     84      0    stevel 	 */
     85    523    basabi 	(void) setlocale(LC_ALL, "");
     86   4774  as145665 	(void) textdomain(TEXT_DOMAIN);
     87      0    stevel 	if (argc < 2)
     88      0    stevel 		usage();
     89      0    stevel 
     90      0    stevel 	--argc; ++argv;
     91      0    stevel 
     92    523    basabi 	pp = getuser((user = getuid()));
     93      0    stevel 	if (pp == NULL)
     94      0    stevel 		atabort(INVALIDUSER);
     95      0    stevel 	if (strlcpy(login, pp, sizeof (login)) >= sizeof (login))
     96      0    stevel 		atabort(NAMETOOLONG);
     97      0    stevel 	if (strlcpy(login_authchk, pp, sizeof (login_authchk))
     98      0    stevel 	    >= sizeof (NAMETOOLONG))
     99      0    stevel 		atabort(INVALIDUSER);
    100      0    stevel 	if (!allowed(login, ATALLOW, ATDENY))
    101      0    stevel 		atabort(NOTALLOWED);
    102      0    stevel 
    103      0    stevel 	/*
    104      0    stevel 	 * Process command line flags.
    105      0    stevel 	 * Special case the "-" option so that others may be grouped.
    106      0    stevel 	 */
    107      0    stevel 	while (argc > 0 && **argv == '-') {
    108      0    stevel 		*(*argv)++;
    109    523    basabi 		while (**argv) {
    110    523    basabi 			switch (*(*argv)++) {
    111      0    stevel 
    112      0    stevel 			case 'a':	++allflag;
    113      0    stevel 					break;
    114      0    stevel 
    115      0    stevel 			case 'f':	++fflag;
    116      0    stevel 					break;
    117      0    stevel 
    118      0    stevel 			case 'i':	++iflag;
    119      0    stevel 					break;
    120      0    stevel 
    121      0    stevel 			default:	usage();
    122    523    basabi 			}
    123      0    stevel 		}
    124      0    stevel 		++argv; --argc;
    125      0    stevel 	}
    126      0    stevel 
    127      0    stevel 	/*
    128    523    basabi 	 * If all jobs are to be removed and extra command line arguments
    129      0    stevel 	 * are given, print usage info and exit.
    130      0    stevel 	 */
    131    523    basabi 	if (allflag && argc)
    132      0    stevel 		usage();
    133      0    stevel 
    134      0    stevel 	/*
    135      0    stevel 	 * If only certain jobs are to be removed and no job #'s or user
    136      0    stevel 	 * names are specified, print usage info and exit.
    137      0    stevel 	 */
    138    523    basabi 	if (!allflag && !argc)
    139      0    stevel 		usage();
    140      0    stevel 
    141      0    stevel 	/*
    142      0    stevel 	 * If interactive removal and quiet removal are requested, override
    143      0    stevel 	 * quiet removal and run interactively.
    144      0    stevel 	 */
    145      0    stevel 	if (iflag && fflag)
    146      0    stevel 		fflag = 0;
    147      0    stevel 
    148      0    stevel 
    149      0    stevel 	/*
    150      0    stevel 	 * Move to spooling directory and get a list of the files in the
    151      0    stevel 	 * spooling area.
    152      0    stevel 	 */
    153    523    basabi 	numjobs = getjoblist(&namelist, &statlist, strcmp);
    154      0    stevel 	/*
    155      0    stevel 	 * If all jobs belonging to the user are to be removed, compare
    156      0    stevel 	 * the user's id to the owner of the file. If they match, remove
    157      0    stevel 	 * the file. If the user is the super-user, don't bother comparing
    158      0    stevel 	 * the id's. After all files are removed, exit (status 0).
    159      0    stevel 	 */
    160      0    stevel 	if (allflag) {
    161    523    basabi 		for (i = 0; i < numjobs; ++i) {
    162  11115  Nobutomo 			if (cron_admin(login_authchk) ||
    163      0    stevel 			    user == statlist[i]->st_uid)
    164      0    stevel 				(void) removentry(namelist[i]->d_name,
    165      0    stevel 				    statlist[i], user);
    166      0    stevel 		}
    167      0    stevel 		exit(0);
    168      0    stevel 	}
    169      0    stevel 
    170      0    stevel 	/*
    171      0    stevel 	 * If only certain jobs are to be removed, interpret each command
    172      0    stevel 	 * line argument. A check is done to see if it is a user's name or
    173      0    stevel 	 * a job number (inode #). If it's a user's name, compare the argument
    174      0    stevel 	 * to the files owner. If it's a job number, compare the argument to
    175    523    basabi 	 * the file name. In either case, if a match occurs, try to
    176      0    stevel 	 * remove the file.
    177      0    stevel 	 */
    178      0    stevel 
    179      0    stevel 	while (argc--) {
    180      0    stevel 		jobexists = 0;
    181      0    stevel 		for (i = 0; i < numjobs; ++i) {
    182      0    stevel 
    183      0    stevel 			/* if the inode number is 0, this entry was removed */
    184      0    stevel 			if (statlist[i]->st_ino == 0)
    185      0    stevel 				continue;
    186      0    stevel 
    187    523    basabi 			/*
    188      0    stevel 			 * if argv is a username, compare his/her uid to
    189      0    stevel 			 * the uid of the owner of the file......
    190      0    stevel 			 */
    191      0    stevel 			if (pwd = getpwnam(*argv)) {
    192      0    stevel 				if (statlist[i]->st_uid != pwd->pw_uid)
    193      0    stevel 					continue;
    194      0    stevel 			/*
    195      0    stevel 			 * otherwise, we assume that the argv is a job # and
    196      0    stevel 			 * thus compare argv to the file name.
    197      0    stevel 			 */
    198      0    stevel 			} else {
    199    523    basabi 				if (strcmp(namelist[i]->d_name, *argv))
    200      0    stevel 					continue;
    201      0    stevel 			}
    202      0    stevel 			++jobexists;
    203      0    stevel 			/*
    204      0    stevel 			 * if the entry is ultimately removed, don't
    205      0    stevel 			 * try to remove it again later.
    206      0    stevel 			 */
    207    523    basabi 			if (removentry(namelist[i]->d_name, statlist[i],
    208    523    basabi 			    user)) {
    209      0    stevel 				statlist[i]->st_ino = 0;
    210      0    stevel 			}
    211      0    stevel 		}
    212      0    stevel 
    213      0    stevel 		/*
    214      0    stevel 		 * If a requested argument doesn't exist, print a message.
    215      0    stevel 		 */
    216      0    stevel 		if (!jobexists && !fflag) {
    217    523    basabi 			fprintf(stderr, "atrm: %s: no such job number\n",
    218    523    basabi 			    *argv);
    219      0    stevel 		}
    220      0    stevel 		++argv;
    221      0    stevel 	}
    222    523    basabi 	return (0);
    223      0    stevel }
    224      0    stevel 
    225      0    stevel /*
    226      0    stevel  * Print usage info and exit.
    227      0    stevel  */
    228    523    basabi static void
    229    523    basabi usage(void)
    230      0    stevel {
    231    523    basabi 	fprintf(stderr, "usage: atrm [-f] [-i] [-a] [[job #] [user] ...]\n");
    232      0    stevel 	exit(1);
    233      0    stevel }
    234      0    stevel 
    235      0    stevel 
    236      0    stevel /*
    237      0    stevel  * Remove an entry from the queue. The access of the file is checked for
    238      0    stevel  * write permission (since all jobs are mode 644). If access is granted,
    239      0    stevel  * unlink the file. If the fflag (suppress announcements) is not set,
    240      0    stevel  * print the job number that we are removing and the result of the access
    241    523    basabi  * check (either "permission denied" or "removed"). If we are running
    242    523    basabi  * interactively (iflag), prompt the user before we unlink the file. If
    243    523    basabi  * the super-user is removing jobs, inform him/her who owns each file before
    244      0    stevel  * it is removed.  Return TRUE if file removed, else FALSE.
    245      0    stevel  */
    246      0    stevel int
    247    523    basabi removentry(char *filename, struct stat *statptr, uid_t user)
    248      0    stevel {
    249      0    stevel 	struct passwd *pwd;
    250      0    stevel 	char *pp;
    251      0    stevel 	int r;
    252   4774  as145665 
    253   4774  as145665 	if (init_yes() < 0) {
    254   4774  as145665 		(void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
    255   4774  as145665 		    strerror(errno));
    256   4774  as145665 		exit(1);
    257   4774  as145665 	}
    258      0    stevel 
    259      0    stevel 	if (!fflag)
    260    523    basabi 		printf("%s: ", filename);
    261      0    stevel 
    262  11115  Nobutomo 	if (user != statptr->st_uid && !cron_admin(login_authchk)) {
    263      0    stevel 
    264      0    stevel 		if (!fflag) {
    265      0    stevel 			printf("permission denied\n");
    266      0    stevel 		}
    267      0    stevel 		return (0);
    268      0    stevel 
    269      0    stevel 	} else {
    270      0    stevel 		if (iflag) {
    271  11115  Nobutomo 			if (cron_admin(login_authchk)) {
    272      0    stevel 				printf("\t(owned by ");
    273      0    stevel 				powner(filename);
    274      0    stevel 				printf(") ");
    275      0    stevel 			}
    276   4774  as145665 			printf(gettext("remove it? "));
    277   4774  as145665 			if (yes() == 0)
    278      0    stevel 				return (0);
    279      0    stevel 		}
    280      0    stevel 
    281  11115  Nobutomo 		if (cron_admin(login_authchk)) {
    282    523    basabi 			pp = getuser((uid_t)statptr->st_uid);
    283      0    stevel 			if (pp == NULL)
    284      0    stevel 				atabort(INVALIDUSER);
    285      0    stevel 			if (strlcpy(login, pp, sizeof (login)) >=
    286      0    stevel 			    sizeof (login))
    287      0    stevel 				atabort(NAMETOOLONG);
    288      0    stevel 		}
    289    523    basabi 		cron_sendmsg(DELETE, login, filename, AT);
    290      0    stevel 		if ((r = unlink(filename)) < 0) {
    291      0    stevel 			if (!fflag) {
    292      0    stevel 				fputs("could not remove\n", stdout);
    293      0    stevel 				(void) fprintf(stderr, "atrm: %s: %s\n",
    294      0    stevel 				    filename, errmsg(errno));
    295      0    stevel 			}
    296      0    stevel 			audit_at_delete(filename, NULL, r);
    297      0    stevel 			return (0);
    298      0    stevel 		}
    299      0    stevel 		audit_at_delete(filename, NULL, r);
    300      0    stevel 		if (!fflag && !iflag)
    301      0    stevel 			printf("removed\n");
    302      0    stevel 		return (1);
    303      0    stevel 	}
    304      0    stevel }
    305      0    stevel 
    306      0    stevel /*
    307      0    stevel  * Print the owner of the job. This is the owner of the spoolfile.
    308      0    stevel  * If we run into trouble getting the name, we'll just print "???".
    309      0    stevel  */
    310    523    basabi static void
    311    523    basabi powner(char *file)
    312      0    stevel {
    313      0    stevel 	struct stat statb;
    314      0    stevel 	char *getname();
    315      0    stevel 
    316    523    basabi 	if (stat(file, &statb) < 0) {
    317    523    basabi 		printf("%s", "???");
    318    523    basabi 		(void) fprintf(stderr, "atrm: Couldn't stat spoolfile %s: %s\n",
    319      0    stevel 		    file, errmsg(errno));
    320    523    basabi 		return;
    321      0    stevel 	}
    322      0    stevel 
    323    523    basabi 	printf("%s", getname(statb.st_uid));
    324      0    stevel }
    325      0    stevel 
    326      0    stevel 
    327      0    stevel int
    328    523    basabi getjoblist(struct dirent ***namelistp, struct stat ***statlistp,
    329    523    basabi     int (*sortfunc)())
    330      0    stevel {
    331    523    basabi 	int numjobs;
    332    523    basabi 	struct dirent **namelist;
    333    523    basabi 	int i;
    334    523    basabi 	struct stat *statptr;	/* pointer to file stat structure */
    335    523    basabi 	struct stat **statlist;
    336      0    stevel 	extern int filewanted();	/* should a file be listed in queue? */
    337      0    stevel 	if (chdir(ATDIR) < 0)
    338      0    stevel 		atabortperror(CANTCD);
    339      0    stevel 
    340      0    stevel 	/*
    341      0    stevel 	 * Get a list of the files in the spooling area.
    342      0    stevel 	 */
    343   6628  jk217608 	if ((numjobs = scandir(".", namelistp, filewanted, sortfunc)) < 0)
    344      0    stevel 		atabortperror(NOREADDIR);
    345      0    stevel 
    346    523    basabi 	if ((statlist =
    347    523    basabi 	    (struct stat **)malloc(numjobs * sizeof (struct stat ***)))
    348    523    basabi 	    == NULL)
    349      0    stevel 		atabort("Out of memory");
    350      0    stevel 
    351      0    stevel 	namelist = *namelistp;
    352      0    stevel 
    353      0    stevel 	/*
    354      0    stevel 	 * Build an array of pointers to the file stats for all jobs in
    355      0    stevel 	 * the spooling area.
    356      0    stevel 	 */
    357    523    basabi 	for (i = 0; i < numjobs; ++i) {
    358    523    basabi 		statptr = (struct stat *)malloc(sizeof (struct stat));
    359      0    stevel 		if (statptr == NULL)
    360      0    stevel 			atabort("Out of memory");
    361      0    stevel 		if (stat(namelist[i]->d_name, statptr) < 0) {
    362    523    basabi 			atperror2("Can't stat", namelist[i]->d_name);
    363      0    stevel 			continue;
    364      0    stevel 		}
    365      0    stevel 		statlist[i] = statptr;
    366      0    stevel 	}
    367      0    stevel 
    368      0    stevel 	*statlistp = statlist;
    369      0    stevel 	return (numjobs);
    370      0    stevel }
    371      0    stevel 
    372      0    stevel /*
    373      0    stevel  * Get the full login name of a person using his/her user id.
    374      0    stevel  */
    375      0    stevel char *
    376    523    basabi getname(uid_t uid)
    377      0    stevel {
    378    523    basabi 	struct passwd *pwdinfo;		/* password info structure */
    379      0    stevel 
    380      0    stevel 
    381      0    stevel 	if ((pwdinfo = getpwuid(uid)) == 0)
    382    523    basabi 		return ("???");
    383    523    basabi 	return (pwdinfo->pw_name);
    384      0    stevel }
    385      0    stevel 
    386    523    basabi static void
    387    523    basabi aterror(char *msg)
    388      0    stevel {
    389    523    basabi 	fprintf(stderr, "atrm: %s\n", msg);
    390      0    stevel }
    391      0    stevel 
    392    523    basabi static void
    393    523    basabi atperror(char *msg)
    394      0    stevel {
    395    523    basabi 	fprintf(stderr, "atrm: %s: %s\n", msg, errmsg(errno));
    396      0    stevel }
    397      0    stevel 
    398    523    basabi static void
    399    523    basabi atperror2(char *msg, char *name)
    400    523    basabi {
    401    523    basabi 	fprintf(stderr, "atrm: %s %s: %s\n", msg, name, errmsg(errno));
    402    523    basabi }
    403    523    basabi 
    404    523    basabi static void
    405    523    basabi atabort(char *msg)
    406      0    stevel {
    407      0    stevel 	aterror(msg);
    408      0    stevel 	exit(1);
    409      0    stevel }
    410      0    stevel 
    411    523    basabi static void
    412    523    basabi atabortperror(char *msg)
    413      0    stevel {
    414      0    stevel 	atperror(msg);
    415      0    stevel 	exit(1);
    416      0    stevel }
    417