1/* xqtfil.c 2 Routines to read execute files. 3 4 Copyright (C) 1991, 1992, 1993, 1995, 2002 Ian Lance Taylor 5 6 This file is part of the Taylor UUCP package. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucp.h" 26 27#if USE_RCS_ID 28const char xqtfil_rcsid[] = "$Id: xqtfil.c,v 1.13 2002/03/05 19:10:42 ian Rel $"; 29#endif 30 31#include "uudefs.h" 32#include "sysdep.h" 33#include "system.h" 34 35#include <errno.h> 36 37#if HAVE_OPENDIR 38#if HAVE_DIRENT_H 39#include <dirent.h> 40#else /* ! HAVE_DIRENT_H */ 41#include <sys/dir.h> 42#define dirent direct 43#endif /* ! HAVE_DIRENT_H */ 44#endif /* HAVE_OPENDIR */ 45 46/* Under the V2 or BSD42 spool directory scheme, all execute files are 47 in the main spool directory. Under the BSD43 scheme, they are all 48 in the directory X.. Under the HDB or SVR4 scheme, they are in 49 directories named after systems. Under the ULTRIX scheme, they are 50 in X. subdirectories of subdirectories of sys. Under the TAYLOR 51 scheme, they are all in the subdirectory X. of a directory named 52 after the system. 53 54 This means that for HDB, ULTRIX, SVR4 or TAYLOR, we have to search 55 directories of directories. */ 56 57#if SPOOLDIR_V2 || SPOOLDIR_BSD42 58#define ZDIR "." 59#define SUBDIRS 0 60#endif 61#if SPOOLDIR_HDB || SPOOLDIR_SVR4 || SPOOLDIR_TAYLOR 62#define ZDIR "." 63#define SUBDIRS 1 64#endif 65#if SPOOLDIR_ULTRIX 66#define ZDIR "sys" 67#define SUBDIRS 1 68#endif 69#if SPOOLDIR_BSD43 70#define ZDIR "X." 71#define SUBDIRS 0 72#endif 73 74/* Static variables for the execute file scan. */ 75 76static DIR *qSxqt_topdir; 77#if ! SUBDIRS 78static const char *zSdir; 79#else /* SUBDIRS */ 80static boolean fSone_dir; 81static char *zSdir; 82static DIR *qSxqt_dir; 83static char *zSsystem; 84#endif /* SUBDIRS */ 85 86/* Initialize the scan for execute files. The function 87 usysdep_get_xqt_free will clear the data out when we are done with 88 the system. This returns FALSE on error. */ 89 90/*ARGSUSED*/ 91boolean 92fsysdep_get_xqt_init (zsystem) 93 const char *zsystem; 94{ 95 usysdep_get_xqt_free ((const char *) NULL); 96 97#if SUBDIRS 98 if (zsystem != NULL) 99 { 100#if SPOOLDIR_HDB || SPOOLDIR_SVR4 101 zSdir = zbufcpy (zsystem); 102#endif 103#if SPOOLDIR_ULTRIX 104 zSdir = zsappend3 ("sys", zsystem, "X."); 105#endif 106#if SPOOLDIR_TAYLOR 107 zSdir = zsysdep_in_dir (zsystem, "X."); 108#endif 109 110 qSxqt_dir = opendir ((char *) zSdir); 111 if (qSxqt_dir != NULL) 112 { 113 qSxqt_topdir = qSxqt_dir; 114 fSone_dir = TRUE; 115 zSsystem = zbufcpy (zsystem); 116 return TRUE; 117 } 118 } 119 120 fSone_dir = FALSE; 121#endif 122 123 qSxqt_topdir = opendir ((char *) ZDIR); 124 if (qSxqt_topdir == NULL) 125 { 126 if (errno == ENOENT) 127 return TRUE; 128 ulog (LOG_ERROR, "opendir (%s): %s", ZDIR, strerror (errno)); 129 return FALSE; 130 } 131 132 return TRUE; 133} 134 135/* Return the name of the next execute file to read and process. If 136 this returns NULL, *pferr must be checked. If will be TRUE on 137 error, FALSE if there are no more files. On a successful return 138 *pzsystem will be set to the system for which the execute file was 139 created. */ 140 141/*ARGSUSED*/ 142char * 143zsysdep_get_xqt (zsystem, pzsystem, pferr) 144 const char *zsystem ATTRIBUTE_UNUSED; 145 char **pzsystem; 146 boolean *pferr; 147{ 148 *pferr = FALSE; 149 150 if (qSxqt_topdir == NULL) 151 return NULL; 152 153 /* This loop continues until we find a file. */ 154 while (TRUE) 155 { 156 DIR *qdir; 157 struct dirent *q; 158 159#if ! SUBDIRS 160 zSdir = ZDIR; 161 qdir = qSxqt_topdir; 162#else /* SUBDIRS */ 163 /* This loop continues until we find a subdirectory to read. */ 164 while (qSxqt_dir == NULL) 165 { 166 struct dirent *qtop; 167 168 qtop = readdir (qSxqt_topdir); 169 if (qtop == NULL) 170 { 171 (void) closedir (qSxqt_topdir); 172 qSxqt_topdir = NULL; 173 return NULL; 174 } 175 176 /* No system name may start with a dot This allows us to 177 quickly skip impossible directories. */ 178 if (qtop->d_name[0] == '.') 179 continue; 180 181 DEBUG_MESSAGE1 (DEBUG_SPOOLDIR, 182 "zsysdep_get_xqt: Found %s in top directory", 183 qtop->d_name); 184 185 ubuffree (zSdir); 186 187#if SPOOLDIR_HDB || SPOOLDIR_SVR4 188 zSdir = zbufcpy (qtop->d_name); 189#endif 190#if SPOOLDIR_ULTRIX 191 zSdir = zsappend3 ("sys", qtop->d_name, "X."); 192#endif 193#if SPOOLDIR_TAYLOR 194 zSdir = zsysdep_in_dir (qtop->d_name, "X."); 195#endif 196 197 ubuffree (zSsystem); 198 zSsystem = zbufcpy (qtop->d_name); 199 200 qSxqt_dir = opendir (zSdir); 201 202 if (qSxqt_dir == NULL 203 && errno != ENOTDIR 204 && errno != ENOENT) 205 ulog (LOG_ERROR, "opendir (%s): %s", zSdir, strerror (errno)); 206 } 207 208 qdir = qSxqt_dir; 209#endif /* SUBDIRS */ 210 211 q = readdir (qdir); 212 213#if DEBUG > 1 214 if (q != NULL) 215 DEBUG_MESSAGE2 (DEBUG_SPOOLDIR, 216 "zsysdep_get_xqt: Found %s in subdirectory %s", 217 q->d_name, zSdir); 218#endif 219 220 /* If we've found an execute file, return it. We have to get 221 the system name, which is easy for HDB or TAYLOR. For other 222 spool directory schemes, we have to pull it out of the X. 223 file name; this would be insecure, except that zsfind_file 224 clobbers the file name to include the real system name. */ 225 if (q != NULL 226 && q->d_name[0] == 'X' 227 && q->d_name[1] == '.') 228 { 229 char *zret; 230 231#if SPOOLDIR_HDB || SPOOLDIR_SVR4 || SPOOLDIR_TAYLOR 232 *pzsystem = zbufcpy (zSsystem); 233#else 234 { 235 size_t clen; 236 237 clen = strlen (q->d_name) - 7; 238 *pzsystem = zbufalc (clen + 1); 239 memcpy (*pzsystem, q->d_name + 2, clen); 240 (*pzsystem)[clen] = '\0'; 241 } 242#endif 243 244 zret = zsysdep_in_dir (zSdir, q->d_name); 245#if DEBUG > 1 246 DEBUG_MESSAGE2 (DEBUG_SPOOLDIR, 247 "zsysdep_get_xqt: Returning %s (system %s)", 248 zret, *pzsystem); 249#endif 250 return zret; 251 } 252 253 /* If we've reached the end of the directory, then if we are 254 using subdirectories loop around to read the next one, 255 otherwise we are finished. */ 256 if (q == NULL) 257 { 258 (void) closedir (qdir); 259 260#if SUBDIRS 261 qSxqt_dir = NULL; 262 if (! fSone_dir) 263 continue; 264#endif 265 266 qSxqt_topdir = NULL; 267 return NULL; 268 } 269 } 270} 271 272/* Free up the results of an execute file scan, when we're done with 273 this system. */ 274 275/*ARGSUSED*/ 276void 277usysdep_get_xqt_free (zsystem) 278 const char *zsystem ATTRIBUTE_UNUSED; 279{ 280 if (qSxqt_topdir != NULL) 281 { 282 (void) closedir (qSxqt_topdir); 283 qSxqt_topdir = NULL; 284 } 285#if SUBDIRS 286 if (qSxqt_dir != NULL) 287 { 288 (void) closedir (qSxqt_dir); 289 qSxqt_dir = NULL; 290 } 291 ubuffree (zSdir); 292 zSdir = NULL; 293 ubuffree (zSsystem); 294 zSsystem = NULL; 295 fSone_dir = FALSE; 296#endif 297} 298