source: trunk/athena/bin/gms/message_daemon.c @ 12181

Revision 12181, 5.9 KB checked in by ghudson, 26 years ago (diff)
Normalize copyright statements and RCS IDs.
Line 
1/* Copyright 1988, 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16static const char rcsid[] = "$Id: message_daemon.c,v 1.13 1998-12-03 19:38:32 ghudson Exp $";
17
18#include "globalmessage.h"
19#ifndef GMS_SERVER_MESSAGE
20#define GMS_SERVER_MESSAGE "/var/gms/Message"
21#endif /* GMS_SERVER_MESSAGE */
22
23#include <sys/types.h>
24#include <stdio.h>
25#include <fcntl.h>
26#include <errno.h>
27#include <sys/socket.h>
28#include <netinet/in.h>
29#include <sys/stat.h>
30#include <string.h>
31#include <syslog.h>
32#include <com_err.h>
33
34/*
35 * This version of the daemon is run out of inetd, with a conf line of:
36 * globalmessage dgram udp wait unswitched nobody /usr/athena/etc/messaged messaged
37 */
38
39#define saddr_list(sin) (unsigned)sin[0],(unsigned)sin[1],(unsigned)sin[2],(unsigned)sin[3]
40int main(argc,argv)
41     int argc;
42     char **argv;
43{
44  char buf[BFSZ];
45  int readstat, readlen, msgfile;
46  struct sockaddr from;
47  /* these strange casts are so that I can print out the address of
48   * the incoming packet.
49   */
50  struct sockaddr_in *cast1 = (struct sockaddr_in *)&from;
51  char *cast2 = (char *)(&(cast1->sin_addr.s_addr));
52  int fromlen = sizeof(from);
53  time_t timestamp;
54  int headerlen;
55
56  /* initialize syslog connection for DAEMON */
57  /* log_pid has the side effect of forcing log messages to be unique,
58   * not listed as ``message the same, repeated 6 times'' but that
59   * shouldn't be a problem.
60   */
61  openlog(argv[0], LOG_PID, LOG_DAEMON);
62 
63  /* gms is just return values; the other com_err tables used will
64   * init themselves.
65   */
66  init_gms_err_tbl();
67
68  /* read the packet from the socket (stdin, since we run from inetd)
69   * and also record the from address so we can send a reply.
70   */
71  readstat = recvfrom(0, buf, BFSZ, 0, &from, &fromlen);
72  if(readstat == -1) {
73    syslog(LOG_INFO, "GMS daemon recvfrom failure %s", error_message(errno));
74    exit(errno);
75  }
76
77  /* We got a packet successfully, so if logging is enabled record the
78   * requesting address.
79   */
80  if(argc>1 && !strcmp(argv[1],"-log")) {
81    syslog(LOG_INFO, "GMS request succeeded [%s] from %ud.%ud.%ud.%ud",
82           buf, saddr_list(cast2));
83  }
84
85  /* Check the version number, and log if it is in error. */
86  if(strncmp(buf, GMS_VERSION_STRING, GMS_VERSION_STRING_LEN)) {
87    syslog(LOG_INFO, "GMS bogus version [%s] from %ud.%ud.%ud.%ud",
88           buf, saddr_list(cast2));
89    exit(GMS_CLIENT_VERSION);
90  }
91
92  /* Open the message file to read it in. Note that even were we to
93   * want to cache the data for efficiency, we must stat the file to
94   * make sure it hasn't changed under us. Since we're running, we
95   * must open it because we have no state.
96   */
97  msgfile = open(GMS_SERVER_MESSAGE, O_RDONLY, 0);
98
99  if(msgfile == -1) {
100    /* no file, special case of 0 timestamp indicating to also delete
101     * the remote cached copy. If the error is ENOENT, then we just
102     * assume it is an expected disappearance; all other errors are
103     * `interesting' and are logged. In any case, the tester can see
104     * that there is no new message.
105     */
106    if(errno == ENOENT) {
107      /* it didn't exist, we can deal with that... */
108      timestamp = 0;
109    } else {
110      /* something went wrong, but we can't do much about it;
111       * let's not trash the remote state -- just don't answer the
112       * connection.
113       */
114      syslog(LOG_INFO, "GMS daemon open error [%s] reading message file <%s>",
115             error_message(errno), GMS_SERVER_MESSAGE);
116      exit(errno);
117    }
118  } else {
119    struct stat sbuf;
120   
121    fstat(msgfile, &sbuf);
122    if(sbuf.st_size == 0) {
123      /* an empty file means the same to the remote as a missing one. */
124      timestamp = 0;
125    } else {
126      /* for convenient maintenance, use the real timestamp as version
127       * number. */
128      timestamp = sbuf.st_mtime;
129    }
130  }
131  strcpy(buf,GMS_VERSION_STRING);
132  {
133    char tsbuf[GMS_TIMESTAMP_LEN];
134
135    /* sprintf (and _doprnt in general) are slow memory hogs. However,
136     * syslog is already including _doprnt, so it's already over; it
137     * is cheaper just to use sprintf here instead of coding or
138     * linking in the fast integer one.
139     * It is almost readable, too...
140     */
141    sprintf(tsbuf, " %lu\n", timestamp);
142    strcat(buf,tsbuf);
143    headerlen = strlen(buf);
144  }
145
146  /* Now that we have the header, we have to read the rest of the file
147   * into the packet after it. The length-1 specification is to
148   * preserve a NUL at the end of the buffer. Use msgfile to remember
149   * that we couldn't open it.
150   */
151  if(msgfile != -1) {
152    readlen = read(msgfile, buf + headerlen, BFSZ-headerlen-1);
153    if(readlen == -1) {
154      /* read failed but open didn't, so record the error */
155      syslog(LOG_INFO, "GMS daemon read error [%s] reading message file <%s>",
156             error_message(errno), GMS_SERVER_MESSAGE);
157      exit(errno);
158    }
159    /* protect the fencepost... */
160    buf[BFSZ-1] = '\0';
161    close(msgfile);
162  } else {
163    readlen = 0;
164  }
165  /* send the packet back where it came from */
166  if(-1 == sendto(0, buf, readlen+headerlen, 0, &from, sizeof(from))) {
167    /* the send failed (probably a local error, or bad address or
168     * something so log the attempt.
169     */
170    syslog(LOG_INFO, "GMS daemon sendto failure [%s] to %d.%d.%d.%d",
171           error_message(errno), saddr_list(cast2));
172    exit(errno);
173  }
174  /* everything worked, die happy... */
175  exit(0);
176}
Note: See TracBrowser for help on using the repository browser.