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