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

Revision 3235, 5.7 KB checked in by epeisach, 34 years ago (diff)
4.2 SYSLOG fix
Line 
1/* This file is part of the Project Athena Global Message System.
2 * Created by: Mark W. Eichin <eichin@athena.mit.edu>
3 * $Source: /afs/dev.mit.edu/source/repository/athena/bin/gms/message_daemon.c,v $
4 * $Author: epeisach $
5 *
6 *      Copyright (c) 1988 by the Massachusetts Institute of Technology.
7 *      For copying and distribution information, see the file
8 *      "mit-copyright.h".
9 */
10#include <mit-copyright.h>
11#ifndef lint
12static char rcsid_message_daemon_c[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/gms/message_daemon.c,v 1.5 1990-07-12 14:04:36 epeisach Exp $";
13#endif lint
14
15#include "globalmessage.h"
16#ifndef GMS_SERVER_MESSAGE
17#define GMS_SERVER_MESSAGE "/site/Message"
18#endif /* GMS_SERVER_MESSAGE */
19
20#include <fcntl.h>
21#include <errno.h>
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <sys/stat.h>
26
27/*
28 * This version of the daemon is run out of inetd, with a conf line of:
29 * globalmessage dgram udp wait unswitched nobody /etc/messaged messaged
30 */
31#include <syslog.h>
32char *error_message();
33
34#define saddr_list(sin) (unsigned)sin[0],(unsigned)sin[1],(unsigned)sin[2],(unsigned)sin[3]
35main(argc,argv)
36     int argc;
37     char **argv;
38{
39  char buf[BFSZ];
40  int readstat, errstat, readlen, msgfile;
41  char *index();
42  struct sockaddr from;
43  /* these strange casts are so that I can print out the address of
44   * the incoming packet.
45   */
46  struct sockaddr_in *cast1 = (struct sockaddr_in *)&from;
47  char *cast2 = (char *)(&(cast1->sin_addr.s_addr));
48  int fromlen = sizeof(from);
49  time_t timestamp;
50  int headerlen;
51
52  /* initialize syslog connection for DAEMON */
53  /* log_pid has the side effect of forcing log messages to be unique,
54   * not listed as ``message the same, repeated 6 times'' but that
55   * shouldn't be a problem.
56   */
57#ifdef LOG_DAEMON
58  openlog(argv[0], LOG_PID, LOG_DAEMON);
59#else
60  openlog(argv[0], LOG_PID);
61#endif
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  }
163  /* send the packet back where it came from */
164  if(-1 == sendto(0, buf, readlen+headerlen, 0, &from, sizeof(from))) {
165    /* the send failed (probably a local error, or bad address or
166     * something so log the attempt.
167     */
168    syslog(LOG_INFO, "GMS daemon sendto failure [%s] to %d.%d.%d.%d",
169           error_message(errno), saddr_list(cast2));
170    exit(errno);
171  }
172  /* everything worked, die happy... */
173  exit(0);
174}
Note: See TracBrowser for help on using the repository browser.