DtSvc/DtUtil1: fix implicit function declarations
[oweals/cde.git] / cde / lib / DtSvc / DtUtil1 / DtsDb.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
25  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
26  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
27  * (c) Copyright 1993, 1994 Novell, Inc.                                *
28  */
29 /*
30  *+SNOTICE
31  *
32  *      $TOG: DtsDb.c /main/10 1998/10/23 13:48:04 mgreess $
33  *
34  *      RESTRICTED CONFIDENTIAL INFORMATION:
35  *      
36  *      The information in this document is subject to special
37  *      restrictions in a confidential disclosure agreement bertween
38  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
39  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
40  *      Sun's specific written approval.  This documment and all copies
41  *      and derivative works thereof must be returned or destroyed at
42  *      Sun's request.
43  *
44  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
45  *
46  *+ENOTICE
47  */
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <unistd.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #include <fcntl.h>
54 #ifdef  SUN_DB
55 #include <sys/mman.h>
56 #endif
57 #include <string.h>
58 #include <Dt/DbReader.h>
59 #include "Dt/DtsDb.h"
60 #include <Dt/UserMsg.h>
61 #include "DtSvcLock.h"
62
63 extern int _MMWriteDb(DtDirPaths *dirs, int num_db, DtDtsDbDatabase **db_list,
64                       const char *CacheFile);
65
66
67
68 #define PADMEM 10
69
70 typedef int     (*genfunc)(const void *, const void *);
71
72 static  DtDtsDbDatabase **db_list;
73 static  int     num_db = 0;
74
75 void
76 _DtDtsDbPrintFields(DtDtsDbRecord  *rec_ptr, FILE *fd)
77 {
78         int             fld;
79         DtDtsDbField    *fld_ptr;
80
81         for(fld = 0; fld < rec_ptr->fieldCount; fld++)
82         {
83                 fld_ptr = rec_ptr->fieldList[fld];
84                 fprintf(fd, "\t\t[%d]\t%s\t%s\n", fld,
85                         XrmQuarkToString(fld_ptr->fieldName),
86                         fld_ptr->fieldValue?
87                                 fld_ptr->fieldValue:"(NULL)");
88         }
89 }
90
91 void
92 _DtDtsDbPrintRecords(DtDtsDbDatabase  *db_ptr, FILE *fd)
93 {
94         int             rec;
95         DtDtsDbRecord   *rec_ptr;
96
97         _DtSvcProcessLock();
98         fprintf(fd, "%d Records\n", db_ptr->recordCount);
99         for(rec = 0; rec < db_ptr->recordCount; rec++)
100         {
101                 rec_ptr = db_ptr->recordList[rec];
102                 fprintf(fd, "\tRec[%d] name = %s\n\t%d Fields\n", rec,
103                         XrmQuarkToString(rec_ptr->recordName),
104                         rec_ptr->fieldCount);
105                 _DtDtsDbPrintFields(rec_ptr, fd);
106         }
107         _DtSvcProcessUnlock();
108 }
109
110 void
111 _DtDtsDbPrint(FILE *org_fd)
112 {
113         int             db;
114         int             rec;
115         DtDtsDbDatabase *db_ptr;
116         DtDtsDbRecord   *rec_ptr;
117         FILE            *fd = org_fd;
118
119         _DtSvcProcessLock();
120         for(db = 0; db < num_db; db++)
121         {
122                 if(!db_list[db])
123                 {
124                         continue;
125                 }
126                 db_ptr = db_list[db];
127                 if(fd == 0)
128                 {
129                         chdir("/tmp");
130                         if((fd = fopen(db_ptr->databaseName, "w")) == NULL)
131                         {
132                             _DtSimpleError(
133                                         DtProgName, DtError, NULL,
134                                         db_ptr->databaseName, NULL);
135                             continue;
136                         }
137                 }
138                 fprintf(fd, "DB[%d] ", db);
139                 fprintf(fd, "name = %s\n", db_ptr->databaseName);
140                 _DtDtsDbPrintRecords(db_ptr, fd);
141                 if(org_fd == 0)
142                 {
143                         fclose(fd);
144                         fd = 0;
145                 }
146         }
147         _DtSvcProcessUnlock();
148 }
149
150 int
151 _DtDtsDbCompareRecordNames(DtDtsDbRecord **a, DtDtsDbRecord **b)
152 {
153         return ((*a)->recordName - (*b)->recordName);
154 }
155
156 int
157 _DtDtsDbCompareFieldNames(DtDtsDbField **a, DtDtsDbField **b)
158 {
159         return ((*a)->fieldName - (*b)->fieldName);
160 }
161
162 #include <Dt/Dts.h>
163
164 DtDtsDbDatabase **
165 _DtDtsDbInit(void)
166 {
167         DtDtsDbDatabase **db;
168
169         _DtSvcProcessLock();
170         num_db = 0;
171         db = db_list = (DtDtsDbDatabase **)calloc(num_db+3, sizeof(DtDtsDbDatabase *));
172         db_list[0] = (DtDtsDbDatabase *)calloc(1, sizeof(DtDtsDbDatabase));
173         db_list[0]->databaseName = (char *)strdup(DtDTS_DC_NAME);
174         db_list[0]->ActionSequenceNumber = 0;
175         num_db++;
176
177         db_list[1] = (DtDtsDbDatabase *)calloc(1, sizeof(DtDtsDbDatabase));
178         db_list[1]->databaseName = (char *)strdup(DtDTS_DA_NAME);
179         db_list[1]->ActionSequenceNumber = 0;
180         num_db++;
181
182         _DtSvcProcessUnlock();
183         return(db);
184 }
185
186 char **
187 _DtsDbListDb(void)
188 {
189         int     i;
190         char    **list = 0;
191
192         _DtSvcProcessLock();
193         for ( i = 0; db_list[i]; i++ );
194
195         if(i > 0)
196         {
197                 list = (char **)calloc(i+1, sizeof(char *));
198                 for ( i = 0; db_list[i]; i++ )
199                 {
200                         list[i] = (char *)strdup(db_list[i]->databaseName);
201                 }
202         }
203         _DtSvcProcessUnlock();
204         return(list);
205 }
206
207 DtDtsDbDatabase *
208 _DtDtsDbAddDatabase( char *db_name )
209 {
210         int i = 0;
211         DtDtsDbDatabase **new_db_list;
212         DtDtsDbDatabase *ret_db;
213
214         _DtSvcProcessLock();
215         if ( !db_list )
216         {
217                 _DtDtsDbInit();
218         }
219         for ( i = 0; db_list[i]; i++ )
220         {
221                 if ( !strcmp(db_list[i]->databaseName,db_name) )
222                 {
223                         /*
224                          * A database with the given name already exists.
225                          * return a pointer to the existing database.
226                          */
227                         ret_db = db_list[i];
228                         _DtSvcProcessUnlock();
229
230                         return ret_db;
231                 }
232         }       
233         /*
234          * We now have a count of the existing databases.
235          * allocate enough space for the existing databases + the new one 
236          * + a NULL pointer to terminate the vector.
237          */
238
239         new_db_list = (DtDtsDbDatabase **)calloc(i+2,sizeof(DtDtsDbDatabase *));
240
241         memmove(new_db_list,db_list,sizeof(DtDtsDbDatabase *) * i );
242         new_db_list[i] = (DtDtsDbDatabase *)calloc(1, sizeof(DtDtsDbDatabase));
243         new_db_list[i]->databaseName = strdup(db_name);
244         new_db_list[i]->ActionSequenceNumber = 0;
245         free(db_list);
246         db_list = new_db_list;
247         num_db++;
248
249         ret_db = db_list[i];
250         _DtSvcProcessUnlock();
251
252         return ret_db;
253 }
254
255 int
256 _DtDtsDbDeleteDb(DtDtsDbDatabase *db)
257 {
258         int     i;
259         int     flag = 0;
260
261         _DtSvcProcessLock();
262         _DtDtsDbDeleteRecords(db);
263         free(db->databaseName);
264         free(db);
265
266         for(i = 0; db_list[i]; i++)
267         {
268                 if(db_list[i] == db)
269                 {
270                         flag = 1;
271                         db_list[i] = 0;
272                 }
273                 if(flag)
274                 {
275                         db_list[i] = db_list[i+1];
276                 }
277         }
278         if(db_list[0] == 0)
279         {
280                 free(db_list);
281                 db_list = 0;
282         }
283         _DtSvcProcessUnlock();
284         return(0);
285 }
286
287
288 DtDtsDbDatabase *
289 _DtDtsDbGet(char *name)
290 {
291         DtDtsDbDatabase *ret_db;
292         int             i;
293
294         _DtSvcProcessLock();
295         if(!db_list)
296         {
297                 _DtDtsDbInit();
298         }
299         for(i = 0; db_list && db_list[i] && db_list[i]->databaseName; i++)
300         {
301                 if(strcmp(db_list[i]->databaseName, name) == 0)
302                 {
303                         ret_db = db_list[i];
304                         _DtSvcProcessUnlock();
305
306                         return(ret_db);
307                 }
308         }
309         _DtSvcProcessUnlock();
310         return(NULL);
311 }
312
313 void
314 _DtDtsDbFieldSort(DtDtsDbRecord *rec, _DtDtsDbFieldCompare compare)
315 {
316         if(compare == NULL)
317         {
318                 compare = _DtDtsDbCompareFieldNames;
319         }
320         qsort(rec->fieldList,
321                 rec->fieldCount,
322                 sizeof(DtDtsDbField *),
323                 (genfunc)compare);
324         rec->compare = compare;
325 }
326
327 void
328 _DtDtsDbRecordSort(DtDtsDbDatabase *db, _DtDtsDbRecordCompare compare)
329 {
330         if(compare == NULL)
331         {
332                 compare = _DtDtsDbCompareRecordNames;
333         }
334         qsort(db->recordList,
335                 db->recordCount,
336                 sizeof(DtDtsDbRecord *),
337                 (genfunc)compare);
338         db->compare = compare;
339 }
340
341 DtDtsDbField *
342 _DtDtsDbGetField(DtDtsDbRecord *rec, char *name)
343 {
344         int i;
345
346         /*
347          * Field names have been quarked so quark 'name' and
348          * do a linear search for the quark'ed field name.
349          */
350         XrmQuark        tmp = XrmStringToQuark (name);
351
352         for (i = 0; i < rec->fieldCount; i++)
353         {
354                 if (rec->fieldList[i]->fieldName == tmp)
355                 {
356                         return (rec->fieldList[i]);
357                 }
358         }
359         return(NULL);
360 }
361
362 char *
363 _DtDtsDbGetFieldByName(DtDtsDbRecord *rec, char *name)
364 {
365         DtDtsDbField    *result;
366
367         result = _DtDtsDbGetField(rec, name);
368         if(result)
369         {
370                 return(result->fieldValue);
371         }
372         else
373         {
374                 return(NULL);
375         }
376
377 }
378
379 DtDtsDbRecord *
380 _DtDtsDbGetRecordByName(DtDtsDbDatabase *db, char *name)
381 {
382         DtDtsDbRecord   srch;
383         DtDtsDbRecord   **result;
384         DtDtsDbRecord   *s = &srch;
385         int i;
386         XrmQuark        name_quark = XrmStringToQuark(name);
387
388         /*
389          * If the fields are not sorted in alphanumeric order
390          * by name a binary search will fail.  So do the slow but
391          * sure linear search.
392          */
393         if(db->compare != _DtDtsDbCompareRecordNames)
394         {
395
396                 for (i = 0; i < db->recordCount; i++)
397                 {
398                         if (db->recordList[i]->recordName == name_quark)
399                         {
400                                 return (db->recordList[i]);
401                         }
402                 }
403                 return NULL;
404         }
405
406         srch.recordName = name_quark;   
407
408         if(db->recordCount == 0 || db->recordList == NULL)
409         {
410                 result = NULL;
411         }
412         else
413         {
414                 result = (DtDtsDbRecord **)bsearch(&s,
415                         db->recordList,
416                         db->recordCount,
417                         sizeof(DtDtsDbRecord *),
418                         (genfunc)_DtDtsDbCompareRecordNames);
419         }
420
421         if(result)
422         {
423                 return(*result);
424         }
425         else
426         {
427                 return(NULL);
428         }
429
430 }
431
432 DtDtsDbRecord *
433 _DtDtsDbAddRecord(DtDtsDbDatabase *db)
434 {
435         DtDtsDbRecord   **newlist;
436         int             rec = db->recordCount;
437
438         db->compare = (_DtDtsDbRecordCompare)NULL;
439         if(rec%PADMEM == 0)
440         {
441                 newlist = (DtDtsDbRecord **)calloc(rec+PADMEM,
442                                 sizeof(DtDtsDbRecord *));
443                 if(db->recordList)
444                 {
445                         memmove(newlist, db->recordList,
446                                 rec*sizeof(DtDtsDbRecord *));
447                         free(db->recordList);
448                 }
449                 db->recordList = newlist;
450         }
451         db->recordList[rec] = (DtDtsDbRecord *)calloc(1, sizeof(DtDtsDbRecord));
452         db->recordCount++;
453
454         return(db->recordList[rec]);
455 }
456
457 int
458 _DtDtsDbDeleteRecord(DtDtsDbRecord *rec, DtDtsDbDatabase *db)
459 {
460         int     i;
461
462         _DtDtsDbDeleteFields(rec);
463         free(rec);
464
465         for(i = 0; i < db->recordCount; i++)
466         {
467                 if(db->recordList[i] == rec)
468                 {
469                         memmove(        &(db->recordList[i]),
470                                 &(db->recordList[i+1]),
471                                 (db->recordCount - i - 1)*
472                                         sizeof(DtDtsDbRecord *));
473                         db->recordCount--;
474                         return(1);
475                 }
476         }
477
478         return(0);
479 }
480
481 int
482 _DtDtsDbDeleteRecords(DtDtsDbDatabase *db)
483 {
484         int     i;
485
486         for(i = 0; i < db->recordCount; i++)
487         {
488                 _DtDtsDbDeleteFields(db->recordList[i]);
489                 free(db->recordList[i]);
490         }
491         free(db->recordList);
492         db->recordList = 0;
493         return(0);
494 }
495
496 DtDtsDbField *
497 _DtDtsDbAddField(DtDtsDbRecord *rec)
498 {
499         DtDtsDbField    **newlist;
500         int             flds = rec->fieldCount;
501
502         if(flds%PADMEM == 0)
503         {
504                 newlist = (DtDtsDbField **)calloc(flds+PADMEM,
505                                 sizeof(DtDtsDbField *));
506                 if(rec->fieldList)
507                 {
508                         memmove(newlist, rec->fieldList,
509                                 flds*sizeof(DtDtsDbField *));
510                         free(rec->fieldList);
511                 }
512                 rec->fieldList = newlist;
513         }
514         rec->fieldList[flds] = (DtDtsDbField *)calloc(1, sizeof(DtDtsDbField));
515         rec->fieldCount++;
516
517         return(rec->fieldList[flds]);
518 }
519
520 int
521 _DtDtsDbDeleteField(DtDtsDbField *fld, DtDtsDbRecord *rec)
522 {
523         int     i;
524
525         free(fld);
526         for(i = 0; i < rec->fieldCount; i++)
527         {
528                 if(rec->fieldList[i] == fld)
529                 {
530                         memmove(        &(rec->fieldList[i]),
531                                 &(rec->fieldList[i+1]),
532                                 (rec->fieldCount - i - 1)*
533                                         sizeof(DtDtsDbField *));
534                         rec->fieldCount--;
535                         return(1);
536                 }
537         }
538
539         return(0);
540 }
541
542 int
543 _DtDtsDbDeleteFields(DtDtsDbRecord *rec)
544 {
545         int     i;
546
547         for(i = 0; i < rec->fieldCount; i++)
548         {
549                 free(rec->fieldList[i]->fieldValue);
550                 free(rec->fieldList[i]);
551         }
552         free(rec->fieldList);
553         rec->fieldList = 0;
554         return(0);
555 }
556
557 int
558 _DtDtsMMCreateFile(DtDirPaths *dirs, const char *CacheFile)
559 {
560         return _MMWriteDb(dirs, num_db, db_list, CacheFile);
561 }