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(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 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 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 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