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