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 This module contains routines that find C. files
34 in a system spool directory, return the next C. file
35 to process, and break up the C. line into arguments
36 for processing.
37 */
38
39 #include "uucp.h"
40
41 #define BOOKMARK_PRE 'A'
42 #define CLEAN_RETURN(fp) {\
43 if (fp != NULL) \
44 (void) fclose(fp); \
45 fp = NULL; \
46 return(0); \
47 /* NOTREACHED */ \
48 }
49
50 /* C.princetN0026 - ('C' + '.') - "princet" */
51 #define SUFSIZE (MAXBASENAME - 2 - SYSNSIZE)
52 #define LLEN 50
53 #define MAXRQST 250
54
55 static void insert();
56 static int anlwrk(), bldflst();
57 extern int iswrk(), gtwvec(), gnamef();
58
59 static char Filent[LLEN][NAMESIZE]; /* array of C. file names (text) */
60 static char *Fptr[LLEN]; /* pointers to names in Filent */
61 static short Nnext; /* index of next C. file in Fptr list */
62 static short Nfiles = 0; /* Number of files in Filent */
63
64 /*
65 * read a line from the workfile (C.file)
66 * file -> work file (Input/Output) made '\0' after work completion
67 * wvec -> address of array to return arguments (Output)
68 * wcount -> maximum # of arguments to return in wvec
69 * NOTE: wvec should be large enough to accept wcount + 1 pointers
70 * since NULL is inserted after last item.
71 * returns:
72 * 0 -> no more work in this file
73 * positive # -> number of arguments
74 */
75 static int
anlwrk(file,wvec,wcount)76 anlwrk(file, wvec, wcount)
77 char *file, **wvec;
78 {
79 int i;
80 FILE *p_bookmark; /* pointer to afile */
81 static FILE *fp = NULL; /* currently opened C. file pointer */
82 static char afile[NAMESIZE]; /* file with line count for book marks */
83 static char str[MAXRQST]; /* the string which wvec points to */
84 static short acount;
85 struct stat stbuf;
86 int nargs; /* return value == # args in the line */
87
88 if (file[0] == '\0') {
89 if (fp != NULL)
90 errent("anlwrk",
91 "attempt made to use old workfile was thwarted", 0,
92 __FILE__, __LINE__);
93 CLEAN_RETURN(fp);
94 /* NOTREACHED */
95 }
96 if (fp == NULL) {
97 fp = fopen(file, "r");
98
99 if (fp == NULL){ /* can't open C. file! */
100 errent(Ct_OPEN,file,errno, __FILE__, __LINE__);
101 /* this may not work, but we'll try it */
102 /* It will fail if the C. name is more than */
103 /* the standard 14 characters - if this is the */
104 /* tocorrupt will exit with ASSERT */
105 toCorrupt(file);
106 return(0);
107 }
108 (void) fstat(fileno(fp), &stbuf);
109 Nstat.t_qtime = stbuf.st_mtime;
110
111 (void) strncpy(afile, BASENAME(file, '/'), NAMESIZE);
112 afile[NAMESIZE-1] = NULLCHAR;
113 *afile = BOOKMARK_PRE; /* make up name by replacing C with A */
114 acount = 0;
115 p_bookmark = fopen(afile, "r");
116 if (p_bookmark != NULL) {
117 /* get count of already completed work */
118 i = fscanf(p_bookmark, "%hd", &acount);
119 (void) fclose(p_bookmark);
120 if (i <= 0)
121 acount = 0;
122
123 /* skip lines which have already been processed */
124 for (i = 0; i < acount; i++) {
125 if (fgets(str, MAXRQST, fp) == NULL)
126 break;
127 }
128 }
129
130 }
131
132 if (fgets(str, MAXRQST, fp) == NULL) {
133 ASSERT(unlink(file) == 0, Ct_UNLINK, file, errno);
134 (void) unlink(afile);
135 DEBUG(4,"Finished Processing file: %s\n",file);
136 *file = '\0';
137 CLEAN_RETURN(fp);
138 /*NOTREACHED*/
139 }
140
141 nargs = getargs(str, wvec, wcount);
142
143 /* sanity checks for C. file */
144 if ((str[0] != 'R' && str[0] != 'S') /* legal wrktypes are R and S */
145 || (str[0] == 'R' && nargs < 6) /* R lines need >= 6 entries */
146 || (str[0] == 'S' && nargs < 7)) { /* S lines need >= 7 entries */
147 /* bad C. file - stash it */
148 toCorrupt(file);
149 (void) unlink(afile);
150 *file = '\0';
151 CLEAN_RETURN(fp);
152 /*NOTREACHED*/
153 }
154
155 p_bookmark = fopen(afile, "w"); /* update bookmark file */
156 if (p_bookmark == NULL)
157 errent(Ct_OPEN, afile, errno, __FILE__, __LINE__);
158 else {
159 chmod(afile, CFILEMODE);
160 (void) fprintf(p_bookmark, "%d", acount);
161 (void) fclose(p_bookmark);
162 }
163 acount++;
164 return(nargs);
165 }
166
167 /*
168 * Check the list of work files (C.sys).
169 * If it is empty or the present work is exhausted, it
170 * will call bldflst to generate a new list.
171 *
172 * If there are no more jobs in the current job grade,
173 * it will call findgrade to get the new job grade to process.
174 *
175 * file -> address of array to return full pathname in
176 * returns:
177 * 0 -> no more work (or some error)
178 * 1 -> there is work
179 */
180 extern int
181 iswrk(file)
182 char *file;
183 {
184 char newspool[MAXFULLNAME];
185 char lockname[MAXFULLNAME];
186 char gradedir[2*MAXBASENAME];
187
188 if (Nfiles == 0) {
189 /* If Role is MASTER and JobGrade is null, then
190 * there is no work for the remote.
191 *
192 * In the case of uucico slave, the job grade
193 * to process should be determined before building
194 * the work list.
195 */
196 if (Role == MASTER) {
197 if (*JobGrade == NULLCHAR)
198 return(0);
199
200 if (bldflst() != 0) {
201 (void) sprintf(file, "%s/%s", RemSpool, Fptr[Nnext]);
202 Nfiles--;
203 Nnext++;
204 return(1);
205 }
206 (void) sprintf(lockname, "%.*s.%s", SYSNSIZE, Rmtname, JobGrade);
207 delock(LOCKPRE, lockname);
208 } else {
209 (void) sprintf(lockname, "%ld", (long) getpid());
210 delock(LOCKPRE, lockname);
211 }
212
213 (void) sprintf(newspool, "%s/%s", SPOOL, Rmtname);
214 ASSERT(chdir(newspool) == 0, Ct_CHDIR, newspool, errno);
215
216 findgrade(newspool, JobGrade);
217 DEBUG(4, "Job grade to process - %s\n", JobGrade);
218 if (*JobGrade == NULLCHAR)
219 return(0);
220
221 (void) sprintf(lockname, "%.*s.%s", SYSNSIZE, Rmtname, JobGrade);
222 (void) umlock(LOCKPRE, lockname);
223
224 /* Make the new job grade directory the working directory
225 * and set RemSpool.
226 */
227 (void) sprintf(gradedir, "%s/%s", Rmtname, JobGrade);
228 chremdir(gradedir);
229 bldflst();
230 }
231
232 (void) sprintf(file, "%s/%s", RemSpool, Fptr[Nnext]);
233 Nfiles--;
234 Nnext++;
235 return(1);
236 }
237
238
239 /*
240 * build list of work files for given system using an insertion sort
241 * Nfiles, Nnext, RemSpool and Rmtname are global
242 *
243 * return:
244 * number of C. files in list - (Nfiles)
245 */
246 static int
bldflst()247 bldflst()
248 {
249 DIR *pdir;
250 char filename[NAMESIZE];
251 char prefix[SYSNSIZE+3];
252
253 Nnext = Nfiles = 0;
254 if ((pdir = opendir(RemSpool)) == NULL)
255 return(0);
256
257 (void) sprintf(prefix, "C.%.*s", SYSNSIZE, Rmtname);
258 while (gnamef(pdir, filename) ) {
259 if (!PREFIX(prefix, filename))
260 continue;
261 if ((strlen(filename)-strlen(prefix)) != SUFSIZE) {
262 errent("bldflst: Funny filename", filename, 0,
263 __FILE__, __LINE__);
264 continue;
265 }
266 insert(filename);
267 }
268 closedir(pdir);
269 return(Nfiles);
270 }
271
272 /*
273 * get work return
274 * file -> place to deposit file name
275 * wrkvec -> array to return arguments
276 * wcount -> max number of args for wrkvec
277 * returns:
278 * nargs -> number of arguments
279 * 0 -> no arguments - fail
280 */
281 extern int
282 gtwvec(file, wrkvec, wcount)
283 char *file, **wrkvec;
284 {
285 int nargs;
286
287 DEBUG(7, "gtwvec: dir %s\n", RemSpool);
288 while ((nargs = anlwrk(file, wrkvec, wcount)) == 0) {
289 if (!iswrk(file))
290 return(0);
291 }
292 DEBUG(7, " return - %d\n", nargs);
293 return(nargs);
294 }
295
296
297 /*
298 * insert - insert file name in sorted list
299 * return - none
300 */
301 static void
insert(file)302 insert(file)
303 char *file;
304 {
305 int i, j;
306 char *p;
307
308 DEBUG(7, "insert(%s) ", file);
309 for (i = Nfiles; i>0; i--) {
310 if (strcmp(file, Fptr[i-1]) > 0)
311 break;
312 }
313 if (i == LLEN) /* if this is off the end get out */
314 return;
315
316 /* get p (pointer) to where the text of name will go */
317 if (Nfiles == LLEN) /* last possible entry */
318 /* put in text of last and decrement Nfiles for make hole */
319 p = strcpy(Fptr[--Nfiles], file);
320 else
321 p = strcpy(Filent[Nfiles], file); /* copy to next free */
322
323 /* make a hole for new entry */
324 for (j = Nfiles; j >i; j--)
325 Fptr[j] = Fptr[j-1];
326
327 DEBUG(7, "insert %s ", p);
328 DEBUG(7, "at %d\n", i);
329 Fptr[i] = p;
330 Nfiles++;
331 return;
332 }
333