xref: /illumos-gate/usr/src/cmd/bnu/uusched.c (revision 462be471)
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 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #include	"uucp.h"
34 
35 #define USAGE	"[-xNUM] [-uNUM]"
36 #define MAXGRADE	52
37 
38 struct m {
39 	char	mach[15];
40 	char	jgrade[2*MAXGRADE+1];
41 } M[UUSTAT_TBL+2];
42 
43 short Uopt;
44 void cleanup(), exuucico();
45 
46 void logent(){}		/* to load ulockf.c */
47 
48 int
49 main(argc, argv, envp)
50 int argc;
51 char *argv[];
52 char **envp;
53 {
54 	struct m *m, *machine();
55 	DIR *spooldir, *subdir, *gradedir;
56 	char f[256], g[256], fg[256], subf[256];
57 	int numgrade;
58 	char *gradelist, *gradeptr[MAXGRADE+1];
59 	short num, snumber;
60 	char lckname[MAXFULLNAME];
61 	struct limits limitval;
62 	int i, maxnumb;
63 	FILE *fp;
64 
65 	Uopt = 0;
66 	Env = envp;
67 
68 	(void) strcpy(Progname, "uusched");
69 	while ((i = getopt(argc, argv, "u:x:")) != EOF) {
70 		switch(i){
71 		case 'x':
72 			Debug = atoi(optarg);
73 			if (Debug <= 0) {
74 				fprintf(stderr,
75 				"WARNING: %s: invalid debug level %s ignored, using level 1\n",
76 				Progname, optarg);
77 				Debug = 1;
78 			}
79 #ifdef SMALL
80 			fprintf(stderr,
81 			"WARNING: uusched built with SMALL flag defined -- no debug info available\n");
82 #endif /* SMALL */
83 			break;
84 		case 'u':
85 			Uopt = atoi(optarg);
86 			if (Uopt <= 0) {
87 				fprintf(stderr,
88 				"WARNING: %s: invalid debug level %s ignored, using level 1\n",
89 				Progname, optarg);
90 				Uopt = 1;
91 			}
92 			break;
93 		default:
94 			(void) fprintf(stderr, "\tusage: %s %s\n",
95 			    Progname, USAGE);
96 			cleanup(1);
97 		}
98 	}
99 	if (argc != optind) {
100 		(void) fprintf(stderr, "\tusage: %s %s\n", Progname, USAGE);
101 		cleanup(1);
102 	}
103 
104 	DEBUG(9, "Progname (%s): STARTED\n", Progname);
105 	if (scanlimit("uusched", &limitval) == FAIL) {
106 	    DEBUG(1, "No limits for uusched in %s\n", LIMITS);
107 	    maxnumb = -1;
108 	} else {
109 	    maxnumb = limitval.totalmax;
110 	    if (maxnumb < 0) {
111 		DEBUG(4, "Non-positive limit for uusched in %s\n", LIMITS);
112 		DEBUG(1, "No limits for uusched\n%s", "");
113 	    } else {
114 		DEBUG(4, "Uusched limit %d -- ", maxnumb);
115 		i = cuantos(S_LOCKPRE, X_LOCKDIR);
116 		if (i >= maxnumb) {
117 			DEBUG(4, "found %d -- cleaning up\n", i);
118 			cleanup(0);
119 		}
120 		DEBUG(4, "continuing\n", maxnumb);
121 	    }
122 	}
123 
124 	if (chdir(SPOOL) != 0 || (spooldir = opendir(SPOOL)) == NULL)
125 		cleanup(101);		/* good old code 101 */
126 	while (gdirf(spooldir, f, SPOOL) == TRUE) {
127 	    subdir = opendir(f);
128 	    ASSERT(subdir != NULL, Ct_OPEN, f, errno);
129 	    while (gdirf(subdir, g, f) == TRUE) {
130 		(void) sprintf(fg, "%s/%s", f, g);
131 		gradedir = opendir(fg);
132 		ASSERT(gradedir != NULL, Ct_OPEN, g, errno);
133 		while (gnamef(gradedir, subf) == TRUE) {
134 		    if (subf[1] == '.') {
135 		        if (subf[0] == CMDPRE) {
136 			    /* Note - we can break now, since we
137 			     * have found a job grade with at least
138 			     * one C. file.
139 			    */
140 			    (void) strncat(machine(f)->jgrade, g, strlen(g));
141 			    break;
142 			}
143 		    }
144 		}
145 		closedir(gradedir);
146 	    }
147 	    closedir(subdir);
148 	}
149 
150 	/* Make sure the overflow entry is null since it may be incorrect */
151 	M[UUSTAT_TBL].mach[0] = NULLCHAR;
152 
153 	/* count the number of systems */
154 	for (num=0, m=M; m->mach[0] != '\0'; m++, num++) {
155 	    DEBUG(5, "machine: %s, ", M[num].mach);
156 	    DEBUG(5, "job grade list: %s\n", M[num].jgrade);
157 	}
158 	DEBUG(5, "Execute num=%d \n", num);
159 	while (num > 0) {
160 	    /*
161 	     * create lock file once we have work to do
162 	     * (but only if there is a job limit)
163 	     */
164 	    if (maxnumb > 0) {
165 	    	    for (i = 0; i < maxnumb; i++) {
166 			    (void) sprintf(lckname, "%s.%d", S_LOCK, i);
167 			    if (mklock(lckname) == SUCCESS)
168 			    	    break;
169 		    }
170 		    if (i == maxnumb) {
171 			    DEBUG(4, "found %d -- cleaning up\n", i);
172 			    cleanup(0);
173 		    }
174 	    }
175 	    snumber = (time((time_t *) 0) % num);  /* random num */
176 	    (void) strcpy(Rmtname, M[snumber].mach);
177 	    gradelist = M[snumber].jgrade;
178 	    DEBUG(5, "num=%d, ", num);
179 	    DEBUG(5, "snumber=%d, ", snumber);
180 	    DEBUG(5, "Rmtname=%s, ", Rmtname);
181 	    DEBUG(5, "job grade list= %s\n", gradelist);
182 
183 	    numgrade = getargs(gradelist, gradeptr, MAXGRADE);
184 	    for (i=0; i<numgrade; i++) {
185 		(void) sprintf(lckname, "%s.%s.%s", LOCKPRE, Rmtname, gradeptr[i]);
186 		if (cklock(lckname) != FAIL && callok(Rmtname) == 0) {
187 		    /* no lock file and status time ok */
188 		    DEBUG(5, "call exuucico(%s)\n", Rmtname);
189 		    exuucico(Rmtname);
190 		    break;
191 		}
192 		else {
193 		    /* job grade locked - look for the next one */
194 		    DEBUG(5, "job grade %s locked or inappropriate status\n",
195 			gradeptr[i]);
196 		}
197 	    }
198 
199 	    M[snumber] = M[num-1];
200 	    num--;
201 	}
202 	cleanup(0);
203 
204 	/* NOTREACHED */
205 	return (0);
206 }
207 
208 struct m	*
209 machine(name)
210 char	*name;
211 {
212 	struct m *m;
213 	size_t	namelen;
214 
215 	namelen = strlen(name);
216 	DEBUG(9, "machine(%s) called\n", name);
217 	for (m = M; m->mach[0] != '\0'; m++)
218 		/* match on overlap? */
219 		if (EQUALSN(name, m->mach, MAXBASENAME)) {
220 			/* check for job grade */
221 			if (m->jgrade[0] != NULLCHAR)
222 				(void) strncat(m->jgrade, " ", 1);
223 
224 			/* use longest name */
225 			if (namelen > strlen(m->mach))
226 				(void) strcpy(m->mach, name);
227 			return(m);
228 		}
229 
230 	/*
231 	 * The table is set up with 2 extra entries
232 	 * When we go over by one, output error to errors log
233 	 * When more than one over, just reuse the previous entry
234 	 */
235 	if (m-M >= UUSTAT_TBL) {
236 	    if (m-M == UUSTAT_TBL) {
237 		errent("MACHINE TABLE FULL", "", UUSTAT_TBL,
238 		__FILE__, __LINE__);
239 	    }
240 	    else
241 		/* use the last entry - overwrite it */
242 		m = &M[UUSTAT_TBL];
243 	}
244 
245 	(void) strcpy(m->mach, name);
246 	m->jgrade[0] = NULLCHAR;
247 	return(m);
248 }
249 
250 void
251 exuucico(name)
252 char *name;
253 {
254 	char cmd[BUFSIZ];
255 	int status;
256 	pid_t pid, ret;
257 	char uopt[5];
258 	char sopt[BUFSIZ];
259 
260 	(void) sprintf(sopt, "-s%s", name);
261 	if (Uopt)
262 	    (void) sprintf(uopt, "-x%.1d", Uopt);
263 
264 	if ((pid = vfork()) == 0) {
265 	    if (Uopt)
266 	        (void) execle(UUCICO, "UUCICO", "-r1", uopt, sopt, (char *) 0, Env);
267 	    else
268 	        (void) execle(UUCICO, "UUCICO", "-r1", sopt, (char *) 0, Env);
269 
270 	    cleanup(100);
271 	}
272 	while ((ret = wait(&status)) != pid)
273 	    if (ret == -1 && errno != EINTR)
274 		break;
275 
276 	DEBUG(3, "ret=%ld, ", (ret == pid ? (long) status : (long) ret));
277 	return;
278 }
279 
280 
281 void
282 cleanup(code)
283 int	code;
284 {
285 	rmlock(CNULL);
286 	exit(code);
287 }
288