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
chkgrp(carray,na)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
chkusr(carray,na)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
fgrade(scfile)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
fdgrade()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
job_size(scfile)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
jsize(scfile,climit,nlimit)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
lcase(s,t,lim)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
mailAdmin(msg)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
putdfiles(scfile)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
rdfulline(fd,line,lim)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
upermit(carray,na)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
vergrd(grade)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
wfremove(file)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
findgrade(dir,jobgrade)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