/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* * (c) Copyright 1993, 1994 Hewlett-Packard Company * * (c) Copyright 1993, 1994 International Business Machines Corp. * * (c) Copyright 1993, 1994 Sun Microsystems, Inc. * * (c) Copyright 1993, 1994 Novell, Inc. * */ /* *+SNOTICE * * $TOG: Dts.c /main/18 1999/10/15 12:18:39 mgreess $ * * RESTRICTED CONFIDENTIAL INFORMATION: * * The information in this document is subject to special * restrictions in a confidential disclosure agreement bertween * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this * document outside HP, IBM, Sun, USL, SCO, or Univel wihtout * Sun's specific written approval. This documment and all copies * and derivative works thereof must be returned or destroyed at * Sun's request. * * Copyright 1993 Sun Microsystems, Inc. All rights reserved. * *+ENOTICE */ #include #include #include #include #include #include #include #include #include #if defined(CSRG_BASED) #define MAXINT INT_MAX #else #include #endif #include #include #ifdef _SUN_OS #include #endif #include #define X_INCLUDE_STRING_H #define XOS_USE_XT_LOCKING #include #include
#include "Dt/DtsMM.h" #include "Dt/Dts.h" #include "DtSvcLock.h" #include
#include #include #ifdef X_NOT_STDC_ENV extern int errno; #endif struct list { int boson; DtDtsMMRecord *rec; }; typedef struct type_info { char *file_path; char *name; const struct stat *file_stat; const struct stat *file_lstat; int file_fd; const char *buffer; int buff_size; int mmap_size_to_free; int size_to_free; const char *opt_name; int error; const char *link_path; const char *link_name; int set_datatype; char *ot; char *mb; int mb_size; int name_type; int *name_prev; int name_count; char *orig_attr; } type_info_t; static DtShmBoson dtdts_path_pattern = 0; static DtShmBoson dtdts_name_pattern = 0; static DtShmBoson dtdts_mode = 0; static DtShmBoson dtdts_link_name = 0; static DtShmBoson dtdts_link_path = 0; static DtShmBoson dtdts_content = 0; static DtShmBoson dtdts_data_attributes_name = 0; static DtShmBoson dtdts_da_is_action = 0; static DtShmBoson dtdts_da_icon = 0; static DtShmBoson dtdts_da_description = 0; static DtShmBoson dtdts_da_label = 0; #define MB_SIZE 100 #define _MBLEN(p) (mblen(p, MB_CUR_MAX) > 1 ? mblen(p, MB_CUR_MAX) : 1) #define _MBADV(p) ((p) += _MBLEN(p)) /* external functions */ extern char *strdup(const char *); extern FILE *popen(const char *, const char *); extern char *DtActionIcon(const char *); extern char *DtActionDescription(const char *); extern char *DtActionLabel(const char *); extern XtAppContext _DtAppContext; /* local functions */ static DtDtsMMRecord * name_list(type_info_t *linfo, DtDtsMMDatabase *db, DtDtsMMRecord *rec_ptr); static const struct stat *get_stat(); static int csh_match(const char *, const char *); static int csh_match_star(const char *, const char *); /* filetype comparison function for sorting */ extern int cde_dc_compare(DtDtsMMRecord **entry1, DtDtsMMRecord **entry2); extern int cde_da_compare(DtDtsMMRecord **entry1, DtDtsMMRecord **entry2); extern int cde_dc_field_compare(DtDtsMMField **entry1, DtDtsMMField **entry2); void _DtDtsClear(void) { _DtSvcProcessLock(); dtdts_path_pattern = 0; dtdts_name_pattern = 0; dtdts_mode = 0; dtdts_link_name = 0; dtdts_link_path = 0; dtdts_content = 0; dtdts_data_attributes_name = 0; dtdts_da_is_action = 0; dtdts_da_icon = 0; dtdts_da_description = 0; dtdts_da_label = 0; _DtSvcProcessUnlock(); } static int gmatch(const char *string, const char *pattern) { wchar_t string_ch; int k; wchar_t pattern_ch; wchar_t lower_bound; char *p; top: for (; 1; _MBADV(pattern), _MBADV(string)) { lower_bound = (wchar_t)MAXINT; mbtowc(&string_ch, string, MB_CUR_MAX); mbtowc(&pattern_ch, pattern, MB_CUR_MAX); switch (pattern_ch) { case L'[': k = 0; for(mbtowc(&pattern_ch, _MBADV(pattern), MB_CUR_MAX); pattern_ch != L'\0'; mbtowc(&pattern_ch, _MBADV(pattern), MB_CUR_MAX)) { switch (pattern_ch) { case L']': if (!k) { return 0; } _MBADV(string); _MBADV(pattern); goto top; case L'-': if(lower_bound <= string_ch) { p = (char *)pattern; mbtowc(&pattern_ch, _MBADV(pattern), MB_CUR_MAX); k |= (string_ch <= pattern_ch); pattern = p; } else k |= 0; /* Fall through... */ default: if (string_ch == (lower_bound = pattern_ch)) { k++; } } } return 0; case L'*': return csh_match_star(string, _MBADV(pattern)); case L'\0': return ((string_ch != L'\0') ? 0 : 1); case L'?': if (string_ch == L'\0') { return 0; } break; default: if (pattern_ch != string_ch) { return 0; } break; } } /* NOTREACHED */ } /* * csh_match_star(string, pattern) This matches the '*' portion of a pattern. */ static int csh_match_star(const char *string, const char *pattern) { wchar_t pattern_ch; wchar_t string_ch; mbtowc(&pattern_ch, pattern, MB_CUR_MAX); switch (pattern_ch) { case L'\0': return 1; case L'[': case L'?': case L'*': while (*string) { if(gmatch(string, pattern)) { _MBADV(string); return 1; } else _MBADV(string); } break; default: mbtowc(&pattern_ch, pattern, MB_CUR_MAX); _MBADV(pattern); while (*string) { mbtowc(&string_ch, string, MB_CUR_MAX); _MBADV(string); if(string_ch == pattern_ch && gmatch(string, pattern)) { return 1; } } break; } return 0; } static char * max_buf(size_t size, type_info_t *info) { if(!info->mb) { info->mb_size += MB_SIZE; info->mb = (char *)calloc(info->mb_size, 1); } if(!size) { return(info->mb); } if(size > info->mb_size) { info->mb = (char *)realloc(info->mb, info->mb_size); info->mb_size = size; } return(info->mb); } static type_info_t * set_vals(const char *fn, const char *buf, const int bs, const struct stat *fs, const char *ln, const struct stat *ls, const char *on) { char *tmp; type_info_t *linfo = (type_info_t *)calloc(1, sizeof(type_info_t)); linfo->buff_size = -1; linfo->file_fd = -1; linfo->error = 0; linfo->mmap_size_to_free = -1; linfo->size_to_free = -1; linfo->set_datatype = 0; linfo->ot = 0; linfo->mb = 0; linfo->mb_size = 0; linfo->orig_attr = 0; if(fn) { linfo->file_path = strdup(fn); linfo->name = strrchr(linfo->file_path, '/'); if(linfo->name) { linfo->name++; } else { char path[MAXPATHLEN]; char *tmp; getcwd(path, MAXPATHLEN); strcat(path, "/"); strcat(path, linfo->file_path); tmp = linfo->file_path; linfo->file_path = strdup(path); linfo->name = strstr(linfo->file_path, tmp); free(tmp); } } else if(buf) { if(!fs) { struct stat *buf; buf = malloc(sizeof(struct stat)); memset(buf, '\0', sizeof(struct stat)); buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR | S_IWOTH | S_IWGRP | S_IWUSR; linfo->file_stat = (const struct stat *)buf; } } if(buf) { linfo->buffer = buf; } /* * 04/30/96 - What should this if() REALLY be? Chances are * pretty good that bs will either not equal 0 or not equal -1! */ if(bs != 0 || bs != -1) { linfo->buff_size = bs; } if(fs) { linfo->file_stat = (struct stat *)malloc(sizeof(struct stat)); memcpy((void *)linfo->file_stat, (struct stat *)fs, sizeof(struct stat)); } if(ln) { if(*ln == '/') { linfo->link_path = (char *)strdup(ln); linfo->link_name = strrchr(ln, '/'); if(linfo->link_name) { linfo->link_name++; } } else { linfo->link_name = (char *)ln; } } if(ls) { linfo->file_lstat = (struct stat *)malloc(sizeof(struct stat)); memcpy((void*)linfo->file_lstat, (struct stat *)ls, sizeof(struct stat)); } if(on) { linfo->opt_name = strdup(on); } return(linfo); } static char * cleanup(char *ot, type_info_t *info) { if(ot) { ot = strdup(ot); } else if(info->ot) { ot = strdup(info->ot); } else { ot = strdup(DtDTS_DT_UNKNOWN); } if(info->ot) { free(info->ot); } if(info->file_stat) { free((void *)info->file_stat); } if(info->file_lstat) { free((void *)info->file_lstat); } info->file_stat = 0; info->file_lstat = 0; if(info->buffer) { if(info->mmap_size_to_free != -1) { if(munmap((caddr_t)info->buffer, info->mmap_size_to_free) != 0) { _DtSimpleError( DtProgName, DtError, NULL, "munmap", NULL); } info->buffer = 0; info->mmap_size_to_free = -1; } else if(info->size_to_free != -1) { free((void *)info->buffer); info->buffer = 0; info->size_to_free = -1; } } if(info->file_fd != -1) { close(info->file_fd); info->file_fd = -1; } info->buffer = 0; if(info->file_path) { free((void *)info->file_path); info->file_path = 0; info->name = 0; } if(info->name) { free((void *)info->name); info->name = 0; } info->file_path = 0; info->name = 0; info->file_fd = -1; info->buff_size = -1; info->error = 0; if(info->link_path != (char *)0 && info->link_path != (char *)-1) { free((void *)info->link_path); } if(info->opt_name) { free((void *)info->opt_name); } if(info->mb) { free(info->mb); } if(info->orig_attr) { _DtDtsMMSafeFree(info->orig_attr); } free(info); info = 0; return(ot); } static const char* get_opt_name(type_info_t *info) { return(info->opt_name); } static const char* get_name(type_info_t *info) { return(info->name); } static const char* get_file_path(type_info_t *info) { if(info->file_path) { return(info->file_path); } else { return(0); } } static int get_fd(type_info_t *info) { if(!info->error && info->file_fd == -1) { if(info->file_path == 0) { return(-1); } if((info->file_fd = open(info->file_path, O_RDONLY|O_NOCTTY, 0)) == -1) { info->error = errno; return(-1); } } return(info->file_fd); } static const struct stat * get_lstat(type_info_t *info) { struct stat buf; if(!info->file_lstat) { if(NULL == info->file_path) { info->error = ENOENT; info->file_lstat = 0; return(0); } else if(lstat(info->file_path, &buf) == -1) { info->error = errno; info->file_lstat = 0; return(0); } else { info->file_lstat = (struct stat *)malloc(sizeof(struct stat)); memcpy((char *)info->file_lstat, &buf, sizeof(buf)); } } return(info->file_lstat); } static const struct stat * get_stat(type_info_t *info) { struct stat buf; int fd; if (!info->file_stat) { if(NULL == get_file_path(info)) { info->error = ENOENT; info->file_stat = 0; } else if(stat(get_file_path(info), &buf) == -1) { if(errno == ENOENT) { if(get_lstat(info)) { info->ot = strdup(DtDTS_DT_BROKEN_LINK); } } info->error = errno; info->file_stat = 0; } else { info->file_stat = (struct stat *)malloc(sizeof(struct stat)); memcpy((char *)info->file_stat, &buf, sizeof(buf)); } } return(info->file_stat); } static int islink(type_info_t *info) { if(info->file_lstat || info->link_path || info->link_name) { return(1); } return(0); } void get_link_info(type_info_t *info) { char buff[MAXPATHLEN]; const char *name = 0; int n; if(info->link_path == 0) { if((name = get_file_path(info)) == 0) { info->link_path = (char *)-1; info->link_name = (char *)-1; return; } else { name = strdup(name); } while((n = readlink(name, buff, MAXPATHLEN)) > 0) { buff[n - 1] = 0; free((void *)name); name = strdup(buff); } if(errno == EINVAL || errno == ENOENT) { info->link_path = name; info->link_name = strrchr(info->link_path, '/'); if(info->link_name == 0) { info->link_name = info->link_path; } else { info->link_name++; } } else { info->error = errno; info->link_path = (char *)-1; info->link_name = (char *)-1; } } return; } static const char * get_link_path(type_info_t *info) { get_link_info(info); return(info->link_path); } static const char * get_link_name(type_info_t *info) { get_link_info(info); return(info->link_name); } static const char * get_buff(type_info_t *info) { const struct stat *buf; if(!info->buffer && info->buffer != (char *)-1) { buf = get_stat(info); if(buf && buf->st_size) { if ((info->file_fd == -1) && (get_fd(info) == -1)) return 0; info->mmap_size_to_free = buf->st_size; if((info->buffer = mmap(NULL, buf->st_size, PROT_READ, MAP_PRIVATE, info->file_fd, 0)) == (char *)-1) { info->mmap_size_to_free = -1; info->size_to_free = buf->st_size+1; info->buffer = malloc(info->size_to_free); if(read(info->file_fd, (void *)info->buffer, info->size_to_free) == -1) { return(0); } } info->buff_size = buf->st_size; } else { return((char *)0); } } return(info->buffer); } int get_buff_size(type_info_t *info) { return(info->buff_size); } static DtDtsMMDatabase * get_dc_db(void) { DtDtsMMDatabase *dc_db = 0; if(!dc_db) { #ifdef DEBUG fprintf(stderr, "Load DataCriteria\n"); #endif dc_db = _DtDtsMMGet(DtDTS_DC_NAME); if(!dc_db) { _DtSimpleError( DtProgName, DtError, NULL, "No DataBase loaded\n", NULL); return(NULL); } } #ifdef NO_MMAP if(dc_db->compare != cde_dc_compare) { int i; for(i = 0; i < dc_db->recordCount; i++) { if(dc_db->recordList[i]->compare !=cde_dc_field_compare) { _DtDtsMMFieldSort(dc_db->recordList[i], cde_dc_field_compare); } } _DtDtsMMRecordSort(dc_db, cde_dc_compare); #ifdef DEBUG _DtDtsMMPrint(stdout); #endif } #endif return(dc_db); } static DtDtsMMDatabase * get_da_db(void) { DtDtsMMDatabase *da_db = 0; if(!da_db) { #ifdef DEBUG fprintf(stderr, "Load DataAttributes\n"); #endif da_db = _DtDtsMMGet(DtDTS_DA_NAME); if(!da_db) { _DtSimpleError( DtProgName, DtError, NULL, "No DataBase loaded\n", NULL); return(NULL); } } #ifdef NO_MMAP if(da_db->compare != _DtDtsMMCompareRecordNames) { int i; for(i = 0; i < da_db->recordCount; i++) { if(da_db->recordList[i]->compare != _DtDtsMMCompareFieldNames) { _DtDtsMMFieldSort(da_db->recordList[i], _DtDtsMMCompareFieldNames); } } _DtDtsMMRecordSort(da_db, _DtDtsMMCompareRecordNames); } #endif return(da_db); } #define DTSATTRVAL(attr_name) if(_DtDtsMMStringToBoson(attr_name) == fld_ptr->fieldName) static int type_content(char *attr, type_info_t *info) { int match = 0; char *c; int end = 0, s; const char *buff = 0; const struct stat *buf; char *p; _Xstrtokparams strtok_buf; if(buf = get_stat(info)) { if((buf->st_mode&S_IFMT) == S_IFDIR && (c = strstr(attr, "filename"))) { char *file; const char *path; c = _XStrtok(c, " \t\n", strtok_buf); c = _XStrtok(NULL, " \t\n", strtok_buf); path = get_file_path(info); file = calloc(1, strlen(path)+strlen(c)+2); sprintf(file, "%s/%s", path, c); if(access(file, F_OK)) { free(file); return(0); } else { free(file); return(1); } } else if((buf->st_mode&S_IFMT) != S_IFREG) { return(0); } } buff = get_buff(info); if((long)buff == 0 || (long)buff == -1) { return(0); } attr = strdup(attr); c = _XStrtok(attr, " \t\n", strtok_buf); if(!isdigit(*c) && *c != '-') { /* find where c is in buff */ printf("start as string not ready yet\n"); match = 0; } else { if(*c == '-') { end = 1; c++; } s = atoi(c); if(end) { if (buf) { if (s > buf->st_size) { free(attr); return(match); } s = buf->st_size - s; } else { if (!info->buff_size || (s > info->buff_size)) { free(attr); return(match); } s = info->buff_size - s; } } c = _XStrtok(NULL, " \t\n", strtok_buf); switch(c[1]) { case 't': /* string */ { int cl; c = _XStrtok(NULL, "\n", strtok_buf); cl = strlen(c); if((info->buff_size-s) >= cl && memcmp(&buff[s], c, cl) == 0) { match = 1; } else { match = 0; } break; } case 'y': /* byte */ { unsigned char lv; unsigned char num; int i = 0; match = 0; while(c = _XStrtok(NULL, "\t \n", strtok_buf)) { if(s+i*sizeof(lv)+sizeof(lv) > get_buff_size(info)) { match = 0; break; } memcpy(&lv, &buff[s+i*sizeof(lv)], sizeof(lv)); num = (unsigned char)strtol(c, &p, 0); if (num != lv || c == p) { match = 0; break; } else { match = 1; } i++; } break; } case 'h': /* short */ { unsigned short lv; unsigned short num; int i = 0; const unsigned char *bufPtr; match = 0; for(i = 0;(c = _XStrtok(NULL, "\t \n", strtok_buf)); i++) { if(s+i*sizeof(lv)+sizeof(lv) > get_buff_size(info)) { match = 0; break; } bufPtr = (unsigned char *) &buff[s + (i * sizeof(lv))]; lv = (((unsigned short)*bufPtr) << 8) | ((unsigned short)*(bufPtr + 1)); num = (unsigned short)strtol(c, &p, 0); if (num != lv || c == p) { match = 0; break; } else { match = 1; } } break; } case 'o': /* long */ { /* Not true long - really 4 bytes. */ unsigned int lv; unsigned int num; int i = 0; const unsigned char *bufPtr; match = 0; for(i = 0;(c = _XStrtok(NULL, "\t \n", strtok_buf)); i++) { if(s+i*sizeof(lv)+sizeof(lv) > get_buff_size(info)) { match = 0; break; } bufPtr = (unsigned char *) &buff[s + (i * sizeof(lv))]; lv = (((unsigned int)*bufPtr) << 24) | (((unsigned int)*(bufPtr + 1)) << 16) | (((unsigned int)*(bufPtr + 2)) << 8) | ((unsigned int)*(bufPtr + 3)); num = (unsigned int)strtol(c, &p, 0); if (num != lv || c == p) { match = 0; break; } else { match = 1; } } break; } default: match = 0; } } free(attr); return(match); } static char * _DtDtsGetDataType(const char *file) { int fd; char *name; struct stat file_stat; u_char *buff = 0; int start; char *dt = 0; int end; name = calloc(1, MAXPATHLEN+1); sprintf(name, "%s/%s", file, DtDTS_DT_DIR); if((fd = open(name, O_RDONLY, 0644)) != -1) { if(fstat(fd, &file_stat) == 0) { buff = (u_char *)calloc((size_t)1, file_stat.st_size+1); read(fd, buff, file_stat.st_size); } dt = strstr((char *)buff, DtDTS_DATA_ATTRIBUTES_NAME); if(dt != NULL) { start = dt-(char*)buff; while(!isspace(buff[start])) start++; while(isspace(buff[start]))start++; end = start; while(!isspace(buff[end])) end++; buff[end] = '\0'; dt = strdup((char *)&buff[start]); } close(fd); } free(buff); free(name); return(dt); } static int type_mode(char *attr, type_info_t *info) { int match = 0; const struct stat *buf = get_stat(info); const struct stat *lbuf; if (!buf || !*attr) { return(0); } do { match = 0; switch(*attr) { case 'f': match = (buf->st_mode&S_IFMT) == S_IFREG; break; case 'c': match = (buf->st_mode&S_IFMT) == S_IFCHR; break; case 'b': match = (buf->st_mode&S_IFMT) == S_IFBLK; break; case 'd': if((buf->st_mode&S_IFMT) == S_IFDIR) { int n; int fd; match = 1; if(!info->set_datatype) { info->set_datatype = 1; info->ot = _DtDtsGetDataType(get_file_path(info)); if(info->ot) return(match); } } else { match = 0; } break; case 'l': if(islink(info)) { match = 1; } else if(lbuf = get_lstat(info)) { match = (lbuf->st_mode&S_IFMT) == S_IFLNK; } else { match = 0; } break; case 'r': if(buf->st_mode&S_IROTH || \ buf->st_mode&S_IRGRP || \ buf->st_mode&S_IRUSR ) { match = 1; } else { match = 0; } break; case 'w': if(buf->st_mode&S_IWOTH || \ buf->st_mode&S_IWGRP || \ buf->st_mode&S_IWUSR ) { match = 1; } else { match = 0; } break; case 'x': if(buf->st_mode&S_IXOTH || \ buf->st_mode&S_IXGRP || \ buf->st_mode&S_IXUSR ) { match = 1; } else { match = 0; } break; case 'g': match = buf->st_mode&S_ISGID; break; case 'u': match = buf->st_mode&S_ISUID; break; } attr++; } while(*attr && match); return(match); } static int type_name(const char *name, char *attr) { int match = 0; if(name && name != (char *)-1) { #ifdef USE_FNMATCH match = !fnmatch(attr, name, 0); #else match = gmatch(name, attr); #endif } return(match); } static int type_path(const char *path, char *attr) { char *c; int match = 0; if(path && (intptr_t)path != -1) { #ifdef USE_FNMATCH match = !fnmatch(attr, path, 0); #else match = gmatch(path, attr); #endif } return(match); } static char * next_sep(char *str, char *sep) { char *c; char *prev; c = str; while(*c) { c = _dt_strpbrk(c, sep); if(!c) { return(c); } prev = c-1; if((c == str) || (_is_previous_single(str, c) && (*prev != '\\'))) { return(c); } _MBADV(c); } return((char *)0); } char * DtDtsDataToDataType(const char *fp, const void *buf, const int bs, const struct stat *fs, const char *ln, const struct stat *ls, const char *on) { DtDtsMMDatabase *db; DtDtsMMRecord *rec_ptr = 0; DtDtsMMRecord *rec_ptr_list; DtDtsMMField *fld_ptr; DtDtsMMField *fld_ptr_list; type_info_t *info = 0; int i; int j; int rec_m = 0; int fld_m = 0; int atr_m = 0; int p_atr_m = 1; int c_atr_m = 1; char *ot = NULL; char *file; char *attr; char op; _DtSvcAppLockDefault(); _DtSvcProcessLock(); db = get_dc_db(); if(!db) { _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return(strdup("UNKNOWN")); } info = set_vals(fp, buf, bs, fs, ln, ls, on); if(!dtdts_path_pattern) { dtdts_path_pattern = _DtDtsMMStringToBoson(DtDTS_PATH_PATTERN); dtdts_name_pattern = _DtDtsMMStringToBoson(DtDTS_NAME_PATTERN); dtdts_mode = _DtDtsMMStringToBoson(DtDTS_MODE); dtdts_link_name = _DtDtsMMStringToBoson(DtDTS_LINK_NAME); dtdts_link_path = _DtDtsMMStringToBoson(DtDTS_LINK_PATH); dtdts_content = _DtDtsMMStringToBoson(DtDTS_CONTENT); dtdts_data_attributes_name = _DtDtsMMStringToBoson(DtDTS_DATA_ATTRIBUTES_NAME); dtdts_da_is_action = _DtDtsMMStringToBoson(DtDTS_DA_IS_ACTION); dtdts_da_icon = _DtDtsMMStringToBoson(DtDTS_DA_ICON); dtdts_da_description = _DtDtsMMStringToBoson(DtDTS_DA_DESCRIPTION); dtdts_da_label = _DtDtsMMStringToBoson(DtDTS_DA_LABEL); } for(i = 0; !rec_m && (rec_ptr = name_list(info, db, rec_ptr)); i++) { fld_ptr_list = _DtDtsMMGetPtr(rec_ptr->fieldList); fld_m = 1; for(j=0; fld_m && j < rec_ptr->fieldCount; j++) { char sep = '&'; DtDtsMMField *fld_ptr = &fld_ptr_list[j]; p_atr_m = 1; c_atr_m = 1; info->orig_attr = _DtDtsMMExpandValue( _DtDtsMMBosonToString(fld_ptr->fieldValue)); attr = info->orig_attr; do { int neg = 0; char *new_sep; int n; char *c; atr_m = 1; while(*attr == '!') { neg = !neg; attr++; } new_sep = next_sep(attr, "&|\0"); if(new_sep == 0) { new_sep = attr + strlen(attr); } n = new_sep-attr+1; c = max_buf((size_t)n, info); strncpy(c, attr, new_sep-attr); c[new_sep-attr] = '\0'; attr = new_sep; new_sep = c; /* while(new_sep = (char *)_dt_strpbrk(new_sep, "&|")) { new_sep--; strcpy(new_sep, &new_sep[1]); new_sep++; } */ if(fld_ptr->fieldName == dtdts_path_pattern) { atr_m = type_path( get_file_path(info), max_buf((size_t)0, info)); } else if(fld_ptr->fieldName == dtdts_name_pattern) { if(get_file_path(info)) { atr_m = type_name( get_name(info), max_buf((size_t)0, info)); } else { atr_m = type_name( get_opt_name(info), max_buf((size_t)0, info)); } } else if(fld_ptr->fieldName == dtdts_mode) { if(get_file_path(info)) { atr_m = type_mode( max_buf((size_t)0, info), info); } else { atr_m = !neg; } } else if(fld_ptr->fieldName == dtdts_link_name) { atr_m = type_name( get_link_name(info), max_buf((size_t)0, info)); } else if(fld_ptr->fieldName == dtdts_link_path) { atr_m = type_path( get_link_path(info), max_buf((size_t)0, info)); } else if(fld_ptr->fieldName == dtdts_content) { atr_m = type_content( max_buf((size_t)0, info), info); } else if(fld_ptr->fieldName == dtdts_data_attributes_name) { info->ot = strdup(max_buf((size_t)0, info)); } if(info->error == ELOOP) { _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return( cleanup(DtDTS_DT_RECURSIVE_LINK, info) ); } if(info->ot) { _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return(cleanup(0, info)); } atr_m=(neg)?!atr_m:atr_m; switch(sep) { case '&': p_atr_m = atr_m && p_atr_m; break; case '|': p_atr_m = atr_m || p_atr_m; break; } if(attr && *attr) { sep = *attr; attr++; switch(sep) { case '&': c_atr_m = p_atr_m?1:0; break; case '|': c_atr_m = p_atr_m?0:1; break; } } else { c_atr_m = 0; } } while ( c_atr_m ); if(info->orig_attr) { _DtDtsMMSafeFree(info->orig_attr); info->orig_attr = 0; } if(!p_atr_m) { fld_m = 0; } } if(fld_m) { rec_m = 1; } } _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return(cleanup(0, info)); } char * DtDtsFileToDataType(const char *filepath) { char *dt = DtDtsDataToDataType(filepath, 0, -1, 0, 0, 0, 0); return(dt); } char * DtDtsBufferToDataType(const void *buffer, const int size, const char *name) { char *dt = DtDtsDataToDataType(0, buffer, size, 0, 0, 0, name); return(dt); } static char * expand_keyword(const char *attr_in, const char *in_pathname) { char *buf; char *netPath; char *c; char *tmp; int i; int n; char *p; char *attr = (char *)attr_in; if(!attr) { return(attr); } if(in_pathname) { n = strlen(attr)+1; buf = (char *) calloc(1, n); netPath = strdup(in_pathname); for(c = attr, i= 0; *c && i < n; c++) { if ( *c != '%' ) { buf[i++] = *c; buf[i]=0; /* ensure null string termination */ continue; } /* check for keyword matches */ if ( !strncmp(c,"%file%",6) ) { n += strlen(netPath) - 6; buf = (char *)realloc(buf, n); strcpy((buf+i), netPath); i += strlen(netPath); c += 5; continue; } else if ( !strncmp(c,"%dir%",5) ) { tmp = strrchr(netPath, '/'); *tmp = '\0'; n += strlen(netPath) - 5; buf = (char *)realloc(buf, n); strcpy((buf+i),netPath); i += strlen(netPath); *tmp = '/'; c += 4; } else if ( !strncmp(c,"%name%",6) ) { tmp = strrchr(netPath, '/'); tmp ++; n += strlen(tmp) - 6; buf = (char *)realloc(buf, n); strcpy((buf+i),tmp); i +=strlen(tmp); c += 5; } else if ( !strncmp(c,"%suffix%",8) ) { if ((p = strrchr(netPath,'.')) != NULL) { p++; n += strlen(p) - 8; buf = (char *)realloc(buf, n); strcpy((buf+i),p); i +=strlen(p); } c += 7; } else if ( !strncmp(c,"%base%",6) ) { tmp = strrchr(netPath, '/'); tmp ++; if ((p = strrchr(tmp,'.')) != NULL) { n += p-tmp - 6; buf = (char *)realloc(buf, n); strncpy((buf+i),tmp,p-tmp); buf[i+p-tmp] = '\0'; i += p-tmp; } c += 5; } else { /* no match -- just copy the character */ buf[i++] = *c; buf[i]=0; /* ensure null string termination */ continue; } } free(netPath); return(buf); } else { return(strdup(attr)); } } char * append(char *old, char *add) { char *new; if(old) { new = realloc(old, strlen(old)+strlen(add)+1); } else { new = malloc(strlen(add)+1); *new = '\0'; } strcat(new, add); return(new); } char * expand_shell(const char *attr) { char *srch; char *nattr; char *start, *end; int size; FILE *fd; char buff[200]; char *results = 0; if(!attr) { return(NULL); } nattr = strdup(attr); srch = nattr; while((start = DtStrchr(srch, '`')) != NULL) { if((srch != start) && _is_previous_single(srch, start) && (*(start-1) == '`')) { srch = start + 1; continue; } if((end = DtStrchr(&start[1], '`')) == NULL) { srch = start + 1; continue; } *start = '\0'; *end = '\0'; results = append(results, srch); if((fd = popen(&start[1], "r")) == NULL) { _DtSimpleError( DtProgName, DtError, NULL, (char*) &start[1], NULL); free(nattr); free(results); return(NULL); } memset(buff, '\0', sizeof(buff)); while(size = fread(buff, 1, sizeof(buff)-1, fd)) { buff[sizeof(buff)-1] = '\0'; results = append(results, buff); memset(buff, '\0', sizeof(buff)); } srch = end+1; } results = append(results, srch); free(nattr); return(results); } static char * expand_value(DtShmBoson attr, char *in_pathname) { char *tmp; char *exp; char *shell_exp; if(attr && attr != -1) { tmp = _DtDtsMMExpandValue(_DtDtsMMBosonToString(attr)); exp = expand_keyword(tmp, in_pathname); shell_exp = expand_shell(exp); _DtDtsMMSafeFree(tmp); if(shell_exp) { free(exp); exp = expand_keyword(shell_exp, in_pathname); free(shell_exp); } } else { exp = NULL; } return(exp); } char * DtDtsDataTypeToAttributeValue(const char *obj_type, const char *attr, const char *filename) { DtDtsMMDatabase *db; DtDtsMMRecord *entry; char *value = 0; _DtSvcAppLockDefault(); _DtSvcProcessLock(); db = get_da_db(); if(db && obj_type) { entry = _DtDtsMMGetRecordByName(db, (char *)obj_type); if(entry) { char *name = 0; DtDtsMMField *fld = _DtDtsMMGetField(entry,(char *)attr); if ( fld ) { value = expand_value(fld->fieldValue, (char *)filename); } } } _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return(value); } DtDtsAttribute ** DtDtsDataTypeToAttributeList(const char *obj_type, const char *filename) { DtDtsMMDatabase *db; DtDtsMMRecord *entry; DtDtsMMField *fld_ptr_list; DtDtsMMField *fld_ptr; DtDtsAttribute **list = NULL; int i; int action_flag = 0; int sort_flag = 0; int found_flag = 0; DtDtsMMField *fld; _DtSvcAppLockDefault(); _DtSvcProcessLock(); db = get_da_db(); entry = _DtDtsMMGetRecordByName(db, (char *)obj_type); if(!db || !obj_type || !entry) { _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return (list); } list = (DtDtsAttribute **)calloc(entry->fieldCount+1, sizeof(DtDtsAttribute *)); fld_ptr_list = _DtDtsMMGetPtr(entry->fieldList); for(i = 0; i < entry->fieldCount; i++) { char *tmp; fld_ptr = &fld_ptr_list[i]; list[i] = (DtDtsAttribute *)malloc(sizeof(DtDtsAttribute)); list[i]->name = expand_value(fld_ptr->fieldName, (char *)filename); list[i]->value = expand_value(fld_ptr->fieldValue, (char *)filename); } list[i] = 0; _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return(list); } void DtDtsFreeAttributeList(DtDtsAttribute **list) { DtDtsAttribute **item = list; int i = 0; if(list) { while(list[i] && list[i]->name) { free(list[i]->name); free(list[i]->value); free(list[i]); i++; } free(list); } } DtDtsAttribute ** DtDtsFileToAttributeList(const char *filepath) { char *ot = DtDtsFileToDataType(filepath); DtDtsAttribute **al = DtDtsDataTypeToAttributeList(ot, filepath); DtDtsFreeDataType(ot); return(al); } DtDtsAttribute ** DtDtsBufferToAttributeList(const void *buffer, const int size, const char *name) { char *ot = DtDtsBufferToDataType(buffer, size, name); DtDtsAttribute **al = DtDtsDataTypeToAttributeList(ot, NULL); DtDtsFreeDataType(ot); return(al); } char * DtDtsFileToAttributeValue(const char *filepath, const char *attr) { char *ot = DtDtsFileToDataType(filepath); char *value = DtDtsDataTypeToAttributeValue(ot, attr, filepath); DtDtsFreeDataType(ot); return(value); } char * DtDtsBufferToAttributeValue(const void *buffer, const int size, const char *attr, const char *name) { char *ot = DtDtsBufferToDataType(buffer, size, name); char *value = DtDtsDataTypeToAttributeValue(ot, attr, name); DtDtsFreeDataType(ot); return(value); } void DtDtsFreeAttributeValue(char *value) { free(value); } void DtDtsFreeDataType(char *datatype) { free(datatype); } int DtDtsDataTypeIsAction(const char *datatype) { char *val; if(val = DtDtsDataTypeToAttributeValue(datatype, "IS_ACTION", NULL)) { DtDtsFreeAttributeValue(val); return(1); } else { return(0); } } char ** DtDtsDataTypeNames(void) { DtDtsMMDatabase *db; DtDtsMMRecord *rec_list; DtDtsMMRecord *rec_ptr; int i = 0, j=0; char **names; _DtSvcAppLockDefault(); _DtSvcProcessLock(); db = get_da_db(); if(!db) { _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return(NULL); } names = (char **)malloc((db->recordCount+1)*sizeof(char *)); rec_list = _DtDtsMMGetPtr(db->recordList); for(i = 0; i < db->recordCount; i++) { rec_ptr = &rec_list[i]; names[j] = strdup((char *)_DtDtsMMBosonToString(rec_ptr->recordName)); j++; } names[j] = 0; _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return(names); } void DtDtsRelease(void) { } char ** DtDtsFindAttribute(const char *name, const char *value) { DtDtsMMDatabase *ot; int i; int j = 0; char **list; char *v; DtDtsMMRecord *rec_ptr; DtDtsMMRecord *rec_ptr_list; _DtSvcAppLockDefault(); _DtSvcProcessLock(); /* To avoid deadlock with DtDtsMMDatabase mutex lock */ ot = get_da_db(); if(!ot || ot->recordCount == 0) { _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return(NULL); } list = (char **)calloc(ot->recordCount, sizeof(char *)); rec_ptr_list = _DtDtsMMGetPtr(ot->recordList); for(i = 0; i < ot->recordCount; i++) { rec_ptr = &rec_ptr_list[i]; v = _DtDtsMMExpandValue(_DtDtsMMGetFieldByName(rec_ptr, (char *)name)); if(v && !strcmp(value, v)) { list[j++] = strdup(_DtDtsMMBosonToString(rec_ptr->recordName)); } _DtDtsMMSafeFree(v); } list[j] = 0; _DtSvcProcessUnlock(); _DtSvcAppUnlockDefault(); return(list); } void DtDtsFreeDataTypeNames(char **list) { int i = 0; while(list[i]) { free(list[i]); list[i++] = 0; } free(list); } #define DIR_INFO "DIR_INFO\n{\n\t%s\t%s\n}\n" char * DtDtsSetDataType(const char *filename, const char *datatype_in, const int overide) { int fsize; char *file; int fd; char *dt; int size; u_char *buff = NULL; struct stat file_stat; char *datatype = 0; fsize = strlen(filename)+strlen(DtDTS_DT_DIR)+2; file = (char *)calloc(1,fsize); sprintf(file, "%s/%s", filename, DtDTS_DT_DIR); if((fd = open(file, O_EXCL|O_CREAT|O_RDWR, 0644)) != -1) { int write_size; size = strlen(DIR_INFO); size += strlen(DtDTS_DATA_ATTRIBUTES_NAME); size += strlen(datatype_in); size-=3; buff = (u_char *)calloc((size_t)1, size); sprintf((char *)buff, DIR_INFO, DtDTS_DATA_ATTRIBUTES_NAME, datatype_in); write_size = write(fd, buff, size); if(write_size != size) { _DtSimpleError( DtProgName, DtError, NULL, (char*) buff, NULL); } datatype = strdup(datatype_in); free(buff); close(fd); } else if(overide && (fd = open(file, O_RDWR, 0644)) != -1) { int start; int end; int dtsize = strlen(datatype_in); int write_size; if(fstat(fd, &file_stat) == 0) { buff = (u_char *)calloc((size_t)1, file_stat.st_size+1); read(fd, buff, file_stat.st_size); } dt = strstr((char *)buff, DtDTS_DATA_ATTRIBUTES_NAME); if(dt == NULL) { free(buff); size = strlen(DIR_INFO); size += strlen(DtDTS_DATA_ATTRIBUTES_NAME); size += dtsize; size-=3; buff = (u_char *)calloc((size_t)1, size); sprintf((char *)buff, DIR_INFO, DtDTS_DATA_ATTRIBUTES_NAME, datatype_in); write_size = write(fd, buff, size); if(write_size != size) { _DtSimpleError( DtProgName, DtError, NULL, (char*) buff, NULL); } datatype = strdup(datatype_in); } else { int off, total; start = dt-(char *)buff; while(!isspace(buff[start])) start++; while(isspace(buff[start]))start++; end = start; while(!isspace(buff[end])) end++; lseek(fd, start, SEEK_SET); if(write(fd, datatype_in, dtsize) != dtsize) { _DtSimpleError( DtProgName, DtError, NULL, (char*) file, NULL); } off = write(fd, &buff[end], strlen((char *)&buff[end])+1); if(off != strlen((char *)&buff[end])+1) { _DtSimpleError( DtProgName, DtError, NULL, (char*) file, NULL); } else { total = file_stat.st_size-(end-start)+dtsize; ftruncate(fd, total); datatype = strdup(datatype_in); } } free(buff); close(fd); } else if (access(file, R_OK) == 0) { datatype = _DtDtsGetDataType(filename); } else { datatype = 0; } free(file); return(datatype); } static int srch(const void *a, const void *b) { int results = ((struct list *)a)->boson - ((struct list *)b)->boson; if(results == 0) { results = ((struct list *)a)->rec - ((struct list *)b)->rec; } return(results); } int * get_name_list(char *name, int *count) { int boson = name?_DtDtsMMStringToBoson((const char *)name):-1; int *results; int *list; int size; *count = 0; if(boson == -1) { return((int *)-1); } results = (int *)_DtShmFindIntTabEntry(_DtDtsMMGetDCNameIndex(&size), boson); if (!results) { return((int *)-1); } if(*results < 0) { list = (int *)_DtDtsMMGetPtr(-(*results)); *count = _DtDtsMMGetPtrSize(-(*results)); } else { list = results; *count = 1; } return(list); } static DtDtsMMRecord * name_list(type_info_t *linfo, DtDtsMMDatabase *db, DtDtsMMRecord *rec_ptr) { int i; char *src_str; char *name; int size; int isnew; DtDtsMMRecord *record_list; char *suffix = 0; if(rec_ptr == 0) { /* if this is the first time */ if(linfo->name) { /* get the name */ name = linfo->name; } else { /* if not name use opt name */ name = (char *)linfo->opt_name; } /* initialize name count */ linfo->name_count = 0; if(!name) { /* a name could not be found so this must be a buffer */ linfo->name_prev = (int *) _DtDtsMMGetBufferIndex(&linfo->name_count); linfo->name_type = 3; } else { if(name && *name) { /* now find suffix if any */ suffix = strrchr(name, '.'); } } if(!linfo->name_count && name) { /* find if name exist in our list */ linfo->name_prev = get_name_list(name, &linfo->name_count); linfo->name_type = 1; } if(!linfo->name_count && suffix) { /* find if suffix exist in our list */ linfo->name_prev = get_name_list(suffix, &linfo->name_count); linfo->name_type = 2; } if(!linfo->name_count) { /* neither exist so check ambugious ones */ linfo->name_prev = (int *)_DtDtsMMGetNoNameIndex(&linfo->name_count); linfo->name_type = 3; } } else { /* we found one befor so . . . */ if(linfo->name_count > 0) { /* if there are more on the list get the next one */ linfo->name_prev++; } else { /* go to the next list */ switch(linfo->name_type) { case 1: /* if we were in a name portion then we need to check for a suffix */ suffix = strrchr(linfo->name, '.'); if(suffix) { /* if found us it */ linfo->name_prev = get_name_list(suffix, &linfo->name_count); linfo->name_type = 2; break; } /* other wise */ case 2: /* use the ambigous list */ linfo->name_prev = _DtDtsMMGetNoNameIndex(&linfo->name_count); linfo->name_type = 3; break; case 3: /* start now with the buffer list */ linfo->name_prev = (int *) _DtDtsMMGetBufferIndex(&linfo->name_count); linfo->name_type = 3; default: return(0); } } } record_list = _DtDtsMMGetPtr(db->recordList); if(linfo->name_count == 0) { return(0); } else { linfo->name_count--; return(&record_list[*linfo->name_prev]); } } #ifdef NEED_STRCASECMP /* * In case strcasecmp is not provided by the system here is one * which does the trick. */ static int strcasecmp(const char *s1, const char *s2) { int c1, c2; while (*s1 && *s2) { c1 = isupper(*s1) ? tolower(*s1) : *s1; c2 = isupper(*s2) ? tolower(*s2) : *s2; if (c1 != c2) return (c1 - c2); s1++; s2++; } return (int) (*s1 - *s2); } #endif Boolean DtDtsIsTrue(const char *str) { if (str && ((strcasecmp(str, "true") == 0) || (strcasecmp(str, "yes") == 0) || (strcasecmp(str, "on") == 0) || (strcasecmp(str, "1") == 0))) { return(TRUE); } else { return(FALSE); } }