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