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