]> arthur.barton.de Git - netatalk.git/blob - contrib/timelord/timelord.c
massive commenting/autoconf changes
[netatalk.git] / contrib / timelord / timelord.c
1 /*
2  * $Id: timelord.c,v 1.5 2001-06-29 14:14:46 rufustfirefly Exp $
3  *
4  * Copyright (c) 1990,1992 Regents of The University of Michigan.
5  * All Rights Reserved. See COPYRIGHT.
6  *
7  * The "timelord protocol" was reverse engineered from Timelord,
8  * distributed with CAP, Copyright (c) 1990, The University of
9  * Melbourne.  The following copyright, supplied by The University
10  * of Melbourne, may apply to this code:
11  *
12  *      This version of timelord.c is based on code distributed
13  *      by the University of Melbourne as part of the CAP package.
14  *
15  *      The tardis/Timelord package for Macintosh/CAP is
16  *      Copyright (c) 1990, The University of Melbourne.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif /* HAVE_CONFIG_H */
22
23 #include <sys/param.h>
24 #include <sys/types.h>
25 #include <sys/time.h>
26 #include <sys/file.h>
27 #include <sys/uio.h>
28 #include <netatalk/at.h>
29 #include <netatalk/endian.h>
30 #include <atalk/atp.h>
31
32 #include <time.h>
33 #ifdef HAVE_SGTTY_H
34 #include <sgtty.h>
35 #endif /* HAVE_SGTTY_H */
36 #include <signal.h>
37 #include <syslog.h>
38 #include <stdio.h>
39 #include <strings.h>
40 #ifdef HAVE_NETDB_H
41 #include <netdb.h>
42 #endif /* HAVE_NETDB_H */
43
44 #ifdef HAVE_FCNTL_H
45 #include <fcntl.h>
46 #endif /* HAVE_FCNTL_H */
47 #ifdef HAVE_SYS_FCNTL_H
48 #include <sys/fcntl.h>
49 #endif /* HAVE_SYS_FCNTL_H */
50
51 #ifdef HAVE_TERMIOS_H
52 #include <termios.h>
53 #endif /* HAVE_TERMIOS_H */
54 #ifdef HAVE_SYS_TERMIOS_H
55 #include <sys/termios.h>
56 #endif /* HAVE_SYS_TERMIOS_H */
57
58 #define TL_GETTIME      0
59 #define TL_OK           12
60 #define TL_BAD          10
61 #define EPOCH           0x7C25B080      /* 00:00:00 GMT Jan 1, 1970 for Mac */
62
63 int     debug = 0;
64 char    *bad = "Bad request!";
65 char    buf[ 4624 ];
66 char    *server;
67
68 usage( p )
69     char        *p;
70 {
71     char        *s;
72
73     if (( s = rindex( p, '/' )) == NULL ) {
74         s = p;
75     } else {
76         s++;
77     }
78     fprintf( stderr, "Usage:\t%s -d -n nbpname\n", s );
79     exit( 1 );
80 }
81
82 /*
83  * Unregister ourself on signal.
84  */
85 void
86 goaway(int signal)
87 {
88     if ( nbp_unrgstr( server, "TimeLord", "*" ) < 0 ) {
89         syslog( LOG_ERR, "Can't unregister %s", server );
90         exit( 1 );
91     }
92     syslog( LOG_INFO, "going down" );
93     exit( 0 );
94 }
95
96 main( ac, av )
97     int         ac;
98     char        **av;
99 {
100     ATP                 atp;
101     struct sockaddr_at  sat;
102     struct atp_block    atpb;
103     struct timeval      tv;
104     struct timezone     tz;
105     struct iovec        iov;
106     struct tm           *tm;
107     char                hostname[ MAXHOSTNAMELEN ];
108     char                *p;
109     int                 c;
110     long                req, mtime, resp;
111     extern char         *optarg;
112     extern int          optind;
113
114     if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
115         perror( "gethostname" );
116         exit( 1 );
117     }
118     if (( server = index( hostname, '.' )) != 0 ) {
119         *server = '\0';
120     }
121     server = hostname;
122
123     while (( c = getopt( ac, av, "dn:" )) != EOF ) {
124         switch ( c ) {
125         case 'd' :
126             debug++;
127             break;
128         case 'n' :
129             server = optarg;
130             break;
131         default :
132             fprintf( stderr, "Unknown option -- '%c'\n", c );
133             usage( *av );
134         }
135     }
136
137     /*
138      * Disassociate from controlling tty.
139      */
140     if ( !debug ) {
141         int             i, dt;
142
143         switch ( fork()) {
144         case 0 :
145             dt = getdtablesize();
146             for ( i = 0; i < dt; i++ ) {
147                 (void)close( i );
148             }
149             if (( i = open( "/dev/tty", O_RDWR )) >= 0 ) {
150                 (void)ioctl( i, TIOCNOTTY, 0 );
151                 setpgrp( 0, getpid());
152                 (void)close( i );
153             }
154             break;
155         case -1 :
156             perror( "fork" );
157             exit( 1 );
158         default :
159             exit( 0 );
160         }
161     }
162
163     if (( p = rindex( *av, '/' )) == NULL ) {
164         p = *av;
165     } else {
166         p++;
167     }
168
169 #ifdef ultrix
170     openlog( p, LOG_PID );
171 #else /* ultrix */
172     openlog( p, LOG_NDELAY|LOG_PID, LOG_DAEMON );
173 #endif /* ultrix */
174
175     /* allocate memory */
176     memset (&sat.sat_addr, 0, sizeof (sat.sat_addr));
177
178     if (( atp = atp_open( ATADDR_ANYPORT, &sat.sat_addr )) == NULL ) {
179         syslog( LOG_ERR, "main: atp_open: %m" );
180         exit( 1 );
181     }
182
183     if ( nbp_rgstr( atp_sockaddr( atp ), server, "TimeLord", "*" ) < 0 ) {
184         syslog( LOG_ERR, "Can't register %s", server );
185         exit( 1 );
186     }
187     syslog( LOG_INFO, "%s:TimeLord started", server );
188
189         signal(SIGHUP, goaway);
190         signal(SIGTERM, goaway);
191
192     for (;;) {
193         /*
194          * Something seriously wrong with atp, since these assigns must
195          * be in the loop...
196          */
197         atpb.atp_saddr = &sat;
198         atpb.atp_rreqdata = buf;
199         bzero( &sat, sizeof( struct sockaddr_at ));
200         atpb.atp_rreqdlen = sizeof( buf );
201         if ( atp_rreq( atp, &atpb ) < 0 ) {
202             syslog( LOG_ERR, "main: atp_rreq: %m" );
203             exit( 1 );
204         }
205
206         p = buf;
207         bcopy( p, &req, sizeof( long ));
208         req = ntohl( req );
209         p += sizeof( long );
210
211         switch( req ) {
212         case TL_GETTIME :
213             if ( atpb.atp_rreqdlen > 5 ) {
214                     bcopy( p + 1, &mtime, sizeof( long ));
215                     mtime = ntohl( mtime );
216                     syslog( LOG_INFO, "gettime from %s %s was %u",
217                             (*( p + 5 ) == '\0' ) ? "<unknown>" : p + 5,
218                             ( *p == 0 ) ? "at boot" : "in chooser",
219                             mtime );
220             } else {
221                     syslog( LOG_INFO, "gettime" );
222             }
223
224             if ( gettimeofday( &tv, &tz ) < 0 ) {
225                 syslog( LOG_ERR, "main: gettimeofday: %m" );
226                 exit( 1 );
227             }
228             if (( tm = gmtime( &tv.tv_sec )) == 0 ) {
229                 perror( "localtime" );
230                 exit( 1 );
231             }
232
233             mtime = tv.tv_sec + EPOCH;
234             mtime = htonl( mtime );
235
236             resp = TL_OK;
237             bcopy( &resp, buf, sizeof( long ));
238             bcopy( &mtime, buf + sizeof( long ), sizeof( long ));
239             iov.iov_len = sizeof( long ) + sizeof( long );
240             break;
241
242         default :
243             syslog( LOG_ERR, bad );
244
245             resp = TL_BAD;
246             bcopy( &resp, buf, sizeof( long ));
247             *( buf + 4 ) = (unsigned char)strlen( bad );
248             strcpy( buf + 5, bad );
249             iov.iov_len = sizeof( long ) + 2 + strlen( bad );
250             break;
251         }
252
253         iov.iov_base = buf;
254         atpb.atp_sresiov = &iov;
255         atpb.atp_sresiovcnt = 1;
256         if ( atp_sresp( atp, &atpb ) < 0 ) {
257             syslog( LOG_ERR, "main: atp_sresp: %m" );
258             exit( 1 );
259         }
260     }
261 }