xref: /illumos-gate/usr/src/cmd/bnu/anlwrk.c (revision 5422785d352a2bb398daceab3d1898a8aa64d006)
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
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
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
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