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