Imported Upstream version 5.1
[debian/gcpegg] / genlib.c
1 /* PROGRAM:     eggsh
2  * FILE:        $Header: /home/egg/src/RCS/genlib.c,v 1.6 1999/02/28 20:05:18 ghn Exp $
3  * PURPOSE:     General library
4  * AUTHOR:      Greg Nelson
5  * DATE:        98-05-09
6  *
7  * REVISED:
8  * $Log: genlib.c,v $
9  * Revision 1.6  1999/02/28 20:05:18  ghn
10  * Version 5.1: Changed dquad2sockaddr interface to support ip/mm mask,
11  * created hl2dquad to translate host-long to dotted quad, and modified
12  * sockaddr2dquad to use this.
13  *
14  * Revision 1.5  1998/12/31 22:07:56  ghn
15  * Rev 5 code: includes multi-reg support, HTML, etc.
16  *
17  * Revision 1.4  1998/08/03 20:43:35  kelvin
18  * File byte-order independence.
19  *
20  * Revision 1.3  1998/08/01  18:51:25  ghn
21  * Added John's byte-order-independence changes.
22  *
23  * Revision 1.2  1998/08/01 17:07:29  ghn
24  * Casting fixes from John plus better parsing.
25  *
26  * Revision 1.1  1998/07/21 11:38:15  ghn
27  * Initial revision
28  * 
29  * Copyright 1998 - Greg Nelson
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/utsname.h>
38 #include "global.h"
39 #include "genlib.h"
40
41 int32 getzulutime(struct timeval *ztv) {
42   struct timeval ttv;
43
44   if (ztv) {
45     gettimeofday(ztv, NULL);
46     return ztv->tv_sec;
47   } else {
48     gettimeofday(&ttv, NULL);
49     return ttv.tv_sec;
50   }
51 }
52
53 /* Get time difference (tv1-tv2) in msec.  Only works if less than 24
54    days have passed. */
55 int32 deltams(struct timeval *tv1, struct timeval *tv2) {
56   return (tv1->tv_sec - tv2->tv_sec) * 1000L +
57          (tv1->tv_usec - tv2->tv_usec) / 1000L;
58 }
59
60 /* Look up an EGG id.  If we can't get it from environment, do a nutty
61    thing using CRC of uname block, which should be pretty unique. */
62 uint16 GetID(void) {
63   char *idstr;
64   struct utsname utsname;
65
66   if ((idstr = getenv("EGGID")) != NULL) {
67     return atoi(idstr);
68   } else {
69     uname(&utsname);
70     return BlockCRC16((byte *)(&utsname), sizeof(struct utsname));
71   }
72 }
73
74 char *Packetize(EggCarton *src) {
75   char *rbuf;
76   uint32 lbuf;
77   uint16 pktsize, rec;
78   char *pktP;
79
80   pktsize = (7 * sizeof(uint16)) + sizeof(trial) +          /* Header */
81             sizeof(char) +                                  /* ...including pad byte for trialsz */
82             (src->hdr.numrec * (sizeof(uint32) +            /* Trial data */
83                 src->hdr.samp_rec * sizeof(trial))) +
84             sizeof(uint32);                                 /* CRC and terminator */
85   rbuf = pktP = (char *) malloc(pktsize);
86
87   /* Assemble header fields into data packet. */
88
89   packShort(src->hdr.type = DATA_PACKET);
90   packShort(src->hdr.pktsize = pktsize);
91   packShort(src->hdr.eggid);
92   packShort(src->hdr.samp_rec);
93   packShort(src->hdr.sec_rec);
94   packShort(src->hdr.rec_pkt);
95   packByte(0);                        /* Pad byte in case we want to expand trialsz */
96   packByte(src->hdr.trialsz);
97   packShort(src->hdr.numrec);
98
99   /* Append data records to packet. */
100
101   for (rec = 0; rec < src->hdr.numrec; rec++) {
102     packLong(src->records[rec].timestamp);
103     packBytes(&(src->records[rec].trials), src->hdr.samp_rec);
104   }
105   /* Get CRC, pack into base(32,32,64) notation, and add tag byte (0xFF) */
106   lbuf = BlockCRC16((byte *) rbuf, pktP - rbuf);
107   lbuf = ((lbuf & 0xF800) << 13) |
108          ((lbuf & 0x07C0) << 10) |
109          ((lbuf & 0x003F) << 8) |
110          (0x00FF);
111   packLong(lbuf);
112   if ((pktP - rbuf) != pktsize) {
113     fprintf(stderr, "Length mismatch assembling packet.  Computed: %d, actually packed: %d.\n",
114         pktsize, pktP - rbuf);
115   }
116   return rbuf;
117 }
118
119 int32 Unpacketize(EggCarton *dst, char *src) {
120   char *pktP = src;
121   char pad;
122   uint16 rec;
123   uint32 lbuf, filecrc;
124
125   /* Unpack the portable header into a host-order and aligned
126      EggHeader packet. */
127
128   unpackShort(dst->hdr.type);
129   unpackShort(dst->hdr.pktsize);
130   unpackShort(dst->hdr.eggid);
131   unpackShort(dst->hdr.samp_rec);
132   unpackShort(dst->hdr.sec_rec);
133   unpackShort(dst->hdr.rec_pkt);
134   unpackByte(pad);                    /* Pad in case we later grow trialsz */
135   unpackByte(dst->hdr.trialsz);
136   unpackShort(dst->hdr.numrec);
137
138   if (dst->hdr.type != DATA_PACKET) {
139 #ifdef DEBUG
140     fprintf(stderr, "Invalid header type 0x%04X in packet read from file.\n", dst->hdr.type);
141 #endif
142     return -1;
143   }
144
145   /* Unpack the data records from the file packet. */
146
147   for (rec = 0; rec < dst->hdr.numrec; rec++) {
148     unpackLong(dst->records[rec].timestamp);
149     /* Assumes sizeof(trial) = 1 */
150     unpackBytes(&(dst->records[rec].trials), dst->hdr.samp_rec);
151   }
152
153   /* Compute the CRC, reassemble into record terminator,
154      and compare with terminator in file. */
155
156   lbuf = BlockCRC16((byte *) src, pktP - src);
157   lbuf = ((lbuf & 0xF800) << 13) |
158          ((lbuf & 0x07C0) << 10) |
159          ((lbuf & 0x003F) << 8) |
160          (0x00FF);
161
162   unpackLong(filecrc);
163
164   if (lbuf != filecrc) {
165 #ifdef DEBUG
166     fprintf(stderr, "Bad CRC in packet read from file.  Read 0x%08lX, computed 0x%08lX.\n", filecrc, lbuf);
167 #endif
168     return -2;
169   }
170
171   if (dst->hdr.pktsize != (pktP - src)) {
172 #ifdef DEBUG
173     fprintf(stderr, "Length mismatch decoding packet.  Header: %d, length decoded: %d.\n",
174       dst->hdr.pktsize, pktP - src);
175 #endif
176     return -1;
177   }
178
179   /* One final little tweak.  Since we included a pad byte to allow
180      for growth in trialsz, hdr.pktsize will include it.  Subtract
181      one to hide the existence of the pad in the file from the
182      caller.  In all probability the caller isn't going to look at
183      pktsize, but you can't be too careful. */
184
185   dst->hdr.pktsize--;
186
187   return 0;
188 }
189
190 void Parse(char *input, int *argc, char *argv[]) {
191   char *tp;
192
193   *argc = 0;
194
195   tp = strtok(input, " \t\n");
196   while (tp != NULL && *argc < MAX_PARSE) {
197     argv[*argc] = tp;
198     *argc += 1;
199     tp = strtok(NULL, " \t\n");
200   }
201 }
202
203 char *mallocpy(char *input) {
204   char *res;
205
206   res = (char *)malloc(1+strlen(input));
207   if (res) strcpy(res, input);
208   return res;
209 }
210
211 void dquad2sockaddr(struct sockaddr_in *sinp, int16 *mask, char *dquad) {
212   char *tp, *loser;
213   long saddr;
214   short qcount;
215
216   loser = mallocpy(dquad);
217
218   tp = strtok(loser, ".");
219   for (qcount = 0, saddr = 0; qcount < 4 && tp != NULL; qcount++) {
220     saddr = (saddr << 8) | (atoi(tp) & 0xFF);
221     tp = strtok(NULL, ".");
222   }
223   if (mask) {
224     *mask = 32;
225     strcpy(loser, dquad);
226     tp = strtok(loser, "/");
227     if (tp) {
228       tp = strtok(NULL, "/");
229       if (tp) *mask = atoi(tp);
230     }
231   }
232   free(loser);
233
234   sinp->sin_family = AF_INET;
235   sinp->sin_port = 0;           /* To be filled in later */
236   sinp->sin_addr.s_addr = htonl(saddr);
237 }
238
239 char *sockaddr2dquad(struct sockaddr_in *sinp) {
240   long saddr;
241   
242   saddr = ntohl(sinp->sin_addr.s_addr);
243   return hl2dquad(saddr);
244 }
245
246 char *hl2dquad(long addr) {
247   static char resout[16];
248
249   sprintf(resout, "%ld.%ld.%ld.%ld",
250           (addr >> 24) & 0xFF, (addr >> 16) & 0xFF,
251           (addr >> 8) & 0xFF, addr & 0xFF);
252   
253   return resout;
254 }