// vim: nowrap #include "postfixconf.h" #include "postfixconf.m" #include #include #include #include #include #include #include #include #include PUBLIC DATA::DATA (const char *namevar) // construct a variable { name_variable = namevar; exist = 0; } PUBLIC DATAMAIN::DATAMAIN (void) // list of variable that can be manipulate by module { add (new DATA ("queue_directory")); // 0 add (new DATA ("command_directory")); // 1 add (new DATA ("daemon_directory")); // 2 add (new DATA ("mail_owner")); // 3 add (new DATA ("default_privs")); // 4 add (new DATA ("myhostname")); // 5 add (new DATA ("mydomain")); // 6 add (new DATA ("myorigin")); // 7 add (new DATA ("inet_interfaces")); // 8 add (new DATA ("mydestination")); // 9 add (new DATA ("local_recipient_maps")); // 10 add (new DATA ("alias_maps")); // 11 add (new DATA ("alias_database")); // 12 add (new DATA ("recipient_delimiter")); // 13 add (new DATA ("home_mailbox")); // 14 add (new DATA ("mail_spool_directory")); // 15 add (new DATA ("mailbox_command")); // 16 add (new DATA ("mailbox_transport")); // 17 add (new DATA ("fallback_transport")); // 18 add (new DATA ("luser_relay")); // 19 add (new DATA ("header_checks")); // 20 add (new DATA ("relay_domains")); // 21 add (new DATA ("mynetworks")); // 22 add (new DATA ("smtpd_banner")); // 23 add (new DATA ("local_destination_concurrency_limit")); // 24 add (new DATA ("default_destination_concurrency_limit")); // 25 add (new DATA ("debug_peer_level")); // 26 add (new DATA ("debug_peer_list")); // 27 add (new DATA ("debugger_command")); // 28 add (new DATA ("allow_percent_hack")); // 29 add (new DATA ("append_at_myorigin")); // 30 add (new DATA ("append_dot_mydomain")); // 31 add (new DATA ("empty_address_recipient")); // 32 add (new DATA ("masquerade_domains")); // 33 add (new DATA ("masquerade_exceptions")); // 34 add (new DATA ("swap_bangpath")); // 35 add (new DATA ("canonical_maps")); // 36 add (new DATA ("recipient_canonical_maps")); // 37 add (new DATA ("sender_canonical_maps")); // 38 add (new DATA ("virtual_maps")); // 39 add (new DATA ("relocated_maps")); // 40 add (new DATA ("transport_maps")); // 41 add (new DATA ("best_mx_transport")); // 42 add (new DATA ("fallback_relay")); // 43 add (new DATA ("ignore_mx_lookup_error")); // 44 add (new DATA ("smtp_skip_4xx_greeting")); // 45 add (new DATA ("smtp_skip_quit_response")); // 46 add (new DATA ("smtp_destination_concurrency_limit")); // 47 add (new DATA ("smtp_destination_recipient_limit")); // 48 add (new DATA ("smtp_connect_timeout")); // 49 add (new DATA ("smtp_helo_timeout")); // 50 add (new DATA ("smtp_mail_timeout")); // 51 add (new DATA ("smtp_rcpt_timeout")); // 52 add (new DATA ("smtp_data_init_timeout")); // 53 add (new DATA ("smtp_data_xfer_timeout")); // 54 add (new DATA ("smtp_data_done_timeout")); // 55 add (new DATA ("smtp_quit_timeout")); // 56 add (new DATA ("always_bcc")); // 57 add (new DATA ("daemon_timeout")); // 58 add (new DATA ("default_database_type")); // 59 add (new DATA ("default_transport")); // 60 add (new DATA ("double_bounce_sender")); // 61 add (new DATA ("hash_queue_depth")); // 62 add (new DATA ("hash_queue_names")); // 63 add (new DATA ("hopcount_limit")); // 64 add (new DATA ("ipc_idle")); // 65 add (new DATA ("ipc_timeout")); // 66 add (new DATA ("mail_name")); // 67 add (new DATA ("mail_version")); // 68 add (new DATA ("max_idle")); // 69 add (new DATA ("max_use")); // 70 add (new DATA ("notify_classes")); // 71 add (new DATA ("bounce_notice_recipient")); // 72 add (new DATA ("2bounce_notice_recipient")); // 73 add (new DATA ("delay_notice_recipient")); // 74 add (new DATA ("error_notice_recipient")); // 75 add (new DATA ("process_id_directory")); // 76 add (new DATA ("program_directory")); // 77 add (new DATA ("sun_mailtool_compatibility")); // 78 add (new DATA ("trigger_timeout")); // 79 add (new DATA ("delay_warning_time")); // 80 add (new DATA ("disable_vrfy_command")); // 81 add (new DATA ("smtpd_etrn_restrictions")); // 82 add (new DATA ("smtpd_recipient_limit")); // 83 add (new DATA ("smtpd_timeout")); // 84 add (new DATA ("smtpd_error_sleep_time")); // 85 add (new DATA ("smtpd_soft_error_limit")); // 86 add (new DATA ("smtpd_hard_error_limit")); // 87 add (new DATA ("smtpd_client_restrictions")); // 88 add (new DATA ("smtpd_helo_required")); // 89 add (new DATA ("smtpd_helo_restrictions")); // 90 add (new DATA ("smtpd_sender_restrictions")); // 91 add (new DATA ("smtpd_recipient_restrictions")); // 92 add (new DATA ("allow_untrusted_routing")); // 93 add (new DATA ("maps_rbl_domains")); // 94 add (new DATA ("access_map_reject_code")); // 95 add (new DATA ("invalid_hostname_reject_code")); // 96 add (new DATA ("maps_rbl_reject_code")); // 97 add (new DATA ("reject_code")); // 98 add (new DATA ("relay_domains_reject_code")); // 99 add (new DATA ("unknown_address_reject_code")); // 100 add (new DATA ("unknown_client_reject_code")); // 101 add (new DATA ("unknown_hostname_reject_code")); // 102 add (new DATA ("bounce_size_limit")); // 103 add (new DATA ("command_time_limit")); // 104 add (new DATA ("default_process_limit")); // 105 add (new DATA ("deliver_lock_attempts")); // 106 add (new DATA ("deliver_lock_delay")); // 107 add (new DATA ("duplicate_filter_limit")); // 108 add (new DATA ("fork_attempts")); // 109 add (new DATA ("fork_delay")); // 110 add (new DATA ("header_size_limit")); // 111 add (new DATA ("line_length_limit")); // 112 add (new DATA ("message_size_limit")); // 113 add (new DATA ("qmgr_message_active_limit")); // 114 add (new DATA ("qmgr_message_recipient_limit")); // 115 add (new DATA ("queue_minfree")); // 116 add (new DATA ("stale_lock_time")); // 117 add (new DATA ("transport_retry_time")); // 118 add (new DATA ("relayhost")); // 119 add (new DATA ("body_checks")); // 120 add (new DATA ("ldap_lookup_timeout")); // 121 add (new DATA ("ldap_search_base")); // 122 add (new DATA ("ldap_server_host")); // 123 add (new DATA ("local_transport")); // 124 add (new DATA ("local_command_shell")); // 125 add (new DATA ("forward_path")); // 126 add (new DATA ("allow_mail_to_commands")); // 127 add (new DATA ("allow_mail_to_files")); // 128 add (new DATA ("local_destination_recipient_limit")); // 129 add (new DATA ("prepend_delivered_header")); // 130 add (new DATA ("default_destination_recipient_limit")); // 131 add (new DATA ("initial_destination_concurrency")); // 132 add (new DATA ("maximal_backoff_time")); // 133 add (new DATA ("maximal_queue_lifetime")); // 134 add (new DATA ("minimal_backoff_time")); // 135 add (new DATA ("queue_run_delay")); // 136 add (new DATA ("defer_transports")); // 137 } PUBLIC DATA *DATAMAIN::getitem(int no) { return (DATA*)ARRAY::getitem(no); } /* DESCRIPTION: Open the cfg file. Search each variable of the list and look for them in the cf file and get the value. RETURN: 1 if success -1 if something really bad ocurr */ PUBLIC int DATAMAIN::load (void) { int ret = -1; VIEWITEMS_PARSER vip; VIEWITEMS items; vip.quotchar = 0; if (items.read (cf_postfix_main)!=-1){ // read the cf file ret = 1; int nb = getnb(); char tmp[1000]; for (int i=0; iname_variable, tmp); // locate variable value if (t!=NULL){ SSTRING s(t); char again = 1; while ( has_more(s.get()) && again){ // verify if the variable value continues on the next line. If continues... int k; VIEWITEM *it = items.locateassign(d->name_variable); // locate the VIEWITEM of the variable for (k=0; kline.get())!=' '){ // next line isn't a continuation again = 0; break; } s.append(items.getitem(k+1)->line.get()); // append the string with the contents items.remove_del(k+1); // remove this continuation. again = 1; break; } } items.update (d->name_variable, (s.get())); } d->var.setfrom(s.get()); // set the value of the variable in class d->exist = 1; // variable exist } } items.write(cf_postfix_main, NULL); // save the cfg file } return ret; } /* DESCRIPTION: Scan all variables from DATAMAIN and save its values to cf file. Generally, if variable exist its value is writing, if not, the module compare its value with the default value of its respective variable, if the value is different, the variable-value is writing, if not, nothing is done. Some exceptions occurs. If variable's value is empty, the variable is removed from cf file, if exist. If variable's value isn't empty, the variable value is updated/added. RETURN: 1 if success -1 if something really bad ocurr */ PUBLIC int DATAMAIN::save (void) { int ret = -1; VIEWITEMS_PARSER vip; VIEWITEMS items (vip); vip.quotchar = 0; if (items.read (cf_postfix_main)!=-1){ int nb = getnb(); for (int i=0; ivar.strip_end(); d->var.setfrom(str_skip(d->var.get())); if (i==V_LDAP_LOOKUP_TIMEOUT || i==V_LDAP_SEARCH_BASE || i==V_LDAP_SERVER_HOST || i==V_DEBUGGER_COMMAND){ // exceptions if (d->var.is_empty()){ VIEWITEM *it = items.locateassign (d->name_variable); if (it != NULL) items.remove_del(it); }else{ items.update (d->name_variable, (d->var)); } continue; } if (d->exist==1){ // general items.update (d->name_variable, (d->var)); }else{ if ( d->var.cmp(d->defvar.get())!=0 ) items.update (d->name_variable, (d->var)); } } items.write(cf_postfix_main, NULL); ret = 1; } return ret; } /* DESCRIPTION: Write one variable value one the cf file. If the variable exist on the cf file, its updated otherwise its added. RETURN: -1 if the cf file can't be read 0 if variable is not recognized by module 1 if variable value is updated */ PUBLIC int DATAMAIN::write_one (const char *name, const char *value) { int ret = -1; VIEWITEMS_PARSER vip; VIEWITEMS items (vip); vip.quotchar = 0; if (items.read (cf_postfix_main)!=-1){ ret = 0; if ( getvarvariable(name)!=NULL){ items.update (name, value); ret = 1; } items.write(cf_postfix_main, NULL); } return ret; } /* DESCRIPTION: Generate a backup of the cf file pointed by cf_postfix_main. If a backup file exist its overide. RETURN: -1 error 1 success */ PUBLIC int DATAMAIN::backup_file (){ int ret = -1; char buffer[1024]; FILE *fsrc, *fdest; const char *fileor=cf_postfix_main.getpath(); sprintf (buffer,"%s%s",cf_postfix_main.getpath(),".old"); const char *filedest=buffer; if ( (fsrc=fopen (fileor,"r")) && (fdest=fopen (filedest,"w")) ){ fgets (buffer, 1023, fsrc); while(!feof(fsrc)){ fwrite (buffer, 1, strlen(buffer), fdest); fgets (buffer, 1023, fsrc); }; fclose (fsrc); fclose (fdest); ret = 1; } return ret; } /* DESCRIPTION: Return a pointer to the first caracter. RETURN: A pointer to this variable */ PRIVATE const char *DATAMAIN::filterin (const char *str) { while (*str==' ') str++; return (const char*)str; } /* DESCRIPTION: Postfix variables can continue on next line. Thie metho check if line finish with ','. RETURN: 0 - fail 1 - success */ PRIVATE int DATAMAIN::has_more (const char *v){ int t = strlen(v)-1; while (t > 0){ if (*(v+t)==',') return 1; if (*(v+t)!=' ') return 0; t--; } return 0; } /* DESCRIPTION: These methods verify how much items exist in var. The items separator is ',' RETURN: number of items */ PRIVATE int DATAMAIN::getnitem (const char *str){ int num = 1; while (*str!='\0'){ if (*str==',') num++; str++; } return num; } PUBLIC int DATAMAIN::getnitemvar (int n){ SSTRING *tmp = getvarvariable(n); if (tmp!=NULL && !tmp->is_empty()) return getnitem (tmp->get()); return 0; } PUBLIC int DATAMAIN::getnitemvar (const char *name){ SSTRING *tmp = getvarvariable(name); if (tmp!=NULL && !tmp->is_empty()) return getnitem (tmp->get()); return 0; } /* DESCRIPTION: This method gets the name of variable RETURN: name variable */ PUBLIC const char *DATAMAIN::getnamevariable (int n){ DATA *d = getitem(n); if (d!=NULL){ return d->name_variable; } return NULL; } /* DESCRIPTION: These methods gets the default value of variable RETURN: defaul value */ PUBLIC const char *DATAMAIN::getdefvariable (int n){ DATA *d = getitem(n); if (d!=NULL){ return d->defvar.get(); } return NULL; } PUBLIC const char *DATAMAIN::getdefvariable (const char *name){ for (int i=0; iname_variable)==0 ) return d->defvar.get(); } return NULL; } /* DESCRIPTION: get a pointer to SSTRING object of variable by number RETURN: SSTRING or NULL */ PUBLIC SSTRING *DATAMAIN::getvarvariable (int n){ DATA *d = getitem (n); if (d!=NULL){ return &(d->var); } return NULL; } /* DESCRIPTION: get a pointer to SSTRING object of default variable RETURN: SSTRING or NULL */ PUBLIC SSTRING *DATAMAIN::getdefvarvariable (int n){ DATA *d = getitem (n); if (d!=NULL){ return &(d->defvar); } return NULL; } /* DESCRIPTION: get a pointer to SSTRING object of variable by number RETURN: SSTRING or NULL */ PUBLIC SSTRING *DATAMAIN::getvarvariable (const char *name){ for (int i=0; iname_variable)==0 ) return &(d->var); } return NULL; } /* DESCRIPTION: get status of variable RETURN: 1 if variable already exist in cf 0 if variable not exist in cf */ PUBLIC char DATAMAIN::getstatus (int n){ DATA *d = getitem(n); if (d!=NULL){ return d->exist; } return 0; } /* DESCRIPTION: set the status of variable RETURN: void */ PUBLIC void DATAMAIN::setstatus (int n, char val){ DATA *d = getitem(n); if (d!=NULL){ d->exist = val; } } /* DESCRIPTION: set the value of variable to default value by number RETURN: -1 if error 1 if success */ PUBLIC int DATAMAIN::setvartodefault (int n){ int ret = -1; DATA *d = getitem(n); if (d!=NULL){ d->var.setfrom(d->defvar); ret = 1; } return ret; } /* DESCRIPTION: set the value of variable to default value by name RETURN: -1 if error 1 if success */ PUBLIC int DATAMAIN::setvartodefault (const char *name){ int ret = -1; for (int i=0; iname_variable)==0 ){ d->var.setfrom(d->defvar); ret = 1; break; } } return ret; } /* DESCRIPTION: Get total number of occurrency of subs in string str RETURN: -1 if error number of ocurrency */ PUBLIC int DATAMAIN::strsubscheck (const char *str, const char **subs){ int iguais=-1; SSTRINGS* strs = str_popul_sstrings (str); if (strs!=NULL && subs!=NULL){ iguais=0; for (int i=0; *(subs+i)!=NULL; i++){ for (int j=0; jgetnb(); j++){ SSTRING *s=strs->getitem(i); if (s->strstr(*(subs+i))) iguais++; } } delete (strs); } return iguais; } /* DESCRIPTION: Check the occurrency of substring (subs) in str RETURN: -1 if error number of substring */ PUBLIC int DATAMAIN::strcheck (const char *str, const char *subs){ int same=-1; SSTRINGS* strs = str_popul_sstrings (str); if (strs!=NULL && subs!=NULL){ same=0; for (int j=0; jgetnb(); j++){ SSTRING* s=strs->getitem(j); if (s->strstr(subs)) same = 1; } delete (strs); } return same; } /* DESCRIPTION: Check the exactly occurrency of substring (subs) in str RETURN: -1 if error number of substring */ PUBLIC int DATAMAIN::strcheckexactly (const char *str, const char *subs){ int iguais=-1; SSTRINGS* strs = str_popul_sstrings (str); if (strs!=NULL && subs!=NULL){ iguais=0; for (int j=0; jgetnb(); j++){ SSTRING* s = strs->getitem(j); if ( s->cmp(subs)==0 ) iguais++; } delete (strs); } return iguais; } // p // str = , " check_helo_access map:type, maptype:mapename, check_client_access mapttt:typettt " // s // e /* DESCRIPTION: This This method take a string that contains postfix items separated by comma and populate these items in SSTRINGS. RETURN: NULL if error A pointer to SSTRINGS if success */ PUBLIC SSTRINGS *DATAMAIN::str_popul_sstrings (const char *p){ SSTRINGS *strstrings = new SSTRINGS(); if (p==NULL) return NULL; if (*p==0) return strstrings; while (*p!=0){ while (*p!=0 && (*p == ' ' || *p == '\t' || *p == ',')) p++; if (*p==0) break; char *s = (char *)p; char *e = (char *)p; for (;*p!=0 && *p!=',';p++){ if (*p!=' ' && *p!='\t'){ e = (char *)p; } } e++; SSTRING *string = new SSTRING(); string->setfrom(s,e-s); strstrings->add(string); } return strstrings; } /* DESCRIPTION: Remove an item from variable. RETURN: -1 if error 1 if success */ PUBLIC int DATAMAIN::removeitemfromvar (const char *item, int namevar){ int ret = -1; SSTRING *var = getvarvariable(namevar); SSTRINGS *itens = str_popul_sstrings(var->get()); // populate all items of variable on SSTRING if (itens!=NULL){ for (int i=0; igetnb();i++){ // remove item from var SSTRING *s = itens->getitem(i); if ( s->cmp(item)==0 ) itens->remove_del(s); } var->setfrom(""); bool need_comas = false; for (int i=0; igetnb();i++){ // regroup items into variable if (need_comas) var->append(" ,"); var->append(itens->getitem(i)->get()); need_comas = true; } delete (itens); ret = 1; } return ret; } /* DESCRIPTION: Take a list of table:/path (in SSTRINGS), populate the recognized tables and return an SSTRINGS. RETURN: a pointer to SSTRINGS */ PUBLIC SSTRINGS *DATAMAIN::checktables (SSTRING *strt){ // populate variable contents and check its contents SSTRINGS *tables = str_popul_sstrings(strt->get()); // populate the contents of strt in SSTRINGS if (tables!=NULL){ tables->sort(); tables->remove_empty(); tables->remove_dups(); for (int i=0; igetnb(); i++){ // verify each item, only items recognized by module are accepted const char *str = (char *) tables->getitem(i)->get(); // if an item is not included its erased from SSTRINGS // if an item start with '/' its accepted. Because the type of variable is taken from database_type if ( !(strstr(str,"btree:") || strstr(str, "dbm:") || strstr(str, "hash:") || (*str=='/')) ){ tables->remove_del(tables->getitem(i)); } } } return tables; } /* DESCRIPTION: This method execute the 'command' for all item in 'namevar'. The execution messages is stored in SSTRING 'notice'. The 'namevar' must be a list of type:/path for tables. These items are separated by 'str_popul_sstrings', called from 'checktables' that return the valid item tables. RETURN: -1 if the tables == NULL 0 if nothing is executed 1 if success */ PUBLIC int DATAMAIN::execall (const char *command, int namevar, SSTRING ¬ice){ int ret = -1; notice.setfrom(""); // populate items SSTRING *strt = getvarvariable(namevar); SSTRINGS *tables = checktables(strt); // tables must conatin only local tables if (tables==NULL) return ret; int nb = tables->getnb(); if (nb>0){ ret = 0; // every table must be compiled for (int i=0; igetnb(); i++){ const char *args = tables->getitem(i)->get(); POPEN pop (command,args); // execute 'command' for each if (pop.isok()){ ret = 1; char buf[100]; sprintf(buf,"%s %s\n",command,args); notice.append (buf); while (pop.wait(1)>=0){ // general execution messages if (pop.readout(buf,sizeof(buf)-1)!=-1){ notice.append (buf); } if (pop.readerr (buf,sizeof(buf)-1)==0){ notice.append (buf); } } }else{ xconf_notice ("ERROR executing '%s%s'",command,args); } pop.close(); } } delete (tables); return ret; } /* DESCRIPTION: Generate a tmp file that contain the default variables of postfix getting by command 'postconf -d' and store its values default variable of class DATA. RETURN: -1 if an error 0 if the tmp file was generated but an error ocurr. 1 if the file can be read */ PUBLIC int DATAMAIN::setdefaultvalues (){ int ret = -1; CONFIG_FILE cf_postfix_default("/etc/vardef.tmp",help_nil, CONFIGF_OPTIONAL|CONFIGF_MANAGED, subsys_postfix); // the tmo file FILE_CFG *foutin = cf_postfix_default.fopen ("w"); if (foutin!=NULL){ // if the file can be read const char *command = "postconf"; const char *args = "-d"; POPEN pop (command,args); if (pop.isok()){ // if the command was executed while (pop.wait(1)>=0){ char buf[500]; while (pop.readout (buf,sizeof(buf)-1)==0){ // read the stdout of command into tmp file fprintf(foutin,buf); } } }else return ret; pop.close(); ret = fclose(foutin); if (ret==0){ // if the file was closed VIEWITEMS_PARSER vip; VIEWITEMS items (vip); vip.quotchar = 0; if (items.read (cf_postfix_default)!=-1){ // read the tmp cf file ret = 1; int nb = getnb(); char tmp[1000]; for (int i=0; iexist==0) t = items.locateval ("default_destination_concurrency_limit", tmp); else t = getvarvariable(V_DEFAULT_DESTINATION_CONCURRENCY_LIMIT)->get(); }else if ( (i==V_SMTP_DESTINATION_CONCURRENCY_LIMIT) ){ if (getitem(V_DEFAULT_DESTINATION_CONCURRENCY_LIMIT)->exist==0) t = items.locateval ("default_destination_concurrency_limit", tmp); else t = getvarvariable(V_DEFAULT_DESTINATION_CONCURRENCY_LIMIT)->get(); }else if ( (i==V_SMTP_DESTINATION_RECIPIENT_LIMIT) ){ if (getitem(V_DEFAULT_DESTINATION_RECIPIENT_LIMIT)->exist==0) t = items.locateval ("default_destination_recipient_limit", tmp); else t = getvarvariable(V_DEFAULT_DESTINATION_RECIPIENT_LIMIT)->get(); }else{ t = items.locateval (d->name_variable, tmp); } if (t!=NULL && *t!='\0'){ d->defvar.setfrom(t); } } } if (cf_postfix_default.unlink()!=0){ // remove the tmp file xconf_error (MSG_U(E_REMOVEDEFAULTFILE,"Couldn't remove temporary file '%s'"),cf_postfix_default.getpath()); } } } return ret; } /* DESCRIPTION: Used only for debug... Generate a SSTRING that conatin all name of variables, its values and default. RETURN: Nothing */ PUBLIC void DATAMAIN::viewvardefault (SSTRING &strgen){ strgen.setfrom("VARIABLE\t\t\tVALUE\t\t\tDEFAULT\n"); for (int i=0; iname_variable,d->var.get(),d->defvar.get()); } } /* DESCRIPTION: If the variable isn't in the cf file, copy it default value to variable. RETURN: Nothing */ PUBLIC void DATAMAIN::sincronizedefault (){ for (int i=0; iexist==0){ d->var.setfrom(d->defvar); } } } /* DESCRIPTION: Show all default, value and name of each variable. This method is used by command line arguments. RETURN: Nothing */ PUBLIC void DATAMAIN::showvalues (){ for (int i=0; iname_variable,d->var.get(),d->defvar.get()); } } /* DESCRIPTION: Set a list of variables, instance of DATA, to its default value. The -1 is expect at the end of list. RETURN: Nothing */ PUBLIC void DATAMAIN::setdefaultvarvalues (int i[]){ for (int j=0; i[j]!=-1; j++){ DATA *d = getitem(i[j]); d->var.setfrom(d->defvar); } } /* DESCRIPTION: Set a variable, instance of DATA, to it default value. RETURN: Nothing */ PUBLIC void DATAMAIN::setdefaultvar (int i){ DATA *d = getitem(i); d->var.setfrom(d->defvar); } /* DESCRIPTION: It's only call the is_empty function of SSTRINGs for an variable, instance of DATA. RETURN: The return of SSTRING::is_empty method */ PUBLIC int DATAMAIN::is_varempty (int i){ DATA *d = getitem(i); if (d!=NULL){ return d->var.is_empty(); } return -1; } /* DESCRIPTION: Check if the path is a directory RETURN: 0 if not 1 if is a valid dir */ PUBLIC int DATAMAIN::is_dir (const char *pathfile){ int ret = 0; struct stat buf; if( stat(pathfile, &buf)==0 ){ if (buf.st_mode & S_IFDIR){ ret = 1; } } return ret; } /*xconf_notice ("st_dev:'%d'\n" "st_ino:'%d'\n" "st_mode:'%d'\n" "st_nlink:'%d'\n" "st_uid:'%d'\n" "st_gid:'%d'\n" "st_rdev:'%d'\n" "st_size:'%d'\n" "st_blksize:'%lu'\n" "st_blocks:'%lu'\n" "st_atime:'%d'\n" "st_mtime:'%d'\n" "st_ctime:'%d'\n" ,buf.st_dev ,buf.st_ino ,buf.st_mode ,buf.st_nlink ,buf.st_uid ,buf.st_gid ,buf.st_rdev ,buf.st_size ,buf.st_blksize ,buf.st_blocks ,buf.st_atime ,buf.st_mtime ,buf.st_ctime);*/