*** 1.33r5/linuxconf/rules.mak Fri Sep 10 13:48:40 2004 --- 1.33r5/linuxconf/rules.mak Mon Nov 15 11:01:30 2004 *************** *** 27,33 **** endif CC=gcc LINUXCONF_REV=1.34 ! LINUXCONF_SUBREV=0 LINUXCONF_SUBSUBREV=0 # liblinuxconf revision LIB_REV=1 --- 27,33 ---- endif CC=gcc LINUXCONF_REV=1.34 ! LINUXCONF_SUBREV=2 LINUXCONF_SUBSUBREV=0 # liblinuxconf revision LIB_REV=1 *************** *** 55,60 **** --- 55,64 ---- WWWBASE=$(HOME)/n/dnshtml WWWTECHBASE=$(WWWBASE)/linuxconf/tech + + USRX11LIB = $(shell test -d /usr/X11R6/lib64 && echo /usr/X11R6/lib64 || echo /usr/X11R6/lib) + + SPEC_FILE = $(shell $(GCC) -v 2>&1 | head -1 | sed 's/^.* //') LD_FILE = $(notdir $(shell cat $(SPEC_FILE) | sed -n -e '/:-dynamic-linker/s/^.*:-dynamic-linker \([^}]*\).*/\1/p')) ifeq ($(LD_FILE),%(elf_dynamic_linker)) *** 1.33r5/linuxconf/dialog/textarea.cc Tue Aug 10 17:30:21 2004 --- 1.33r5/linuxconf/dialog/textarea.cc Thu Nov 11 15:46:25 2004 *************** *** 527,537 **** while (*pt != '\0'){ char line[1000]; char *dst = line; ! while (*pt != '\n' && *pt != '\0' && (unsigned)(dst-line)Operate only on groups

Instead of limiting the scope of the deletion process (explained above) ! to group above a certain threshold, you can enumerate the group on which the process must operate. Any user account not member of those ! groups won't be deleted, even if it is not part of the data file.

3.3 Parsing

--- 87,113 ----

Operate only on groups

Instead of limiting the scope of the deletion process (explained above) ! to group above a certain threshold, you can enumerate the groups on which the process must operate. Any user account not member of those ! groups won't be deleted/disabled, even if it is not part of the data file.

!

You can specify a single star (*) as well. This means the module ! is authoritative on all groups found in the input file.

! !

Authorization command

! !

When attempting to delete or disable accounts, accountbatch may ! run a command operating as a filter. The command reads a list ! of account proposed for deletion on its standard input and ! produces a result list on its standard output. The result ! simply confirm which accounts may be deleted.

!

In general, you write a shell to protect some special accounts ! not created by accountbatch (not part of the input file).

! !

Log file

! !

Accountbatch produces extensive statistics about the account it ! created, updated, disabled or deleted. If you specify a log file, all ! the reports will be copied silently (appended) to that file.

3.3 Parsing

