Home | History | Annotate | Download | only in bnu
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     23 /*	  All Rights Reserved  	*/
     24 
     25 /*
     26  * Copyright (c) 2000 by Sun Microsystems, Inc.
     27  * All rights reserved.
     28  */
     29 
     30 #ident	"%Z%%M%	%I%	%E% SMI"	/* from SVR4 bnu:grades.c 1.7 */
     31 
     32 #include "uucp.h"
     33 #include <grp.h>
     34 
     35 #define G_EXT	0
     36 #define	G_INT	1
     37 #define	G_RES	2
     38 #define	G_ACT	3
     39 #define	G_IDF	4
     40 #define	G_MAX	512	/* max number of fields in the Grades file line */
     41 #define	SMBUF	128
     42 
     43 #define	TYPE	0
     44 #define FILE1	1
     45 #define	FILE2	2
     46 #define	USER	3
     47 #define	OPTS	4
     48 #define	FILE3	5
     49 
     50 extern int rdfulline(), jsize(), gdirf(), gnamef();
     51 extern void wfcommit();
     52 
     53 static void	mailAdmin();		/* Send mail to administrator. */
     54 
     55 /*
     56  * chkgrp - checks to see the group has permission
     57  *		to use a service grade queue.
     58  *
     59  * returns
     60  *
     61  *	SUCCESS - if the group has permissions
     62  *	FAIL - if group does not
     63  *
     64  */
     65 
     66 static int
     67 chkgrp(carray,na)
     68 char **carray;
     69 int na;
     70 {
     71 	struct group *grp;
     72 	int i;
     73 	gid_t gid;
     74 
     75 	gid = getgid();
     76 	grp = getgrgid(gid);
     77 
     78 	for (i = G_IDF; i < na; i++)
     79 			if (EQUALS(carray[i], grp->gr_name))
     80 				return(SUCCESS);
     81 
     82 	return(FAIL);
     83 }
     84 
     85 /*
     86  * chkusr - checks the permission fields of the Grades file
     87  *	    to determine if the user can queue to a particular service grade.
     88  *
     89  * returns
     90  *
     91  *	SUCCESS - if the user can queue to the service grade.
     92  *	FAIL - if the user can not queue to this service grade.
     93  *
     94  */
     95 
     96 static int
     97 chkusr(carray, na)
     98 char **carray;
     99 int na;
    100 {
    101 	int i;
    102 
    103 	/*
    104 	 * start at the point where the users are supposed to be in the
    105 	 * Grades file. Loop thru until the end of the user list is
    106 	 * found or the user name is found. If the user name is found then
    107 	 * return TRUE. If the end of the list is found, return FAIL.
    108 	 */
    109 
    110 	DEBUG(9, "User (%s)\n", User);
    111 
    112 	/* check for any user and return if so */
    113 
    114 	if (EQUALS(carray[G_IDF], "Any"))
    115 		return(SUCCESS);
    116 
    117 	DEBUG(9, "Members of administrator defined service grade (%s)\n", carray[G_EXT]);
    118 
    119 	for (i = G_IDF; i < na; i++) {
    120 		DEBUG(9, "%s\n", carray[i]);
    121 		if (EQUALS(User, carray[i]))
    122 			return(SUCCESS);
    123 	}
    124 
    125 	return(FAIL);
    126 }
    127 
    128 /*
    129  *	fgrade - finds the appropiate queue to queue a job into
    130  *
    131  *	returns
    132  *		SUCCESS	-> found a queue
    133  *		FAIL	-> can't find a queue
    134  */
    135 
    136 int
    137 fgrade(scfile)
    138 struct cs_struct *scfile;
    139 {
    140 	char fdgrade();
    141 	FILE *cfd;
    142 	char line[BUFSIZ];
    143 	char *carray[G_MAX];
    144 	long climit;
    145 
    146 	/* Check for the default service grade first */
    147 
    148 	if (strcmp(scfile->sgrade, "default") == 0) {
    149 		scfile->grade = fdgrade();
    150 		return(SUCCESS);
    151 	}
    152 
    153 	/* open grades file to begin a linear for the grade requested */
    154 
    155 	cfd = fopen(GRADES, "r");
    156 
    157 	/* loop until the file is empty or we find the grade we want */
    158 
    159 	while (rdfulline(cfd, line, BUFSIZ) != 0) {
    160 		(void) getargs(line, carray, G_MAX);
    161 
    162 		/* check to see if this is the grade we want */
    163 
    164 		if (!EQUALS(scfile->sgrade, carray[G_EXT]))
    165 			continue;
    166 
    167 		if (jsize(scfile, carray[G_RES], &climit) != FAIL) {
    168 			(void) fclose(cfd);
    169 			scfile->grade = *carray[G_INT];
    170 			return(SUCCESS);
    171 		}
    172 	}
    173 
    174 	(void) fclose(cfd);
    175 
    176 	(void) fprintf(stderr, gettext("Job size (%ld bytes)"
    177 	    " exceeds maximum number of bytes (%ld bytes)"
    178 	    " allowed into this service grade (%s).\n"
    179 	    "Job queued to default grade.\n"),
    180 	    scfile->jsize, climit, scfile->sgrade);
    181 
    182 	scfile->grade = fdgrade();
    183 	return(SUCCESS);
    184 }
    185 
    186 /*
    187  *	fdgrade - finds the default queue for this system
    188  *
    189  *	returns
    190  *		a one char name for the default queue
    191  *
    192  */
    193 
    194 char
    195 fdgrade()
    196 {
    197 	FILE *cfd;
    198 	char line[BUFSIZ];
    199 	char *carray[G_MAX];
    200 
    201 	/* Check for the default grade first */
    202 
    203 		cfd = fopen(GRADES, "r");
    204 
    205 		/* loop until the end of the file is read */
    206 
    207 		for (; rdfulline(cfd, line, BUFSIZ) != 0;) {
    208 
    209 			/* parse the fields of this line */
    210 
    211 			(void) getargs(line, carray, G_MAX);
    212 
    213 			/* check to see if the administrator has defined
    214 			 * a default grade for the machine.
    215 			 */
    216 
    217 			if (strcmp(carray[G_EXT], "default") != 0)
    218 				continue;
    219 
    220 			/* default must be defined in the file
    221 			 *  close the file, get the queue name, and return.
    222 			 */
    223 
    224 			(void) fclose(cfd);
    225 			return(*carray[G_INT]);
    226 		}
    227 
    228 		/* no default defined in this file. close file.
    229 		 * get our default queue and return.
    230 		 */
    231 
    232 		(void) fclose(cfd);
    233 		return(D_QUEUE);
    234 }
    235 
    236 /*
    237  * job_size - determines the size of a job
    238  *
    239  * returns
    240  *
    241  *	SUCCESS - if the size of the job can be determined
    242  *	FAIL	- otherwise
    243  */
    244 
    245 int
    246 job_size(scfile)
    247 struct cs_struct *scfile;
    248 {
    249 	extern int Dfileused;
    250 	struct stat s;
    251 	FILE *fp;
    252 	char line[BUFSIZ];
    253 	char *carray[G_MAX];
    254 	int na;
    255 	int nodfile = FALSE;
    256 	int ret;
    257 
    258 	scfile->jsize = 0;
    259 
    260 	fp = fopen(scfile->file, "r");
    261 
    262 	if (fp == NULL) {
    263 		toCorrupt(scfile->file);
    264 		errent(Ct_OPEN, scfile->file, errno, __FILE__,  __LINE__);
    265 	}
    266 
    267 	while (fgets(line, BUFSIZ, fp) != NULL) {
    268 		na = getargs(line, carray, G_MAX);
    269 
    270 		if (na < 6) {
    271 			(void) fclose(fp);
    272 			toCorrupt(scfile->file);
    273 			errent("BAD NUMBER OF ARGUMENTS", scfile->file, 0,
    274 				__FILE__, __LINE__);
    275 		}
    276 
    277 		/* if the type of a transfer is not a push
    278 		 * then don't try to determine the size of
    279 		 * the data file, because you can't.
    280 		 */
    281 
    282 		if (*carray[TYPE] == 'R')
    283 			continue;
    284 
    285 		/* find the data dile that is to be transferred */
    286 
    287 		if ((ret = stat(carray[FILE3], &s)) != 0) {
    288 			if (errno == ENOENT) {
    289 				nodfile = TRUE;
    290 				ret = stat(carray[FILE1], &s);
    291 			}
    292 		}
    293 		else
    294 			Dfileused = TRUE;
    295 
    296 		/*
    297 		 * check to see if the return code from stat was 0
    298 		 * if return code was not 0, write message to error
    299 		 * log and quit. Otherwise, add size of file to job
    300 		 * size and continue looping.
    301 		 */
    302 
    303 		if (ret != 0) {
    304 			(void) fclose(fp);
    305 			errent(Ct_STAT, nodfile ?
    306 				carray[FILE1] : carray[FILE3], errno,
    307 				__FILE__, __LINE__);
    308 		}
    309 
    310 		nodfile = FALSE;
    311 		scfile->jsize += s.st_size;
    312 	}
    313 	(void) fclose(fp);
    314 	return(SUCCESS);
    315 }
    316 
    317 /*
    318  * jsize - determines whether if a job is small enough to
    319  * 	   be placed in the appropiate queue.
    320  *
    321  * returns
    322  *
    323  *	SUCCESS - if the size of the job is less than or
    324  *		  equal to the number of bytes in the restriction
    325  *		  of the GRADES file.
    326  *
    327  *	FAIL	- otherwise
    328  */
    329 
    330 int
    331 jsize(scfile, climit, nlimit)
    332 struct cs_struct *scfile;
    333 char *climit;
    334 long *nlimit;
    335 {
    336 #define ONE_K (1024)
    337 #define ONE_MEG ((1024)*(1024))
    338 
    339 	static void lcase();
    340 	char rest[SMBUF];
    341 	char msg[BUFSIZ], *p;
    342 
    343 	if (EQUALS(climit, "Any"))
    344 		return(SUCCESS);
    345 
    346 	lcase(climit, rest, SMBUF);
    347 
    348 	if (!(p = strchr(rest, 'k')) && (!(p = strchr(rest, 'm')))) {
    349 
    350 		for(p = climit; *p; ++p) {
    351 			if (isdigit(*p))
    352 				continue;
    353 
    354 			/* corrupt restriction field in the Grades file.
    355 			 * report it to the uucp administrator.
    356 			 */
    357 
    358 			snprintf(msg, sizeof (msg),
    359 			    gettext("Error encountered in the"
    360 			    " restrictions field of the Grades file."
    361 			    "  Field contents (%s)."), climit);
    362 			mailAdmin(msg);
    363 			return(SUCCESS);
    364 		}
    365 
    366 		*nlimit = atol(climit);
    367 	}
    368 	else if (*p == 'k') {
    369 		*p = '\0';
    370 		*nlimit = (long) (atof(rest) * ONE_K);
    371 	}
    372 	else {
    373 		*p = '\0';
    374 		*nlimit = (long) (atof(rest) * ONE_MEG);
    375 	}
    376 
    377 	if (scfile->jsize <= *nlimit)
    378 		return(SUCCESS);
    379 	else
    380 		return(FAIL);
    381 }
    382 
    383 static void
    384 lcase(s, t, lim)
    385 char s[], t[];
    386 int lim;
    387 {
    388 	char *p;
    389 	int i;
    390 
    391 
    392 	p = s;
    393 
    394 	for (i = 0; i < lim-1 && *p; i++)
    395 		if (isupper(*p))
    396 			t[i] = tolower(*p++);
    397 		else
    398 			t[i] = *p++;
    399 
    400 	t[i] = '\0';
    401 	return;
    402 }
    403 
    404 /*
    405  * mailAdmin - mail a message to the uucp administrator.
    406  *
    407  * returns:
    408  *
    409  *	nothing
    410  */
    411 
    412 static void
    413 mailAdmin (msg)
    414 
    415 char *	msg;
    416 
    417 {
    418 	char	cmd[BUFSIZ];		/* Place to build mail command. */
    419 	FILE *	mail;			/* Channel to write mail on. */
    420 
    421 	(void) sprintf(cmd, "%s %s %s", PATH, MAIL, "uucp");
    422 	if ((mail = popen(cmd, "w")) != (FILE *) NULL)
    423 	{
    424 		(void) fprintf(mail, "To: uucp\nSubject: %s\n\n%s\n",
    425 		    gettext("Grades file problem"), msg);
    426 		(void) pclose(mail);
    427 	}
    428 
    429 	/*
    430 	 * Ignore popen failure.  There is not much that we can do if
    431 	 * it fails, since we are already trying to notify the administrator
    432 	 * of a problem.
    433 	 */
    434 	return;
    435 }
    436 
    437 /*
    438  * putdfiles - moves any and all of the D. to the spool directory for
    439  * 	       a C. file.
    440  *
    441  * returns
    442  *
    443  *	nothing
    444  */
    445 
    446 void
    447 putdfiles(scfile)
    448 struct cs_struct scfile;
    449 {
    450 	FILE *fp;
    451 	char line[BUFSIZ];
    452 	char *carray[G_MAX];
    453 	int na;
    454 	struct stat s;
    455 
    456 	fp = fopen(scfile.file, "r");
    457 
    458 	if (fp == NULL) {
    459 		toCorrupt(scfile.file);
    460 		errent(Ct_OPEN, scfile.file, errno, __FILE__, __LINE__);
    461 	}
    462 
    463 	while (fgets(line, BUFSIZ, fp) != NULL) {
    464 
    465 		na = getargs(line, carray, G_MAX);
    466 		if (na < 6) {
    467 			(void) fclose(fp);
    468 			toCorrupt(scfile.file);
    469 			errent("BAD NUMBER OF ARGUMENTS", scfile.file, 0,
    470 				__FILE__, __LINE__);
    471 		}
    472 
    473 		if (*carray[TYPE] == 'R')
    474 			continue;
    475 
    476 	    	/* move D. file to the spool area */
    477 
    478 		if (stat(carray[FILE3], &s) != -1)
    479 			wfcommit(carray[FILE3], carray[FILE3], scfile.sys);
    480 	}
    481 
    482 	(void) fclose(fp);
    483 	return;
    484 }
    485 
    486 /*
    487  * reads a line from a file and takes care of comment lines
    488  * and continuations (\) in last column.
    489  *
    490  * return:
    491  *	the number of chars that are placed in line.
    492  */
    493 
    494 int
    495 rdfulline(fd, line, lim)
    496 FILE *fd;
    497 char *line;
    498 int lim;
    499 {
    500 	register char *p, *c;
    501 	char buf[BUFSIZ];
    502 	size_t blr, btox;
    503 
    504 	p = line;
    505 	for (;fgets(buf, BUFSIZ, fd) != NULL;) {
    506 		/* check to see if it is a comment */
    507 
    508 		if (buf[0] == '#')
    509 			continue;
    510 
    511 		/* remove trailing white space */
    512 		c = &buf[strlen(buf)-1];
    513 		while (c>=buf && (*c == '\n' || *c == '\t' || *c == ' ') )
    514 			*c-- = NULLCHAR;
    515 
    516 		if (buf[0] == '\n' || buf[0] == NULLCHAR)
    517 			continue;
    518 
    519 		blr = lim - 1 - (p - line);
    520 		btox = blr < strlen(buf) ? blr : strlen(buf);
    521 
    522 		if (btox <= 0)
    523 			break;
    524 
    525 		(void) strncpy(p, buf, btox);
    526 		p += btox - 1;
    527 
    528 		if ( *(p-1) == '\\')
    529 			p--;
    530 		else
    531 			break;
    532 	}
    533 
    534 	*++p = '\0';
    535 	return(p-line-1);
    536 }
    537 
    538 /*	upermit - checks to determine if the user has permissions
    539  *	to use administrator defined service grade.
    540  *
    541  *	returns
    542  *		SUCCESS -> if the user can queue to this service grade.
    543  *		FAIL -> if the user cannot queue to this service grade.
    544  */
    545 
    546 int
    547 upermit(carray, na)
    548 char **carray;
    549 int na;
    550 {
    551 #define G_USR "user"
    552 #define G_NUSR "non-user"
    553 #define G_GRP "group"
    554 #define G_NGRP "non-group"
    555 
    556 	static void lcase();
    557 	char actn[SMBUF];
    558 	char ufld[SMBUF];
    559 	char msg[BUFSIZ];
    560 
    561 	(void) strcpy(actn, carray[G_ACT]);
    562 
    563 	lcase(actn, ufld, SMBUF);
    564 
    565 	if (EQUALS(ufld, G_USR))
    566 		return(chkusr(carray,na));
    567 
    568 	if (EQUALS(ufld, G_NUSR))
    569 		return((chkusr(carray, na) != SUCCESS) ? SUCCESS : FAIL);
    570 
    571 	if (EQUALS(ufld, G_GRP))
    572 		return(chkgrp(carray, na));
    573 
    574 	if (EQUALS(ufld, G_NGRP))
    575 		return((chkgrp(carray, na) != SUCCESS) ? SUCCESS : FAIL);
    576 
    577 	(void) snprintf(msg, sizeof (msg),
    578 	    gettext("Error encountered in action field of"
    579 	    " the Grades file. Field contents (%s)."), carray[G_ACT]);
    580 	mailAdmin(msg);
    581 	return(FAIL);
    582 }
    583 
    584 /*
    585  *	vergrd - verify if the grade name is a valid administrator
    586  *		 defined service grade name and if the user has the
    587  *		 appropiate permission to use this grade.
    588  *
    589  *	returns
    590  *		SUCCESS	-> grade is valid and user is
    591  *			   permitted to use this grade.
    592  *		FAIL	-> otherwise
    593  *
    594  */
    595 
    596 int
    597 vergrd(grade)
    598 char *grade;
    599 {
    600 	FILE *cfd;
    601 	char line[BUFSIZ];
    602 	char *carray[G_MAX];
    603 	int na;
    604 
    605 	/* Check for the default grade first */
    606 
    607 	if (EQUALS(grade, "default"))
    608 		return(SUCCESS);
    609 
    610 	/* open grades file to begin a linear for the grade requested */
    611 
    612 	cfd = fopen(GRADES, "r");
    613 
    614 	/* loop until the file is empty or we find the grade we want */
    615 
    616 	while (rdfulline(cfd, line, BUFSIZ) != 0) {
    617 		na = getargs(line, carray, G_MAX);
    618 
    619 		/* check to see if this is the grade we want */
    620 
    621 		if (!EQUALS(grade, carray[G_EXT]))
    622 			continue;
    623 
    624 		/* check for the permission on this grade */
    625 
    626 		if (upermit(carray, na) != FAIL) {
    627 			(void) fclose(cfd);
    628 			return(SUCCESS);
    629 		}
    630 		else {
    631 			(void) fclose(cfd);
    632 			(void) fprintf(stderr, gettext("User does not have"
    633 			    " permission to use this service grade (%s).\n"
    634 			    "Job has not been queued.\n"
    635 			    "Use (uuglist) to find which service grades"
    636 			    " you can queue to.\n"), grade);
    637 			return(FAIL);
    638 		}
    639 	}
    640 
    641 	(void) fclose(cfd);
    642 
    643 	(void) fprintf(stderr, gettext(
    644 	    "Service grade (%s) does not exist on this machine."
    645 	    "  Job not queued.\n"
    646 	    "Use (uuglist) to find which service grades are available on"
    647 	    " this machine.\n"), grade);
    648 	return(FAIL);
    649 }
    650 
    651 /*
    652  * wfremove - removes a C. file from the Workspace directory and all of its
    653  * D. files.
    654  */
    655 
    656 void
    657 wfremove(file)
    658 char *file;
    659 {
    660 	FILE *fp;
    661 	char line[BUFSIZ];
    662 	char *carray[G_MAX];
    663 	int na;
    664 	struct stat s;
    665 
    666 	fp = fopen(file, "r");
    667 
    668 	if (fp == NULL) {
    669 		toCorrupt(file);
    670 		errent(Ct_OPEN, file, errno, __FILE__, __LINE__);
    671 	}
    672 
    673 	while (fgets(line, BUFSIZ, fp) != NULL) {
    674 		na = getargs(line, carray, G_MAX);
    675 
    676 		if (na < 6) {
    677 			(void) fclose(fp);
    678 			toCorrupt(file);
    679 			errent("BAD NUMBER OF ARGUMENTS", file, 0,
    680 				__FILE__, __LINE__);
    681 		}
    682 
    683 		if (*carray[TYPE] == 'R')
    684 			continue;
    685 
    686 	    	/* remove D. file */
    687 
    688 	    	DEBUG(4, "Removing data file (%s)\n", carray[FILE3]);
    689 
    690 		if ((stat(carray[FILE3], &s) != -1) && (unlink(carray[FILE3]) != 0)) {
    691 			(void) fclose(fp);
    692 			toCorrupt(file);
    693 			toCorrupt(carray[FILE3]);
    694 			errent(Ct_UNLINK, carray[FILE3], errno, __FILE__,
    695 				__LINE__);
    696 		}
    697 	}
    698 
    699 	(void) fclose(fp);
    700 
    701 	DEBUG(4, "Removing work file (%s)\n", file);
    702 
    703 	if (unlink(file) != 0) {
    704 		toCorrupt(file);
    705 		errent(Ct_UNLINK, file, errno, __FILE__, __LINE__);
    706 	}
    707 	return;
    708 }
    709 
    710 /*
    711  * findgrade - finds the highest priority job grade that is not locked
    712  * and that has jobs.
    713  *
    714  * job grade name is null, if no job grade is found.
    715  */
    716 
    717 void
    718 findgrade(dir, jobgrade)
    719 char *dir, *jobgrade;
    720 {
    721 	char prevgrade[MAXBASENAME+1], curgrade[MAXBASENAME+1],
    722 	     gradedir[MAXBASENAME+1];
    723 	char lockname[MAXFULLNAME];
    724 	char Cfile[MAXBASENAME+1];
    725 	DIR *p, *q;
    726 
    727 	*prevgrade = NULLCHAR;
    728 	p = opendir(dir);
    729 	ASSERT(p != NULL, Ct_OPEN, dir, errno);
    730 
    731 	while (gdirf(p, gradedir, dir) == TRUE) {
    732 		(void) sprintf(lockname, "%s.%.*s.%s", LOCKPRE, SYSNSIZE,
    733 		    Rmtname, gradedir);
    734 		if (cklock(lockname) == FAIL)
    735 			continue;
    736 		q = opendir(gradedir);
    737 		ASSERT(q != NULL, Ct_OPEN, gradedir, errno);
    738 		while (gnamef(q, Cfile) == TRUE) {
    739 			if (Cfile[0] == CMDPRE) {
    740 				if (*prevgrade == NULLCHAR) {
    741 					(void) strcpy(prevgrade, gradedir);
    742 					break;
    743 				}
    744 				(void) strcpy(curgrade, gradedir);
    745 				if (strcmp(curgrade, prevgrade) < 0)
    746 					(void) strcpy(prevgrade, curgrade);
    747 			}
    748 		}
    749 		closedir(q);
    750 	}
    751 	closedir(p);
    752 	(void) strncpy(jobgrade, prevgrade, MAXBASENAME);
    753 	jobgrade[MAXBASENAME] = NULLCHAR;
    754 	return;
    755 }
    756