1/*
2 * sht.c - Testprogram for shared memory refclock
3 * read/write shared memory segment; see usage
4 */
5#ifndef SYS_WINNT
6#include <sys/types.h>
7#include <sys/ipc.h>
8#include <sys/shm.h>
9#include <stdio.h>
10#include <time.h>
11#include <unistd.h>
12#include <stdlib.h>
13#else
14#include <windows.h>
15#include <time.h>
16#include <stdlib.h>
17#include <stdio.h>
18#include <iostream.h>
19#define sleep(x) Sleep(x*1000)
20#endif
21#include <assert.h>
22struct shmTime {
23	int    mode; /* 0 - if valid set
24		      *       use values,
25		      *       clear valid
26		      * 1 - if valid set
27		      *       if count before and after read of values is equal,
28		      *         use values
29		      *       clear valid
30		      */
31	int    count;
32	time_t clockTimeStampSec;
33	int    clockTimeStampUSec;
34	time_t receiveTimeStampSec;
35	int    receiveTimeStampUSec;
36	int    leap;
37	int    precision;
38	int    nsamples;
39	int    valid;
40};
41
42struct shmTime *
43getShmTime (
44	int unit
45	)
46{
47#ifndef SYS_WINNT
48	int shmid=shmget (0x4e545030+unit, sizeof (struct shmTime), IPC_CREAT|0777);
49	if (shmid==-1) {
50		perror ("shmget");
51		exit (1);
52	}
53	else {
54		struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
55		if ((int)(long)p==-1) {
56			perror ("shmat");
57			p=0;
58		}
59		assert (p!=0);
60		return p;
61	}
62#else
63	char buf[10];
64	LPSECURITY_ATTRIBUTES psec=0;
65	sprintf (buf,"NTP%d",unit);
66	SECURITY_DESCRIPTOR sd;
67	SECURITY_ATTRIBUTES sa;
68	HANDLE shmid;
69
70	assert (InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION));
71	assert (SetSecurityDescriptorDacl(&sd,1,0,0));
72	sa.nLength=sizeof (SECURITY_ATTRIBUTES);
73	sa.lpSecurityDescriptor=&sd;
74	sa.bInheritHandle=0;
75	shmid=CreateFileMapping ((HANDLE)0xffffffff, 0, PAGE_READWRITE,
76				 psec, sizeof (struct shmTime),buf);
77	if (!shmid) {
78		shmid=CreateFileMapping ((HANDLE)0xffffffff, 0, PAGE_READWRITE,
79					 0, sizeof (struct shmTime),buf);
80		cout <<"CreateFileMapping with psec!=0 failed"<<endl;
81	}
82
83	if (!shmid) {
84		char mbuf[1000];
85		FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
86			       0, GetLastError (), 0, mbuf, sizeof (mbuf), 0);
87		int x=GetLastError ();
88		cout <<"CreateFileMapping "<<buf<<":"<<mbuf<<endl;
89		exit (1);
90	}
91	else {
92		struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid,
93								    FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
94		if (p==0) {
95			char mbuf[1000];
96			FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
97				       0, GetLastError (), 0, mbuf, sizeof (mbuf), 0);
98			cout <<"MapViewOfFile "<<buf<<":"<<mbuf<<endl;
99			exit (1);
100		}
101		return p;
102	}
103	return 0;
104#endif
105}
106
107
108int
109main (
110	int argc,
111	char *argv[]
112	)
113{
114	volatile struct shmTime *p=getShmTime(2);
115	if (argc<=1) {
116		printf ("usage: %s r[c][l]|w|snnn\n",argv[0]);
117		printf ("       r read shared memory\n");
118		printf ("        c clear valid-flag\n");
119		printf ("        l loop (so, rcl will read and clear in a loop\n");
120		printf ("       w write shared memory with current time\n");
121		printf ("       snnnn set nsamples to nnn\n");
122		printf ("       lnnnn set leap to nnn\n");
123		printf ("       pnnnn set precision to -nnn\n");
124		exit (0);
125	}
126	switch (argv[1][0]) {
127	    case 's': {
128		    p->nsamples=atoi(&argv[1][1]);
129	    }
130	    break;
131	    case 'l': {
132		    p->leap=atoi(&argv[1][1]);
133	    }
134	    break;
135	    case 'p': {
136		    p->precision=-atoi(&argv[1][1]);
137	    }
138	    break;
139	    case 'r': {
140		    char *ap=&argv[1][1];
141		    int clear=0;
142		    int loop=0;
143		    printf ("reader\n");
144		    while (*ap) {
145			    switch (*ap) {
146				case 'l' : loop=1; break;
147				case 'c' : clear=1; break;
148			    }
149			    ap++;
150		    }
151		    do {
152			    printf ("mode=%d, count=%d, clock=%d.%d, rec=%d.%d,\n",
153				    p->mode,p->count,p->clockTimeStampSec,p->clockTimeStampUSec,
154				    p->receiveTimeStampSec,p->receiveTimeStampUSec);
155			    printf ("  leap=%d, precision=%d, nsamples=%d, valid=%d\n",
156				    p->leap, p->precision, p->nsamples, p->valid);
157			    if (!p->valid)
158				printf ("***\n");
159			    if (clear) {
160				    p->valid=0;
161				    printf ("cleared\n");
162			    }
163			    if (loop)
164				sleep (1);
165		    } while (loop);
166	    }
167	    break;
168	    case 'w': {
169		    printf ("writer\n");
170		    p->mode=0;
171		    if (!p->valid) {
172			    p->clockTimeStampSec=time(0)-20;
173			    p->clockTimeStampUSec=0;
174			    p->receiveTimeStampSec=time(0)-1;
175			    p->receiveTimeStampUSec=0;
176			    printf ("%d %d\n",p->clockTimeStampSec, p->receiveTimeStampSec);
177			    p->valid=1;
178		    }
179		    else {
180			    printf ("p->valid still set\n"); /* not an error! */
181		    }
182	    }
183	    break;
184	}
185}
186