Changed header.
[egate.git] / util / iso2709.c
1 /*
2  * Iso2709 record management
3  *
4  * Europagate, 1994-1995.
5  *
6  * $Log: iso2709.c,v $
7  * Revision 1.7  1995/02/22 21:28:03  adam
8  * Changed header.
9  *
10  * Revision 1.5  1995/02/22  15:24:14  adam
11  * Function iso2709_cvt makes a litte check for the format. It returns
12  * NULL if the buffer parameter can never be a MARC record.
13  *
14  * Revision 1.4  1995/02/15  17:45:44  adam
15  * Bug fix in iso2709 module.
16  *
17  * Revision 1.3  1995/02/10  17:05:18  adam
18  * New function iso2709_display to display MARC records in a
19  * line-by-line format. The iso2709_cvt function no longer
20  * prints the record to stderr.
21  *
22  * Revision 1.2  1995/02/10  16:50:32  adam
23  * Indicator field moved to 'struct iso2709_dir' from 'struct
24  * iso2709_field'.
25  * Function iso2709_rm implemented - to delete a MARC record.
26  *
27  * Revision 1.1.1.1  1995/02/09  17:27:11  adam
28  * Initial version of email gateway under CVS control.
29  *
30  */
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <assert.h>
36 #include <ctype.h>
37
38 #include <iso2709p.h>
39
40 static int atoin (const char *buf, int n)
41 {
42     int val = 0;
43     while (--n >= 0)
44     {
45         if (isdigit(*buf))
46             val = val*10 + (*buf - '0');
47         buf++;
48     }
49     return val;
50 }
51
52 static void strncpyx (char *d, const char *s, int n)
53 {
54     while (--n >= 0 && *s)
55         if (*s != ISO2709_IDFS)
56             *d++ = *s++;
57         else
58         {
59             *d++ = ' ';
60             s++;
61         }
62     *d = '\0';
63 #if 0
64     strncpy (d, s, n);
65     d[n] = '\0';
66 #endif
67 }
68
69 char *iso2709_read (FILE *inf)
70 {
71     char length_str[5];
72     int size;
73     char *buf;
74
75     if (fread (length_str, 1, 5, inf) != 5)
76         return NULL;
77     size = atoin (length_str, 5);
78     if (size <= 6)
79         return NULL;
80     if (!(buf = malloc (size+1)))
81         return NULL;
82     if (fread (buf+5, 1, size-5, inf) != (size-5))
83     {
84         free (buf);
85         return NULL;
86     }
87     memcpy (buf, length_str, 5);
88     buf[size] = '\0';
89     return buf;
90 }
91
92 Iso2709Rec iso2709_cvt (const char *buf)
93 {
94     struct iso2709_dir **dpp, *dp;
95     int pos = 24;
96     Iso2709Rec p;
97
98     if (!(p = malloc (sizeof(*p))))
99         return NULL;
100
101     /* deal with record label (24 characters) */
102     p->record_length = atoin (buf, 5);
103     strncpyx (p->record_status, buf+5, 1);
104     strncpyx (p->implementation_codes, buf+6, 4);
105     p->indicator_length = atoin (buf+10, 1);
106     p->identifier_length = atoin (buf+11, 1);
107     p->base_address = atoin (buf+12, 4);
108     strncpyx (p->user_systems, buf+17, 3);
109
110     if (p->record_length < 26)
111     {
112         free (p);
113         return NULL;
114     }
115     p->length_data_entry = atoin (buf+20, 1);
116     p->length_starting = atoin (buf+21, 1);
117     p->length_implementation = atoin (buf+22, 1);
118     strncpyx (p->future_use, buf+23, 1);
119
120     /* deal with directory */
121     dpp = &p->directory;
122     *dpp = NULL;
123     while (buf[pos] != ISO2709_FS)
124     {
125         *dpp = malloc (sizeof(**dpp));
126         (*dpp)->next = NULL;
127         strncpyx ((*dpp)->tag, buf+pos, 3);
128         pos += 3;
129         (*dpp)->length = atoin (buf+pos, p->length_data_entry);
130         pos += p->length_data_entry;
131         (*dpp)->offset = atoin (buf+pos, p->length_starting);
132         pos += p->length_starting + p->length_implementation;
133
134         dpp = &(*dpp)->next;
135     }
136     pos++;
137     /* deal with datafields */
138     for (dp = p->directory; dp; dp = dp->next)
139     {
140         int tag00;
141         struct iso2709_field **fpp;
142         int dpos = pos+dp->offset;
143
144         fpp = &dp->fields;
145
146         *fpp = malloc (sizeof(**fpp));
147         (*fpp)->next = NULL;
148         if (p->indicator_length && memcmp (dp->tag, "00", 2))
149         {
150             dp->indicator = malloc (p->indicator_length+1);
151             strncpyx (dp->indicator, buf+dpos, p->indicator_length);
152             dpos += p->indicator_length;
153         }
154         else
155             dp->indicator = NULL;
156
157         if (memcmp (dp->tag, "00", 2))
158             tag00 = 0;
159         else
160             tag00 = 1;
161         while (1)
162         {
163             int dpos_n;
164             if (p->identifier_length && !tag00)
165             {
166                 (*fpp)->identifier = malloc (p->identifier_length+1);
167                 strncpyx ((*fpp)->identifier, buf+dpos+1,
168                           p->identifier_length-1);
169                 dpos += p->identifier_length;
170             }
171             else
172                 (*fpp)->identifier = NULL;
173
174             dpos_n = dpos;
175             while (buf[dpos_n] != ISO2709_FS && buf[dpos_n] != ISO2709_IDFS &&
176                    buf[dpos_n] != ISO2709_RS)
177                 dpos_n++;
178
179             (*fpp)->data = malloc (dpos_n - dpos + 1);
180             strncpyx ((*fpp)->data, buf+dpos, dpos_n - dpos);
181             dpos = dpos_n;
182             
183             if (buf[dpos] == ISO2709_FS || buf[dpos] == ISO2709_RS)
184                 break;
185             
186             fpp = &(*fpp)->next;
187             *fpp = malloc (sizeof(**fpp));
188             (*fpp)->next = NULL;
189         }
190     }
191     return p;
192 }
193
194 void iso2709_rm (Iso2709Rec rec)
195 {
196     struct iso2709_dir *dir, *dir1;
197
198     for (dir = rec->directory; dir; dir = dir1)
199     {
200         struct iso2709_field *field, *field1;
201
202         for (field = dir->fields; field; field = field1)
203         {
204             free (field->identifier);
205             free (field->data);
206             field1 = field->next;
207             free (field);
208         }
209         free (dir->indicator);
210         dir1 = dir->next;
211         free (dir);
212     }
213 }