*************** *** 109,114 **** --- 127,133 ----
  • Shell
  • Password
  • Home directory>
  • +
  • Alt. groups
  • *************** *** 190,195 **** --- 209,219 ----

    Any Linux account not found in the data file, member of one of the specified group, or with a group id above a given threshold will be deleted.

    +

    Disable old accounts

    + +

    Instead of deleting accounts, the module may disable them. You must + use Delete or Disable, not both.

    +

    Deletion mode

    You may want to preserve the data owned by the account you are deleting. *** 1.33r5/linuxconf/help.files/sources/accountbatch/batch.help Tue Sep 2 18:09:10 2003 --- 1.33r5/linuxconf/help.files/sources/accountbatch/batch.help Tue Sep 14 16:17:49 2004 *************** *** 120,129 **** 3.2.4. Operate only on groups Instead of limiting the scope of the deletion process (explained ! above) to group above a certain threshold, you can enumerate the group ! on which the process must operate. Any user account not member of ! those groups won't be deleted, even if it is not part of the data ! file. 3.3. Parsing --- 120,152 ---- 3.2.4. Operate only on groups Instead of limiting the scope of the deletion process (explained ! above) to group above a certain threshold, you can enumerate the ! groups on which the process must operate. Any user account not member ! of those groups won't be deleted/disabled, even if it is not part of ! the data file. ! ! You can specify a single star (*) as well. This means the module is ! authoritative on all groups found in the input file. ! ! ! ! 3.2.5. Authorization command ! ! When attempting to delete or disable accounts, accountbatch may run a ! command operating as a filter. The command reads a list of account ! proposed for deletion on its standard input and produces a result list ! on its standard output. The result simply confirm which accounts may ! be deleted. ! ! In general, you write a shell to protect some special accounts not ! created by accountbatch (not part of the input file). ! ! ! 3.2.6. Log file ! ! Accountbatch produces extensive statistics about the account it ! created, updated, disabled or deleted. If you specify a log file, all ! the reports will be copied silently (appended) to that file. 3.3. Parsing *************** *** 149,154 **** --- 172,179 ---- +o Home directory> + +o Alt. groups + For every field, there is two input in the parsing section. The first is a list box where you can select the following *************** *** 234,240 **** deleted. ! 3.4.4. Deletion mode You may want to preserve the data owned by the account you are deleting. Or you may want to delete it or archive it. You can select --- 259,271 ---- deleted. ! 3.4.4. Disable old accounts ! ! Instead of deleting accounts, the module may disable them. You must ! use Delete or Disable, not both. ! ! ! 3.4.5. Deletion mode You may want to preserve the data owned by the account you are deleting. Or you may want to delete it or archive it. You can select *** 1.33r5/linuxconf/help.files/sources/accountbatch/batch.sgml Tue Sep 2 17:53:28 2003 --- 1.33r5/linuxconf/help.files/sources/accountbatch/batch.sgml Tue Sep 14 16:17:42 2004 *************** *** 115,123 **** Operate only on groups

    Instead of limiting the scope of the deletion process (explained above) ! to group above a certain threshold, you can enumerate the group on which the process must operate. Any user account not member of those ! groups won't be deleted, even if it is not part of the data file. Parsing

    --- 115,143 ---- Operate only on groups

    Instead of limiting the scope of the deletion process (explained above) ! to group above a certain threshold, you can enumerate the groups on which the process must operate. Any user account not member of those ! groups won't be deleted/disabled, even if it is not part of the data file. ! ! You can specify a single star (*) as well. This means the module ! is authoritative on all groups found in the input file. ! ! Authorization command !

    ! When attempting to delete or disable accounts, accountbatch may ! run a command operating as a filter. The command reads a list ! of account proposed for deletion on its standard input and ! produces a result list on its standard output. The result ! simply confirm which accounts may be deleted. ! ! In general, you write a shell to protect some special accounts ! not created by accountbatch (not part of the input file). ! ! Log file !

    ! Accountbatch produces extensive statistics about the account it ! created, updated, disabled or deleted. If you specify a log file, all ! the reports will be copied silently (appended) to that file. Parsing

    *************** *** 137,142 **** --- 157,163 ---- Shell Password Home directory> + Alt. groups *************** *** 213,218 **** --- 234,244 ---- Any Linux account not found in the data file, member of one of the specified group, or with a group id above a given threshold will be deleted. + Disable old accounts +

    + Instead of deleting accounts, the module may disable them. You must + use Delete or Disable, not both. + Deletion mode

    You may want to preserve the data owned by the account you are deleting. *** 1.33r5/linuxconf/main/linuxconf.cc Sat Feb 22 15:01:22 2003 --- 1.33r5/linuxconf/main/linuxconf.cc Wed Oct 13 17:59:09 2004 *************** *** 191,197 **** } return netconf_system_if ("loadkeys",km); } ! #if defined(i386) static const char keymap_arch[]="i386"; #elif defined(__sparc__) static const char keymap_arch[]="sparc"; --- 191,197 ---- } return netconf_system_if ("loadkeys",km); } ! #if defined(i386) || defined (__x86_64__) static const char keymap_arch[]="i386"; #elif defined(__sparc__) static const char keymap_arch[]="sparc"; *** 1.33r5/linuxconf/messages/sources/dhcpd.dic Sat Feb 3 15:52:11 2001 --- 1.33r5/linuxconf/messages/sources/dhcpd.dic Tue Nov 9 19:31:55 2004 *************** *** 154,156 **** --- 154,158 ---- :E Invalid Network number %s for netmask %s\nt\t\tHint: %s !E_IVLDNETHOSTIP :E Invalid IP range %s for network %s + !F_FILENAME + :E Boot file *** 1.33r5/linuxconf/messages/sources/mailconf.dic Tue Jun 8 17:50:46 2004 --- 1.33r5/linuxconf/messages/sources/mailconf.dic Tue Sep 28 17:42:33 2004 *************** *** 856,858 **** --- 856,862 ---- :E Yes !I_NO :E No + !F_DOUBLEBOUNCE + :E Double bounce dest. + !I_DEVNULL + :E to /dev/null *** 1.33r5/linuxconf/messages/sources/accountbatch.dic Thu Sep 9 21:05:29 2004 --- 1.33r5/linuxconf/messages/sources/accountbatch.dic Tue Sep 14 16:18:56 2004 *************** *** 217,223 **** !I_STAR :E authoritative on all groups in file !F_CHKCMD ! :E Autorisation command !E_ALTGR :E Line %d: %s\n !E_SOMEERROR --- 217,223 ---- !I_STAR :E authoritative on all groups in file !F_CHKCMD ! :E Authorization command !E_ALTGR :E Line %d: %s\n !E_SOMEERROR *** 1.33r5/linuxconf/messages/sources/tcptool.dic Thu Sep 28 23:50:36 2000 --- 1.33r5/linuxconf/messages/sources/tcptool.dic Fri Oct 29 10:08:14 2004 *************** *** 55,57 **** --- 55,61 ---- :E RECEIVED: !F_COMMENT :E Comment + !I_PRINTFDS + :E Print file handle and sockets for processes\n + !I_PID + :E Process ID *** 1.33r5/linuxconf/misc/sstring.cc Thu Sep 9 20:43:30 2004 --- 1.33r5/linuxconf/misc/sstring.cc Sat Nov 13 21:44:27 2004 *************** *** 251,257 **** { char *one = str; if (one == NULL) one = ""; ! return stricmp(one,other); } /* --- 251,257 ---- { char *one = str; if (one == NULL) one = ""; ! return strcasecmp(one,other); } /* *************** *** 261,266 **** --- 261,283 ---- { return icmp(other.get()); } + /* + Perform a strnicmp on the string and the other one. + */ + PUBLIC int SSTRING::nicmp (const char *other, int len) const + { + char *one = str; + if (one == NULL) one = ""; + return strncasecmp(one,other,len); + } + + /* + Perform a stricmp on the string and the other one. + */ + PUBLIC int SSTRING::nicmp (const SSTRING &other, int len) const + { + return nicmp(other.get(),len); + } /* Find the occurence of a character in the string. *************** *** 418,423 **** --- 435,468 ---- } /* + Change one character in the string. + The pointer must point inside the string. + The string won't be enlarged. + + Return false if the operation was not performed. + */ + PUBLIC bool SSTRING::setchar(const char *pt, const char car) + { + bool ret = false; + if (pt >= str && pt < str + getlen()){ + *(char*)pt = car; + ret = true; + } + return ret; + } + /* + Change one character in the string. + The position (starting at 0) must point inside the string. + The string won't be enlarged. + + Return false if the operation was not performed. + */ + PUBLIC bool SSTRING::setchar(int pos, const char car) + { + return setchar (str+pos,car); + } + + /* Record the comment part of the CSSTRING */ PUBLIC void CSSTRING::setcomment(const SSTRING &com) *** 1.33r5/linuxconf/misc/sstring.h Thu Sep 9 20:43:37 2004 --- 1.33r5/linuxconf/misc/sstring.h Sat Nov 13 21:44:10 2004 *************** *** 44,49 **** --- 44,51 ---- bool is_num (void)const; int ncmp (const SSTRING&other, int len)const; int ncmp (const char *other, int len)const; + int nicmp (const SSTRING&other, int len)const; + int nicmp (const char *other, int len)const; bool operator != (const SSTRING&other)const; bool operator != (const char *other)const; SSTRING&operator += (const SSTRING&_str); *************** *** 52,57 **** --- 54,61 ---- SSTRING&operator = (const char *_str); bool operator == (const SSTRING&other)const; bool operator == (const char *other)const; + bool setchar (const char *pt, const char car); + bool setchar (int pos, const char car); void setempty (void); void setfrom (const SSTRING *src); void setfrom (const SSTRING&src); *** 1.33r5/linuxconf/misc/misc.p Thu Sep 9 20:43:37 2004 --- 1.33r5/linuxconf/misc/misc.p Sat Nov 13 21:44:10 2004 *************** *** 346,352 **** int popen_getloginuid (void); /* samples.cc 06/04/2001 22.46.22 */ /* sstream.cc 26/11/2000 22.48.04 */ ! /* sstring.cc 09/09/2004 20.43.30 */ /* sstrings.cc 25/08/2003 11.56.46 */ /* str1.cc 30/04/2002 22.06.38 */ int str_strip (const char *str, char *newstr); --- 346,352 ---- int popen_getloginuid (void); /* samples.cc 06/04/2001 22.46.22 */ /* sstream.cc 26/11/2000 22.48.04 */ ! /* sstring.cc 13/11/2004 21.43.58 */ /* sstrings.cc 25/08/2003 11.56.46 */ /* str1.cc 30/04/2002 22.06.38 */ int str_strip (const char *str, char *newstr); *** 1.33r5/linuxconf/misc/misc.pm Thu Sep 9 20:43:37 2004 --- 1.33r5/linuxconf/misc/misc.pm Sat Nov 13 21:44:10 2004 *************** *** 583,589 **** PUBLIC void SSTREAM_NUL::puts (const char *); PUBLIC char *SSTREAM_NUL::gets (char *, int); PUBLIC long SSTREAM_NUL::getoffset (void); ! /* sstring.cc 09/09/2004 20.43.30 */ PUBLIC SSTRING::SSTRING (void); PUBLIC SSTRING::SSTRING (const char *_str); PUBLIC SSTRING::SSTRING (const char *_str, int _maxsiz); --- 583,589 ---- PUBLIC void SSTREAM_NUL::puts (const char *); PUBLIC char *SSTREAM_NUL::gets (char *, int); PUBLIC long SSTREAM_NUL::getoffset (void); ! /* sstring.cc 13/11/2004 21.43.58 */ PUBLIC SSTRING::SSTRING (void); PUBLIC SSTRING::SSTRING (const char *_str); PUBLIC SSTRING::SSTRING (const char *_str, int _maxsiz); *************** *** 618,623 **** --- 618,625 ---- PUBLIC int SSTRING::ncmp (const SSTRING&other, int len)const; PUBLIC int SSTRING::icmp (const char *other)const; PUBLIC int SSTRING::icmp (const SSTRING&other)const; + PUBLIC int SSTRING::nicmp (const char *other, int len)const; + PUBLIC int SSTRING::nicmp (const SSTRING&other, int len)const; PUBLIC const char *SSTRING::strchr (char carac)const; PUBLIC const char *SSTRING::strrchr (char carac)const; PUBLIC const char *SSTRING::strstr (const char *sub)const; *************** *** 636,641 **** --- 638,645 ---- PUBLIC char *SSTRING::copyword (const char *line); PUBLIC bool SSTRING::truncate (int newlen); PUBLIC bool SSTRING::truncate (const char *pt); + PUBLIC bool SSTRING::setchar (const char *pt, const char car); + PUBLIC bool SSTRING::setchar (int pos, const char car); PUBLIC void CSSTRING::setcomment (const SSTRING&com); PUBLIC void CSSTRING::setfrom_c (const SSTRING&val, const SSTRING&com); *** 1.33r5/linuxconf/modules/dhcpd/dhcpd.h Mon Sep 30 11:14:21 2002 --- 1.33r5/linuxconf/modules/dhcpd/dhcpd.h Tue Nov 9 16:38:49 2004 *************** *** 106,111 **** --- 106,113 ---- TIMESTR default_lease_time; TIMESTR max_lease_time; DHCP_RANGES ranges; + SSTRING filename; + SSTRING next_server; /*~PROTOBEG~ DHCP_SUBNET */ public: DHCP_SUBNET (void); *** 1.33r5/linuxconf/modules/dhcpd/dhcpedit.cc Wed May 14 15:01:19 2003 --- 1.33r5/linuxconf/modules/dhcpd/dhcpedit.cc Tue Nov 9 19:31:51 2004 *************** *** 216,221 **** --- 216,227 ---- if (max_lease_time.seconds != 0){ fprintf (fout,"\tmax-lease-time %ld;\n",max_lease_time.seconds); } + if (filename.is_filled()){ + fprintf (fout,"\tfilename \"%s\";\n",filename.get()); + } + if (next_server.is_filled()){ + fprintf (fout,"\tnext-server \"%s\";\n",next_server.get()); + } options.write ("\t",fout); fputs ("}\n",fout); } *************** *** 590,595 **** --- 596,605 ---- ret = dhcp_readval (par,default_lease_time); }else if (strcmp(word,"max-lease-time")==0){ ret = dhcp_readval (par,max_lease_time); + }else if (strcmp(word,"filename")==0){ + ret = dhcp_readval (par,filename); + }else if (strcmp(word,"next-server")==0){ + ret = dhcp_readval (par,next_server); } } return ret; *************** *** 853,858 **** --- 863,869 ---- dia.last_noempty(); dia.newf_str (MSG_U(F_DEFLEASETIME,"Default lease time"),default_lease_time); dia.newf_str (MSG_U(F_MAXLEASETIME,"Max lease time"),max_lease_time); + dia.newf_str (MSG_U(F_FILENAME,"Boot file"),filename); dia.newf_title (MSG_U(T_RANGES,"Ranges"),1,"",MSG_R(T_RANGES)); int field_range = dia.getnb(); ranges.add (new DHCP_RANGE); *** 1.33r5/linuxconf/modules/dhcpd/dhcpd.m Tue Jan 23 00:31:57 2001 --- 1.33r5/linuxconf/modules/dhcpd/dhcpd.m Tue Nov 9 19:31:55 2004 *************** *** 2,8 **** #ifndef DICTIONARY_REQUEST #define DICTIONARY_REQUEST \ const char **_dictionary_dhcpd;\ ! TRANSLATE_SYSTEM_REQ _dictionary_req_dhcpd("dhcpd",_dictionary_dhcpd,66,0);\ void dummy_dict_dhcpd(){} #endif #ifndef MSG_U --- 2,8 ---- #ifndef DICTIONARY_REQUEST #define DICTIONARY_REQUEST \ const char **_dictionary_dhcpd;\ ! TRANSLATE_SYSTEM_REQ _dictionary_req_dhcpd("dhcpd",_dictionary_dhcpd,67,0);\ void dummy_dict_dhcpd(){} #endif #ifndef MSG_U *************** *** 79,81 **** --- 79,82 ---- #define I_CREATELEASE 63 #define E_IVLDNETWORKIP 64 #define E_IVLDNETHOSTIP 65 + #define F_FILENAME 66 *** 1.33r5/linuxconf/modules/mailconf/basic.cc Mon Dec 30 15:52:31 2002 --- 1.33r5/linuxconf/modules/mailconf/basic.cc Tue Sep 28 17:54:11 2004 *************** *** 62,68 **** ,"Builds server aliases from net interfaces")); dia.newf_str (MSG_U(F_LISTENPORT,"Listen on TCP port"),listen.port); dia.newf_str (MSG_U(F_LISTENADDR,"Listen on TCP address"),listen.addr); ! dia.newf_title (MSG_U(T_SMTPFEATURES,"SMTP features"),1,"",MSG_R(T_SMTPFEATURES)); dia.newf_chk ("",features.verify,MSG_U(F_VERIFY,"Enable the VERIFY SMTP command")); --- 62,79 ---- ,"Builds server aliases from net interfaces")); dia.newf_str (MSG_U(F_LISTENPORT,"Listen on TCP port"),listen.port); dia.newf_str (MSG_U(F_LISTENADDR,"Listen on TCP address"),listen.addr); ! { ! static int tb[]={0,1,2}; ! static const char *tbv[]={ ! MSG_R(I_DISABLED), ! MSG_U(I_DEVNULL,"to /dev/null"), ! NULL ! }; ! dia.newf_chkm_str (MSG_U(F_DOUBLEBOUNCE,"Double bounce dest.") ! ,features.doublebounce ! ,features.doublebouncedest ! ,tb,tbv); ! } dia.newf_title (MSG_U(T_SMTPFEATURES,"SMTP features"),1,"",MSG_R(T_SMTPFEATURES)); dia.newf_chk ("",features.verify,MSG_U(F_VERIFY,"Enable the VERIFY SMTP command")); *** 1.33r5/linuxconf/modules/mailconf/confread.cc Thu Mar 18 14:38:29 2004 --- 1.33r5/linuxconf/modules/mailconf/confread.cc Tue Sep 28 17:37:18 2004 *************** *** 87,92 **** --- 87,95 ---- static const char K_MILTER[]="milter"; static const char K_MILTERPORT[]="milterport"; static const char K_MILTERFLAGS[]="milterflags"; + static const char K_DOUBLEBOUNCE[]="doublebounce"; + static const char K_DOUBLEBOUNCEDEST[]="doublebouncedest"; + /* Return the database format for makemap */ *************** *** 124,129 **** --- 127,134 ---- features.authwarnings = confread_getval(AUTHWARNINGS,1); features.queuewarn.setfrom(confread_getval(QUEUEWARN,"4h")); features.queuereturn.setfrom(confread_getval(QUEUERETURN,"5d")); + features.doublebounce = confread_getval(K_DOUBLEBOUNCE,0); + features.doublebouncedest.setfrom (confread_getval(K_DOUBLEBOUNCEDEST,"")); users.dontmasque.setfrom (confread_getval(DONTMASQUE,"root")); users.deliverlocal.setfrom (confread_getval(DELIVERLOCAL,"root")); *************** *** 312,317 **** --- 317,324 ---- confread_replace (AUTHWARNINGS,features.authwarnings); confread_replace (QUEUEWARN,features.queuewarn); confread_replace (QUEUERETURN,features.queuereturn); + confread_replace (K_DOUBLEBOUNCE,features.doublebounce); + confread_replace (K_DOUBLEBOUNCEDEST,features.doublebouncedest); confread_replace (LISTENPORT,listen.port); confread_replace (LISTENADDR,listen.addr); *** 1.33r5/linuxconf/modules/mailconf/internal.h Tue Jun 8 14:28:38 2004 --- 1.33r5/linuxconf/modules/mailconf/internal.h Tue Sep 28 17:34:19 2004 *************** *** 377,382 **** --- 377,384 ---- char probeinterface; SSTRING queuewarn; SSTRING queuereturn; + int doublebounce; + SSTRING doublebouncedest; } features; SSTRINGS dnsfor; // Use the DNS only for those domains // See the large comment about *** 1.33r5/linuxconf/modules/mailconf/mailconf.m Tue Jun 8 17:50:46 2004 --- 1.33r5/linuxconf/modules/mailconf/mailconf.m Tue Sep 28 17:42:33 2004 *************** *** 2,8 **** #ifndef DICTIONARY_REQUEST #define DICTIONARY_REQUEST \ const char **_dictionary_mailconf;\ ! TRANSLATE_SYSTEM_REQ _dictionary_req_mailconf("mailconf",_dictionary_mailconf,385,24);\ void dummy_dict_mailconf(){} #endif #ifndef MSG_U --- 2,8 ---- #ifndef DICTIONARY_REQUEST #define DICTIONARY_REQUEST \ const char **_dictionary_mailconf;\ ! TRANSLATE_SYSTEM_REQ _dictionary_req_mailconf("mailconf",_dictionary_mailconf,387,24);\ void dummy_dict_mailconf(){} #endif #ifndef MSG_U *************** *** 398,400 **** --- 398,402 ---- #define F_PRIORITY 382 #define I_YES 383 #define I_NO 384 + #define F_DOUBLEBOUNCE 385 + #define I_DEVNULL 386 *** 1.33r5/linuxconf/modules/mailconf/generate.cc Tue Jun 22 08:35:39 2004 --- 1.33r5/linuxconf/modules/mailconf/generate.cc Tue Sep 28 17:41:31 2004 *************** *** 383,391 **** "$(ETRN)","$(VERB)","$(MAILQ)","$(RUN)","$(RECEIPTS)","$(GOAWAY)", "$(PROBEINTERFACE)","$(AUTHWARNINGS)", "$(QUEUEWARN)","$(QUEUERETURN)", ! "$(PORT)","$(ADDR)" }; ! char userrepl[17][TOKEN_VALLEN]; strcpy (userrepl[0],"mail:mail"); if (strcmp(linuxconf_getdistdir(),"suse")==0){ strcpy (userrepl[0],"bin:bin"); --- 383,391 ---- "$(ETRN)","$(VERB)","$(MAILQ)","$(RUN)","$(RECEIPTS)","$(GOAWAY)", "$(PROBEINTERFACE)","$(AUTHWARNINGS)", "$(QUEUEWARN)","$(QUEUERETURN)", ! "$(PORT)","$(ADDR)","$(DOUBLE)","$(DOUBLEADDR)" }; ! char userrepl[19][TOKEN_VALLEN]; strcpy (userrepl[0],"mail:mail"); if (strcmp(linuxconf_getdistdir(),"suse")==0){ strcpy (userrepl[0],"bin:bin"); *************** *** 406,412 **** strcpy (userrepl[14],features.queuereturn.get()); listen.port.copy (userrepl[15]); listen.addr.copy (userrepl[16]); ! ret |= copyfile (f_stdoptions,out,usertoken,userrepl,17); } if (milters.size() > 0){ ret |= copyfile (f_milteroptions,out); --- 406,424 ---- strcpy (userrepl[14],features.queuereturn.get()); listen.port.copy (userrepl[15]); listen.addr.copy (userrepl[16]); ! if (features.doublebounce > 0){ ! strcpy (userrepl[17],""); ! if (features.doublebounce == 1){ ! strcpy (userrepl[18],""); ! }else{ ! strcpy (userrepl[18],features.doublebouncedest.get()); ! } ! }else{ ! strcpy (userrepl[17],"#"); ! strcpy (userrepl[18],""); ! } ! ! ret |= copyfile (f_stdoptions,out,usertoken,userrepl,19); } if (milters.size() > 0){ ret |= copyfile (f_milteroptions,out); *** 1.33r5/linuxconf/modules/mailconf/conf/stdoptions.cf Mon Dec 30 15:42:05 2002 --- 1.33r5/linuxconf/modules/mailconf/conf/stdoptions.cf Tue Sep 28 16:56:10 2004 *************** *** 251,257 **** #O UnsafeGroupWrites # where do errors that occur when sending errors get sent? ! #O DoubleBounceAddress # what user id do we assume for the majority of the processing? #O RunAsUser=sendmail --- 251,257 ---- #O UnsafeGroupWrites # where do errors that occur when sending errors get sent? ! $(DOUBLE)O DoubleBounceAddress=$(DOUBLEADDR) # what user id do we assume for the majority of the processing? #O RunAsUser=sendmail *** 1.33r5/linuxconf/modules/redhat/redhat.cc Wed Nov 12 13:03:54 2003 --- 1.33r5/linuxconf/modules/redhat/redhat.cc Tue Nov 9 11:51:39 2004 *************** *** 120,125 **** --- 120,126 ---- {"dnsserver", "bind", MSG_U(I_BINDDESC,"Domain name server (DNS)"),0,1}, {"popserver", "imap", MSG_U(I_IMAPDESC,"POP-3 and IMAP mail servers"),700,2}, {"popserver", "imap", MSG_R(I_IMAPDESC),0,1}, + {"dhcpserver", "dhcp", MSG_R(I_DHCPDESC),900,2}, {"dhcpserver", "dhcp-server", MSG_R(I_DHCPDESC),811,2}, {"dhcpserver", "dhcp", MSG_U(I_DHCPDESC,"Dynamic host configuration protocol server (DHCP)"),700,2}, {"dhcpserver", "dhcp", MSG_R(I_DHCPDESC),0,1}, *** 1.33r5/linuxconf/modules/accountbatch/accountbatch.tlcc Fri Sep 10 11:03:00 2004 --- 1.33r5/linuxconf/modules/accountbatch/accountbatch.tlcc Thu Oct 21 12:34:45 2004 *************** *** 36,41 **** --- 36,48 ---- static const char K_FIELDPOS[]="fieldpos"; static const char K_FIELDDEFVAL[]="fielddefval"; static const char K_IDPREFIX[]="idprefix"; + static const char K_UPDGECOS[]="updgecos"; + static const char K_UPDGROUP[]="updgroup"; + static const char K_UPDSHELL[]="updshell"; + static const char K_UPDHOME[]="updhome"; + static const char K_UPDPASSWD[]="updpasswd"; + static const char K_UPDALTGR[]="updaltgr"; + static const char K_UPDEXTRA[]="updextra"; MODULE_DEFINE_VERSION(accountbatch); static const char *keymenu=NULL; *************** *** 394,400 **** SSTRING datafile; // Input file SSTRING datacmd; // Input produced by this command SSTRING groups; // Groups on which accountbatch is authoritative ! SSTRING autcmd; // Autorisation command. It filters out accounts // accountbatch is now allowed to delete SSTRING logfile; // Each time accountbatch perform action, a // report is added there (there same you have --- 401,407 ---- SSTRING datafile; // Input file SSTRING datacmd; // Input produced by this command SSTRING groups; // Groups on which accountbatch is authoritative ! SSTRING autcmd; // Authorization command. It filters out accounts // accountbatch is now allowed to delete SSTRING logfile; // Each time accountbatch perform action, a // report is added there (there same you have *************** *** 1000,1006 **** } ! static void accountbatch_saveconfig(const char *config, ACCT_CONFIG &conf) { SSTRINGS tb; linuxconf_getall (K_ACCOUNTBATCH,K_INDEX,tb,true); --- 1007,1016 ---- } ! static void accountbatch_saveconfig( ! const char *config, ! ACCT_CONFIG &conf, ! ACCT_UPDATES &updates) { SSTRINGS tb; linuxconf_getall (K_ACCOUNTBATCH,K_INDEX,tb,true); *************** *** 1017,1027 **** linuxconf_replace (key,K_LOGFILE,conf.logfile); linuxconf_replace (key,K_IDPREFIX,conf.parse.idprefix); for (int i=0; iaddopt (g->getname()); } } ! dia.newf_str (MSG_U(F_CHKCMD,"Autorisation command"),conf.autcmd); dia.newf_str (MSG_U(F_LOGFILE,"Log file"),conf.logfile); dia.newf_title (MSG_U(I_PARSING,"Parsing"),1,"",MSG_R(I_PARSING)); --- 1158,1164 ---- comb->addopt (g->getname()); } } ! dia.newf_str (MSG_U(F_CHKCMD,"Authorization command"),conf.autcmd); dia.newf_str (MSG_U(F_LOGFILE,"Log file"),conf.logfile); dia.newf_title (MSG_U(I_PARSING,"Parsing"),1,"",MSG_R(I_PARSING)); *************** *** 1189,1195 **** dia.newf_title (MSG_U(I_UPDATES,"Updates"),1,"",MSG_R(I_UPDATES)); dia.auto_newline(true); - ACCT_UPDATES updates; dia.newf_chk (MSG_U(F_UPDATE,"Update"),updates.gecos,MSG_R(I_GECOS)); dia.newf_chk ("",updates.home,MSG_R(I_HOME)); dia.newf_chk ("",updates.group,MSG_R(I_GROUP)); --- 1237,1242 ---- *************** *** 1237,1243 **** int no = 0; if (pop.editmenu ("",no)==MENU_OK){ config.setfrom (tb.getitem(no)->get()); ! accountbatch_loadconf (config.get(),conf); dia.reload(); } } --- 1284,1290 ---- int no = 0; if (pop.editmenu ("",no)==MENU_OK){ config.setfrom (tb.getitem(no)->get()); ! accountbatch_loadconf (config.get(),conf,updates); dia.reload(); } } *************** *** 1252,1258 **** xconf_error (MSG_U(E_NOSPACE,"No space allowed in configuration name")); nof = 0; }else{ ! accountbatch_saveconfig (config.get(),conf); } if (registry_mode) break; }else if (code == MENU_USR2 --- 1299,1305 ---- xconf_error (MSG_U(E_NOSPACE,"No space allowed in configuration name")); nof = 0; }else{ ! accountbatch_saveconfig (config.get(),conf,updates); } if (registry_mode) break; }else if (code == MENU_USR2 *************** *** 1366,1372 **** fprintf (stderr,MSG_R(E_MISSCONFIG),nextarg); error = true; }else{ ! accountbatch_loadconf (nextarg,conf); } i++; }else if (strcmp(arg,"--test")==0){ --- 1413,1419 ---- fprintf (stderr,MSG_R(E_MISSCONFIG),nextarg); error = true; }else{ ! accountbatch_loadconf (nextarg,conf,updates); } i++; }else if (strcmp(arg,"--test")==0){ *** 1.33r5/linuxconf/modules/tcptool/Makefile Thu Sep 28 23:35:26 2000 --- 1.33r5/linuxconf/modules/tcptool/Makefile Fri Oct 29 10:15:56 2004 *************** *** 2,9 **** VERSION=1 CURDIR=tcptool LOCAL_CLEAN=std_local_clean ! LOCAL_INSTALL=std_local_install ! all: $(CURDIR).so OBJS = session.os tcptool.os _dict.os include ../rules.mak --- 2,9 ---- VERSION=1 CURDIR=tcptool LOCAL_CLEAN=std_local_clean ! LOCAL_INSTALL=local_install ! all: $(CURDIR).so printfds OBJS = session.os tcptool.os _dict.os include ../rules.mak *************** *** 12,16 **** --- 12,23 ---- include ../stdmod.mak + printfds: printfds.o _dict.o + cctlcc printfds.o _dict.o -o printfds + + local_install: std_local_install + mkdir -p $(USRBIN) + install -m 755 -s printfds $(USRBIN)/printfds + # Test program *** 1.33r5/linuxconf/modules/tcptool/tcptool.m Thu Sep 28 23:50:36 2000 --- 1.33r5/linuxconf/modules/tcptool/tcptool.m Fri Oct 29 10:08:14 2004 *************** *** 2,8 **** #ifndef DICTIONARY_REQUEST #define DICTIONARY_REQUEST \ const char **_dictionary_tcptool;\ ! TRANSLATE_SYSTEM_REQ _dictionary_req_tcptool("tcptool",_dictionary_tcptool,27,0);\ void dummy_dict_tcptool(){} #endif #ifndef MSG_U --- 2,8 ---- #ifndef DICTIONARY_REQUEST #define DICTIONARY_REQUEST \ const char **_dictionary_tcptool;\ ! TRANSLATE_SYSTEM_REQ _dictionary_req_tcptool("tcptool",_dictionary_tcptool,29,0);\ void dummy_dict_tcptool(){} #endif #ifndef MSG_U *************** *** 40,42 **** --- 40,44 ---- #define E_ONLYGUI 24 #define I_RECEIVEDLINE 25 #define F_COMMENT 26 + #define I_PRINTFDS 27 + #define I_PID 28 *** 1.33r5/linuxconf/modules/tcptool/tcptool.tlcc Thu Apr 18 22:16:29 2002 --- 1.33r5/linuxconf/modules/tcptool/tcptool.tlcc Sat Nov 13 22:02:47 2004 *************** *** 22,28 **** dia.settype (DIATYPE_POPUP); dia.newf_str (MSG_U(F_HOST,"Host"),host); dia.last_noempty(); ! FIELD_COMBO *comb = dia.newf_combo (MSG_U(F_PORT,"Service"),port); dia.last_noempty(); dia.newf_str (MSG_U(F_COMMENT,"Comment"),comment); int nof = 0; --- 22,28 ---- dia.settype (DIATYPE_POPUP); dia.newf_str (MSG_U(F_HOST,"Host"),host); dia.last_noempty(); ! dia.newf_str (MSG_U(F_PORT,"Service"),port); dia.last_noempty(); dia.newf_str (MSG_U(F_COMMENT,"Comment"),comment); int nof = 0; *** 1.33r5/linuxconf/modules/tcptool/printfds.tlcc --- 1.33r5/linuxconf/modules/tcptool/printfds.tlcc Sat Nov 13 22:25:24 2004 *************** *** 0 **** --- 1,195 ---- + #include + #include + #include + #include + #include + #include + #include + #include + #include "tcptool.m" + #include + #include + + using namespace std; + + static const char *my_readlink (const char *path, SSTRING &buf) + { + buf.setempty(); + const char *ret = NULL; + char val[PATH_MAX]; + int len = readlink (path,val,sizeof(val)-1); + if (len > 0){ + val[len] = '\0'; + buf = val; + ret = buf.get(); + } + return ret; + } + + struct TCP_SOCK{ + unsigned long addr; + unsigned port; + int pid; + TCP_SOCK (){ + addr = 0; + port = 0; + pid = 0; + } + }; + + struct TCP{ + int id; + int uid; + int state; + TCP_SOCK from,to; + }; + + + typedef map TCPS; + + + static void printfds_readtcp(TCPS &tcps) + { + glocal TCPS *tcps = &tcps; + ("/proc/net/tcp",true); + + if (noline > 0){ + SSTRINGS words; + int nb = str_splitline (line,' ',words); + if (nb > 9){ + TCP t; + int inode; + sscanf (words.getitem(1)->get(),"%08lx:%04x",&t.from.addr,&t.from.port); + sscanf (words.getitem(2)->get(),"%08lx:%04x",&t.to.addr,&t.to.port); + sscanf (words.getitem(3)->get(),"%02x",&t.state); + sscanf (words.getitem(7)->get(),"%d",&t.uid); + sscanf (words.getitem(9)->get(),"%d",&inode); + #if 0 + printf ("tcp %08lx:%d %08lx:%d state=%02x uid=%d inode=%d\n",t.from.addr,t.from.port + ,t.to.addr,t.to.port + ,t.state,t.uid,inode); + #endif + (*glocal.tcps)[inode] = t; + } + } + return 0; + + + } + + + typedef map UNIXS; + + + static void printfds_readunix(UNIXS &unixs) + { + glocal UNIXS *unixs = &unixs; + ("/proc/net/unix",true); + + if (noline > 0){ + SSTRINGS words; + int nb = str_splitline (line,' ',words); + if (nb >= 8){ + int inode; + sscanf (words.getitem(6)->get(),"%d",&inode); + const char *path = words.getitem(7)->get(); + // printf ("unix %d -> %s\n",inode,path); + (*glocal.unixs)[inode] = path; + } + } + return 0; + + + } + + + + static void printfds_onepid (int pid, TCPS &tcps, UNIXS &unixs) + { + glocal TCPS *tcps = &tcps; + glocal UNIXS *unixs = &unixs; + glocal int pid = pid; + glocal bool donepid = false; + SSTRING tmp; + tmp.setfromf ("/proc/%d/fd",pid); + (tmp.get()); + + if (!glocal.donepid){ + SSTRING tmp,exe; + tmp.setfromf ("/proc/%d/exe",glocal.pid); + my_readlink(tmp.get(),exe); + printf ("PID %d: %s\n",glocal.pid,exe.get()); + glocal.donepid = true; + } + char val[PATH_MAX]; + int len = readlink(path,val,sizeof(val)-1); + if (len > 0){ + val[len] = '\0'; + if (strncmp(val,"socket:[",8)==0){ + int inode = atoi(val+8); + TCPS::iterator it = glocal.tcps->find (inode); + if (it != glocal.tcps->end()){ + char ip1[20],ip2[20]; + unsigned long from_addr = it->second.from.addr; + unsigned long to_addr = it->second.to.addr; + ipnum_ip2a (ntohl(from_addr),ip1); + ipnum_ip2a (ntohl(to_addr),ip2); + printf ("\t%5s -> TCP %s:%d -> %s:%d\n",basename + ,ip1,it->second.from.port + ,ip2,it->second.to.port); + }else{ + UNIXS::iterator uit = glocal.unixs->find (inode); + if (uit != glocal.unixs->end()){ + printf ("\t%5s -> UNIX %s\n",basename,uit->second.get()); + }else{ + printf ("\t%5s -> %s\n",basename,val); + } + } + }else if (strncmp(val,"pipe:[",6)==0){ + }else{ + printf ("\t%5s -> %s\n",basename,val); + } + + } + + + } + + + + int main (int argc, char *argv[]) + { + glocal int pid = -1; + int ret = (argc,argv,"tcptool"); + + setproginfo ("printfds",PACKAGE_REV + ,MSG_U(I_PRINTFDS,"Print file handle and sockets for processes\n")); + setarg ('p',"pid",MSG_U(I_PID,"Process ID"),glocal.pid,false); + + + glocal TCPS tcps; + glocal UNIXS unixs; + printfds_readtcp (glocal.tcps); + printfds_readunix (glocal.unixs); + if (glocal.pid != -1){ + printfds_onepid (glocal.pid,glocal.tcps,glocal.unixs); + }else{ + ("/proc"); + + return false; + + + if (isdigit(basename[0])){ + int pid = atoi(basename); + printfds_onepid (pid,glocal.tcps,glocal.unixs); + } + + + } + return 0; + + + return ret; + } + + *** 1.33r5/linuxconf/modules/mouseconf/Makefile Thu Jun 27 15:21:36 2002 --- 1.33r5/linuxconf/modules/mouseconf/Makefile Thu Oct 14 11:33:06 2004 *************** *** 62,68 **** # $(CC) -c -o $@ $< -I/usr/include/kudzu/ XFmousereset: XFmousereset.c ! $(CC) -o $@ $< -L/usr/X11R6/lib/ -lX11 -lXext -lXxf86misc -lc LDIR=$(LIB_LINUXCONF)/lib/ DLDIR=$(LIB_LINUXCONF)/device_lists/ --- 62,68 ---- # $(CC) -c -o $@ $< -I/usr/include/kudzu/ XFmousereset: XFmousereset.c ! $(CC) -o $@ $< -L$(USRX11LIB) -lX11 -lXext -lXxf86misc -lc LDIR=$(LIB_LINUXCONF)/lib/ DLDIR=$(LIB_LINUXCONF)/device_lists/ *** 1.33r5/linuxconf/modules/Xkbdconf/Makefile Thu Jun 27 15:23:32 2002 --- 1.33r5/linuxconf/modules/Xkbdconf/Makefile Thu Oct 14 11:32:40 2004 *************** *** 39,45 **** # Test program XFconfig: XFconfig.c ! $(CC) -o $@ $< -I/usr/X11R6/include -L/usr/X11R6/lib -lxkbfile -lX11 -lxf86config -lm -g LDIR=$(LIB_LINUXCONF)/lib/ --- 39,45 ---- # Test program XFconfig: XFconfig.c ! $(CC) -o $@ $< -I/usr/X11R6/include -L$(USRX11LIB) -lxkbfile -lX11 -lxf86config -lm -g LDIR=$(LIB_LINUXCONF)/lib/ *** 1.33r5/linuxconf/modules/diskquotaconf/quota.cc Thu Feb 19 09:42:41 2004 --- 1.33r5/linuxconf/modules/diskquotaconf/quota.cc Thu Oct 21 10:52:34 2004 *************** *** 5,10 **** --- 5,11 ---- #include #include #include + #include #include #include "diskquotaconf.h" #include "diskquotaconf.m" *************** *** 465,470 **** --- 466,472 ---- } static FILE *fcmd = NULL; + static POPEN *pcmd = NULL; static bool fcmd_checked = false; /* Close the batch command file if open. *************** *** 472,478 **** */ void quota_closecmdfile() { ! if (fcmd != NULL){ fclose (fcmd); fcmd = NULL; } --- 474,491 ---- */ void quota_closecmdfile() { ! if (pcmd != NULL){ ! pcmd->closepipe(); ! while (pcmd->wait(10)>0){ ! char buf[1000]; ! while (pcmd->readerr(buf,sizeof(buf)-1)>0){ ! fprintf (stderr,"buferr=%s\n",buf); ! } ! } ! delete pcmd; ! pcmd = NULL; ! fcmd = NULL; ! }else if (fcmd != NULL){ fclose (fcmd); fcmd = NULL; } *************** *** 494,500 **** fcmd_checked = true; const char *bfile = linuxconf_getval (K_QUOTA,K_CMDFILE,NULL); if (bfile != NULL){ ! fcmd = xconf_fopen (bfile,"a"); } } int ret = -1; --- 507,524 ---- fcmd_checked = true; const char *bfile = linuxconf_getval (K_QUOTA,K_CMDFILE,NULL); if (bfile != NULL){ ! const char *pt = str_skip(bfile); ! if (pt[0] == '|'){ ! pcmd = new POPEN (pt+1); ! if (pcmd->isok()){ ! fcmd = pcmd->getfout(); ! }else{ ! delete pcmd; ! pcmd = NULL; ! } ! }else{ ! fcmd = xconf_fopen (pt,"a"); ! } } } int ret = -1; *************** *** 943,949 **** int quota_playcmd (const char *file) { int ret = -1; ! FILE *fin = xconf_fopen (file,"r"); if (fin != NULL){ QUOTA_SPEC spec; char device[PATH_MAX]; --- 967,974 ---- int quota_playcmd (const char *file) { int ret = -1; ! bool use_stdin = strcmp(file,"-")==0; ! FILE *fin = use_stdin ? stdin : xconf_fopen (file,"r"); if (fin != NULL){ QUOTA_SPEC spec; char device[PATH_MAX]; *************** *** 962,968 **** } } if (!feof(fin)) ret = -1; ! fclose (fin); } return ret; } --- 987,993 ---- } } if (!feof(fin)) ret = -1; ! if (!use_stdin) fclose (fin); } return ret; } *** 1.33r5/linuxconf/rpmfiles/rpm.spec-files Wed Apr 14 17:43:00 2004 --- 1.33r5/linuxconf/rpmfiles/rpm.spec-files Fri Oct 29 11:57:42 2004 *************** *** 56,61 **** --- 56,62 ---- /usr/bin/pidsocket /usr/bin/visualuntar /usr/lib/linuxconf/help.eng/shellmod-msg* + /usr/bin/printfds %files gui -f guifiles %defattr(-,root,root) *** 1.33r5/linuxconf/userconf/users.tlcc Wed Sep 8 13:26:34 2004 --- 1.33r5/linuxconf/userconf/users.tlcc Tue Oct 12 11:27:25 2004 *************** *** 831,836 **** --- 831,837 ---- if (ret == -1){ xconf_error (MSG_U(E_FAILCREATE,"Can't create user account")); }else if(createdir){ + usr->sethome (NULL,group,false,*this); chmod (usr->wrkdir.get(),group_getcreateperm(group)); } } *** 1.33r5/linuxconf/vpop3d/vdeliver.cc Tue Aug 24 16:05:17 2004 --- 1.33r5/linuxconf/vpop3d/vdeliver.cc Tue Sep 28 15:25:30 2004 *************** *** 2,7 **** --- 2,8 ---- #include #include #include + #include #include #include #include *************** *** 267,273 **** Return -1 if any error. */ ! static int vdeliver_send (const char *adr, const char *from, FILE *fin) { int ret = -1; if (vdeliver_validadr(adr)){ --- 268,278 ---- Return -1 if any error. */ ! static int vdeliver_send ( ! const char *adr, ! const char *from, ! FILE *fin, ! const char *header) // Optional header to copy first { int ret = -1; if (vdeliver_validadr(adr)){ *************** *** 287,292 **** --- 292,298 ---- if (fout == NULL){ syslog (LOG_ERR,"vdeliver_send: (try %d) Can't talk back to sendmail for user %s (%m)",i,adr); }else{ + fputs (header,fout); ret = vdeliver_copy (fin,fout); int ret2 = pclose(fout); if (ret2 == -1) ret = -1; *************** *** 310,315 **** --- 316,330 ---- return ret; } + static int vdeliver_send ( + const char *adr, + const char *from, + FILE *fin) + { + return vdeliver_send (adr,from,fin,""); + } + + static int vdeliver_reply ( VDEV_CTX &ctx, const char *user, *************** *** 322,330 **** fprintf (stderr,"can't open file %s\n",path); syslog (LOG_ERR,"Can't open file %s (%m)",path); }else{ ! char email[PATH_MAX]; snprintf (email,sizeof(email)-1,"%s@%s",user,domain); ! ret = vdeliver_send (ctx.from,email,fin); fclose (fin); } return ret; --- 337,346 ---- fprintf (stderr,"can't open file %s\n",path); syslog (LOG_ERR,"Can't open file %s (%m)",path); }else{ ! char email[PATH_MAX],header[PATH_MAX]; snprintf (email,sizeof(email)-1,"%s@%s",user,domain); ! snprintf (header,sizeof(header)-1,"to: %s\n",ctx.from); ! ret = vdeliver_send (ctx.from,email,fin,header); fclose (fin); } return ret; *************** *** 406,411 **** --- 422,439 ---- } if (stat(path,&st)!=-1){ // We check if we have already answered this + // The db file may also contain an activation period in the + // form: + // #date: start_date end_date + // The dates are in the following format + // yyyy/mm/dd + char datenow[12]; + { + time_t now = time(NULL); + struct tm *t = localtime (&now); + snprintf (datenow,sizeof(datenow)-1,"%04d/%02d/%02d" + ,t->tm_year + 1900,t->tm_mon+1,t->tm_mday); + } int i; for (i=0; i<10; i++){ FILE *f = fopen (path_list,"r+"); *************** *** 417,430 **** rewind (f); char line[1000]; bool found = false; while (fgets(line,sizeof(line)-1,f)!=NULL){ strip_end (line); if (strcasecmp(line,ctx.head.from.adr)==0){ found = true; break; } } ! if (!found){ fseek (f,ftell(f),SEEK_SET); fprintf (f,"%s\n",ctx.head.from.adr); // We close immediatly, so if the reply takes --- 445,476 ---- rewind (f); char line[1000]; bool found = false; + bool active = true; while (fgets(line,sizeof(line)-1,f)!=NULL){ strip_end (line); if (strcasecmp(line,ctx.head.from.adr)==0){ found = true; break; + }else if (strncmp(line,"#date ",6)==0){ + char *pt = line+6; + while (isspace(*pt)) pt++; + char *start = pt; + while (*pt > ' ') pt++; + if (isspace(*pt)) *pt++ = '\0'; + while (isspace(*pt)) pt++; + char *end = pt; + syslog (LOG_ERR,"Compare :%s: :%s: :%s:\n",datenow,start,end); + if (strcmp(start,datenow)>0){ + active = false; + break; + }else if (isdigit(end[0]) + && strcmp(end,datenow) < 0){ + active = false; + break; + } } } ! if (active && !found){ fseek (f,ftell(f),SEEK_SET); fprintf (f,"%s\n",ctx.head.from.adr); // We close immediatly, so if the reply takes *** 1.33r5/linuxconf/tlmp/tlmpdia/tlmpdia.h Wed Jul 28 20:43:19 2004 --- 1.33r5/linuxconf/tlmp/tlmpdia/tlmpdia.h Fri Oct 29 13:57:11 2004 *************** *** 190,195 **** --- 190,197 ---- virtual _F_diapopup1_ok( )=0; }; + void *forktmp_mapshare (int len); + void forktmp_unmap (void *, int len); template < class T> class SHAREMEM_MMAP{ *** 1.33r5/linuxconf/tlmp/tlmplib/tlmpprogram.cc Sun Feb 29 23:14:59 2004 --- 1.33r5/linuxconf/tlmp/tlmplib/tlmpprogram.cc Thu Nov 4 12:52:24 2004 *************** *** 202,218 **** ,priv->progname.get(),priv->version.get() ,priv->desc.get()); printf ("\n"); for (int i=0; iargs.getnb(); i++){ TLMPARG *arg = priv->args.getitem(i); if (arg->type == TLMPARG::ARG_GROUP){ ! printf ("\n%s\n",arg->desc); }else{ ! printf (" -%c --%s: %s %s\n",arg->letter,arg->name,arg->desc ! ,arg->mandatory ? MSG_U(I_MANDATORY,"(Mandatory)") : ""); if (!arg->mandatory){ // Print the default value, using the value in the variable if (arg->defval.is_filled()){ ! printf (" %s: %s\n",MSG_U(I_DEFVAL,"Default value") ,arg->defval.get()); } } --- 202,244 ---- ,priv->progname.get(),priv->version.get() ,priv->desc.get()); printf ("\n"); + int maxlen = 0; + for (int i=0; iargs.getnb(); i++){ + TLMPARG *arg = priv->args.getitem(i); + if (arg->type != TLMPARG::ARG_GROUP){ + int len = strlen(arg->name); + if (len > maxlen) maxlen = len; + } + } + int fill = maxlen + 9; for (int i=0; iargs.getnb(); i++){ TLMPARG *arg = priv->args.getitem(i); if (arg->type == TLMPARG::ARG_GROUP){ ! printf ("\n%s\n\n",arg->desc); }else{ ! if (isalpha(arg->letter)){ ! printf (" -%c",arg->letter); ! }else{ ! fputs (" ",stdout); ! } ! SSTRINGS lines; ! int nb = str_cnv2lines(arg->desc,lines); ! int len = printf (" --%s ",arg->name); ! int start = 1; ! int fillone = fill - (len+4); ! if (arg->mandatory){ ! printf ("%*s%s\n",fillone,"",MSG_U(I_MANDATORY,"(Mandatory)")); ! start = 0; ! }else{ ! printf ("%*s%s\n",fillone,"",lines.getitem(0)->get()); ! } ! for (int j=start; jget()); ! } if (!arg->mandatory){ // Print the default value, using the value in the variable if (arg->defval.is_filled()){ ! printf ("%*s%s: %s\n",fill,"",MSG_U(I_DEFVAL,"Default value") ,arg->defval.get()); } } *** 1.33r5/linuxconf/tlmp/tlmplib/tlmplib.comp Fri Aug 27 16:13:06 2004 --- 1.33r5/linuxconf/tlmp/tlmplib/tlmplib.comp Thu Nov 4 12:55:21 2004 *************** *** 118,124 **** parsing. ! Single letter option --- 118,129 ---- parsing. ! Single letter option. If the option is ! either a space or a -, it means there is ! no single letter option. The user must ! use the long one. You generally do this ! for important/dangourous options (delete ! something). *************** *** 146,152 **** parsing. ! Single letter option --- 151,163 ---- parsing. ! Single letter option.If the option is ! either a space or a -, it means there is ! no single letter option. The user must ! use the long one. You generally do this ! for important/dangourous options (delete ! something). ! *************** *** 182,188 **** the user completly override them. ! Single letter option --- 193,205 ---- the user completly override them. ! Single letter option. If the option is ! either a space or a -, it means there is ! no single letter option. The user must ! use the long one. You generally do this ! for important/dangourous options (delete ! something). ! *************** *** 210,216 **** parsing. ! Single letter option --- 227,239 ---- parsing. ! Single letter option. If the option is ! either a space or a -, it means there is ! no single letter option. The user must ! use the long one. You generally do this ! for important/dangourous options (delete ! something). ! *************** *** 238,244 **** parsing. ! Single letter option --- 261,273 ---- parsing. ! Single letter option. If the option is ! either a space or a -, it means there is ! no single letter option. The user must ! use the long one. You generally do this ! for important/dangourous options (delete ! something). ! *** 1.33r5/linuxconf/tlmp/tlmpnet/Makefile Tue Sep 23 10:26:44 2003 --- 1.33r5/linuxconf/tlmp/tlmpnet/Makefile Thu Oct 28 11:34:44 2004 *************** *** 3,11 **** #LOCAL_INSTALL=local_install OBJS=http.o netevent.o popenhandler.o tcpconnect.o tcpserver.o \ ! tlmpnet.o _dict.o OBJSS=http.os netevent.os popenhandler.os tcpconnect.os \ ! tcpserver.os tlmpnet.os _dict.os all: $(CURDIR).a $(OBJSS) --- 3,11 ---- #LOCAL_INSTALL=local_install OBJS=http.o netevent.o popenhandler.o tcpconnect.o tcpserver.o \ ! tlmpepoll.o tlmpnet.o _dict.o OBJSS=http.os netevent.os popenhandler.os tcpconnect.os \ ! tlmpepoll.os tcpserver.os tlmpnet.os _dict.os all: $(CURDIR).a $(OBJSS) *************** *** 14,28 **** proto: tlproto -co -f$(CURDIR).p -c+ -f$(CURDIR).pm *cc \ -btlmpnet.h+tlmpnet.pm -bnetevent.tlcc+tlmpnet.pm \ ! -bpopenhandler.tlcc+tlmpnet.pm local_clean: rm -f *.o *.bak *~ $(CURDIR).a core *.old tlmpnet.o: tlmpnet.cc tlmpnet.h # Test samples: samples.obt $(GPPLINK) samples.obt -o /tmp/x -llinuxconf -lncurses --- 14,39 ---- proto: tlproto -co -f$(CURDIR).p -c+ -f$(CURDIR).pm *cc \ -btlmpnet.h+tlmpnet.pm -bnetevent.tlcc+tlmpnet.pm \ ! -bpopenhandler.tlcc+tlmpnet.pm \ ! -btlmpepoll.cc+tlmpnet.pm local_clean: rm -f *.o *.bak *~ $(CURDIR).a core *.old tlmpnet.o: tlmpnet.cc tlmpnet.h + tlmpepoll.o: tlmpepoll.cc has_epoll-tmp.bak + + tlmpepoll.os: tlmpepoll.cc has_epoll-tmp.bak + + has_epoll-tmp.bak: + sh has_epoll.sh + # Test samples: samples.obt $(GPPLINK) samples.obt -o /tmp/x -llinuxconf -lncurses + tlmpepoll: tlmpepoll.obt + $(GPPLINK) tlmpepoll.obt -o /tmp/x + *** 1.33r5/linuxconf/tlmp/tlmpnet/tlmpnet.h Tue Mar 16 14:56:55 2004 --- 1.33r5/linuxconf/tlmp/tlmpnet/tlmpnet.h Mon Nov 8 15:27:30 2004 *************** *** 16,21 **** --- 16,64 ---- }; + // TLMPEPOLL is a wrapper to allow usage of epoll on system without it + // using select(2) as needed + enum TLMPEPOLL_CTL{ + TLMPEPOLL_CTL_ADD, + TLMPEPOLL_CTL_DEL, + TLMPEPOLL_CTL_MOD + }; + + #define TLMPEPOLL_IN 1 + #define TLMPEPOLL_OUT 2 + + struct TLMPEPOLL_EVENT{ + int events; // TLMPEPOLL_IN or OUT + int fd; + int id; + void *data; + }; + + class TLMPEPOLL{ + class TLMPEPOLL_private *priv; + public: + /*~PROTOBEG~ TLMPEPOLL */ + public: + TLMPEPOLL (void); + void ctl (TLMPEPOLL_CTL op, int fd, int events); + private: + void ctl_select (TLMPEPOLL_CTL op, + int fd, + int events); + public: + void setdata (int fd, void *data); + void setid (int fd, int id); + int wait (TLMPEPOLL_EVENT events[], + int nbevents, + int timeout); + private: + int wait_select (TLMPEPOLL_EVENT events[], + int nbevents, + int timeout); + public: + ~TLMPEPOLL (void); + /*~PROTOEND~ TLMPEPOLL */ + }; struct TCPCONNECT_INFO{ const char *host; *************** *** 143,148 **** --- 186,194 ---- int iter_init(); int iter_next(void *&data); int iter_next(); + bool is_blocked(); + bool is_blocked(int handle, unsigned long &size, long long &lastwrite); + bool setlisten (int handle, bool on); #define _F_TCPSERVER_newclient(x) void x newclient(int no, unsigned long from, bool &endclient, bool &endserver, TCPSERVER_INFO &info) virtual _F_TCPSERVER_newclient( )=0; #define _F_TCPSERVER_endclient(x) void x endclient(int no, bool &endserver, TCPSERVER_INFO &info) *************** *** 168,176 **** --- 214,226 ---- int time_out); TCPSERVER (_F_TCPSERVER&c, int port, int time_out); private: + void accept_con (int i, + bool&endserver, + TLMPEPOLL *ep); bool dispatch (int select_ret, fd_set&set); void endsession (int cli); public: + void forget_epoll (void); int getnbclients (void)const; private: void init (_F_TCPSERVER&c, *************** *** 179,188 **** --- 229,251 ---- int time_out); public: void inject (int client, ARRAY_OBJ *data); + bool is_blocked (int fd, + unsigned long &size, + long long &last_write); + int iter_init (void *&data); + int iter_init (void); + int iter_next (void *&data); + int iter_next (void); int listen (const char *bindaddr, const char *port); int listen (const char *port); int listen (int port); void loop (void); + private: + void process_data (int fd, bool&endserver); + public: + bool process_epoll (TLMPEPOLL&ep, + TLMPEPOLL_EVENT events[], + int nbevent); void process_select (int select_ret, fd_set&set, long timeout); *************** *** 193,199 **** --- 256,264 ---- int sendto (int client, const void *buf, int len); int sendtof (int client, const char *ctl, ...); void setmaxclients (int n); + bool setnonblock (bool mode, int bufsize); bool setrawmode (bool mode); + void setup_epoll (TLMPEPOLL&ep); int setup_select (fd_set&set, int max_handle); virtual ~TCPSERVER (void); /*~PROTOEND~ TCPSERVER */ *************** *** 241,246 **** --- 306,312 ---- public: NETEVENT_MANAGER (_F_NETEVENT_MANAGER&c); void add (HANDLE_SELECTS&sels); + void add (TCPSERVER&tcp); void loop (int timeout); private: void loopgen (int timeout, *** 1.33r5/linuxconf/tlmp/tlmpnet/samples.tlcc Tue Dec 16 19:14:59 2003 --- 1.33r5/linuxconf/tlmp/tlmpnet/samples.tlcc Mon Nov 8 15:21:48 2004 *************** *** 369,374 **** --- 369,543 ---- } + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + static long long getnow () + { + struct timeval tv; + gettimeofday (&tv,NULL); + return tv.tv_sec *(long long)1000000 + tv.tv_usec; + } + using namespace std; + + static int tcp_server( + const char *port) + { + struct sockaddr_in sin; + sin.sin_family = AF_INET; + struct servent *s = getservbyname(port,"tcp"); + if (s != NULL){ + sin.sin_port = s->s_port; + }else{ + sin.sin_port = htons (atoi(port)); + } + memset (&sin.sin_addr,0,sizeof(sin.sin_addr)); + int listen_handle = -1; + for (int i=0; i<5; i++){ + listen_handle = socket (AF_INET, SOCK_STREAM, 0); + int opt = 1; + if (listen_handle == -1){ + fprintf (stderr,"listen_handle %d(%s)\n" + ,errno + ,strerror(errno)); + }else if (setsockopt(listen_handle,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))==-1){ + fprintf (stderr,"Can't set socket option SO_REUSEADDR (%s)\n" + ,strerror (errno)); + }else if (bind (listen_handle,(struct sockaddr *) &sin, sizeof (sin)) == -1){ + fprintf (stderr,"bind %d(%s)\n",errno + ,strerror(errno)); + }else if (listen (listen_handle,35) == -1){ + fprintf (stderr,"listen %d(%s)\n",errno + ,strerror(errno)); + break; + }else{ + fprintf (stderr,"bind ok\n"); + break; + } + close (listen_handle); + listen_handle = -1; + if (i < 5){ + fprintf (stderr,"Sleeping 5 seconds\n"); + sleep (5); + } + } + return listen_handle; + } + + struct SOFAR{ + int sofar; + int size; + SOFAR(){ + sofar = size = 0; + } + SOFAR(int _size){ + sofar = 0; + size = _size; + } + bool send (int fd){ + int len = size - sofar; + char buf[len]; + memset (buf,'a',len); + buf[len-1] = '\n'; + int rest = write (fd,buf,len); + sofar += rest; + return sofar == size; + } + }; + + static void sample_epoll() + { + TLMPEPOLL ep; + int listen_handle = tcp_server ("8001"); + if (listen_handle != -1){ + ep.ctl (TLMPEPOLL_CTL_ADD,listen_handle,TLMPEPOLL_IN); + ep.setdata (listen_handle,(void*)"listen_handle"); + map mp; + long recsize = 0; + long recpkts = 0; + long long start = getnow(); + while (1){ + TLMPEPOLL_EVENT evs[10]; + int nb = ep.wait (evs,10,15000); + if (nb == 0){ + fprintf (stderr,"Timeout\n"); + }else{ + // fprintf (stderr,"nb=%d\n",nb); + TLMPEPOLL_EVENT *pt = evs; + for (int i=0; ifd; + // fprintf (stderr,"Event fd=%d data=%s\n",fd,(char*)pt->data); + if (fd == listen_handle){ + struct sockaddr_in sin; + socklen_t addrlen=sizeof(sin); + int newfd = accept (listen_handle,(struct sockaddr*)&sin,&addrlen); + fprintf (stderr,"New connection %d\n",newfd); + if (newfd == -1){ + fprintf (stderr,"Accept failed\n"); + }else{ + char tmp[100]; + snprintf (tmp,sizeof(tmp)-1,"handle %d",newfd); + ep.ctl (TLMPEPOLL_CTL_ADD,newfd,TLMPEPOLL_IN); + ep.setdata (newfd,strdup(tmp)); + fcntl (newfd,F_SETFL,O_NONBLOCK); + } + }else{ + if ((pt->events & TLMPEPOLL_IN) != 0){ + char buf[101]; + int len = read (fd,buf,100); + // fprintf (stderr,"read %d -> %d\n",fd,len); + if (len <= 0){ + ep.ctl (TLMPEPOLL_CTL_DEL,fd,0); + close (fd); + }else{ + recsize += len; + recpkts++; + buf[len] = '\0'; + int size = atoi(buf); + if (size == 0){ + len = snprintf (buf,sizeof(buf)-1,"Rec %d bytes\n",len); + write (fd,buf,len); + }else{ + mp[fd] = SOFAR(size); + if (mp[fd].send(fd)){ + ep.ctl (TLMPEPOLL_CTL_MOD,fd,TLMPEPOLL_IN); + }else{ + ep.ctl (TLMPEPOLL_CTL_MOD,fd,TLMPEPOLL_IN|TLMPEPOLL_OUT); + } + } + } + } + if ((pt->events & TLMPEPOLL_OUT) != 0){ + if (mp[fd].send(fd)){ + ep.ctl (TLMPEPOLL_CTL_MOD,fd,TLMPEPOLL_IN); + } + } + } + } + } + if (recpkts > 10000){ + long long end = getnow(); + long long diff = end - start; + printf ("%ld pkts %ld bytes en %ld.%06ld\n" + ,recpkts,recsize,(long)(diff/1000000) + ,(long)(diff%1000000)); + start = end; + recpkts = 0; + recsize = 0; + } + } + } + } + + int main (int argc, char *argv[]) *************** *** 385,390 **** --- 554,560 ---- "/tmp/x echo port\n" "/tmp/x bench host port nbprocess nbsessions nblines\n" "/tmp/x http url realm user password\n" + "/tmp/x epoll (listen on port 8001)\n" ); *************** *** 425,430 **** --- 595,602 ---- }else{ samples_http(argv[1],argv[2],argv[3],argv[4]); } + }else if (strcmp(argv[0],"epoll")==0){ + sample_epoll(); }else{ usage(); } *** 1.33r5/linuxconf/tlmp/tlmpnet/tcpconnect.tlcc Fri May 7 11:12:48 2004 --- 1.33r5/linuxconf/tlmp/tlmpnet/tcpconnect.tlcc Wed Nov 3 16:32:43 2004 *************** *** 296,303 **** PRIVATE void TCPCONNECT::process_lines() { ! char buf[8192]; int len = read (priv->fd,buf,sizeof(buf)-1); if (len <= 0){ close (); priv->end = true; --- 296,304 ---- PRIVATE void TCPCONNECT::process_lines() { ! char buf[32*1024+1]; int len = read (priv->fd,buf,sizeof(buf)-1); + // fprintf (stderr,"TCPCONNECT process_lines len=%d rawmode=%d\n",len,priv->rawmode); if (len <= 0){ close (); priv->end = true; *************** *** 445,453 **** bool _F_tcpconnect::setrawmode(bool mode) { ! bool ret = priv->rawmode; ! priv->rawmode = mode; ! return ret; } void _F_tcpconnect::set_timeout(int seconds) --- 446,455 ---- bool _F_tcpconnect::setrawmode(bool mode) { ! return priv->conn->setrawmode (mode); ! //bool ret = priv->rawmode; ! //priv->rawmode = mode; ! //return ret; } void _F_tcpconnect::set_timeout(int seconds) *** 1.33r5/linuxconf/tlmp/tlmpnet/tcpserver.tlcc Wed Jul 14 10:33:02 2004 --- 1.33r5/linuxconf/tlmp/tlmpnet/tcpserver.tlcc Mon Nov 8 16:26:46 2004 *************** *** 1,6 **** --- 1,7 ---- #include #include #include + #include #include #include #include *************** *** 12,18 **** #include #include #include - //#include #include "tlmpnet.h" #include "tlmpnet.m" #include "../tlmplib/tlmplib.h" --- 13,18 ---- *************** *** 80,125 **** && strcmp(portstr,INETD_PORT)!=0){ int port = tcpserver_getport(portstr); if (port != -1){ ! /* Il faut creer le socket original pour la connection */ ! struct hostent *h; ! char myhost[PATH_MAX]; ! const char *adr = bindaddr; ! if (bindaddr == NULL){ ! gethostname (myhost, sizeof(myhost)); ! h = (struct hostent *) gethostbyname(myhost); ! adr = myhost; ! }else{ ! h = (struct hostent *) gethostbyname(bindaddr); } ! if (h == NULL){ ! tlmp_error ("gethostbyname(%s) failed\n",adr); ! }else{ ! struct sockaddr_in sin; ! sin.sin_family = h->h_addrtype; ! memcpy (&sin.sin_addr,h->h_addr, h->h_length); ! sin.sin_port = htons(port); ! ! int i; ! for (i=0; i<5; i++){ ! int fd = socket (AF_INET, SOCK_STREAM, 0); ! if (bindaddr == NULL) sin.sin_addr.s_addr = INADDR_ANY; ! int opt = 1; ! if (fd != -1){ ! if (reuseadr ! && setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))==-1){ ! fprintf (stderr,"Can't set socket option SO_REUSEADDR (%s)\n" ! ,strerror (errno)); ! }else if (bind (fd,(struct sockaddr *) &sin, sizeof (sin)) == -1){ ! }else if (::listen (fd,35) == -1){ ! break; ! }else{ ! ret = fd; ! break; ! } ! close (fd); } ! if (i < 5) sleep (i*5); } } } }else{ --- 80,116 ---- && strcmp(portstr,INETD_PORT)!=0){ int port = tcpserver_getport(portstr); if (port != -1){ ! struct sockaddr_in sin; ! sin.sin_family = AF_INET; ! memset (&sin.sin_addr,0,sizeof(sin.sin_addr)); ! sin.sin_port = htons(port); ! if (bindaddr != NULL){ ! struct hostent *h = gethostbyname(bindaddr); ! if (h == NULL){ ! tlmp_error ("TCPSERVER: gethostbyname(%s) failed. Using 0.0.0.0\n",bindaddr); ! }else{ ! memcpy (&sin.sin_addr,h->h_addr, h->h_length); ! } } ! for (int i=0; i<5; i++){ ! int fd = socket (AF_INET, SOCK_STREAM, 0); ! if (bindaddr == NULL) sin.sin_addr.s_addr = INADDR_ANY; ! int opt = 1; ! if (fd != -1){ ! if (reuseadr ! && setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))==-1){ ! fprintf (stderr,"Can't set socket option SO_REUSEADDR (%s)\n" ! ,strerror (errno)); ! }else if (bind (fd,(struct sockaddr *) &sin, sizeof (sin)) == -1){ ! }else if (::listen (fd,35) == -1){ ! break; ! }else{ ! ret = fd; ! break; } ! close (fd); } + if (i < 5) sleep (i*5); } } }else{ *************** *** 137,147 **** --- 128,180 ---- return ret; } + struct TCPSERVER_BLOCKBUF{ + void *data; + int len; + int off; // Written so far + void init (const void *_data, int _off, int _len){ + off = _off; + len = _len; + data = malloc(len); + if (data != NULL){ + memcpy (data,_data,_len); + }else{ + len = 0; + } + } + TCPSERVER_BLOCKBUF (const void *_data, int _len){ + init (_data,0,_len); + } + TCPSERVER_BLOCKBUF (const TCPSERVER_BLOCKBUF &s){ + init (s.data,s.off,s.len); + } + ~TCPSERVER_BLOCKBUF(){ + free (data); + } + unsigned getremain() const { + return len - off; + } + }; + struct TCPSERVER_CLIENT{ SSTRING *s; // Input buffer int state; ARRAY_OBJ *data; bool rawmode; + vector blocks; + bool listening; + struct timeval lastwrite; // Allows us to track dead (or very slow) + // connection + void reset(){ + delete s; + delete data; + for (unsigned i=0; ictl (TLMPEPOLL_CTL_MOD,client,TLMPEPOLL_IN|TLMPEPOLL_OUT); ! } ! c.blocks.push_back (new TCPSERVER_BLOCKBUF(data,len)); ! } }; *************** *** 218,223 **** --- 267,295 ---- void *data; return iter_next (data); } + PUBLIC int TCPSERVER::iter_init (void *&data) + { + return priv->c->iter_init(data); + } + PUBLIC int TCPSERVER::iter_init () + { + void *data; + return iter_init (data); + } + PUBLIC int TCPSERVER::iter_next (void *&data) + { + return priv->c->iter_next (data); + } + PUBLIC int TCPSERVER::iter_next () + { + void *data; + return iter_next (data); + } + PUBLIC bool TCPSERVER::is_blocked (int fd, unsigned long &size, long long &last_write) + { + return priv->c->is_blocked (fd,size,last_write); + } + /* Record the IDLE maximum time for a connection */ *************** *** 250,255 **** --- 322,342 ---- priv->rawmode = mode; return ret; } + /* + Set the sockets to non-blocking (for writting). + */ + PUBLIC bool TCPSERVER::setnonblock ( + bool mode, + int bufsize) // TCPSERVER transparently buf the send/sendto request + // when they block so it is transparent to the caller + // But if there is too much buffer to buf, some connection + // will be terminated. + { + bool ret = priv->nonblock; + priv->nonblock = mode; + priv->nonblock_bufsize = bufsize; + return ret; + } /* This is called when the server is idle for a given timeout *************** *** 271,277 **** int _F_TCPSERVER::sendto(int client,const void *buf, int len) { ! return write (client,buf,len); } /* Send a formatted message to the given client --- 358,391 ---- int _F_TCPSERVER::sendto(int client,const void *buf, int len) { ! int ret = -1; ! TCPSERVER_CLIENT &c = priv->tbc[client]; ! if (c.blocks.size() > 0){ ! // We can't write now, there is already some data in the buffer ! // waiting to be sent to the client ! priv->keepbuf (client,(void*)buf,len); ! ret = len; ! }else{ ! while (1){ ! int written = write (client,buf,len); ! // fprintf (stderr,"client %d written %d len %d errno %d(%s)\n",client,written,len,errno,strerror(errno)); ! if (written == -1 && errno == EAGAIN) written = 0; ! if (written == len){ ! ret = len; ! break; ! }else if (written >= 0){ ! gettimeofday (&c.lastwrite,NULL); ! priv->keepbuf (client,(void*)((char*)buf+written),len-written); ! ret = len; ! break; ! }else if (errno != EINTR){ ! // Some error, not EINTR, better to leave ! break; ! } ! // Loop because we were interrupted ! } ! } ! return ret; } /* Send a formatted message to the given client *************** *** 361,384 **** void _F_TCPSERVER::forgetclient() { int cli = priv->curclient; ! //priv->cmd->forgetcli (cli); ! delete priv->tbc[cli].s; ! delete priv->tbc[cli].data; ! priv->tbc[cli].s = NULL; ! priv->tbc[cli].data = NULL; priv->nbclients--; } /* Close one client. */ void _F_TCPSERVER::closeclient(int cli) { ! delete priv->tbc[cli].s; ! delete priv->tbc[cli].data; ! priv->tbc[cli].s = NULL; ! priv->tbc[cli].data = NULL; ! priv->nbclients--; ! ::close (cli); } /* --- 475,497 ---- void _F_TCPSERVER::forgetclient() { int cli = priv->curclient; ! TCPSERVER_CLIENT &c = priv->tbc[cli]; ! c.reset(); priv->nbclients--; + if (priv->ep != NULL) priv->ep->ctl (TLMPEPOLL_CTL_DEL,cli,0); } /* Close one client. */ void _F_TCPSERVER::closeclient(int cli) { ! if (cli >= 0 && (unsigned)cli < priv->tbc.size()){ ! TCPSERVER_CLIENT &c = priv->tbc[cli]; ! c.reset(); ! priv->nbclients--; ! ::close (cli); ! if (priv->ep != NULL) priv->ep->ctl (TLMPEPOLL_CTL_DEL,cli,0); ! } } /* *************** *** 389,394 **** --- 502,536 ---- return priv->nbclients; } /* + Return true if the connection output is blocked (stuff written + using send/sendto() has not been completed yet). + */ + bool _F_TCPSERVER::is_blocked(int handle, unsigned long &size, long long &lastwrite) + { + TCPSERVER_CLIENT &c = priv->tbc[handle]; + int nb = c.blocks.size(); + bool ret = nb > 0; + size = 0; + lastwrite = 0; + if (nb > 0){ + lastwrite = (long long)c.lastwrite.tv_sec *1000000 + + c.lastwrite.tv_usec; + for (int i=0; igetremain(); + } + } + return ret; + } + /* + Return true if the current (active) connection output is blocked. + */ + bool _F_TCPSERVER::is_blocked() + { + unsigned long size; + long long lastwrite; + return is_blocked (priv->curclient,size,lastwrite); + } + /* Return the number of socket with data to process */ int _F_TCPSERVER::getnbpending() *************** *** 396,401 **** --- 538,557 ---- return priv->nbpending; } + bool _F_TCPSERVER::setlisten (int handle, bool on) + { + TCPSERVER_CLIENT &c = priv->tbc[handle]; + bool ret = c.listening; + c.listening = on; + if (on != ret && priv->ep != NULL){ + int op = on ? TLMPEPOLL_IN : 0; + if (c.blocks.size() > 0) op |= TLMPEPOLL_OUT; + priv->ep->ctl (TLMPEPOLL_CTL_MOD,handle,op); + } + return ret; + } + + PUBLIC int TCPSERVER::listen ( const char *bindaddr, const char *port) *************** *** 409,414 **** --- 565,574 ---- if (fd != -1){ priv->fds.push_back(fd); priv->ports.push_back(port); + if (priv->ep != NULL){ + priv->ep->ctl (TLMPEPOLL_CTL_ADD,fd,TLMPEPOLL_IN); + priv->ep->setid (fd,priv->id_listen); + } } return fd; } *************** *** 467,481 **** PRIVATE void _F_TCPSERVER::endsession(int cli) { ! if (cli >= 0 && (unsigned)cli < priv->tbc.size()){ ! close (cli); ! TCPSERVER_CLIENT &ptc = priv->tbc[cli]; ! delete ptc.s; ! delete ptc.data; ! ptc.s = NULL; ! ptc.data = NULL; ! priv->nbclients--; ! } } PRIVATE void TCPSERVER::endsession(int cli) --- 627,633 ---- PRIVATE void _F_TCPSERVER::endsession(int cli) { ! closeclient (cli); } PRIVATE void TCPSERVER::endsession(int cli) *************** *** 496,518 **** PUBLIC void TCPSERVER::loop() { if (priv->fds.size() > 0){ bool endserver = false; priv->since = 0; while (!endserver){ ! fd_set set; ! FD_ZERO (&set); ! int maxhandle = setup_select (set,0); ! struct timeval tm; ! tm.tv_sec = priv->time_out; ! tm.tv_usec = 0; ! int ok = select (maxhandle+1,&set,NULL,NULL ! ,priv->time_out == -1 ? NULL : &tm); ! if (ok == -1){ ! break; }else{ ! endserver = dispatch(ok,set); } } } } --- 648,670 ---- PUBLIC void TCPSERVER::loop() { if (priv->fds.size() > 0){ + fd_set empty; + FD_ZERO (&empty); bool endserver = false; priv->since = 0; + TLMPEPOLL ep; + setup_epoll (ep); while (!endserver){ ! TLMPEPOLL_EVENT events[10]; ! int nbev = ep.wait (events,10,priv->time_out); ! if (nbev == -1) break; ! if (nbev == 0){ ! endserver = dispatch (0,empty); }else{ ! endserver = process_epoll (ep,events,nbev); } } + forget_epoll(); } } *************** *** 530,535 **** --- 682,692 ---- ptc.state = 0; ptc.data = data; ptc.rawmode = priv->rawmode; + ptc.listening = true; + if (priv->ep != NULL){ + priv->ep->ctl (TLMPEPOLL_CTL_ADD,client,TLMPEPOLL_IN); + priv->ep->setid (client,priv->id_data); + } } } *************** *** 539,550 **** } PRIVATE bool TCPSERVER::dispatch (int select_ret, fd_set &set) { - TCPSERVER_INFO info; bool endserver = false; if (select_ret == 0){ priv->since += priv->time_out; priv->c->idle (priv->since,endserver,info); // Even if ok == 0, we must cycle through readnext() // to detect ended client (timeout) --- 696,829 ---- } + PRIVATE void TCPSERVER::accept_con ( + int i, + bool &endserver, + TLMPEPOLL *ep) + { + struct sockaddr_in sacc; + socklen_t size=sizeof(sacc); + int newclient = accept (priv->fds[i],(struct sockaddr *)&sacc,&size); + if (newclient != -1 && (unsigned)newclient < priv->maxclient){ + priv->allocclient(newclient); + if (priv->nonblock) fcntl(newclient,F_SETFL,O_NONBLOCK); + { + TCPSERVER_CLIENT &ptc = priv->tbc[newclient]; + priv->nbclients++; + ptc.s = new SSTRING; + ptc.state = 0; + ptc.data = NULL; + ptc.rawmode = priv->rawmode; + ptc.listening = true; + } + priv->curclient = newclient; + unsigned long addr = ntohl(sacc.sin_addr.s_addr); + #if 0 + struct sockaddr_in adr; + unsigned int len = sizeof(adr); + if (getpeername (newclient,(struct sockaddr*)&adr,&len) != -1){ + addr = ntohl(adr.sin_addr.s_addr); + } + #endif + bool endclient = false; + TCPSERVER_INFO info; + info.data = NULL; + info.port = priv->ports[i].c_str(); + priv->c->newclient (newclient,addr,endclient,endserver,info); + { + TCPSERVER_CLIENT &ptc = priv->tbc[newclient]; + ptc.data = info.data; + } + if (endclient){ + endsession(newclient); + }else{ + //priv->cmd->set_timeout (newclient,priv->time_out); + if (ep != NULL){ + ep->ctl (TLMPEPOLL_CTL_ADD,newclient,TLMPEPOLL_IN); + ep->setid (newclient,priv->id_data); + } + } + } + } + + PRIVATE void TCPSERVER::process_data ( + int fd, + bool &endserver) + { + bool is_timeout = false; // Not done + TCPSERVER_CLIENT &ptc = priv->tbc[fd]; + if (ptc.s != NULL){ + char buf[32*1024+1]; + int nb = read (fd,buf,sizeof(buf)-1); + priv->curclient = fd; + if (nb <= 0){ + if (errno != EINTR){ + TCPSERVER_INFO info; + info.data = ptc.data; + if (is_timeout) priv->c->time_out (fd,endserver,info); + priv->c->endclient (fd,endserver,info); + ptc.data = info.data; + endsession(fd); + } + }else{ + bool endclient = false; + buf[nb] = '\0'; + if (ptc.rawmode){ + TCPSERVER_INFO info; + info.data = ptc.data; + info.rest = NULL; + info.linelen = nb; + priv->c->receive (fd,buf,endclient,endserver + ,ptc.state,info); + ptc.data = info.data; + }else{ + SSTRING *s = ptc.s; + s->append (buf); + const char *pt = s->get(); + while (*pt != '\0'){ + const char *start = pt; + while (*pt != '\0' && *pt != '\n') pt++; + if (*pt == '\n'){ + int len = (int)(pt-start); + char line[len+1]; + strncpy (line,start,len); + line[len] = '\0'; + // Some are sending \r\n lines + if (len > 0 && line[len-1] == '\r'){ + len--; + line[len] = '\0'; + } + pt++; + TCPSERVER_INFO info; + info.data = ptc.data; + info.rest = pt; + info.linelen = len; + priv->c->receive (fd,line,endclient,endserver + ,ptc.state,info); + ptc.data = info.data; + if (endclient || endserver){ + break; + } + }else{ + pt = start; + break; + } + } + s->setfrom (pt); + } + if (endclient){ + endsession (fd); + } + } + } + } + PRIVATE bool TCPSERVER::dispatch (int select_ret, fd_set &set) { bool endserver = false; if (select_ret == 0){ priv->since += priv->time_out; + TCPSERVER_INFO info; priv->c->idle (priv->since,endserver,info); // Even if ok == 0, we must cycle through readnext() // to detect ended client (timeout) *************** *** 553,658 **** for (unsigned i=0; ifds.size(); i++){ int fd = priv->fds[i]; if (FD_ISSET(fd,&set)){ ! struct sockaddr_in sacc; ! socklen_t size=sizeof(sacc); ! int newclient = accept (fd,(struct sockaddr *)&sacc,&size); ! if (newclient != -1 && (unsigned)newclient < priv->maxclient){ ! priv->allocclient(newclient); ! TCPSERVER_CLIENT &ptc = priv->tbc[newclient]; ! priv->nbclients++; ! ptc.s = new SSTRING; ! ptc.state = 0; ! ptc.data = NULL; ! ptc.rawmode = priv->rawmode; ! ! priv->curclient = newclient; ! unsigned long addr = ntohl(sacc.sin_addr.s_addr); ! #if 0 ! struct sockaddr_in adr; ! unsigned int len = sizeof(adr); ! if (getpeername (newclient,(struct sockaddr*)&adr,&len) != -1){ ! addr = ntohl(adr.sin_addr.s_addr); ! } ! #endif ! bool endclient = false; ! info.data = NULL; ! info.port = priv->ports[i].c_str(); ! priv->c->newclient (newclient,addr,endclient,endserver,info); ! ptc.data = info.data; ! if (endclient){ ! endsession(newclient); ! }else{ ! //priv->cmd->set_timeout (newclient,priv->time_out); ! } ! } } } - bool is_timeout = false; // Not done for (unsigned i=0; !endserver && itbc.size(); i++){ if (FD_ISSET(i,&set)){ ! TCPSERVER_CLIENT &ptc = priv->tbc[i]; ! if (ptc.s != NULL){ ! char buf[8192]; ! int nb = read (i,buf,sizeof(buf)-1); ! priv->curclient = i; ! if (nb <= 0){ ! if (errno != EINTR){ ! info.data = ptc.data; ! if (is_timeout) priv->c->time_out (i,endserver,info); ! priv->c->endclient (i,endserver,info); ! ptc.data = info.data; ! endsession(i); ! } ! }else{ ! bool endclient = false; ! buf[nb] = '\0'; ! if (ptc.rawmode){ ! info.data = ptc.data; ! info.rest = NULL; ! info.linelen = nb; ! priv->c->receive (i,buf,endclient,endserver ! ,ptc.state,info); ! ptc.data = info.data; ! }else{ ! SSTRING *s = ptc.s; ! s->append (buf); ! const char *pt = s->get(); ! while (*pt != '\0'){ ! const char *start = pt; ! while (*pt != '\0' && *pt != '\n') pt++; ! if (*pt == '\n'){ ! int len = (int)(pt-start); ! char line[len+1]; ! strncpy (line,start,len); ! line[len] = '\0'; ! // Some are sending \r\n lines ! if (len > 0 && line[len-1] == '\r'){ ! len--; ! line[len] = '\0'; ! } ! pt++; ! info.data = ptc.data; ! info.rest = pt; ! info.linelen = len; ! priv->c->receive (i,line,endclient,endserver ! ,ptc.state,info); ! ptc.data = info.data; ! if (endclient || endserver){ ! break; ! } ! }else{ ! pt = start; ! break; ! } ! } ! s->setfrom (pt); ! } ! if (endclient){ ! endsession (i); ! } ! } ! } } } } --- 832,844 ---- for (unsigned i=0; ifds.size(); i++){ int fd = priv->fds[i]; if (FD_ISSET(fd,&set)){ ! accept_con (i,endserver,NULL); } } for (unsigned i=0; !endserver && itbc.size(); i++){ if (FD_ISSET(i,&set)){ ! process_data (i,endserver); } } } *************** *** 693,698 **** --- 879,965 ---- dispatch (select_ret,set); } + PUBLIC void TCPSERVER::setup_epoll (TLMPEPOLL &ep) + { + priv->ep = &ep; + priv->id_listen = tlmpepoll_allocid(); + priv->id_data = tlmpepoll_allocid(); + for (unsigned i=0; ifds.size(); i++){ + int fd = priv->fds[i]; + ep.ctl (TLMPEPOLL_CTL_ADD,fd,TLMPEPOLL_IN); + ep.setid (fd,priv->id_listen); + } + for (unsigned i=0; itbc.size(); i++){ + TCPSERVER_CLIENT &ptc = priv->tbc[i]; + if (ptc.s != NULL){ + ep.ctl (TLMPEPOLL_CTL_ADD,i,TLMPEPOLL_IN); + ep.setid (i,priv->id_data); + } + } + } + + PUBLIC void TCPSERVER::forget_epoll () + { + priv->ep = NULL; + } + + /* + Process the work in the fd_set. + */ + PUBLIC bool TCPSERVER::process_epoll ( + TLMPEPOLL &ep, + TLMPEPOLL_EVENT events[], + int nbevent) + { + bool endserver = false; + TLMPEPOLL_EVENT *ptev = events; + for (int i=0; ifd; + if (ptev->id == priv->id_listen){ + for (unsigned i=0; ifds.size(); i++){ + if (priv->fds[i] == fd){ + accept_con (i,endserver,&ep); + break; + } + } + }else if (ptev->id == priv->id_data){ + if ((ptev->events & TLMPEPOLL_IN)!=0){ + // While processing other event, we may have turned off + // listening for that connection. But the event was + // already queued. We just ignore the event. When we + // turn listening on, epoll will resend the event + if (priv->tbc[fd].listening) process_data (fd,endserver); + } + if ((ptev->events & TLMPEPOLL_OUT)!=0){ + TCPSERVER_CLIENT &ptc = priv->tbc[fd]; + gettimeofday (&ptc.lastwrite,NULL); + while (1){ + // fprintf (stderr,"epoll out %d blocks %d\n",fd,ptc.blocks.size()); + if (ptc.blocks.size()==0){ + priv->ep->ctl (TLMPEPOLL_CTL_MOD,fd,TLMPEPOLL_IN); + break; + }else{ + TCPSERVER_BLOCKBUF *buf = ptc.blocks[0]; + int len = buf->len - buf->off; + int written = write (fd,buf->data,len); + // fprintf (stderr,"block written %d len %d\n",written,len); + if (written == len){ + delete buf; + ptc.blocks.erase(ptc.blocks.begin()); + }else if (written >= 0){ + buf->off += written; + break; + }else if (errno != EINTR){ + break; + } + } + } + } + } + } + return endserver; + } + /* How many concurent client are accepted. (not exactly, this is the largest file handle accepted). *** 1.33r5/linuxconf/tlmp/tlmpnet/tlmpnet.p Tue May 4 11:39:16 2004 --- 1.33r5/linuxconf/tlmp/tlmpnet/tlmpnet.p Mon Nov 8 15:27:30 2004 *************** *** 1,19 **** /* _dict.cc 10/05/2001 14.16.10 */ ! /* http.tlcc 04/05/2004 11.39.16 */ int http_get (_F_http_get&c, const char *url, const char *realm, const char *user, const char *passwd); int http_get (_F_http_get&c, const char *url); ! /* netevent.tlcc 04/05/2004 11.39.16 */ ! /* popenhandler.tlcc 04/05/2004 11.39.16 */ ! /* samples.tlcc 04/05/2004 11.39.16 */ ! /* tcpconnect.tlcc 04/05/2004 11.39.16 */ int tcpconnect (_F_tcpconnect&c, const char *host, const char *port, int time_out); int tcpconnect (_F_tcpconnect&c, int handle, int time_out); ! /* tcpserver.tlcc 04/05/2004 11.39.16 */ /* tlmpnet.cc 10/05/2001 20.56.32 */ --- 1,21 ---- /* _dict.cc 10/05/2001 14.16.10 */ ! /* http.tlcc 08/11/2004 15.27.30 */ int http_get (_F_http_get&c, const char *url, const char *realm, const char *user, const char *passwd); int http_get (_F_http_get&c, const char *url); ! /* netevent.tlcc 08/11/2004 15.27.30 */ ! /* popenhandler.tlcc 08/11/2004 15.27.30 */ ! /* samples.tlcc 08/11/2004 15.27.30 */ ! /* tcpconnect.tlcc 08/11/2004 15.27.30 */ int tcpconnect (_F_tcpconnect&c, const char *host, const char *port, int time_out); int tcpconnect (_F_tcpconnect&c, int handle, int time_out); ! /* tcpserver.tlcc 08/11/2004 15.27.30 */ ! /* tlmpepoll.cc 28/10/2004 13.38.58 */ ! int tlmpepoll_allocid (void); /* tlmpnet.cc 10/05/2001 20.56.32 */ *** 1.33r5/linuxconf/tlmp/tlmpnet/tlmpnet.pm Tue May 4 11:39:16 2004 --- 1.33r5/linuxconf/tlmp/tlmpnet/tlmpnet.pm Mon Nov 8 15:27:30 2004 *************** *** 1,25 **** /* _dict.cc 10/05/2001 14.16.10 */ ! /* http.tlcc 04/05/2004 11.39.16 */ void _F_http_get::fail (const HTTP_HEADER_INFO&info, const char *msg); void _F_http_get::end (const HTTP_HEADER_INFO&info); void _F_http_get::header (const char *line, int len, const HTTP_HEADER_INFO&info, bool&end); ! /* netevent.tlcc 04/05/2004 11.39.16 */ PUBLIC NETOBJECT::NETOBJECT (HANDLE_SELECTS&_sels); ! PUBLIC NETOBJECT *NETOBJECTS::getitem (int no)const; void _F_NETEVENT_MANAGER::idle (int , bool&, bool); PUBLIC NETEVENT_MANAGER::NETEVENT_MANAGER (_F_NETEVENT_MANAGER&c); PUBLIC NETEVENT_MANAGER::~NETEVENT_MANAGER (void); PUBLIC void NETEVENT_MANAGER::add (HANDLE_SELECTS&sels); PRIVATE void NETEVENT_MANAGER::loopgen (int timeout, bool gui, PRIVATE_MESSAGE&endmsg); PUBLIC void NETEVENT_MANAGER::loop (int timeout); PUBLIC void NETEVENT_MANAGER::loopgui (int timeout, PRIVATE_MESSAGE&endmsg); ! /* popenhandler.tlcc 04/05/2004 11.39.16 */ PUBLIC POPEN_OBJ::POPEN_OBJ (POPENFD *_pop); PUBLIC POPEN_OBJ::~POPEN_OBJ (void); PUBLIC POPEN_OBJ *POPEN_OBJS::getitem (int no)const; --- 1,27 ---- /* _dict.cc 10/05/2001 14.16.10 */ ! /* http.tlcc 08/11/2004 15.27.30 */ void _F_http_get::fail (const HTTP_HEADER_INFO&info, const char *msg); void _F_http_get::end (const HTTP_HEADER_INFO&info); void _F_http_get::header (const char *line, int len, const HTTP_HEADER_INFO&info, bool&end); ! /* netevent.tlcc 08/11/2004 15.27.30 */ PUBLIC NETOBJECT::NETOBJECT (HANDLE_SELECTS&_sels); ! PUBLIC NETOBJECT::NETOBJECT (TCPSERVER&_tcp); ! PUBLIC NETOBJECT::~NETOBJECT (void); void _F_NETEVENT_MANAGER::idle (int , bool&, bool); PUBLIC NETEVENT_MANAGER::NETEVENT_MANAGER (_F_NETEVENT_MANAGER&c); PUBLIC NETEVENT_MANAGER::~NETEVENT_MANAGER (void); PUBLIC void NETEVENT_MANAGER::add (HANDLE_SELECTS&sels); + PUBLIC void NETEVENT_MANAGER::add (TCPSERVER&tcp); PRIVATE void NETEVENT_MANAGER::loopgen (int timeout, bool gui, PRIVATE_MESSAGE&endmsg); PUBLIC void NETEVENT_MANAGER::loop (int timeout); PUBLIC void NETEVENT_MANAGER::loopgui (int timeout, PRIVATE_MESSAGE&endmsg); ! /* popenhandler.tlcc 08/11/2004 15.27.30 */ PUBLIC POPEN_OBJ::POPEN_OBJ (POPENFD *_pop); PUBLIC POPEN_OBJ::~POPEN_OBJ (void); PUBLIC POPEN_OBJ *POPEN_OBJS::getitem (int no)const; *************** *** 34,41 **** PUBLIC void POPENHANDLER::process_select (int select_ret, fd_set&set, long timeout); ! /* samples.tlcc 04/05/2004 11.39.16 */ ! /* tcpconnect.tlcc 04/05/2004 11.39.16 */ void _F_TCPCONNECT::fail (TCPCONNECT_INFO&info); bool _F_TCPCONNECT::setrawmode (bool mode); PUBLIC bool TCPCONNECT::setrawmode (bool mode); --- 36,43 ---- PUBLIC void POPENHANDLER::process_select (int select_ret, fd_set&set, long timeout); ! /* samples.tlcc 08/11/2004 15.27.30 */ ! /* tcpconnect.tlcc 08/11/2004 15.27.30 */ void _F_TCPCONNECT::fail (TCPCONNECT_INFO&info); bool _F_TCPCONNECT::setrawmode (bool mode); PUBLIC bool TCPCONNECT::setrawmode (bool mode); *************** *** 83,96 **** void _F_tcpconnect::time_out (bool&, TCPCONNECT_INFO&); void _F_tcpconnect::end (TCPCONNECT_INFO&info); int _F_tcpconnect::sendf (const char *ctl, ...); ! /* tcpserver.tlcc 04/05/2004 11.39.16 */ int _F_TCPSERVER::iter_next (void *&data); int _F_TCPSERVER::iter_init (void *&data); int _F_TCPSERVER::iter_init (void); int _F_TCPSERVER::iter_next (void); void _F_TCPSERVER::set_timeout (int nbseconds); bool _F_TCPSERVER::setrawmode (bool mode); PUBLIC bool TCPSERVER::setrawmode (bool mode); void _F_TCPSERVER::idle (int , bool&, TCPSERVER_INFO&); void _F_TCPSERVER::time_out (int , bool&, TCPSERVER_INFO&); int _F_TCPSERVER::sendto (int client, const char *line); --- 85,106 ---- void _F_tcpconnect::time_out (bool&, TCPCONNECT_INFO&); void _F_tcpconnect::end (TCPCONNECT_INFO&info); int _F_tcpconnect::sendf (const char *ctl, ...); ! /* tcpserver.tlcc 08/11/2004 15.27.30 */ int _F_TCPSERVER::iter_next (void *&data); int _F_TCPSERVER::iter_init (void *&data); int _F_TCPSERVER::iter_init (void); int _F_TCPSERVER::iter_next (void); + PUBLIC int TCPSERVER::iter_init (void *&data); + PUBLIC int TCPSERVER::iter_init (void); + PUBLIC int TCPSERVER::iter_next (void *&data); + PUBLIC int TCPSERVER::iter_next (void); + PUBLIC bool TCPSERVER::is_blocked (int fd, + unsigned long &size, + long long &last_write); void _F_TCPSERVER::set_timeout (int nbseconds); bool _F_TCPSERVER::setrawmode (bool mode); PUBLIC bool TCPSERVER::setrawmode (bool mode); + PUBLIC bool TCPSERVER::setnonblock (bool mode, int bufsize); void _F_TCPSERVER::idle (int , bool&, TCPSERVER_INFO&); void _F_TCPSERVER::time_out (int , bool&, TCPSERVER_INFO&); int _F_TCPSERVER::sendto (int client, const char *line); *************** *** 107,113 **** --- 117,128 ---- void _F_TCPSERVER::forgetclient (void); void _F_TCPSERVER::closeclient (int cli); int _F_TCPSERVER::getnbclients (void); + bool _F_TCPSERVER::is_blocked (int handle, + unsigned long &size, + long long &lastwrite); + bool _F_TCPSERVER::is_blocked (void); int _F_TCPSERVER::getnbpending (void); + bool _F_TCPSERVER::setlisten (int handle, bool on); PUBLIC int TCPSERVER::listen (const char *bindaddr, const char *port); PUBLIC int TCPSERVER::listen (const char *port); PUBLIC int TCPSERVER::listen (int port); *************** *** 130,140 **** --- 145,164 ---- PUBLIC void TCPSERVER::loop (void); void _F_TCPSERVER::inject (int client, ARRAY_OBJ *data); PUBLIC void TCPSERVER::inject (int client, ARRAY_OBJ *data); + PRIVATE void TCPSERVER::accept_con (int i, + bool&endserver, + TLMPEPOLL *ep); + PRIVATE void TCPSERVER::process_data (int fd, bool&endserver); PRIVATE bool TCPSERVER::dispatch (int select_ret, fd_set&set); PUBLIC int TCPSERVER::setup_select (fd_set&set, int max_handle); PUBLIC void TCPSERVER::process_select (int select_ret, fd_set&set, long timeout); + PUBLIC void TCPSERVER::setup_epoll (TLMPEPOLL&ep); + PUBLIC void TCPSERVER::forget_epoll (void); + PUBLIC bool TCPSERVER::process_epoll (TLMPEPOLL&ep, + TLMPEPOLL_EVENT events[], + int nbevent); PUBLIC void TCPSERVER::setmaxclients (int n); PUBLIC int TCPSERVER::sendallf (const char *ctl, ...); PUBLIC int TCPSERVER::sendall (const void *s, int len); *************** *** 142,145 **** --- 166,184 ---- PUBLIC int TCPSERVER::sendto (int client, const char *line); PUBLIC int TCPSERVER::sendto (int client, const void *buf, int len); PUBLIC int TCPSERVER::sendtof (int client, const char *ctl, ...); + /* tlmpepoll.cc 28/10/2004 13.38.58 */ + PUBLIC TLMPEPOLL::TLMPEPOLL (void); + PUBLIC TLMPEPOLL::~TLMPEPOLL (void); + PRIVATE void TLMPEPOLL::ctl_select (TLMPEPOLL_CTL op, + int fd, + int events); + PUBLIC void TLMPEPOLL::ctl (TLMPEPOLL_CTL op, int fd, int events); + PUBLIC void TLMPEPOLL::setdata (int fd, void *data); + PUBLIC void TLMPEPOLL::setid (int fd, int id); + PRIVATE int TLMPEPOLL::wait_select (TLMPEPOLL_EVENT events[], + int nbevents, + int timeout); + PUBLIC int TLMPEPOLL::wait (TLMPEPOLL_EVENT events[], + int nbevents, + int timeout); /* tlmpnet.cc 10/05/2001 20.56.32 */ *** 1.33r5/linuxconf/tlmp/tlmpnet/netevent.tlcc Tue Feb 17 15:08:25 2004 --- 1.33r5/linuxconf/tlmp/tlmpnet/netevent.tlcc Fri Oct 29 16:11:17 2004 *************** *** 7,39 **** class NETOBJECT: public ARRAY_OBJ{ public: HANDLE_SELECTS *sels; /*~PROTOBEG~ NETOBJECT */ public: NETOBJECT (HANDLE_SELECTS&_sels); /*~PROTOEND~ NETOBJECT */ }; PUBLIC NETOBJECT::NETOBJECT(HANDLE_SELECTS &_sels) { sels = &_sels; } ! class NETOBJECTS: public ARRAY{ ! /*~PROTOBEG~ NETOBJECTS */ ! public: ! NETOBJECT *getitem (int no)const; ! /*~PROTOEND~ NETOBJECTS */ ! }; ! PUBLIC NETOBJECT *NETOBJECTS::getitem(int no) const { ! return (NETOBJECT*)ARRAY::getitem(no); } class NETEVENT_MANAGER_PRIVATE{ public: _F_NETEVENT_MANAGER *c; NETOBJECTS objs; }; --- 7,54 ---- class NETOBJECT: public ARRAY_OBJ{ public: HANDLE_SELECTS *sels; + TCPSERVER *tcp; /*~PROTOBEG~ NETOBJECT */ public: NETOBJECT (HANDLE_SELECTS&_sels); + NETOBJECT (TCPSERVER&_tcp); + ~NETOBJECT (void); /*~PROTOEND~ NETOBJECT */ }; PUBLIC NETOBJECT::NETOBJECT(HANDLE_SELECTS &_sels) { sels = &_sels; + tcp = NULL; } ! PUBLIC NETOBJECT::NETOBJECT(TCPSERVER &_tcp) ! { ! tcp = &_tcp; ! sels = &_tcp; ! } ! PUBLIC NETOBJECT::~NETOBJECT() { ! if (tcp != NULL) tcp->forget_epoll(); } + + + class NETOBJECTS: public ARRAY_OBJS{ + /*~PROTOBEG~ NETOBJECTS */ + /*~PROTOEND~ NETOBJECTS */ + }; + class NETEVENT_MANAGER_PRIVATE{ public: _F_NETEVENT_MANAGER *c; NETOBJECTS objs; + bool one_select; + TLMPEPOLL ep; + NETEVENT_MANAGER_PRIVATE(){ + one_select = false; + } }; *************** *** 55,60 **** --- 70,82 ---- PUBLIC void NETEVENT_MANAGER::add (HANDLE_SELECTS &sels) { priv->objs.add (new NETOBJECT(sels)); + priv->one_select = true; + } + + PUBLIC void NETEVENT_MANAGER::add (TCPSERVER &tcp) + { + priv->objs.add (new NETOBJECT(tcp)); + tcp.setup_epoll (priv->ep); } #if 0 *************** *** 69,106 **** bool gui, PRIVATE_MESSAGE &endmsg) { ! long since = 0; ! bool end = false; ! while (!end){ ! int maxhandle = 0; ! fd_set set; ! FD_ZERO (&set); ! for (int i=0; iobjs.getnb(); i++){ ! NETOBJECT *o = priv->objs.getitem(i); ! maxhandle = o->sels->setup_select (set,maxhandle); ! } ! int sel; ! maxhandle++; ! if (gui){ ! sel = diagui_select (maxhandle,&set,timeout,endmsg); ! if (sel == -2) break; ! }else{ ! struct timeval timeo; ! timeo.tv_sec = timeout; ! timeo.tv_usec = 0; ! sel = select (maxhandle,&set,NULL,NULL,&timeo); ! } ! if (sel == -1) break; ! if (sel == 0){ ! since += timeout; ! priv->c->idle(since,end,maxhandle==0); ! }else{ ! since = 0; ! } ! for (int i=0; iobjs.getnb(); i++){ ! NETOBJECT *o = priv->objs.getitem(i); ! o->sels->process_select (sel,set,timeout); } } } --- 91,150 ---- bool gui, PRIVATE_MESSAGE &endmsg) { ! if (priv->one_select || gui){ ! // We must use select() because the GUI still does not support ! // epoll, nor HANDLE_SELECTS objects ! long since = 0; ! bool end = false; ! while (!end){ ! int maxhandle = 0; ! fd_set set; ! FD_ZERO (&set); ! for (int i=0; iobjs.getnb(); i++){ ! NETOBJECT *o = priv->objs.getitem(i); ! maxhandle = o->sels->setup_select (set,maxhandle); ! } ! int sel; ! maxhandle++; ! if (gui){ ! sel = diagui_select (maxhandle,&set,timeout,endmsg); ! if (sel == -2) break; ! }else{ ! struct timeval timeo; ! timeo.tv_sec = timeout; ! timeo.tv_usec = 0; ! sel = select (maxhandle,&set,NULL,NULL,&timeo); ! } ! if (sel == -1) break; ! if (sel == 0){ ! since += timeout; ! priv->c->idle(since,end,maxhandle==0); ! }else{ ! since = 0; ! } ! for (int i=0; iobjs.getnb(); i++){ ! NETOBJECT *o = priv->objs.getitem(i); ! o->sels->process_select (sel,set,timeout); ! } } + }else{ + long since = 0; + bool end = false; + int mseconds = timeout * 1000; + while (!end){ + TLMPEPOLL_EVENT events[100]; + int nb = priv->ep.wait (events,100,mseconds); + if (nb == 0){ + since += timeout; + priv->c->idle(since,end,false); + }else{ + since = 0; + for (int i=0; iobjs.getnb(); i++){ + NETOBJECT *o = priv->objs.getitem(i); + o->tcp->process_epoll (priv->ep,events,nb); + } + } + } } } *** 1.33r5/linuxconf/tlmp/tlmpnet/tlmpnet.comp Fri Feb 27 08:08:55 2004 --- 1.33r5/linuxconf/tlmp/tlmpnet/tlmpnet.comp Mon Nov 8 05:27:37 2004 *************** *** 385,390 **** --- 385,578 ---- + +

    Close the connection to a client + endclient won't be called. + + + client handle + + + + + Send a packet to a specific client (handle) + This handle is (must be) managed by TCPSERVER. + + + Client handle + + + + Data to send + + + + Data length + + + + + Send a packet to a specific client (handle) + This handle is (must be) managed by TCPSERVER. + + + Client handle + + + + Data to send + + + + + Send a format string using a printf syntax to a client + Return the number of bytes sent or -1 if any error. + + + Client handle + + + + Control string + + + + + + + + Turn on and off nonblocking mode + When you turn non-blocking, the various send* fhelper won't block. + They will always return the total amount of bytes. Extra bytes + not wrtten to the socket are buffered. + + + Non blocking mode on or off + + + + How much data are we allowed to + buffered before attempting to close + or ignore connections. + + + + + Ask the TCPSERVER to listen on another port + Return -1 if the port can't be opened. + If the port starts with "unix:", the rest is taken as the path of a unix + domain socket. TCPSERVER may listen on several socket, including TCP + and Unix all at once. + + + + + + + Send some data to one client + The client must be handled by this TCPSERVER + + + client handle + + + + String to send + + + + + Send some data to one client + The client must be handled by this TCPSERVER + + + client handle + + + + String to send + + + + + + + + Send some data to one client + The client must be handled by this TCPSERVER + + + client handle + + + + String to send + Control string (printf like) + + + + + + + + Iterate over all connections + Starts the iteration over all connected client, returning the + handle of each client and optionally the application stored data + (info.data). iter_init() returns the first connection and iter_next() + returns the rest. Both function returns -1 if there is no more connections. + + + + Iterate over all connections + Starts the iteration over all connected client, returning the + handle of each client and optionally the application stored data + (info.data). iter_init() returns the first connection and iter_next() + returns the rest. Both function returns -1 if there is no more connections. + + + This pointer will contains the application + data (normally found in info.data). + + + + + Returns the next connection + This is called in a loop after iter_init. + + + + Returns the next connection + This is called in a loop after iter_init. + + + This pointer will contains the application + data (normally found in info.data). + + + + + Stop listening on this connection + You generally use this to prevent more request to be queued while you + know the output might be stopped (blocked). + + + + + + + + + + Return true if the output of the current connection is blocked + + + + Return true if the output of the connection is blocked + + + + + It establish the connection, calls its init functag when *** 1.33r5/linuxconf/tlmp/tlmpnet/has_epoll.sh --- 1.33r5/linuxconf/tlmp/tlmpnet/has_epoll.sh Sat Nov 13 22:05:22 2004 *************** *** 0 **** --- 1,23 ---- + #!/bin/sh + # The script detect is the epoll system (replacing select) is + # available on this machine. It simply tries to compile + # a sample program. If it works, it prints "-DHAS_EPOLL" + # If it does not work, it prints nothing. This is used in the Makefile + FILE=/tmp/hasepool-$$.c + cat <<-EOF >$FILE + #include + + void f(){ + int fd = epoll_create(10); + } + EOF + + OUT=has_epoll-tmp.bak + if g++ -c $FILE -o /dev/null 2>/dev/null >/dev/null + then + echo "#define HAS_EPOLL" >$OUT + else + echo "#undef HAS_EPOLL" >$OUT + fi + rm -f $FILE + *** 1.33r5/linuxconf/tlmp/tlmpnet/tlmpepoll.cc --- 1.33r5/linuxconf/tlmp/tlmpnet/tlmpepoll.cc Mon Nov 15 11:11:56 2004 *************** *** 0 **** --- 1,402 ---- + #include + #include + #include + #include + #include + #include "tlmpnet.h" + + #include "has_epoll-tmp.bak" + + #ifdef HAS_EPOLL + #include + #else + + #endif + + + static int allocid=0; + /* + Return an ID for TLMPEPOLL clients so they can tell apart their + events from others when they are sharing the same TLMPEPOLL + */ + int tlmpepoll_allocid() + { + return allocid++; + } + + struct FDDATA{ + int id; + void *data; + }; + + + struct TLMPEPOLL_private{ + fd_set in,out; + fd_set res_in,res_out; + int loop; + int maxfd; + int epfd; + FDDATA *fddata; + int maxdata; + TLMPEPOLL_private(){ + FD_ZERO (&in); + FD_ZERO (&out); + epfd = -1; + maxfd = 0; + loop = 0; + fddata = NULL; + maxdata = 0; + } + ~TLMPEPOLL_private(){ + free (fddata); + } + void grow (int fd){ + if (fd >= maxdata){ + int new_maxdata = fd+100; + fddata = (FDDATA*)realloc(fddata,new_maxdata*sizeof(FDDATA)); + for (int i=maxdata; iepfd = epoll_create (1024); + // fprintf (stderr,"epfd = %d\n",priv->epfd); + #endif + } + + PUBLIC TLMPEPOLL::~TLMPEPOLL() + { + close (priv->epfd); + delete priv; + } + + /* + Special version when epoll is not available + */ + PRIVATE void TLMPEPOLL::ctl_select( + TLMPEPOLL_CTL op, + int fd, + int events) + { + if (op == TLMPEPOLL_CTL_ADD){ + if ((events & TLMPEPOLL_IN)!=0){ + FD_SET (fd,&priv->in); + } + if ((events & TLMPEPOLL_OUT)!=0){ + FD_SET (fd,&priv->out); + } + if (priv->maxfd <= fd) priv->maxfd = fd+1; + }else if (op == TLMPEPOLL_CTL_DEL){ + FD_CLR (fd,&priv->in); + FD_CLR (fd,&priv->out); + }else if (op == TLMPEPOLL_CTL_MOD){ + if ((events & TLMPEPOLL_IN)!=0){ + FD_SET (fd,&priv->in); + }else{ + FD_CLR (fd,&priv->in); + } + if ((events & TLMPEPOLL_OUT)!=0){ + FD_SET (fd,&priv->out); + }else{ + FD_CLR (fd,&priv->out); + } + } + } + + PUBLIC void TLMPEPOLL::ctl ( + TLMPEPOLL_CTL op, + int fd, + int events) + { + #ifdef HAS_EPOLL + if (priv->epfd != -1){ + static int tbop[]={ + EPOLL_CTL_ADD, + EPOLL_CTL_DEL, + EPOLL_CTL_MOD + }; + epoll_event ev; + ev.events = (events & TLMPEPOLL_IN) != 0 ? EPOLLIN : 0; + ev.events |= (events & TLMPEPOLL_OUT) != 0 ? EPOLLOUT : 0; + ev.data.fd = fd; + epoll_ctl (priv->epfd,tbop[op],fd,&ev); + }else{ + ctl_select (op,fd,events); + } + #else + ctl_select (op,fd,events); + #endif + } + + /* + Associate some data to the handle + */ + PUBLIC void TLMPEPOLL::setdata (int fd, void *data) + { + priv->setdata (fd,data); + } + + /* + Associate in ID (or owner) to the handle + */ + PUBLIC void TLMPEPOLL::setid (int fd, int id) + { + priv->setid (fd,id); + } + /* + Special case when epoll is not available + */ + PRIVATE int TLMPEPOLL::wait_select( + TLMPEPOLL_EVENT events[], + int nbevents, + int timeout) + { + int ret = 0; + while (1){ + // fprintf (stderr,"loop %d < %d ret=%d\n",priv->loop,priv->maxfd,ret); + while (priv->loop < priv->maxfd && ret < nbevents){ + int bits = FD_ISSET(priv->loop,&priv->res_in) ? TLMPEPOLL_IN : 0; + bits |= FD_ISSET(priv->loop,&priv->res_out) ? TLMPEPOLL_OUT : 0; + if (bits != 0){ + events[ret].events = bits; + events[ret].fd = priv->loop; + FDDATA *data = priv->fddata+priv->loop; + events[ret].data = data->data; + events[ret].id = data->id; + ret++; + } + priv->loop++; + } + if (ret == 0){ + priv->res_in = priv->in; + priv->res_out = priv->out; + #if 0 + for (int i=0; imaxfd; i++){ + if (FD_ISSET(i,&priv->res_in)) printf ("in[%d]\n",i); + if (FD_ISSET(i,&priv->res_out)) printf ("out[%d]\n",i); + } + fprintf (stderr,"select maxfd %d\n",priv->maxfd); + #endif + struct timeval tm; + tm.tv_sec = timeout / 1000; + tm.tv_usec = (timeout % 1000) * 1000; + int ok = select (priv->maxfd,&priv->res_in,&priv->res_out,NULL + ,timeout == -1 ? NULL : &tm); + if (ok < 0){ + ret = ok; + break; + }else if (ok == 0){ + break; + }else{ + priv->loop = 0; + } + }else{ + break; + } + } + return ret; + } + + PUBLIC int TLMPEPOLL::wait ( + TLMPEPOLL_EVENT events[], + int nbevents, + int timeout) + { + #ifdef HAS_EPOLL + if (priv->epfd != -1){ + epoll_event tmp[nbevents]; + int ret = epoll_wait (priv->epfd,tmp,nbevents,timeout); + TLMPEPOLL_EVENT *pt = events; + epoll_event *pttmp = tmp; + for (int i=0; ievents; + int nx = (x & EPOLLIN) != 0 ? TLMPEPOLL_IN : 0; + nx |= (x & EPOLLOUT) != 0 ? TLMPEPOLL_OUT : 0; + pt->events = nx; + pt->fd = pttmp->data.fd; + FDDATA *data = priv->fddata + pt->fd; + pt->data = data->data; + pt->id = data->id; + } + return ret; + }else{ + return wait_select (events,nbevents,timeout); + } + #else + return wait_select (events,nbevents,timeout); + #endif + } + + + #ifdef TEST + + #include + #include + #include + #include + #include + #include + #include + #include + #include + + using namespace std; + + static int tcp_server( + const char *port) + { + struct sockaddr_in sin; + sin.sin_family = AF_INET; + struct servent *s = getservbyname(port,"tcp"); + if (s != NULL){ + sin.sin_port = s->s_port; + }else{ + sin.sin_port = htons (atoi(port)); + } + memset (&sin.sin_addr,0,sizeof(sin.sin_addr)); + int listen_handle = -1; + for (int i=0; i<5; i++){ + listen_handle = socket (AF_INET, SOCK_STREAM, 0); + int opt = 1; + if (listen_handle == -1){ + fprintf (stderr,"listen_handle %d(%s)\n" + ,errno + ,strerror(errno)); + }else if (setsockopt(listen_handle,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))==-1){ + fprintf (stderr,"Can't set socket option SO_REUSEADDR (%s)\n" + ,strerror (errno)); + }else if (bind (listen_handle,(struct sockaddr *) &sin, sizeof (sin)) == -1){ + fprintf (stderr,"bind %d(%s)\n",errno + ,strerror(errno)); + }else if (listen (listen_handle,35) == -1){ + fprintf (stderr,"listen %d(%s)\n",errno + ,strerror(errno)); + break; + }else{ + fprintf (stderr,"bind ok\n"); + break; + } + close (listen_handle); + listen_handle = -1; + if (i < 5){ + fprintf (stderr,"Sleeping 5 seconds\n"); + sleep (5); + } + } + return listen_handle; + } + + struct SOFAR{ + int sofar; + int size; + SOFAR(){ + sofar = size = 0; + } + SOFAR(int _size){ + sofar = 0; + size = _size; + } + bool send (int fd){ + int len = size - sofar; + char buf[len]; + memset (buf,'a',len); + buf[len-1] = '\n'; + int rest = write (fd,buf,len); + sofar += rest; + return sofar == size; + } + }; + + int main (int argc, char *argv[]) + { + TLMPEPOLL ep; + int listen_handle = tcp_server ("8001"); + if (listen_handle != -1){ + ep.ctl (TLMPEPOLL_CTL_ADD,listen_handle,TLMPEPOLL_IN); + ep.setdata (listen_handle,(void*)"listen_handle"); + map mp; + while (1){ + TLMPEPOLL_EVENT evs[10]; + int nb = ep.wait (evs,10,15000); + if (nb == 0){ + fprintf (stderr,"Timeout\n"); + }else{ + fprintf (stderr,"nb=%d\n",nb); + TLMPEPOLL_EVENT *pt = evs; + for (int i=0; ifd; + fprintf (stderr,"Event fd=%d data=%s\n",fd,(char*)pt->data); + if (fd == listen_handle){ + struct sockaddr_in sin; + socklen_t addrlen=sizeof(sin); + int newfd = accept (listen_handle,(struct sockaddr*)&sin,&addrlen); + fprintf (stderr,"New connection %d\n",newfd); + if (newfd == -1){ + fprintf (stderr,"Accept failed\n"); + }else{ + char tmp[100]; + snprintf (tmp,sizeof(tmp)-1,"handle %d",newfd); + ep.ctl (TLMPEPOLL_CTL_ADD,newfd,TLMPEPOLL_IN); + ep.setdata (newfd,strdup(tmp)); + fcntl (newfd,F_SETFL,O_NONBLOCK); + } + }else{ + if ((pt->events & TLMPEPOLL_IN) != 0){ + char buf[101]; + int len = read (fd,buf,100); + fprintf (stderr,"read %d -> %d\n",fd,len); + if (len <= 0){ + ep.ctl (TLMPEPOLL_CTL_DEL,fd,0); + close (fd); + }else{ + buf[len] = '\0'; + int size = atoi(buf); + len = snprintf (buf,sizeof(buf)-1,"Rec %d bytes\n",len); + write (fd,buf,len); + if (size > 0) mp[fd] = SOFAR(size); + if (mp[fd].send(fd)){ + ep.ctl (TLMPEPOLL_CTL_MOD,fd,TLMPEPOLL_IN); + }else{ + ep.ctl (TLMPEPOLL_CTL_MOD,fd,TLMPEPOLL_IN|TLMPEPOLL_OUT); + } + } + } + if ((pt->events & TLMPEPOLL_OUT) != 0){ + if (mp[fd].send(fd)){ + ep.ctl (TLMPEPOLL_CTL_MOD,fd,TLMPEPOLL_IN); + } + } + } + } + } + } + } + return 0; + } + + + #endif + *** 1.33r5/linuxconf/diawxgtk/remadmin.cc Fri Apr 16 13:47:39 2004 --- 1.33r5/linuxconf/diawxgtk/remadmin.cc Thu Sep 23 22:04:59 2004 *************** *** 956,962 **** gr->delall(); } gr->logicaltop = true; ! gr->max_width = 10000; ctx.newlevel (gr); }else if (bk != NULL){ MFORM *gr; --- 956,962 ---- gr->delall(); } gr->logicaltop = true; ! //gr->max_width = 10000; ctx.newlevel (gr); }else if (bk != NULL){ MFORM *gr; *************** *** 970,976 **** } bk->selpage (gr); gr->logicaltop = true; ! gr->max_width = 10000; ctx.newlevel (gr); }else{ MAINFORM *gr = NULL; --- 970,976 ---- } bk->selpage (gr); gr->logicaltop = true; ! //gr->max_width = 10000; ctx.newlevel (gr); }else{ MAINFORM *gr = NULL; *************** *** 1115,1121 **** setcontext (ctx,args[1]); if (ctx.level > level){ wxFORMBASE *mf = ctx.tbfl[ctx.level]; ! BUG("Dump"); //if (mf == NULL) mf = ctx.tbbk[ctx.level]; if (mf != NULL){ mf->report_button (args[2],true,NULL,"",0); --- 1115,1121 ---- setcontext (ctx,args[1]); if (ctx.level > level){ wxFORMBASE *mf = ctx.tbfl[ctx.level]; ! //BUG("Dump"); //if (mf == NULL) mf = ctx.tbbk[ctx.level]; if (mf != NULL){ mf->report_button (args[2],true,NULL,"",0); *** 1.33r5/linuxconf/diawxgtk/formbase.cc Wed Jun 9 14:03:38 2004 --- 1.33r5/linuxconf/diawxgtk/formbase.cc Thu Sep 23 22:00:04 2004 *************** *** 112,122 **** --- 112,127 ---- */ PUBLIC void wxFORMBASE::fit2top() { + extern int layout_indent; + layout_debug (id,"base fit2top start\n"); + layout_indent++; wxWindow *p = GetParent(); while (p != NULL){ p->Fit(); p = p->GetParent(); } + layout_indent--; + layout_debug (id,"base fit2top end\n"); } /* *************** *** 415,462 **** PUBLIC VIRTUAL bool FORMBASE::doalllayout() { ! bool ret = false; ! #if 0 ! int nb = nbc; ! if (max_height == 10000 && max_width == 10000){ ! // Figure out auto-scroll triggers ! bool autolimit = true; ! for (int i=0; itype == T_FORM ! || c->type == T_TEXT ! || c->type == T_CLIST ! || c->type == T_SHEET ! || c->type == T_BOOK){ ! autolimit = false; ! break; ! } ! } ! if (autolimit){ ! max_height = 200; ! max_width = 600; ! } ! } ! for (int i=0; itype == T_FORM ! || c->type == T_COMBO ! || c->type == T_CLIST ! || c->type == T_SHEET ! || c->type == T_BOOK){ ! FORMBASE *b = c->getformbase(); ! if (b->doalllayout()) ret = true; ! if (c->weightx ==0 && c->weighty == 0){ ! b->getweight(c->weightx,c->weighty); ! } ! } ! } ! if (!gettop()->was_resized() || !layout_once || ret){ ! dolayout(max_width,max_height,false); ! } ! if (pref_width == -1) GetSize (&pref_width,&pref_height); ! #endif ! return ret; } PUBLIC void FORMBASE::resetlayout() --- 420,426 ---- PUBLIC VIRTUAL bool FORMBASE::doalllayout() { ! return false; } PUBLIC void FORMBASE::resetlayout() *** 1.33r5/linuxconf/diawxgtk/layout.cc Wed Apr 7 13:04:12 2004 --- 1.33r5/linuxconf/diawxgtk/layout.cc Thu Sep 23 21:56:34 2004 *************** *** 4,15 **** --- 4,23 ---- int layout_indent = 1; void layout_debug (const char *id, const char *ctl, ...) { + if (1 || strncmp(id,"fram",4)==0){ for (int i=0; i maxh ? maxh : v_pos; + if (strncmp(id,"fram",4)==0) need_vscroll = false; if (need_vscroll){ setvscroll(); maxw -= 20; *************** *** 503,509 **** bool need_hscroll = !istop() && (h_pos > maxw || hscroll != NULL); if (force && maxw > h_pos) h_pos = maxw; int new_width = h_pos > maxw ? maxw : h_pos; ! // fprintf (stderr,"need_hscroll %s %d %p force %d h_pos %d maxw %d doc_width %d\n",id,need_hscroll,hscroll,force,h_pos,maxw,doc_width); if (need_hscroll){ sethscroll(); hscroll->SetScrollbar(0,new_width,document_width,200); --- 512,519 ---- bool need_hscroll = !istop() && (h_pos > maxw || hscroll != NULL); if (force && maxw > h_pos) h_pos = maxw; int new_width = h_pos > maxw ? maxw : h_pos; ! layout_debug (id,"need_hscroll %d %p force %d h_pos %d maxw %d max_width %d\n",need_hscroll,hscroll,force,h_pos,maxw,max_width); ! //if (strncmp(id,"fram",4)==0) need_hscroll = false; if (need_hscroll){ sethscroll(); hscroll->SetScrollbar(0,new_width,document_width,200); *************** *** 539,549 **** PUBLIC VIRTUAL void MFORM::dolayout(int maxw, int maxh, bool force, wxSize &give) { ! //layout_debug (id,"dolayout1\n"); layout_indent++; FitStrategie_marge(sidetitle != NULL ? 20 : 0,0,0,0,true,maxw,maxh, force,give); layout_indent--; ! //layout_debug (id,"dolayout2\n"); } class MFORM_SIZER: public wxSizer{ --- 549,559 ---- PUBLIC VIRTUAL void MFORM::dolayout(int maxw, int maxh, bool force, wxSize &give) { ! layout_debug (id,"dolayout1\n"); layout_indent++; FitStrategie_marge(sidetitle != NULL ? 20 : 0,0,0,0,true,maxw,maxh, force,give); layout_indent--; ! layout_debug (id,"dolayout2\n"); } class MFORM_SIZER: public wxSizer{ *************** *** 583,589 **** mf->dolayout (mf->max_width,mf->max_height,false,give); last_width = std_width = give.GetWidth(); last_height = std_height = give.GetHeight(); ! //layout_debug (mf->id,"MinSize %d %d\n",std_width,std_height); SetMinSize (std_width,std_height); mf->SetSizeHints (std_width,std_height); mf->pref_width = std_width; --- 593,599 ---- mf->dolayout (mf->max_width,mf->max_height,false,give); last_width = std_width = give.GetWidth(); last_height = std_height = give.GetHeight(); ! layout_debug (mf->id,"MinSize %d %d\n",std_width,std_height); SetMinSize (std_width,std_height); mf->SetSizeHints (std_width,std_height); mf->pref_width = std_width; *************** *** 593,601 **** PROTECTED wxSize MFORM_SIZER::CalcMin() { ! //layout_debug (mf->id,"Calcmin1 %d %d\n",last_width,last_height); layout_if(); ! //layout_debug (mf->id,"Calcmin2 %d %d\n",last_width,last_height); return wxSize (std_width,std_height); } --- 603,611 ---- PROTECTED wxSize MFORM_SIZER::CalcMin() { ! layout_debug (mf->id,"Calcmin1 last(%d,%d) std(%d,%d)\n",last_width,last_height,std_width,std_height); layout_if(); ! layout_debug (mf->id,"Calcmin2 last(%d,%d) std(%d,%d)\n",last_width,last_height,std_width,std_height); return wxSize (std_width,std_height); } *************** *** 612,627 **** *pt='a'; } } ! //layout_debug (mf->id,"RecalcSizes1 now[%d %d] last[ %d %d] std[%d %d]\n",width,height,last_width,last_height,std_width,std_height); if (last_width != width || last_height != height){ ! // layout_debug (mf->id,"RecalcSizes2 now[%d %d] last[ %d %d] std[%d %d]\n",width,height,last_width,last_height,std_width,std_height); layout_indent++; mf->resizeitems (width-last_width,height-last_height); last_width = width; last_height = height; layout_indent--; } ! //layout_debug (mf->id,"RecalcSizes3\n"); } /* --- 622,637 ---- *pt='a'; } } ! layout_debug (mf->id,"RecalcSizes1 now[%d %d] last[ %d %d] std[%d %d]\n",width,height,last_width,last_height,std_width,std_height); if (last_width != width || last_height != height){ ! layout_debug (mf->id,"RecalcSizes2 now[%d %d] last[ %d %d] std[%d %d]\n",width,height,last_width,last_height,std_width,std_height); layout_indent++; mf->resizeitems (width-last_width,height-last_height); last_width = width; last_height = height; layout_indent--; } ! layout_debug (mf->id,"RecalcSizes3\n"); } /* *** 1.33r5/linuxconf/diawxgtk/mform.cc Wed Jun 9 15:07:45 2004 --- 1.33r5/linuxconf/diawxgtk/mform.cc Thu Sep 23 21:07:46 2004 *************** *** 258,263 **** --- 258,264 ---- if (trigger != NULL) max_height = atoi(trigger); trigger = rem_getvar("htrigger"); if (trigger != NULL) max_width = atoi(trigger); + fprintf (stderr,"form %s max_width=%d max_height=%d\n",id,max_width,max_height); doc_width = rem_getvarval ("docw"); doc_height = rem_getvarval ("doch"); // fprintf (stderr,"document spec %d %d\n",doc_width,doc_height); *************** *** 1519,1525 **** { int w,h; GetClientSize(&w,&h); ! //layout_debug (id,"Start resizeitems %d %d %d %d\n",w,h,diffx,diffy); } if (diffx == 0 && diffy == 0) return; struct { --- 1520,1526 ---- { int w,h; GetClientSize(&w,&h); ! layout_debug (id,"Start resizeitems %d %d %d %d\n",w,h,diffx,diffy); } if (diffx == 0 && diffy == 0) return; struct { *************** *** 1579,1585 **** GetClientSize (&w,&h); wxSize sz; dolayout(w,h,true,sz); ! //layout_debug (id,"resizeitems dolayout fin %d %d\n",w,h); } PUBLIC void MFORM::getweight (int &w, int &h) --- 1580,1586 ---- GetClientSize (&w,&h); wxSize sz; dolayout(w,h,true,sz); ! layout_debug (id,"resizeitems dolayout fin %d %d\n",w,h); } PUBLIC void MFORM::getweight (int &w, int &h) *** 1.33r5/linuxconf/diawxgtk/wxbook.cc Wed Jun 2 16:05:56 2004 --- 1.33r5/linuxconf/diawxgtk/wxbook.cc Thu Sep 23 22:00:14 2004 *************** *** 23,33 **** --- 23,38 ---- */ PUBLIC void wxBOOK::fit2top() { + extern int layout_indent; + layout_debug (id,"book fit2top start\n"); + layout_indent++; wxWindow *p = GetParent(); while (p != NULL){ p->Fit(); p = p->GetParent(); } + layout_indent--; + layout_debug (id,"book fit2top end\n"); } PUBLIC void wxBOOK::selpage (wxFORMBASE *f) *** 1.33r5/linuxconf/diawxgtk/wxtree.cc Wed Jun 9 13:34:10 2004 --- 1.33r5/linuxconf/diawxgtk/wxtree.cc Fri Sep 17 11:36:16 2004 *************** *** 135,141 **** /* We walk the tree to replace, add or delete nodes. ! Node to be deleted have $del=1. next nodes are also deleted. The client is using the Setval protocol to change the nodes and always send a Setval with $del=1 to ask us to "cut" the end of a branch, even if there is more nodes or not. --- 135,141 ---- /* We walk the tree to replace, add or delete nodes. ! Node to be deleted have $del=1. Next nodes are also deleted. The client is using the Setval protocol to change the nodes and always send a Setval with $del=1 to ask us to "cut" the end of a branch, even if there is more nodes or not.