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