1/* status.c 2 Routines to get and set the status for a system. 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#include "uudefs.h" 28#include "uuconf.h" 29#include "sysdep.h" 30#include "system.h" 31 32#include <errno.h> 33#include <ctype.h> 34 35#if SPOOLDIR_HDB || SPOOLDIR_SVR4 36 37/* If we are using HDB spool layout, store status using HDB status 38 values. SVR4 is a variant of HDB. */ 39 40#define MAP_STATUS 1 41 42static const int aiMapstatus[] = 43{ 44 0, 13, 7, 6, 20, 4, 3, 2 45}; 46#define CMAPENTRIES (sizeof (aiMapstatus) / sizeof (aiMapstatus[0])) 47 48#else /* ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4 */ 49 50#define MAP_STATUS 0 51 52#endif /* ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4 */ 53 54/* Get the status of a system. This assumes that we are in the spool 55 directory. */ 56 57boolean 58fsysdep_get_status (qsys, qret, pfnone) 59 const struct uuconf_system *qsys; 60 struct sstatus *qret; 61 boolean *pfnone; 62{ 63 char *zname; 64 FILE *e; 65 char *zline; 66 char *zend, *znext; 67 boolean fbad; 68 int istat; 69 70 if (pfnone != NULL) 71 *pfnone = FALSE; 72 73 zname = zsysdep_in_dir (".Status", qsys->uuconf_zname); 74 e = fopen (zname, "r"); 75 if (e == NULL) 76 { 77 if (errno != ENOENT) 78 { 79 ulog (LOG_ERROR, "fopen (%s): %s", zname, strerror (errno)); 80 ubuffree (zname); 81 return FALSE; 82 } 83 zline = NULL; 84 } 85 else 86 { 87 size_t cline; 88 89 zline = NULL; 90 cline = 0; 91 if (getline (&zline, &cline, e) <= 0) 92 { 93 xfree ((pointer) zline); 94 zline = NULL; 95 } 96 (void) fclose (e); 97 } 98 99 if (zline == NULL) 100 { 101 /* There is either no status file for this system, or it's been 102 truncated, so fake a good status. */ 103 qret->ttype = STATUS_COMPLETE; 104 qret->cretries = 0; 105 qret->ilast = 0; 106 qret->cwait = 0; 107 qret->zstring = NULL; 108 if (pfnone != NULL) 109 *pfnone = TRUE; 110 ubuffree (zname); 111 return TRUE; 112 } 113 114 /* It turns out that scanf is not used much in this program, so for 115 the benefit of small computers we avoid linking it in. This is 116 basically 117 118 sscanf (zline, "%d %d %ld %d", &qret->ttype, &qret->cretries, 119 &qret->ilast, &qret->cwait); 120 121 except that it's done with strtol. */ 122 123 fbad = FALSE; 124 istat = (int) strtol (zline, &zend, 10); 125 if (zend == zline) 126 fbad = TRUE; 127 128#if MAP_STATUS 129 /* On some systems it may be appropriate to map system dependent status 130 values on to our status values. */ 131 { 132 int i; 133 134 for (i = 0; i < CMAPENTRIES; ++i) 135 { 136 if (aiMapstatus[i] == istat) 137 { 138 istat = i; 139 break; 140 } 141 } 142 } 143#endif /* MAP_STATUS */ 144 145 if (istat < 0 || istat >= (int) STATUS_VALUES) 146 istat = (int) STATUS_COMPLETE; 147 qret->ttype = (enum tstatus_type) istat; 148 znext = zend; 149 qret->cretries = (int) strtol (znext, &zend, 10); 150 if (zend == znext) 151 fbad = TRUE; 152 znext = zend; 153 qret->ilast = strtol (znext, &zend, 10); 154 if (zend == znext) 155 fbad = TRUE; 156 znext = zend; 157 qret->cwait = (int) strtol (znext, &zend, 10); 158 if (zend == znext) 159 fbad = TRUE; 160 161 if (! fbad) 162 { 163 znext = zend; 164 while (isspace (BUCHAR (*znext))) 165 ++znext; 166 if (*znext == '\0') 167 qret->zstring = NULL; 168 else 169 { 170 if (*znext == '"') 171 ++znext; 172 qret->zstring = zbufcpy (znext); 173 zend = qret->zstring + strlen (qret->zstring); 174 while (zend != qret->zstring && *zend != ' ') 175 --zend; 176 if (zend != qret->zstring && zend[-1] == '"') 177 --zend; 178 if (zend != qret->zstring) 179 *zend = '\0'; 180 else 181 { 182 ubuffree (qret->zstring); 183 qret->zstring = NULL; 184 } 185 } 186 } 187 188 xfree ((pointer) zline); 189 190 if (fbad) 191 { 192 ulog (LOG_ERROR, "%s: Bad status file format", zname); 193 ubuffree (zname); 194 return FALSE; 195 } 196 197 ubuffree (zname); 198 199 return TRUE; 200} 201 202/* Set the status of a remote system. This assumes the system is 203 locked when this is called, and that the program is in the spool 204 directory. */ 205 206boolean 207fsysdep_set_status (qsys, qset) 208 const struct uuconf_system *qsys; 209 const struct sstatus *qset; 210{ 211 char *zname; 212 FILE *e; 213 int istat; 214 215 zname = zsysdep_in_dir (".Status", qsys->uuconf_zname); 216 217 e = esysdep_fopen (zname, TRUE, FALSE, TRUE); 218 ubuffree (zname); 219 if (e == NULL) 220 return FALSE; 221 istat = (int) qset->ttype; 222 223#if MAP_STATUS 224 /* On some systems it may be appropriate to map istat onto a system 225 dependent number. */ 226 if (istat >= 0 && istat < CMAPENTRIES) 227 istat = aiMapstatus[istat]; 228#endif /* MAP_STATUS */ 229 230 fprintf (e, "%d %d %ld %d ", istat, qset->cretries, qset->ilast, 231 qset->cwait); 232 233#if SPOOLDIR_SVR4 234 fprintf (e, "\"%s\"", azStatus[(int) qset->ttype]); 235#else 236 fprintf (e, "%s", azStatus[(int) qset->ttype]); 237#endif 238 239 fprintf (e, " %s\n", qsys->uuconf_zname); 240 if (fclose (e) != 0) 241 { 242 ulog (LOG_ERROR, "fclose: %s", strerror (errno)); 243 return FALSE; 244 } 245 246 return TRUE; 247} 248