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