OpenBSD fixed for lib/DtSvc.
[oweals/cde.git] / cde / lib / DtSvc / DtUtil1 / Dts.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 librararies 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: Dts.c /main/18 1999/10/15 12:18:39 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 <unistd.h>
49 #include <string.h>
50 #include <stdlib.h>
51 #include <ctype.h>
52 #include <sys/mman.h>
53 #include <stdio.h>
54 #include <fcntl.h>
55 #include <sys/stat.h>
56 #if defined (__hpux)
57 /*
58  * On HP MAXINT is defined in both <values.h> and <sys/param.h>
59  */
60 #undef MAXINT
61 #elif defined(CSRG_BASED)
62 #define MAXINT INT_MAX
63 #else
64 #include <values.h>
65 #endif
66 #include <sys/param.h>
67 #include <sys/errno.h>
68 #ifdef  _SUN_OS
69 #include <libgen.h>
70 #endif
71 #include <sys/utsname.h>
72 #define X_INCLUDE_STRING_H
73 #define XOS_USE_XT_LOCKING
74 #include <X11/Xos_r.h>
75 #include <Dt/DtNlUtils.h>
76 #include "Dt/DtsMM.h"
77 #include "Dt/Dts.h"
78 #include "DtSvcLock.h"
79 #include <Dt/UserMsg.h>
80
81 #include <X11/Xosdefs.h>
82 #include <errno.h>
83 #ifdef X_NOT_STDC_ENV
84 extern int errno;
85 #endif
86
87 struct  list
88 {
89         int boson;
90         DtDtsMMRecord *rec;
91 };
92
93 typedef struct  type_info
94 {
95         char                    *file_path;
96         char                    *name;
97         const struct stat       *file_stat;
98         const struct stat       *file_lstat;
99         int                     file_fd;
100         const char              *buffer;
101         int                     buff_size;
102         int                     mmap_size_to_free;
103         int                     size_to_free;
104         const char              *opt_name;
105         int                     error;
106         const char              *link_path;
107         const char              *link_name;
108         int                     set_datatype;
109         char                    *ot;
110         char                    *mb;
111         int                     mb_size;
112         int                     name_type;
113         int                     *name_prev;
114         int                     name_count;
115         char                    *orig_attr;
116 } type_info_t;
117
118 static  DtShmBoson      dtdts_path_pattern = 0;
119 static  DtShmBoson      dtdts_name_pattern = 0;
120 static  DtShmBoson      dtdts_mode = 0;
121 static  DtShmBoson      dtdts_link_name = 0;
122 static  DtShmBoson      dtdts_link_path = 0;
123 static  DtShmBoson      dtdts_content = 0;
124 static  DtShmBoson      dtdts_data_attributes_name = 0;
125 static  DtShmBoson      dtdts_da_is_action = 0;
126 static  DtShmBoson      dtdts_da_icon = 0;
127 static  DtShmBoson      dtdts_da_description = 0;
128 static  DtShmBoson      dtdts_da_label = 0;
129
130 #define MB_SIZE 100
131 #define _MBLEN(p) (mblen(p, MB_CUR_MAX) > 1 ? mblen(p, MB_CUR_MAX) : 1)
132 #define _MBADV(p) ((p) += _MBLEN(p))
133
134 /* external functions */
135 extern  char    *strdup(const char *);
136 extern  FILE    *popen(const char *, const char *);
137 extern  char    *DtActionIcon(const char *);
138 extern  char    *DtActionDescription(const char *);
139 extern  char    *DtActionLabel(const char *);
140 extern  XtAppContext _DtAppContext;
141
142 /* local functions */
143 static  DtDtsMMRecord * name_list(type_info_t *linfo,
144                 DtDtsMMDatabase *db,
145                 DtDtsMMRecord *rec_ptr);
146 static  const struct stat *get_stat();
147
148 static int      csh_match(const char *, const char *);
149 static int      csh_match_star(const char *, const char *);
150
151 /* filetype comparison function for sorting */
152 extern  int     cde_dc_compare(DtDtsMMRecord **entry1, DtDtsMMRecord **entry2);
153 extern  int     cde_da_compare(DtDtsMMRecord **entry1, DtDtsMMRecord **entry2);
154 extern  int     cde_dc_field_compare(DtDtsMMField **entry1, DtDtsMMField **entry2);
155
156
157 _DtDtsClear()
158 {
159         _DtSvcProcessLock();
160         dtdts_path_pattern = 0;
161         dtdts_name_pattern = 0;
162         dtdts_mode = 0;
163         dtdts_link_name = 0;
164         dtdts_link_path = 0;
165         dtdts_content = 0;
166         dtdts_data_attributes_name = 0;
167         dtdts_da_is_action = 0;
168         dtdts_da_icon = 0;
169         dtdts_da_description = 0;
170         dtdts_da_label = 0;
171         _DtSvcProcessUnlock();
172 }
173
174 static int
175 gmatch(const char *string, const char *pattern)
176 {
177         wchar_t         string_ch;
178         int             k;
179         wchar_t         pattern_ch;
180         wchar_t         lower_bound;
181         char            *p;
182
183 top:
184         for (; 1; _MBADV(pattern), _MBADV(string))
185         {
186                 lower_bound = (wchar_t)MAXINT;
187                 mbtowc(&string_ch, string, MB_CUR_MAX);
188                 mbtowc(&pattern_ch, pattern, MB_CUR_MAX);
189                 switch (pattern_ch)
190                 {
191                 case L'[':
192                         k = 0;
193                         for(mbtowc(&pattern_ch, _MBADV(pattern), MB_CUR_MAX);
194                             pattern_ch != L'\0';
195                             mbtowc(&pattern_ch, _MBADV(pattern), MB_CUR_MAX))
196                         {
197                                 switch (pattern_ch)
198                                 {
199                                 case L']':
200                                         if (!k)
201                                         {
202                                                 return 0;
203                                         }
204                                         _MBADV(string);
205                                         _MBADV(pattern);
206                                         goto top;
207                                 case L'-':
208                                         if(lower_bound <= string_ch) {
209                                             p = (char *)pattern;
210                                             mbtowc(&pattern_ch, _MBADV(pattern),
211                                                    MB_CUR_MAX);
212                                             k |= (string_ch <= pattern_ch);
213                                             pattern = p;
214                                         }
215                                         else
216                                             k |= 0;
217                                         /* Fall through... */
218                                 default:
219                                         if (string_ch ==
220                                                  (lower_bound = pattern_ch))
221                                         {
222                                                 k++;
223                                         }
224                                 }
225                         }
226                         return 0;
227                 case L'*':
228                         return csh_match_star(string, _MBADV(pattern));
229                 case L'\0':
230                         return ((string_ch != L'\0') ? 0 : 1);
231                 case L'?':
232                         if (string_ch == L'\0')
233                         {
234                                 return 0;
235                         }
236                         break;
237                 default:
238                         if (pattern_ch != string_ch)
239                         {
240                                 return 0;
241                         }
242                         break;
243                 }
244         }
245         /* NOTREACHED */
246 }
247
248 /*
249  * csh_match_star(string, pattern) This matches the '*' portion of a pattern.
250  */
251 static int
252 csh_match_star(const char *string, const char *pattern)
253 {
254         wchar_t         pattern_ch;
255         wchar_t         string_ch;
256
257         mbtowc(&pattern_ch, pattern, MB_CUR_MAX);
258         switch (pattern_ch)
259         {
260         case L'\0':
261                 return 1;
262         case L'[':
263         case L'?':
264         case L'*':
265                 while (*string)
266                 {
267                         if(gmatch(string, pattern)) {
268                             _MBADV(string);
269                             return 1;
270                         }
271                         else
272                             _MBADV(string);
273                 }
274                 break;
275         default:
276                 mbtowc(&pattern_ch, pattern, MB_CUR_MAX);
277                 _MBADV(pattern);
278                 while (*string)
279                 {
280                         mbtowc(&string_ch, string, MB_CUR_MAX);
281                         _MBADV(string);
282                         if(string_ch == pattern_ch && gmatch(string, pattern))
283                         {
284                                 return 1;
285                         }
286                 }
287                 break;
288         }
289         return 0;
290 }
291
292 static char *
293 max_buf(size_t size, type_info_t *info)
294 {
295         if(!info->mb)
296         {
297                 info->mb_size += MB_SIZE;
298                 info->mb = (char *)calloc(info->mb_size, 1);
299         }
300         if(!size)
301         {
302                 return(info->mb);
303         }
304         if(size > info->mb_size)
305         {
306                 info->mb = (char *)realloc(info->mb, info->mb_size);
307                 info->mb_size = size;
308         }
309         return(info->mb);
310 }
311
312 static type_info_t *
313 set_vals(const char             *fn,
314         const char              *buf,
315         const int               bs,
316         const struct stat       *fs,
317         const char              *ln,
318         const struct stat       *ls,
319         const char              *on)
320 {
321         char            *tmp;
322         type_info_t     *linfo = (type_info_t *)calloc(1, sizeof(type_info_t));
323
324         linfo->buff_size = -1;
325         linfo->file_fd = -1;
326         linfo->error = 0;
327         linfo->mmap_size_to_free = -1;
328         linfo->size_to_free = -1;
329         linfo->set_datatype = 0;
330         linfo->ot = 0;
331         linfo->mb = 0;
332         linfo->mb_size = 0;
333         linfo->orig_attr = 0;
334
335         if(fn)
336         {
337                 linfo->file_path = strdup(fn);
338                 linfo->name = strrchr(linfo->file_path, '/');
339                 if(linfo->name)
340                 {
341                         linfo->name++;
342                 }
343                 else
344                 {
345                         char    path[MAXPATHLEN];
346                         char    *tmp;
347
348                         getcwd(path, MAXPATHLEN);
349                         strcat(path, "/");
350                         strcat(path, linfo->file_path);
351
352                         tmp = linfo->file_path;
353                         linfo->file_path = strdup(path);
354                         linfo->name = strstr(linfo->file_path, tmp);
355                         free(tmp);
356                 }
357         }
358         else if(buf)
359         {
360                 if(!fs)
361                 {
362                         struct  stat    *buf;
363                         buf = malloc(sizeof(struct stat));
364                         memset(buf, '\0', sizeof(struct stat));
365                         buf->st_mode =  S_IFREG | S_IROTH | S_IRGRP | 
366                                         S_IRUSR | S_IWOTH | S_IWGRP | 
367                                         S_IWUSR;
368                         linfo->file_stat = (const struct stat *)buf;
369                 }
370         }
371                         
372         if(buf)
373         {
374                 linfo->buffer = buf;
375         }
376         /*
377          * 04/30/96 - What should this if() REALLY be?  Chances are
378          * pretty good that bs will either not equal 0 or not equal -1!
379          */
380         if(bs != 0 || bs != -1)
381         {
382                 linfo->buff_size = bs;
383         }
384         if(fs)
385         {
386                 linfo->file_stat = (struct stat *)malloc(sizeof(struct stat));
387                 memcpy((void *)linfo->file_stat,
388                         (struct stat *)fs,
389                         sizeof(struct stat));
390         }
391         if(ln)
392         {
393                 if(*ln == '/')
394                 {
395                         linfo->link_path = (char *)strdup(ln);
396                         linfo->link_name = strrchr(ln, '/');
397                         if(linfo->link_name)
398                         {
399                                 linfo->link_name++;
400                         }
401                 }
402                 else
403                 {
404                         linfo->link_name = (char *)ln;
405                 }
406         }
407         if(ls)
408         {
409                 linfo->file_lstat = (struct stat *)malloc(sizeof(struct stat));
410                 memcpy((void*)linfo->file_lstat,
411                         (struct stat *)ls,
412                         sizeof(struct stat));
413         }
414         if(on)
415         {
416                 linfo->opt_name = strdup(on);
417         }
418
419         return(linfo);
420 }
421
422 static char *
423 cleanup(char *ot, type_info_t *info)
424 {
425         if(ot)
426         {
427                 ot = strdup(ot);
428         }
429         else if(info->ot)
430         {
431                 ot = strdup(info->ot);
432         }
433         else
434         {
435                 ot = strdup(DtDTS_DT_UNKNOWN);
436         }
437         if(info->ot)
438         {
439                 free(info->ot);
440         }
441
442         if(info->file_stat)
443         {
444                 free((void *)info->file_stat);
445         }
446         if(info->file_lstat)
447         {
448                 free((void *)info->file_lstat);
449         }
450
451         info->file_stat = 0;
452         info->file_lstat = 0;
453         if(info->buffer)
454         {
455                 if(info->mmap_size_to_free != -1)
456                 {
457                         if(munmap((caddr_t)info->buffer, 
458                                 info->mmap_size_to_free) != 0)
459                         {
460                             _DtSimpleError(
461                                         DtProgName, DtError, NULL,
462                                         "munmap", NULL);
463                         }
464                         info->buffer = 0;
465                         info->mmap_size_to_free = -1;
466                 }
467                 else if(info->size_to_free != -1)
468                 {
469                         free((void *)info->buffer);
470                         info->buffer = 0;
471                         info->size_to_free = -1;
472                 }
473         }
474         if(info->file_fd != -1)
475         {
476                 close(info->file_fd);
477                 info->file_fd = -1;
478         }
479         info->buffer = 0;
480         if(info->file_path)
481         {
482                 free((void *)info->file_path);
483                 info->file_path = 0;
484                 info->name = 0;
485         }
486         if(info->name)
487         {
488                 free((void *)info->name);
489                 info->name = 0;
490         }
491         info->file_path = 0;
492         info->name = 0;
493         info->file_fd = -1;
494         info->buff_size = -1;
495         info->error = 0;
496         if(info->link_path != (char *)0 && info->link_path != (char *)-1)
497         {
498                 free((void *)info->link_path);
499         }
500
501         if(info->opt_name)
502         {
503                 free((void *)info->opt_name);
504         }
505         if(info->mb)
506         {
507                 free(info->mb);
508         }
509         if(info->orig_attr)
510         {
511                 _DtDtsMMSafeFree(info->orig_attr);
512         }
513
514         free(info);
515         info = 0;
516         return(ot);
517 }
518
519 static  const char*
520 get_opt_name(type_info_t *info)
521 {
522         return(info->opt_name);
523 }
524
525 static  const char*
526 get_name(type_info_t *info)
527 {
528         return(info->name);
529 }
530
531 static  const char*
532 get_file_path(type_info_t *info)
533 {
534         if(info->file_path)
535         {
536                 return(info->file_path);
537         }
538         else
539         {
540                 return(0);
541         }
542 }
543
544 static int
545 get_fd(type_info_t *info)
546 {
547         if(!info->error && info->file_fd == -1)
548         {
549                 if(info->file_path == 0)
550                 {
551                         return(-1);
552                 }
553                 if((info->file_fd = open(info->file_path, O_RDONLY|O_NOCTTY, 0)) == -1)
554                 {
555                         info->error = errno;
556                         return(-1);
557                 }
558         }
559         return(info->file_fd);
560 }
561
562 static const struct stat *
563 get_lstat(type_info_t *info)
564 {
565         struct  stat    buf;
566
567         if(!info->file_lstat)
568         {
569                 if(NULL == info->file_path)
570                 {
571                         info->error = ENOENT;
572                         info->file_lstat = 0;
573                         return(0);
574                 }
575                 else if(lstat(info->file_path, &buf) == -1)
576                 {
577                         info->error = errno;
578                         info->file_lstat = 0;
579                         return(0);
580                 }
581                 else
582                 {
583                         info->file_lstat = (struct stat *)malloc(sizeof(struct stat));
584                         memcpy((char *)info->file_lstat, &buf, sizeof(buf));
585                 }
586         }
587         return(info->file_lstat);
588 }
589
590 static const struct stat *
591 get_stat(type_info_t *info)
592 {
593         struct  stat    buf;
594         int             fd;
595
596         if (!info->file_stat)
597         {
598                 if(NULL == get_file_path(info))
599                 {
600                         info->error = ENOENT;
601                         info->file_stat = 0;
602                 }
603                 else if(stat(get_file_path(info), &buf) == -1)
604                 {
605                         if(errno == ENOENT)
606                         {
607                                 if(get_lstat(info))
608                                 {
609                                         info->ot = strdup(DtDTS_DT_BROKEN_LINK);
610                                 }
611                         }
612                         info->error = errno;
613                         info->file_stat = 0;
614                 }
615                 else
616                 {
617                         info->file_stat = (struct stat *)malloc(sizeof(struct stat));
618                         memcpy((char *)info->file_stat, &buf, sizeof(buf));
619                 }
620         }
621
622         return(info->file_stat);
623 }
624
625 static int
626 islink(type_info_t *info)
627 {
628         if(info->file_lstat || info->link_path || info->link_name)
629         {
630                 return(1);
631         }
632         return(0);
633 }
634
635 void
636 get_link_info(type_info_t *info)
637 {
638         char            buff[MAXPATHLEN];
639         const   char    *name = 0;
640         int             n;
641
642         if(info->link_path == 0)
643         {
644                 if((name = get_file_path(info)) == 0)
645                 {
646                         info->link_path = (char *)-1;
647                         info->link_name = (char *)-1;
648                         return;
649                 }
650                 else
651                 {
652                         name = strdup(name);
653                 }
654                 while((n = readlink(name, buff, MAXPATHLEN)) > 0)
655                 {
656         
657                         buff[n] = 0;
658                         free((void *)name);
659                         name = strdup(buff);
660                 }
661                 if(errno == EINVAL || errno == ENOENT)
662                 {
663                         info->link_path = name;
664                         info->link_name = strrchr(info->link_path, '/');
665                         if(info->link_name == 0)
666                         {
667                                 info->link_name = info->link_path;
668                         }
669                         else
670                         {
671                                 info->link_name++;
672                         }
673                 }
674                 else
675                 {
676                         info->error = errno;
677                         info->link_path = (char *)-1;
678                         info->link_name = (char *)-1;
679                 }
680         }
681         return;
682 }
683
684 static const char *
685 get_link_path(type_info_t *info)
686 {
687         get_link_info(info);
688         return(info->link_path);
689 }
690
691 static const char *
692 get_link_name(type_info_t *info)
693 {
694         get_link_info(info);
695         return(info->link_name);
696 }
697
698 static const char *
699 get_buff(type_info_t *info)
700 {
701         const struct    stat    *buf;
702
703         if(!info->buffer && info->buffer != (char *)-1)
704         {
705                 buf = get_stat(info);
706                 if(buf && buf->st_size)
707                 {
708                         if ((info->file_fd == -1) && (get_fd(info) == -1))
709                            return 0;
710                         
711                         info->mmap_size_to_free = buf->st_size;
712                         if((info->buffer = mmap(NULL,
713                                 buf->st_size,
714                                 PROT_READ, MAP_PRIVATE,
715                                 info->file_fd, NULL)) == (char *)-1)
716                         {
717                                 info->mmap_size_to_free = -1;
718                                 info->size_to_free = buf->st_size+1;
719                                 info->buffer = malloc(info->size_to_free);
720                                 if(read(info->file_fd, (void *)info->buffer,
721                                                 info->size_to_free) == -1)
722                                 {
723                                         return(0);
724                                 }
725                         }
726                         info->buff_size = buf->st_size;
727                 }
728                 else
729                 {
730                         return((char *)0);
731                 }
732
733         }
734         return(info->buffer);
735 }
736
737 int
738 get_buff_size(type_info_t *info)
739 {
740         return(info->buff_size);
741 }
742 static DtDtsMMDatabase *
743 get_dc_db()
744 {
745         DtDtsMMDatabase *dc_db = 0;
746
747         if(!dc_db)
748         {
749 #ifdef  DEBUG
750 fprintf(stderr, "Load DataCriteria\n");
751 #endif
752                 dc_db = _DtDtsMMGet(DtDTS_DC_NAME);
753                 if(!dc_db)
754                 {
755                         _DtSimpleError(
756                                 DtProgName, DtError, NULL,
757                                 "No DataBase loaded\n", NULL);
758                         return(NULL);
759                 }
760         }
761 #ifdef NO_MMAP
762         if(dc_db->compare != cde_dc_compare)
763         {
764                 int     i;
765                 for(i = 0; i < dc_db->recordCount; i++)
766                 {
767                         if(dc_db->recordList[i]->compare !=cde_dc_field_compare)
768                         {
769                                 _DtDtsMMFieldSort(dc_db->recordList[i], 
770                                         cde_dc_field_compare);
771                         }
772                 }
773                 _DtDtsMMRecordSort(dc_db, cde_dc_compare);
774 #ifdef DEBUG
775 _DtDtsMMPrint(stdout);
776 #endif
777         }
778 #endif
779         return(dc_db);
780 }
781
782 static DtDtsMMDatabase *
783 get_da_db()
784 {
785         DtDtsMMDatabase *da_db = 0;
786         if(!da_db)
787         {
788 #ifdef  DEBUG
789 fprintf(stderr, "Load DataAttributes\n");
790 #endif
791                 da_db = _DtDtsMMGet(DtDTS_DA_NAME);
792                 if(!da_db)
793                 {
794                         _DtSimpleError(
795                                 DtProgName, DtError, NULL,
796                                 "No DataBase loaded\n", NULL);
797                         return(NULL);
798                 }
799         }
800
801 #ifdef NO_MMAP
802         if(da_db->compare != _DtDtsMMCompareRecordNames)
803         {
804                 int     i;
805                 for(i = 0; i < da_db->recordCount; i++)
806                 {
807                         if(da_db->recordList[i]->compare !=
808                                         _DtDtsMMCompareFieldNames)
809                         {
810                                 _DtDtsMMFieldSort(da_db->recordList[i], 
811                                         _DtDtsMMCompareFieldNames);
812                         }
813                 }
814
815                 _DtDtsMMRecordSort(da_db, _DtDtsMMCompareRecordNames);
816         }
817 #endif
818         return(da_db);
819 }
820
821 #define DTSATTRVAL(attr_name) if(_DtDtsMMStringToBoson(attr_name) == fld_ptr->fieldName)
822
823 static int
824 type_content(char *attr, type_info_t *info)
825 {
826         int     match = 0;
827         char    *c;
828         int     end = 0, s;
829         const   char    *buff = 0;
830         const   struct  stat    *buf;
831         char            *p;
832         _Xstrtokparams  strtok_buf;
833
834         if(buf = get_stat(info))
835         {
836                 if((buf->st_mode&S_IFMT) == S_IFDIR && 
837                         (c = strstr(attr, "filename")))
838                 {
839                         char *file;
840                         const char *path;
841
842                         c = _XStrtok(c, " \t\n", strtok_buf);
843                         c = _XStrtok(NULL, " \t\n", strtok_buf);
844                         path = get_file_path(info);
845                         file = calloc(1, strlen(path)+strlen(c)+2);
846                         sprintf(file, "%s/%s", path, c);
847                         if(access(file, F_OK))
848                         {
849                                 free(file);
850                                 return(0);
851                         }
852                         else
853                         {
854                                 free(file);
855                                 return(1);
856                         }
857                 }
858                 else if((buf->st_mode&S_IFMT) != S_IFREG)
859                 {
860                         return(0);
861                 }
862         }
863         buff = get_buff(info);
864         if((long)buff == 0 || (long)buff == -1)
865         {
866                 return(0);
867         }
868
869         attr = strdup(attr);
870         c = _XStrtok(attr, " \t\n", strtok_buf);
871         if(!isdigit(*c) && *c != '-')
872         {
873                 /* find where c is in buff */
874                 printf("start as string not ready yet\n");
875                 match = 0;
876         }
877         else
878         {
879                 if(*c == '-')
880                 {
881                         end = 1;
882                         c++;
883                 }
884
885                 s = atoi(c);
886                 if(end) 
887                 {
888                         if (buf)
889                         {
890                                 if (s > buf->st_size)
891                                 {
892                                         free(attr);
893                                         return(match);
894                                 }
895                                 s = buf->st_size - s;
896                         }
897                         else
898                         {
899                                 if (!info->buff_size || (s > info->buff_size))
900                                 {
901                                         free(attr);
902                                         return(match);
903                                 }
904                                 s = info->buff_size - s;
905                         }
906                 }
907                 c = _XStrtok(NULL, " \t\n", strtok_buf);
908                 switch(c[1])
909                 {
910                 case    't': /* string */
911                 {
912                         int     cl;
913
914                         c = _XStrtok(NULL, "\n", strtok_buf);
915                         cl = strlen(c);
916                         if((info->buff_size-s) >= cl && memcmp(&buff[s], c, cl) == 0)
917                         {
918                                 match = 1;
919                         }
920                         else
921                         {
922                                 match = 0;
923                         }
924                         break;
925                 }
926                 case    'y': /* byte */
927                 {
928                         unsigned char   lv;
929                         unsigned char   num;
930                         int     i = 0;
931
932                         match = 0;
933                         while(c = _XStrtok(NULL, "\t \n", strtok_buf))
934                         {
935                                 if(s+i*sizeof(lv)+sizeof(lv) > get_buff_size(info))
936                                 {
937                                         match = 0;
938                                         break;
939                                 }
940                                 memcpy(&lv, &buff[s+i*sizeof(lv)], sizeof(lv));
941                                 num = (unsigned char)strtol(c, &p, 0);
942                                 if (num != lv || c == p)
943                                 {
944                                         match = 0;
945                                         break;
946                                 }
947                                 else
948                                 {
949                                         match = 1;
950                                 }
951                                 i++;
952                         }
953                         break;
954                 }
955                 case    'h': /* short */
956                 {
957                         unsigned short  lv;
958                         unsigned short  num;
959                         int             i = 0;
960                         const unsigned char *bufPtr;
961
962                         match = 0;
963                         for(i = 0;(c = _XStrtok(NULL, "\t \n", strtok_buf)); i++)
964                         {
965                                 if(s+i*sizeof(lv)+sizeof(lv) > get_buff_size(info))
966                                 {
967                                         match = 0;
968                                         break;
969                                 }
970                                 bufPtr = (unsigned char *)
971                                   &buff[s + (i * sizeof(lv))];
972                                 lv = (((unsigned short)*bufPtr) << 8) |
973                                      ((unsigned short)*(bufPtr + 1));
974                                 num = (unsigned short)strtol(c, &p, 0);
975                                 if (num != lv || c == p)
976                                 {
977                                         match = 0;
978                                         break;
979                                 }
980                                 else
981                                 {
982                                         match = 1;
983                                 }
984                         }
985                         break;
986                 }
987                 case    'o': /* long */
988                 {
989                         /* Not true long - really 4 bytes. */
990                         unsigned int    lv;
991                         unsigned int    num;
992                         int             i = 0;
993                         const unsigned char *bufPtr;
994
995                         match = 0;
996                         for(i = 0;(c = _XStrtok(NULL, "\t \n", strtok_buf)); i++)
997                         {
998                                 if(s+i*sizeof(lv)+sizeof(lv) > get_buff_size(info))
999                                 {
1000                                         match = 0;
1001                                         break;
1002                                 }
1003                                 bufPtr = (unsigned char *)
1004                                   &buff[s + (i * sizeof(lv))];
1005                                 lv = (((unsigned int)*bufPtr) << 24) |
1006                                      (((unsigned int)*(bufPtr + 1)) << 16) |
1007                                      (((unsigned int)*(bufPtr + 2)) << 8) |
1008                                      ((unsigned int)*(bufPtr + 3));
1009                                 num = (unsigned int)strtol(c, &p, 0);
1010                                 if (num != lv || c == p)
1011                                 {
1012                                         match = 0;
1013                                         break;
1014                                 }
1015                                 else
1016                                 {
1017                                         match = 1;
1018                                 }
1019                         }
1020                         break;
1021                 }
1022                 default:
1023                         match = 0;
1024                 }
1025                 
1026         }
1027         free(attr);
1028         return(match);
1029 }
1030
1031 static char *
1032 _DtDtsGetDataType(const char *file)
1033 {
1034         int             fd;
1035         char            *name;
1036         struct stat     file_stat;
1037         u_char          *buff = 0;
1038         int             start;
1039         char            *dt = 0;
1040         int             end;
1041
1042         name = calloc(1, MAXPATHLEN+1);
1043         sprintf(name, "%s/%s", file, DtDTS_DT_DIR);
1044         if((fd = open(name, O_RDONLY, 0644)) != -1)
1045         {
1046                 if(fstat(fd, &file_stat) == 0)
1047                 {
1048                         buff = (u_char *)calloc((size_t)1, file_stat.st_size+1);
1049                         read(fd, buff, file_stat.st_size);
1050                 }
1051                 dt = strstr((char *)buff, DtDTS_DATA_ATTRIBUTES_NAME);
1052                 if(dt != NULL)
1053                 {
1054                         start = dt-(char*)buff;
1055                         while(!isspace(buff[start])) start++;
1056                         while(isspace(buff[start]))start++;
1057                         end = start;
1058                         while(!isspace(buff[end])) end++;
1059                         buff[end] = '\0';
1060                         dt = strdup((char *)&buff[start]);
1061                 }
1062                 close(fd);
1063         }
1064         if(buff)free(buff);
1065         if(name)free(name);
1066         return(dt);
1067 }
1068
1069 static int
1070 type_mode(char *attr, type_info_t *info)
1071 {
1072         int             match = 0;
1073         const   struct  stat    *buf = get_stat(info);
1074         const   struct  stat    *lbuf;
1075
1076         if (!buf || !*attr)
1077         {
1078                 return(0);
1079         }
1080
1081         do
1082         {
1083                 match = 0;
1084                 switch(*attr)
1085                 {
1086                 case    'f':
1087                         match = (buf->st_mode&S_IFMT) == S_IFREG;
1088                         break;
1089                 case    'c':
1090                         match = (buf->st_mode&S_IFMT) == S_IFCHR;
1091                         break;
1092                 case    'b':
1093                         match = (buf->st_mode&S_IFMT) == S_IFBLK;
1094                         break;
1095                 case    'd':
1096                         if((buf->st_mode&S_IFMT) == S_IFDIR)
1097                         {
1098                                 int     n;
1099                                 int     fd;
1100
1101                                 match = 1;
1102                                 if(!info->set_datatype)
1103                                 {
1104                                         info->set_datatype = 1;
1105                                         info->ot = 
1106                                               _DtDtsGetDataType(get_file_path(info));
1107                                         if(info->ot) return(match);
1108                                 }
1109                         }
1110                         else
1111                         {
1112                                 match = 0;
1113                         }
1114         
1115                         break;
1116                 case    'l':
1117                         if(islink(info))
1118                         {
1119                                 match = 1;
1120                         }
1121                         else if(lbuf = get_lstat(info))
1122                         {
1123                                 match = (lbuf->st_mode&S_IFMT) == S_IFLNK;
1124                         }
1125                         else
1126                         {
1127                                 match = 0;
1128                         }
1129                         break;
1130                 case    'r':
1131                         if(buf->st_mode&S_IROTH || \
1132                            buf->st_mode&S_IRGRP || \
1133                            buf->st_mode&S_IRUSR )
1134                         {
1135                                 match = 1;
1136                         }
1137                         else
1138                         {
1139                                 match = 0;
1140                         }
1141                         break;
1142                 case    'w':
1143                         if(buf->st_mode&S_IWOTH || \
1144                            buf->st_mode&S_IWGRP || \
1145                            buf->st_mode&S_IWUSR )
1146                         {
1147                                 match = 1;
1148                         }
1149                         else
1150                         {
1151                                 match = 0;
1152                         }
1153                         break;
1154                 case    'x':
1155                         if(buf->st_mode&S_IXOTH || \
1156                            buf->st_mode&S_IXGRP || \
1157                            buf->st_mode&S_IXUSR ) 
1158                         {
1159                                 match = 1;
1160                         }
1161                         else
1162                         {
1163                                 match = 0;
1164                         }
1165                         break;
1166                 case    'g':
1167                         match = buf->st_mode&S_ISGID;
1168                         break;
1169                 case    'u':
1170                         match = buf->st_mode&S_ISUID;
1171                         break;
1172                 }
1173                 attr++;
1174         } while(*attr && match);
1175         return(match);
1176 }
1177
1178 static int
1179 type_name(const char *name, char *attr)
1180 {
1181         int     match = 0;
1182
1183         if(name && (int)name != -1)
1184         {
1185 #ifdef USE_FNMATCH
1186                 match = !fnmatch(attr, name, 0);
1187 #else
1188                 match =  gmatch(name, attr);
1189 #endif
1190         }
1191         return(match);
1192 }
1193
1194 static int
1195 type_path(const char *path, char *attr)
1196 {
1197         char    *c;
1198         int     match = 0;
1199
1200         if(path && (int)path != -1)
1201         {
1202 #ifdef USE_FNMATCH
1203                 match = !fnmatch(attr, path, 0);
1204 #else
1205                 match = gmatch(path, attr);
1206 #endif
1207         }
1208         return(match);
1209 }
1210
1211 static char *
1212 next_sep(char *str, char *sep)
1213 {
1214         char    *c;
1215         char    *prev;
1216
1217         c = str;
1218         while(*c)
1219         {
1220                 c = _dt_strpbrk(c, sep);
1221                 if(!c)
1222                 {
1223                         return(c);
1224                 }
1225                 prev = c-1;
1226                 if((c == str) || (_is_previous_single(str, c) && (*prev != '\\')))
1227                 {
1228                         return(c);
1229                 }
1230                 _MBADV(c);
1231         }
1232         return((char *)0);
1233 }
1234
1235 char    *
1236 DtDtsDataToDataType(const char *fp,
1237         const void              *buf,
1238         const int               bs,
1239         const struct stat       *fs,
1240         const char              *ln,
1241         const struct stat       *ls,
1242         const char              *on)
1243 {
1244         DtDtsMMDatabase *db;
1245         DtDtsMMRecord   *rec_ptr = 0;
1246         DtDtsMMRecord   *rec_ptr_list;
1247         DtDtsMMField    *fld_ptr;
1248         DtDtsMMField    *fld_ptr_list;
1249         type_info_t     *info = 0;
1250         int     i;
1251         int     j;
1252         int     rec_m = 0;
1253         int     fld_m = 0;
1254         int     atr_m = 0;
1255         int     p_atr_m = 1;
1256         int     c_atr_m = 1;
1257         char    *ot = NULL;
1258         char    *file;
1259         char    *attr;
1260         char    op;
1261
1262         _DtSvcAppLockDefault();
1263         _DtSvcProcessLock();
1264         db = get_dc_db();
1265         if(!db)
1266         {
1267                 _DtSvcProcessUnlock();
1268                 _DtSvcAppUnlockDefault();
1269                 return(strdup("UNKNOWN"));
1270         }
1271
1272         info = set_vals(fp, buf, bs, fs, ln, ls, on);
1273         if(!dtdts_path_pattern)
1274         {
1275                 dtdts_path_pattern = _DtDtsMMStringToBoson(DtDTS_PATH_PATTERN);
1276                 dtdts_name_pattern = _DtDtsMMStringToBoson(DtDTS_NAME_PATTERN);
1277                 dtdts_mode = _DtDtsMMStringToBoson(DtDTS_MODE);
1278                 dtdts_link_name = _DtDtsMMStringToBoson(DtDTS_LINK_NAME);
1279                 dtdts_link_path = _DtDtsMMStringToBoson(DtDTS_LINK_PATH);
1280                 dtdts_content = _DtDtsMMStringToBoson(DtDTS_CONTENT);
1281                 dtdts_data_attributes_name = _DtDtsMMStringToBoson(DtDTS_DATA_ATTRIBUTES_NAME);
1282
1283                 dtdts_da_is_action = _DtDtsMMStringToBoson(DtDTS_DA_IS_ACTION);
1284                 dtdts_da_icon = _DtDtsMMStringToBoson(DtDTS_DA_ICON);
1285                 dtdts_da_description = _DtDtsMMStringToBoson(DtDTS_DA_DESCRIPTION);
1286                 dtdts_da_label = _DtDtsMMStringToBoson(DtDTS_DA_LABEL);
1287         }
1288
1289         for(i = 0; !rec_m && (rec_ptr = name_list(info, db, rec_ptr)); i++)
1290         {
1291                 fld_ptr_list = _DtDtsMMGetPtr(rec_ptr->fieldList);
1292                 fld_m = 1;
1293                 for(j=0; fld_m && j < rec_ptr->fieldCount; j++)
1294                 {
1295                         char    sep = '&';
1296                         DtDtsMMField    *fld_ptr = &fld_ptr_list[j];
1297
1298                         p_atr_m = 1;
1299                         c_atr_m = 1;
1300                         info->orig_attr = _DtDtsMMExpandValue(
1301                                         _DtDtsMMBosonToString(fld_ptr->fieldValue));
1302                         attr = info->orig_attr;
1303                         do
1304                         {
1305                                 int     neg = 0;
1306                                 char    *new_sep;
1307                                 int     n;
1308                                 char    *c;
1309
1310                                 atr_m = 1;
1311                                 while(*attr == '!')
1312                                 {
1313                                         neg = !neg;
1314                                         attr++;
1315                                 }
1316                                 new_sep = next_sep(attr, "&|\0");
1317                                 if(new_sep == 0)
1318                                 {
1319                                         new_sep = attr + strlen(attr);
1320                                 }
1321                                 n = new_sep-attr+1;
1322                                 c = max_buf((size_t)n, info);
1323
1324                                 strncpy(c, attr, new_sep-attr);
1325                                 c[new_sep-attr] = '\0';
1326                                 attr = new_sep;
1327                                 new_sep = c;
1328 /*
1329                                 while(new_sep = (char *)_dt_strpbrk(new_sep, "&|"))
1330                                 {
1331                                         new_sep--;
1332                                         strcpy(new_sep, &new_sep[1]);
1333                                         new_sep++;
1334                                 }
1335 */
1336
1337                                 if(fld_ptr->fieldName == dtdts_path_pattern)
1338                                 {
1339                                         atr_m = type_path(
1340                                                         get_file_path(info),
1341                                                         max_buf((size_t)0, info));
1342                                 }
1343                                 else if(fld_ptr->fieldName == dtdts_name_pattern)
1344                                 {
1345                                         if(get_file_path(info))
1346                                         {
1347                                                 atr_m = type_name(
1348                                                         get_name(info),
1349                                                         max_buf((size_t)0, info));
1350                                         }
1351                                         else
1352                                         {
1353                                                 atr_m = type_name(
1354                                                         get_opt_name(info),
1355                                                         max_buf((size_t)0, info));
1356                                         }
1357                                 }
1358                                 else if(fld_ptr->fieldName == dtdts_mode)
1359                                 {
1360                                         if(get_file_path(info))
1361                                         {
1362                                                 atr_m = type_mode(
1363                                                         max_buf((size_t)0, info), info);
1364                                         }
1365                                         else
1366                                         {
1367                                                 atr_m = !neg;
1368                                         }
1369                                 }
1370                                 else if(fld_ptr->fieldName == dtdts_link_name)
1371                                 {
1372                                         atr_m = type_name(
1373                                                         get_link_name(info),
1374                                                         max_buf((size_t)0, info));
1375
1376                                 }
1377                                 else if(fld_ptr->fieldName == dtdts_link_path)
1378                                 {
1379                                         atr_m = type_path(
1380                                                         get_link_path(info),
1381                                                         max_buf((size_t)0, info));
1382                                 }
1383                                 else if(fld_ptr->fieldName == dtdts_content)
1384                                 {
1385                                         atr_m = type_content(
1386                                                         max_buf((size_t)0, info), info);
1387                                 }
1388                                 else if(fld_ptr->fieldName == dtdts_data_attributes_name)
1389                                 {
1390                                         info->ot = strdup(max_buf((size_t)0, info));
1391                                 }
1392
1393                                 if(info->error == ELOOP)
1394                                 {
1395                                         _DtSvcProcessUnlock();
1396                                         _DtSvcAppUnlockDefault();
1397                                         return(
1398                                            cleanup(DtDTS_DT_RECURSIVE_LINK, info)
1399                                                 );
1400                                 }
1401                                 if(info->ot)
1402                                 {
1403                                         _DtSvcProcessUnlock();
1404                                         _DtSvcAppUnlockDefault();
1405                                         return(cleanup(0, info));
1406                                 }
1407
1408                                 atr_m=(neg)?!atr_m:atr_m;
1409
1410                                 switch(sep)
1411                                 {
1412                                 case    '&':
1413                                         p_atr_m = atr_m && p_atr_m;
1414                                         break;
1415                                 case    '|':
1416                                         p_atr_m = atr_m || p_atr_m;
1417                                         break;
1418                                 }
1419                                 if(attr && *attr)
1420                                 {
1421                                         sep = *attr;
1422                                         attr++;
1423                                         switch(sep)
1424                                         {
1425                                         case    '&':
1426                                                 c_atr_m = p_atr_m?1:0;
1427                                                 break;
1428                                         case    '|':
1429                                                 c_atr_m = p_atr_m?0:1;
1430                                                 break;
1431                                         }
1432                                 }
1433                                 else
1434                                 {
1435                                         c_atr_m = 0;
1436                                 }
1437                         } while ( c_atr_m );
1438                         if(info->orig_attr)
1439                         {
1440                                 _DtDtsMMSafeFree(info->orig_attr);
1441                                 info->orig_attr = 0;
1442                         }
1443
1444                         if(!p_atr_m)
1445                         {
1446                                 fld_m = 0;
1447                         }
1448                 }
1449                 if(fld_m)
1450                 {
1451                         rec_m = 1;
1452                 }
1453         }
1454         _DtSvcProcessUnlock();
1455         _DtSvcAppUnlockDefault();
1456         return(cleanup(0, info));
1457 }
1458
1459 char    *
1460 DtDtsFileToDataType(const char *filepath)
1461 {
1462         char *dt = DtDtsDataToDataType(filepath, 0, -1, 0, 0, 0, 0);
1463         return(dt);
1464 }
1465
1466 char    *
1467 DtDtsBufferToDataType(const void *buffer, const int size, const char *name)
1468 {
1469         char *dt = DtDtsDataToDataType(0, buffer, size, 0, 0, 0, name);
1470         return(dt);
1471 }
1472
1473 static char *
1474 expand_keyword(const char *attr_in, const char *in_pathname)
1475 {
1476         char    *buf;
1477         char    *netPath;
1478         char    *c;
1479         char    *tmp;
1480         int     i;
1481         int     n;
1482         char    *p;
1483         char    *attr = (char *)attr_in;
1484
1485
1486         if(!attr)
1487         {
1488                 return(attr);
1489         }
1490         if(in_pathname)
1491         {
1492                 n = strlen(attr)+1;
1493                 buf = (char *) calloc(1, n);
1494                 netPath = strdup(in_pathname);
1495
1496                 for(c = attr, i= 0; *c && i < n; c++)
1497                 {
1498                         if ( *c != '%' )
1499                         {
1500                                 buf[i++] = *c;
1501                                 buf[i]=0;   /* ensure null string termination */
1502                                 continue;
1503                         }
1504                         /* check for keyword matches */
1505                         if ( !strncmp(c,"%file%",6) )
1506                         {
1507                                 n += strlen(netPath) - 6;
1508                                 buf = (char *)realloc(buf, n);
1509                                 strcpy((buf+i), netPath);
1510                                 i += strlen(netPath);
1511                                 c += 5;
1512                                 continue;
1513                         }
1514                         else if ( !strncmp(c,"%dir%",5) )
1515                         {
1516                                 tmp = strrchr(netPath, '/');
1517                                 *tmp = '\0';
1518                                 n += strlen(netPath) - 5;
1519                                 buf = (char *)realloc(buf, n);
1520                                 strcpy((buf+i),netPath);
1521                                 i += strlen(netPath);
1522                                 *tmp = '/';
1523                                 c += 4;
1524                         }
1525                         else if ( !strncmp(c,"%name%",6) )
1526                         {
1527                                 tmp = strrchr(netPath, '/');
1528                                 tmp ++;
1529                                 n += strlen(tmp) - 6;
1530                                 buf = (char *)realloc(buf, n);
1531                                 strcpy((buf+i),tmp);
1532                                 i +=strlen(tmp);
1533                                 c += 5;
1534                         }
1535                         else if ( !strncmp(c,"%suffix%",8) )
1536                         {
1537                                 if ((p = strrchr(netPath,'.')) != NULL)
1538                                 {
1539                                         p++;
1540                                         n += strlen(p) - 8;
1541                                         buf = (char *)realloc(buf, n);
1542                                         strcpy((buf+i),p);
1543                                         i +=strlen(p);
1544                                 }
1545                                 c += 7;
1546                         }
1547                         else if ( !strncmp(c,"%base%",6) )
1548                         {
1549                                 tmp = strrchr(netPath, '/');
1550                                 tmp ++;
1551                                 if ((p = strrchr(tmp,'.')) != NULL)
1552                                 {
1553                                         n += p-tmp - 6;
1554                                         buf = (char *)realloc(buf, n);
1555                                         strncpy((buf+i),tmp,p-tmp);
1556                                         buf[i+p-tmp] = '\0';
1557                                         i += p-tmp;
1558                                 }
1559                                 c += 5;
1560                         }
1561                         else
1562                         { /* no match -- just copy the character */
1563                                 buf[i++] = *c;
1564                                 buf[i]=0;   /* ensure null string termination */
1565                                 continue;
1566                         }
1567                 }
1568                 if(netPath)free(netPath);
1569                 return(buf);
1570         }
1571         else
1572         {
1573                 return(strdup(attr));
1574         }
1575 }
1576
1577 char *
1578 append(char *old, char *add)
1579 {
1580         char    *new;
1581
1582         if(old)
1583         {
1584                 new = realloc(old, strlen(old)+strlen(add)+1);
1585         }
1586         else
1587         {
1588                 new = malloc(strlen(add)+1);
1589                 *new = '\0';
1590         }
1591
1592         strcat(new, add);
1593
1594         return(new);
1595 }
1596
1597 char *
1598 expand_shell(const char *attr)
1599 {
1600         char    *srch;
1601         char    *nattr;
1602         char    *start, *end;
1603         int     size;
1604         FILE    *fd;
1605         char    buff[200];
1606         char    *results = 0;
1607
1608         if(!attr)
1609         {
1610                 return(NULL);
1611         }
1612         nattr = strdup(attr);
1613         srch = nattr;
1614         while((start = DtStrchr(srch, '`')) != NULL)
1615         {
1616                 if((srch != start) && _is_previous_single(srch, start) && 
1617                    (*(start-1) == '`'))
1618                 {
1619                         srch = start + 1;
1620                         continue;
1621                 }
1622                 if((end = DtStrchr(&start[1], '`')) == NULL)
1623                 {
1624                         srch = start + 1;
1625                         continue;
1626                 }
1627                 *start = '\0';
1628                 *end = '\0';
1629                 results = append(results, srch);
1630
1631
1632                 if((fd = popen(&start[1], "r")) == NULL)
1633                 {
1634                         _DtSimpleError(
1635                                 DtProgName, DtError, NULL,
1636                                 (char*) &start[1], NULL);
1637                         if(nattr)free(nattr);
1638                         if(results)free(results);
1639                         return(NULL);
1640                 }
1641
1642                 memset(buff, '\0', sizeof(buff));
1643                 while(size = fread(buff, 1, sizeof(buff)-1, fd))
1644                 {
1645                         buff[sizeof(buff)-1] = '\0';
1646                         results = append(results, buff);
1647                         memset(buff, '\0', sizeof(buff));
1648                 }
1649                 srch = end+1;
1650         }
1651         results = append(results, srch);
1652         if(nattr) free(nattr);
1653         return(results);
1654 }
1655
1656 static char *
1657 expand_value(DtShmBoson attr, char *in_pathname)
1658 {
1659         char *tmp;
1660         char *exp;
1661         char *shell_exp;
1662
1663         if(attr && attr != -1)
1664         {
1665                 tmp = _DtDtsMMExpandValue(_DtDtsMMBosonToString(attr));
1666                 exp = expand_keyword(tmp, in_pathname);
1667                 shell_exp = expand_shell(exp);
1668
1669                 _DtDtsMMSafeFree(tmp);
1670                 if(shell_exp)
1671                 {
1672                         free(exp);
1673                         exp = expand_keyword(shell_exp, in_pathname);
1674                         free(shell_exp);
1675                 }
1676         }
1677         else
1678         {
1679                 exp = NULL;
1680         }
1681
1682         return(exp);
1683 }
1684
1685 char    *
1686 DtDtsDataTypeToAttributeValue(const char *obj_type, const char *attr, const char *filename)
1687 {
1688         DtDtsMMDatabase *db;
1689         DtDtsMMRecord   *entry;
1690         char            *value = 0;
1691
1692         _DtSvcAppLockDefault();
1693         _DtSvcProcessLock();
1694         db = get_da_db();
1695         if(db && obj_type)
1696         {
1697                 entry = _DtDtsMMGetRecordByName(db, (char *)obj_type);
1698
1699                 if(entry)
1700                 {
1701                         char    *name = 0;
1702                         DtDtsMMField *fld = _DtDtsMMGetField(entry,(char *)attr);
1703
1704
1705                         if ( fld )
1706                         {
1707                                 value = expand_value(fld->fieldValue,
1708                                         (char *)filename);
1709                         }
1710                 }
1711         }
1712         _DtSvcProcessUnlock();
1713         _DtSvcAppUnlockDefault();
1714         return(value);
1715 }
1716
1717 DtDtsAttribute  **
1718 DtDtsDataTypeToAttributeList(const char *obj_type, const char *filename)
1719 {
1720         DtDtsMMDatabase *db;
1721         DtDtsMMRecord   *entry;
1722         DtDtsMMField    *fld_ptr_list;
1723         DtDtsMMField    *fld_ptr;
1724         DtDtsAttribute  **list = NULL;
1725         int             i;
1726         int             action_flag = 0;
1727         int             sort_flag = 0;
1728         int             found_flag = 0;
1729         DtDtsMMField    *fld;
1730
1731         _DtSvcAppLockDefault();
1732         _DtSvcProcessLock();    
1733         db = get_da_db();
1734         entry = _DtDtsMMGetRecordByName(db, (char *)obj_type);
1735
1736         if(!db || !obj_type || !entry)
1737         {
1738                 _DtSvcProcessUnlock();
1739                 _DtSvcAppUnlockDefault();
1740                 return (list);
1741         }
1742
1743         list = (DtDtsAttribute  **)calloc(entry->fieldCount+1, 
1744                                                 sizeof(DtDtsAttribute *));
1745         fld_ptr_list = _DtDtsMMGetPtr(entry->fieldList);
1746         for(i = 0; i < entry->fieldCount; i++)
1747         {
1748                 char    *tmp;
1749                 fld_ptr = &fld_ptr_list[i];
1750
1751                 list[i] = (DtDtsAttribute *)malloc(sizeof(DtDtsAttribute));
1752                 list[i]->name = 
1753                         expand_value(fld_ptr->fieldName,
1754                                          (char *)filename);
1755
1756                 list[i]->value = 
1757                         expand_value(fld_ptr->fieldValue, (char *)filename);
1758         }
1759         list[i] = 0;
1760         _DtSvcProcessUnlock();
1761         _DtSvcAppUnlockDefault();
1762         return(list);
1763 }
1764
1765 void
1766 DtDtsFreeAttributeList(DtDtsAttribute **list)
1767 {
1768         DtDtsAttribute **item = list;
1769         int i = 0;
1770
1771         if(list)
1772         {
1773                 while(list[i] && list[i]->name)
1774                 {
1775                         if(list[i]->name)free(list[i]->name);
1776                         if(list[i]->value)free(list[i]->value);
1777                         if(list[i]) free(list[i]);
1778                         i++;
1779                 }
1780                 free(list);
1781         }
1782 }
1783
1784 DtDtsAttribute  **
1785 DtDtsFileToAttributeList(const char *filepath)
1786 {
1787         char    *ot = DtDtsFileToDataType(filepath);
1788         DtDtsAttribute **al = DtDtsDataTypeToAttributeList(ot, filepath);
1789
1790         DtDtsFreeDataType(ot);
1791         return(al);
1792 }
1793
1794 DtDtsAttribute  **
1795 DtDtsBufferToAttributeList(const void *buffer, const int size, const char *name)
1796 {
1797         char    *ot = DtDtsBufferToDataType(buffer, size, name);
1798         DtDtsAttribute **al = DtDtsDataTypeToAttributeList(ot, NULL);
1799
1800         DtDtsFreeDataType(ot);
1801         return(al);
1802 }
1803
1804 char    *
1805 DtDtsFileToAttributeValue(const char *filepath, const char *attr)
1806 {
1807         char    *ot = DtDtsFileToDataType(filepath);
1808         char    *value = DtDtsDataTypeToAttributeValue(ot, attr, filepath);
1809
1810         DtDtsFreeDataType(ot);
1811         return(value);
1812 }
1813
1814 char    *
1815 DtDtsBufferToAttributeValue(const void *buffer, const int size, const char *attr, const char *name)
1816 {
1817         char    *ot = DtDtsBufferToDataType(buffer, size, name);
1818         char    *value = DtDtsDataTypeToAttributeValue(ot, attr, name);
1819
1820         DtDtsFreeDataType(ot);
1821         return(value);
1822 }
1823
1824 void
1825 DtDtsFreeAttributeValue(char *value)
1826 {
1827         if(value) free(value);
1828 }
1829
1830 void
1831 DtDtsFreeDataType(char *datatype)
1832 {
1833         if(datatype) free(datatype);
1834 }
1835
1836 int
1837 DtDtsDataTypeIsAction(const char *datatype)
1838 {
1839         char    *val;
1840         if(val = DtDtsDataTypeToAttributeValue(datatype, "IS_ACTION", NULL))
1841         {
1842                 DtDtsFreeAttributeValue(val);
1843                 return(1);
1844         }
1845         else
1846         {
1847                 return(0);
1848         }
1849 }
1850
1851 char **
1852 DtDtsDataTypeNames(void)
1853 {
1854         DtDtsMMDatabase *db;
1855         DtDtsMMRecord   *rec_list;
1856         DtDtsMMRecord   *rec_ptr;
1857         int             i = 0, j=0;
1858         char            **names;
1859
1860         _DtSvcAppLockDefault();
1861         _DtSvcProcessLock();    
1862         db = get_da_db();
1863         if(!db)
1864         {
1865                 _DtSvcProcessUnlock();
1866                 _DtSvcAppUnlockDefault();
1867                 return(NULL);
1868         }
1869
1870         names = (char **)malloc((db->recordCount+1)*sizeof(char *));
1871
1872         rec_list = _DtDtsMMGetPtr(db->recordList);
1873         for(i = 0; i < db->recordCount; i++)
1874         {
1875                 rec_ptr = &rec_list[i];
1876                 names[j] = strdup((char *)_DtDtsMMBosonToString(rec_ptr->recordName));
1877                 j++;
1878         }
1879         names[j] = 0;
1880         _DtSvcProcessUnlock();
1881         _DtSvcAppUnlockDefault();
1882         return(names);
1883 }
1884
1885 void
1886 DtDtsRelease(void)
1887 {
1888 }
1889
1890 char **
1891 DtDtsFindAttribute(const char *name, const char *value)
1892 {
1893         DtDtsMMDatabase *ot;
1894         int             i;
1895         int             j = 0;
1896         char            **list;
1897         char            *v;
1898         DtDtsMMRecord   *rec_ptr;
1899         DtDtsMMRecord   *rec_ptr_list;
1900
1901         _DtSvcAppLockDefault();
1902         _DtSvcProcessLock();    /* To avoid deadlock with DtDtsMMDatabase mutex
1903                                    lock */
1904         ot = get_da_db();
1905         if(!ot || ot->recordCount == 0)
1906         {
1907                 _DtSvcProcessUnlock(); 
1908                 _DtSvcAppUnlockDefault();
1909                 return(NULL);
1910         }
1911
1912         list = (char **)calloc(ot->recordCount, sizeof(char *));
1913         rec_ptr_list = _DtDtsMMGetPtr(ot->recordList);
1914         for(i = 0; i < ot->recordCount; i++)
1915         {
1916                 rec_ptr = &rec_ptr_list[i];
1917                 v = _DtDtsMMExpandValue(_DtDtsMMGetFieldByName(rec_ptr, (char *)name));
1918                 if(v && !strcmp(value, v))
1919                 {
1920                         list[j++] = strdup(_DtDtsMMBosonToString(rec_ptr->recordName));
1921                 }
1922                 _DtDtsMMSafeFree(v);
1923         }
1924         list[j] = 0;
1925         _DtSvcProcessUnlock();
1926         _DtSvcAppUnlockDefault();
1927         return(list);
1928 }
1929
1930 void
1931 DtDtsFreeDataTypeNames(char **list)
1932 {
1933         int     i = 0;
1934
1935         while(list[i])
1936         {
1937                 free(list[i]);
1938                 list[i++] = 0;
1939         }
1940         free(list);
1941 }
1942
1943 #define DIR_INFO        "DIR_INFO\n{\n\t%s\t%s\n}\n"
1944 char *
1945 DtDtsSetDataType(const char *filename, const char *datatype_in, const int overide)
1946 {
1947         int             fsize;
1948         char            *file;
1949         int             fd;
1950         char            *dt;
1951         int             size;
1952         u_char          *buff;
1953         struct stat     file_stat;
1954         char            *datatype = 0;
1955
1956         fsize = strlen(filename)+strlen(DtDTS_DT_DIR)+2;
1957         file = (char *)calloc(1,fsize);
1958         sprintf(file, "%s/%s", filename, DtDTS_DT_DIR);
1959
1960         if((fd = open(file, O_EXCL|O_CREAT|O_RDWR, 0644)) != -1)
1961         {
1962                 int     write_size;
1963
1964                 size = strlen(DIR_INFO);
1965                 size += strlen(DtDTS_DATA_ATTRIBUTES_NAME);
1966                 size += strlen(datatype_in);
1967                 size-=3;
1968                 buff = (u_char *)calloc((size_t)1, size);
1969                 sprintf((char *)buff, DIR_INFO, DtDTS_DATA_ATTRIBUTES_NAME, datatype_in);
1970
1971                 write_size = write(fd, buff, size);
1972                 if(write_size != size)
1973                 {
1974                     _DtSimpleError(
1975                                 DtProgName, DtError, NULL,
1976                                 (char*) buff, NULL);
1977                 }
1978                 datatype = strdup(datatype_in);
1979                 free(buff);
1980                 close(fd);
1981         }
1982         else if(overide && (fd = open(file, O_RDWR, 0644)) != -1)
1983         {
1984                 int     start;
1985                 int     end;
1986                 int     dtsize = strlen(datatype_in);
1987                 int     write_size;
1988
1989                 if(fstat(fd, &file_stat) == 0)
1990                 {
1991                         buff = (u_char *)calloc((size_t)1, file_stat.st_size+1);
1992                         read(fd, buff, file_stat.st_size);
1993                 }
1994                 dt = strstr((char *)buff, DtDTS_DATA_ATTRIBUTES_NAME);
1995                 if(dt == NULL)
1996                 {
1997                         free(buff);
1998                         size = strlen(DIR_INFO);
1999                         size += strlen(DtDTS_DATA_ATTRIBUTES_NAME);
2000                         size += dtsize;
2001                         size-=3;
2002                         buff = (u_char *)calloc((size_t)1, size);
2003                         sprintf((char *)buff, DIR_INFO,
2004                                         DtDTS_DATA_ATTRIBUTES_NAME,
2005                                         datatype_in);
2006                         write_size = write(fd, buff, size);
2007                         if(write_size != size)
2008                         {
2009                             _DtSimpleError(
2010                                         DtProgName, DtError, NULL,
2011                                         (char*) buff, NULL);
2012                         }
2013                         datatype = strdup(datatype_in);
2014                 }
2015                 else
2016                 {
2017                         int     off, total;
2018
2019                         start = dt-(char *)buff;
2020                         while(!isspace(buff[start])) start++;
2021                         while(isspace(buff[start]))start++;
2022                         end = start;
2023                         while(!isspace(buff[end])) end++;
2024                         lseek(fd, start, SEEK_SET);
2025                         if(write(fd, datatype_in, dtsize) != dtsize)
2026                         {
2027                             _DtSimpleError(
2028                                         DtProgName, DtError, NULL,
2029                                         (char*) file, NULL);
2030                         }
2031                         off = write(fd, &buff[end], strlen((char *)&buff[end])+1);
2032                         if(off != strlen((char *)&buff[end])+1)
2033                         {
2034                             _DtSimpleError(
2035                                         DtProgName, DtError, NULL,
2036                                         (char*) file, NULL);
2037                         }
2038                         else
2039                         {
2040                                 total = file_stat.st_size-(end-start)+dtsize;
2041                                 ftruncate(fd, total);
2042                                 datatype = strdup(datatype_in);
2043                         }
2044                 }
2045                 free(buff);
2046                 close(fd);
2047         }
2048         else if (access(file, R_OK) == 0)
2049         {
2050                 datatype = _DtDtsGetDataType(filename);
2051         }
2052         else
2053         {
2054                 datatype = 0;
2055         }
2056         free(file);
2057         return(datatype);
2058 }
2059
2060 static int
2061 srch(const void *a, const void *b)
2062 {
2063         int results = ((struct list *)a)->boson - ((struct list *)b)->boson;
2064
2065         if(results == 0)
2066         {
2067                 results = ((struct list *)a)->rec - ((struct list *)b)->rec;
2068         }
2069         return(results);
2070 }
2071
2072 int *
2073 get_name_list(char *name, int *count)
2074 {
2075         int     boson = name?_DtDtsMMStringToBoson((const char *)name):-1;
2076         int     *results;
2077         int     *list;
2078         int     size;
2079
2080         *count = 0;
2081         if(boson == -1)
2082         {
2083                 return((int *)-1);
2084         }
2085         results = (int *)_DtShmFindIntTabEntry(_DtDtsMMGetDCNameIndex(&size), boson);
2086         if (!results)
2087         {
2088                 return((int *)-1);
2089         }
2090         if(*results < 0)
2091         {
2092                 list = (int *)_DtDtsMMGetPtr(-(*results));
2093                 *count = _DtDtsMMGetPtrSize(-(*results));
2094         }
2095         else
2096         {
2097                 list = results;
2098                 *count = 1;
2099         }
2100         return(list);
2101 }
2102
2103 static DtDtsMMRecord *
2104 name_list(type_info_t *linfo, DtDtsMMDatabase   *db, DtDtsMMRecord *rec_ptr)
2105 {
2106         int                     i;
2107         char                    *src_str;
2108         char                    *name;
2109         int                     size;
2110         int                     isnew;
2111         DtDtsMMRecord           *record_list;
2112         char                    *suffix = 0;
2113
2114         if(rec_ptr == 0)
2115         {
2116                 /* if this is the first time */
2117                 if(linfo->name)
2118                 {
2119                         /* get the name */
2120                         name = linfo->name;
2121                 }
2122                 else
2123                 {
2124                         /* if not name use opt name */
2125                         name = (char *)linfo->opt_name;
2126                 }
2127
2128                 /* initialize name count */
2129                 linfo->name_count = 0;
2130                 if(!name)
2131                 {
2132                         /* a name could not be found so this must be a buffer */
2133                         linfo->name_prev = (int *)
2134                                 _DtDtsMMGetBufferIndex(&linfo->name_count);
2135                         linfo->name_type = 3;
2136                 }
2137                 else
2138                 {
2139                         if(name && *name)
2140                         {
2141                                 /* now find suffix if any */
2142                                 suffix = strrchr(name, '.');
2143                         }
2144                 }
2145
2146                 if(!linfo->name_count && name)
2147                 {
2148                         /* find if name exist in our list */
2149                         linfo->name_prev = get_name_list(name, 
2150                                         &linfo->name_count);
2151                         linfo->name_type = 1;
2152                 }
2153                 if(!linfo->name_count && suffix)
2154                 {
2155                         /* find if suffix exist in our list */
2156                         linfo->name_prev = get_name_list(suffix, 
2157                                         &linfo->name_count);
2158                         linfo->name_type = 2;
2159                 }
2160                 if(!linfo->name_count)
2161                 {
2162                         /* neither exist so check ambugious ones */
2163                         linfo->name_prev = (int *)_DtDtsMMGetNoNameIndex(&linfo->name_count);
2164                         linfo->name_type = 3;
2165                 }
2166         }
2167         else
2168         {
2169                 /* we found one befor so . . . */
2170                 if(linfo->name_count > 0)
2171                 {
2172                         /* if there are more on the list get the next one */
2173                         linfo->name_prev++;
2174                 }
2175                 else
2176                 {
2177                         /* go to the next list */
2178                         switch(linfo->name_type)
2179                         {
2180                         case    1:
2181                                 /* if we were in a name portion then we need to
2182                                         check for a suffix */
2183                                 suffix = strrchr(linfo->name, '.');
2184                                 if(suffix)
2185                                 {
2186                                         /* if found us it */
2187                                         linfo->name_prev = get_name_list(suffix, 
2188                                                 &linfo->name_count);
2189                                         linfo->name_type = 2;
2190                                         break;
2191                                 }
2192                                 /* other wise */
2193                         case    2:
2194                                 /* use the ambigous list */
2195                                 linfo->name_prev = 
2196                                         _DtDtsMMGetNoNameIndex(&linfo->name_count);
2197                                 linfo->name_type = 3;
2198                                 break;
2199                         case    3:
2200                                 /* start now with the buffer list */
2201                                 linfo->name_prev = (int *)
2202                                         _DtDtsMMGetBufferIndex(&linfo->name_count);
2203                                 linfo->name_type = 3;
2204
2205                         default:
2206                                 return(0);
2207                         }
2208                 }
2209         }
2210         record_list = _DtDtsMMGetPtr(db->recordList);
2211         if(linfo->name_count == 0)
2212         {
2213                 return(0);
2214         }
2215         else
2216         {
2217                 linfo->name_count--;
2218                 return(&record_list[*linfo->name_prev]);
2219         }
2220 }
2221                 
2222 #ifdef NEED_STRCASECMP
2223 /*
2224  * In case strcasecmp is not provided by the system here is one
2225  * which does the trick.
2226  */
2227 static int
2228 strcasecmp(register const char *s1,
2229            register const char *s2)
2230 {
2231     register int c1, c2;
2232
2233     while (*s1 && *s2) {
2234         c1 = isupper(*s1) ? tolower(*s1) : *s1;
2235         c2 = isupper(*s2) ? tolower(*s2) : *s2;
2236         if (c1 != c2)
2237             return (c1 - c2);
2238         s1++;
2239         s2++;
2240     }
2241     return (int) (*s1 - *s2);
2242 }
2243 #endif
2244
2245 Boolean
2246 DtDtsIsTrue(const char *str)
2247 {
2248         if (str && ((strcasecmp(str, "true") == 0)
2249          || (strcasecmp(str, "yes") == 0)
2250          || (strcasecmp(str, "on") == 0)
2251          || (strcasecmp(str, "1") == 0)))
2252         {
2253                 return(TRUE);
2254         }
2255         else
2256         {
2257                 return(FALSE);
2258         }
2259 }
2260