home *** CD-ROM | disk | FTP | other *** search
/ Danny Amor's Online Library / Danny Amor's Online Library - Volume 1.iso / html / faqs / faq / solaris2 / porting-faq < prev    next >
Encoding:
Text File  |  1995-07-25  |  59.7 KB  |  1,691 lines

  1. Subject: Solaris 2 Porting FAQ
  2. Newsgroups: comp.unix.solaris,comp.answers,news.answers
  3. From: meyer@frostbite-falls.uoregon.edu (David M. Meyer 503/346-1747)
  4. Date: 13 Oct 1994 12:46:01 GMT
  5.  
  6.  
  7. Archive-name:   Solaris2/porting-FAQ
  8. Last-modified:  Thursday, October 13, 1994
  9. Version:        2.16
  10.  
  11. Solaris 2 Porting FAQ
  12. [Last modified: 13 October 1994]
  13.  
  14. This article contains the answers to some Frequently Asked
  15. Questions (FAQ) often seen in comp.unix.solaris that relate to
  16. porting BSD/Solaris 1 applications to Solaris 2. Over the first
  17. few days of its existence, it has evolved into a more general
  18. discussion about portability among Unix systems, especially as it
  19. relates to BSD, ANSI, POSIX, and SVID compliant systems.  It is
  20. hoped that this document will help reduce volume in this
  21. newsgroup and to provide hard-to-find information of general
  22. interest.
  23.         
  24.         Please redistribute this article!
  25.  
  26. This FAQ is maintained by David Meyer (meyer@ns.uoregon.edu).
  27. Send updates and corrections to me at this address.  It would
  28. help if the subject line contained the phrase "FAQ".
  29.  
  30. This article includes answers to the following questions.  Ones
  31. marked with a + indicate questions new to this issue; those with
  32. changes of content since the last issue are marked by *:
  33.  
  34. 0)  Which preprocessor symbols to use?
  35. 1)  Some Include File Issues
  36. 2)  Libraries
  37. 3)* Possible ANSI/POSIX/SVR4 replacements for some popular BSD functions 
  38. 4)  Signal Primer
  39. 5)  Waiting for Children to Exit
  40. 6)  Dealing with Shadow Password Files
  41. 7)  Some Compatibility Problems
  42. 8)  Other Resources
  43.  
  44. -----------------------------------------------------------------------------
  45. 0) TOPIC: Which preprocessor symbols to use?
  46.  
  47. [Last modified: 11 October 93]
  48.  
  49. [Editor's Note: This section began life as a Solaris 1 and 
  50. Solaris 2 centric discussion. However, it has grown into a more 
  51. generalized portability discussion. I believe that this is a
  52. useful discussion, but it appears that contrasting styles,
  53. preferences, and requirements will make consensus difficult. DM]
  54.  
  55. Answer: This is a difficult and controversial question.
  56.  
  57. In order to understand the following discussion, we need to be
  58. aware of the following standards:
  59.  
  60. ANSI C (ANSI X3J11) 
  61.                 
  62.         This is the standard C definition, originally adopted as
  63.         American National Standard X3.159-1989 and has since been
  64.         adopted as international standard ISO/IEC 9899:1990.
  65.  
  66.                 
  67. POSIX.1 (IEEE 1003.1-1990)
  68.  
  69.         POSIX.1, the Portable Operating System Interface for
  70.         Computer Environments,  is a system level API that deals
  71.         with the function and format of system calls and
  72.         utilities such as signal handling. 
  73.  
  74. SVID3
  75.  
  76.         SVID3, the System V Interface Definition Issue 3, is is
  77.         fully compliant with POSIX.1, and is a arguably subset of
  78.         the SVR4 system API. For example, SVID3 doesn't have
  79.         "-ldl", but many people consider it of the SVR4 API. That
  80.         is, a system could be SVID3-compliant without necessarily
  81.         being an SVR4 system.
  82.  
  83. XPG
  84.  
  85.         XPG, X/Open Company Ltd's X/Open Portability Guide, is a
  86.         broad document which covers a great number of areas,
  87.         including operating systems and programming languages,
  88.         system interfaces, and internetworking. The latest
  89.         version, XPG4, groups these components into "profiles",
  90.         which are packaged together according to market needs.
  91.  
  92.  
  93. Two additional standards are relevant for Suns:
  94.  
  95. SCD 2.0 and x86 ABIs
  96.  
  97.         SCD 2.0 is the SPARC Compliance Definition 2.0. The SCD
  98.         has two components: On the hardware side, 
  99.  
  100.          (i).   System Compliance Test verifies that the hardware
  101.                 and operating system successfully emulates what
  102.                 Sun is doing. It covers low level system issues
  103.                 such as alignment, and linking and loading. 
  104.  
  105.         (ii).   The SPARC Application Verifier tests software to
  106.                 be sure that it runs on SCD hardware. 
  107.  
  108.                 
  109. As an example of subtle differences that exist between the BSD
  110. interface and SVID/POSIX standards, consider the BSD mktemp(3)
  111. call. The SunOS 4.1 mktemp() replaced the trailing X characters
  112. with the letter (e.g., X) and the current process ID. The SVID
  113. and SVR4 versions specify only that the six trailing Xs be
  114. replaced with a character string that can be used to create a
  115. unique filename, and does not depend on the specific name of the
  116. file.  Thus, the BSD and SVR4/SVID3 versions are only
  117. semantically equivalent in the case where only the application
  118. cares that the filename is unique.
  119.  
  120. Now, the basic philosophical question of which preprocessor
  121. contstucts to use here would appear to revolve around the
  122. following choices: 
  123.  
  124.         (i).    Use a high level, large grained standard
  125.                 definition (e.g., _POSIX_SOURCE). In this case,
  126.                 features are implicitly defined. One problem with
  127.                 such definitions is that they may cause other
  128.                 useful functions to become unavailable. However,
  129.                 there are several such definitions in common use.
  130.                 For operating systems, we have
  131.  
  132.                         SVR4
  133.                         SYSV
  134.                         BSD
  135.                         OSF1
  136.  
  137.                 to name a few. For standards, we are mainly
  138.                 interested interested symbols such as 
  139.  
  140.                         __STDC__
  141.                         _POSIX_SOURCE
  142.                         _XOPEN_SOURCE
  143.                 
  144.   
  145.                 This method is not without pitfalls.  For
  146.                 example, the Sun SC2.0.1 compiler defines
  147.                 __STDC__ as 0 when compiling in transition mode
  148.                 (-Xt), only setting it to 1 when the strict ANSI 
  149.                 mode (-Xc) is used. The expression 
  150.  
  151.                         #if (__STDC__ - 0 == 0) 
  152.  
  153.                 can be used to recognize strict v. transition
  154.                 ANSI modes. On Solaris 2, if you compile with
  155.                 -Xc, you will lose all non-ANSI functionality.
  156.                 However, you can define _POSIX_SOURCE or
  157.                 _XOPEN_SOURCE to get a POSIX or XOPEN
  158.                 environment.   
  159.                 
  160.                 If you use _POSIX_SOURCE, .eg., 
  161.                 
  162.                         #define _POSIX_SOURCE 1
  163.  
  164.                 then all symbols not defined by Standard C or the
  165.                 POSIX standard will be hidden (except those with
  166.                 leading underscores). If you wish to use
  167.                 _POSIX_SOURCE, be sure to define it before
  168.                 including any standard header files, and avoid
  169.                 name clashes by not defining any symbols that
  170.                 begin with "_" (Similarly, note that almost all
  171.                 names beginning with  "E" are reserved by
  172.                 errno.h, and many names prefixed by "va_"
  173.                 reserved by stadarg.h). 
  174.  
  175.                 One more note on _POSIX_SOURCE:   SunOS 5.3 has
  176.                 introduced the new header file <sys/feature_tests.h>. 
  177.                 This file is included in all files which have
  178.                 _POSIX_SOURCE dependancies. 
  179.  
  180.                 A new symbol,  _POSIX_C_SOURCE was introduced in POSIX.2
  181.                 (V1 P720, L51) as a mechanism to enable POSIX.1 and
  182.                 POSIX.2 symbols. Its values are as follows:
  183.  
  184.                 /*
  185.                  *      Values of _POSIX_C_SOURCE
  186.                  *
  187.                  *              undefined       not a POSIX compilation
  188.                  *                      1       POSIX.1-1990 compilation
  189.                  *                      2       POSIX.2-1992 compilation
  190.                  *                1993xxL       POSIX.4-1993 compilation
  191.                  */
  192.  
  193.  
  194.                 This means that POSIX.2 says that a value of 1 = POSIX.1
  195.                 and a value of 2 = POSIX.1 & POSIX.2. The idea here is
  196.                 to provide a single control point over the POSIX namespace,
  197.                 rather than having to edit each file individually. 
  198.  
  199.                 Another potential portability pitfall is the
  200.                 __svr4__ feature defined by the FSF (gcc). If you
  201.                 depend on __svr4__, you may lose portability.
  202.                 gcc also defines sun if you don't give the -ansi
  203.                 argument. If you use -ansi,  then sun is not
  204.                 defined and __sun__ is.
  205.  
  206.                 Finally, complexity may arise surrounding a
  207.                 feature which may be part of some vendor's
  208.                 version of some system Y, but may also exist in
  209.                 non-Y compliant systems. Consider, for example,
  210.                 shadow passwording. Systems conforming to the
  211.                 latest SVID (e.g., SVR4) have shadow.h, but there
  212.                 are many systems that have shadow.h without
  213.                 conforming to the SVID.
  214.  
  215.                 So, in general, for code that uses a STD_FEATURE and
  216.                 runs on systems W, Y, and Z, you are left with 
  217.                 something that may look like   
  218.  
  219.                         #if defined(W)                          ||
  220.                            (defined(Y) && _Y_VERSION_ > 3)      ||
  221.                            (defined(Z) || defined(__Z__))
  222.                         #include <STD_FEATURE.h>
  223.                         #endif
  224.  
  225.                 [W, Y, Z are things like SVR4, AIX, NeXT, BSD,
  226.                 and so on. STD_FEATURE.h is something like shadow.h] 
  227.  
  228.                 This example exposes two problems the large
  229.                 grained method. First, it forces one to keep
  230.                 track of exactly which vendors supply
  231.                 <STD_FEATURE.h>.  Second, the complexity of the
  232.                 preprocessor expressions may be a serious
  233.                 consideration, since their complexity is
  234.                 something like     
  235.  
  236.                         O(n*m) where
  237.  
  238.                         n = the number of standard features, and
  239.                         m = number of vendors/systems
  240.  
  241.  
  242.         (ii).   Define new fine-grained feature tests (e.g.,
  243.                 HAVE_POSIX_SIGNALS, or HAVE_SHADOW_H) for
  244.                 features of interest. Such fine-grained features
  245.                 could be used in conjunction with large grained
  246.                 definitions. An nice example of using feature
  247.                 definitions is the GNU configure program. It
  248.                 uses, for example, the features HAVE_BCOPY and
  249.                 HAVE_MEMSET to enable either the bcopy (BSD) or
  250.                 memset (ANSI) functions.   
  251.  
  252.                 Feature testing has the advantage of being useful
  253.                 for automatic configuration with programs such as
  254.                 GNU configure. GNU configure outputs statements
  255.                 of the form
  256.                 
  257.  
  258.                         #define HAVE_aaaa
  259.                         #define HAVE_bbbb
  260.                         #define HAVE_cccc
  261.                         ....
  262.  
  263.                 Another way to generate a feature set is by
  264.                 using the symbol defining the system, e.g., 
  265.  
  266.                         #ifdef SVR4
  267.                         #define HAVE_aaaa
  268.                         #define HAVE_bbbb
  269.                         #define HAVE_cccc
  270.                         ....
  271.  
  272.                         #endif
  273.                         #ifdef BSD43
  274.                         #define HAVE_yyyy
  275.                         ...
  276.                         #endif
  277.                         #ifdef NEWTHING
  278.                         #define HAVE_zzzz
  279.                         ...
  280.                         #endif
  281.         
  282.                 Feature testing also helps to avoid constructs
  283.                 such as 
  284.  
  285.                 #if defined(_POSIX_SOURCE) || defined(_XOPEN_SOURCE)
  286.  
  287.                 [Editor's Note: Finally, an observation: The real
  288.                 issue here appears to be how many of these
  289.                 "features" are migrating to the standard
  290.                 operating systems and interfaces, and how many
  291.                 vendors are implementing these standards. In
  292.                 general, some people feel that feature testing
  293.                 improves portability (and readability), and
  294.                 others believe that the feature testing style 
  295.                 decreases portability and readability. DM]  
  296.  
  297.  
  298.         (iii).  Use some part of the feature's definition itself
  299.                 to enable the feature, for example 
  300.  
  301.                         #ifdef _IOLBF
  302.                                 setvbuf(stderr, NULL, _IOLBF, 0);
  303.                         #else
  304.                                 setlinebuf(stderr);
  305.                         #endif  /* _IOLBF  */
  306.  
  307.                 Note that in this case, another, possibly better
  308.                 option is (consider the case in which some vendor
  309.                 has inadvertently defined _IOLBF for some other
  310.                 purpose):
  311.  
  312.                         #ifdef   __STDC__
  313.                                 setvbuf(stderr, NULL, _IOLBF, 0);
  314.                         #else
  315.                                 setlinebuf(stderr);
  316.                         #endif  /* __STDC__  */
  317.  
  318.                 since setvbuf is required by Standard C.
  319.  
  320.  
  321.  
  322.         Finally, some people have suggested the use of
  323.         expressions like 
  324.  
  325.                 #if defined(sun) && defined(__svr4__)
  326.                         <Solaris 2 centric code>
  327.                 #else 
  328.                         ...
  329.                 #endif
  330.  
  331.  
  332.         As noted above, the __svr4__ feature is defined by the
  333.         FSF (gcc). If you depend on __svr4__, you may lose 
  334.         portability. gcc also defines sun if you don't give the
  335.         -ansi argument. If you use -ansi,  then sun is not
  336.         defined and __sun__ is. The implication here is that
  337.         depending on symbols defined by a given compiler can
  338.         reduce portability.
  339.  
  340.         In general, such a construct should be used if and only if
  341.         the code in question cannot be covered by some standard
  342.         (e.g., SVR4, _POSIX_SOURCE, etc.). Note that it is also
  343.         compiler specific.
  344.         
  345.  
  346. -----------------------------------------------------------------------------
  347. 1) TOPIC: Include File Issues
  348.  
  349. [Last modified: 19 August 93]
  350.  
  351. The first and apparently most common problem is that
  352. /usr/include/strings.h is not ANSI compliant, and as such does not
  353. exist on Solaris 2 (or SVR4). It should be replaced by
  354. /usr/include/string.h, e.g. (following GNU feature definition
  355. conventions)
  356.  
  357.         #if HAVE_STRING_H || defined(STDC_HEADERS)
  358.         #include <string.h>
  359.         #else
  360.         #include <strings.h>
  361.         #endif
  362.         #if defined(STDC_HEADERS)
  363.         #include <stdlib.h>
  364.         #endif /* HAVE_STRING_H */
  365.  
  366.         while ANSI-C requires the name be string.h, one might
  367.         define this as
  368.  
  369.         #ifdef __STDC__
  370.         #include <string.h>
  371.         #else
  372.         #include <strings.h>
  373.         #endif  /* __STDC__ */
  374.  
  375.         However, this again neglects the case in which the vendor 
  376.         provides string.h in a non-ANSI environment.
  377.  
  378.                         
  379. Another thing to watch is for the symbols O_CREAT, O_TRUNC, and
  380. O_EXCL being undefined. On BSD systems, these are defined in
  381. <sys/file.h>. On Solaris 1 systems (beginning with SunOS 4.0) ,
  382. these are defined in <sys/fnctlcom.h> (which is included in
  383. <sys/file.h>). On a POSIX compliant system, these symbols are
  384. defined in <fcntl.h>, which is not included in <sys/file.h>.
  385. Since <fcntl.h> is defined on SunOS 4.1.x, replacing <sys/file.h>
  386. with <fcntl.h> works for both SunOS 4.1.x and SVR4. See, for
  387. example, section 5.3.1.1 of the POSIX spec.
  388.  
  389.  
  390. -----------------------------------------------------------------------------
  391.  
  392. 2) TOPIC: Libraries
  393.  
  394. [Last modified: 12 Feburary 94]
  395.  
  396. Network Libraries:
  397.  
  398. Many of the network functions and definitions that were present
  399. in the BSD libc are now in libnsl.so and libsocket.so. Thus
  400. networking code will generally need to be linked with -lsocket
  401. -lnsl. Since libsocket.so requires libnsl.so (it is NEEDED), you must
  402. specify them in this order. Note that you need libnsl.so for functions
  403. like gethostbyname (see gethostbyname note below). Incidently, you can
  404. look at selected parts of an object file using dump(1), e.g.,  
  405.  
  406.         % dump -Lv /usr/lib/libsocket.so
  407.  
  408.         /usr/lib/libsocket.so:
  409.  
  410.           **** DYNAMIC SECTION INFORMATION ****
  411.         .dynamic :
  412.         [INDEX] Tag      Value
  413.         [1]     NEEDED   libnsl.so.1
  414.         [2]     INIT     0x3174
  415.  
  416.         [...]
  417.         
  418. Regular Expressions
  419.  
  420. Another problem frequently encountered is that the regexp
  421. functions (see regexpr(3G)) are not defined in libc. On Solaris
  422. 2, you must link with libgen.a (-lgen) in order to get these
  423. definitions. See Intro(3) for a more complete discussion.
  424.  
  425. Name List (nlist)
  426.  
  427. You must link with libelf.a (-lelf) to get the nlist(3E)
  428. definition. 
  429.  
  430. -----------------------------------------------------------------------------
  431.  
  432. 3)* TOPIC: Possible ANSI/POSIX/SVR4 replacements for some popular
  433.            BSD functions  
  434.  
  435. [Last modified: 13 September 1994]
  436.  
  437. [Editor's Note: Once again, this section began life a SunOS 4.1.x 
  438. and SunOS 5.x centric discussion.  It too has grown into a
  439. discussion dealing with general portability for BSD to other
  440. standards. DM]
  441.  
  442. Problems finding functions that were defined in the BSD libc.a is
  443. one of the most frequently asked porting questions. The following
  444. table and code fragments suggest substitutes for some common BSD
  445. constructs (more complete lists can be found in some of the texts
  446. listed in section 7 below). 
  447.  
  448. In addtion to the possibilites listed below, many people have 
  449. created compatability libraries using GNU autoconfigure. An
  450. example of this is the "generic" libary from Dan Stromberg
  451. (strombrg@hydra.acs.uci.edu). It can be found on 
  452. ftp.uci.edu:/pub/generic/generic.tar.gz.
  453.  
  454.  
  455. BSD                     Possibilities           Standards/Notes
  456. ============================================================================
  457. srandom(seed)           srand(seed)             ANSI-C (Also, some older UNIX)
  458.                         srand48(seed)           SVR4
  459.  
  460. non-ANSI signal()       sigset()                SVR4   (systems calls not
  461. (e.g., SunOS)                                          restarted, but bytes r/w
  462.                                                        returned, else EINTR) 
  463.                         sigaction               POSIX  (but extensible by
  464.                                                        implementation) 
  465.  
  466. sigvec                  sigaction               POSIX
  467. sigblock                sigprocmask             POSIX
  468.                         sigset(.., SIG_HOLD)
  469.                         sighold                 SVR4
  470. sigsetmask              sigprocmask             POSIX
  471.                         sigset/sigrelse         SVR4    
  472.  
  473. sigpause                sigsuspend              POSIX
  474.         
  475. setjmp                  sigsetjmp               POSIX 
  476. longjmp                 siglongjmp              POSIX 
  477.  
  478. statfs                  statvfs                 SVR4
  479.  
  480. bcopy                   memmove                 ANSI-C (BSD bcopy() handles
  481.                                                        overlapping areas
  482.                                                        correctly, as does
  483.                                                        memmove, but not memcpy)
  484.  
  485. bzero                   memset                  ANSI-C
  486.  
  487. index                   strchr                  ANSI-C
  488. rindex                  strrchr                 ANSI-C
  489.  
  490. getwd                   getcwd                  POSIX
  491.  
  492. getrusage               open,ioctl              The getrusage information
  493.                                                 (and a whole lot more) can be
  494.                                                 found in the prusage structure.
  495.                                                 Use the PIOCUSAGE ioctl. See
  496.                                                 the example below and the
  497.                                                 proc(4) man page for detail. 
  498.  
  499.  
  500. gethostname             sysinfo(SI_HOSTNAME,..) SVR4   See sysinfo(2) for
  501.                                                        many other possible
  502.                                                        values
  503.  
  504. getdtablesize           sysconf(_SC_OPEN_MAX)   POSIX  See sysconf(3C) for
  505.                                                        many other values
  506.                                                        available via sysconf.
  507.  
  508. strptime                                                See code from Kevin Ruddy
  509.                                                         below
  510.  
  511. timelocal               mktime                          
  512.  
  513. wait3 w/o rusage        waitpid                 POSIX
  514. wait3                   waitid                  SVR4
  515.  
  516. usleep                   nanosleep              POSIX See nanosleep(3R) on
  517.                                                 Solaris 2.3 (see libposix4.a) 
  518.                                                 For a Solaris 2.[0-2], see the
  519.                                                 example below.
  520.  
  521.  
  522.  
  523.  
  524. ------------------------------------------------------------------
  525.  
  526.         Timing Problems
  527.         ---------------
  528.  
  529.         POSIX defines the <sys/times.h> function for subsecond
  530.         timing.  Sun seems to provide about 1/60 second accuracy. 
  531.  
  532.         #include <stdio.h>
  533.         #include <sys/times.h>   /* for struct tms and times() */
  534.         #include <time.h>        /* for CLK_TCK value */
  535.  
  536.         int main(void) {
  537.            struct tms tms_start, tms_finish;  /* user and system time */
  538.            clock_t start, finish;             /* real time */
  539.            start = times( &tms_start );
  540.            /* ... do something ... */
  541.            finish = times( &tms_finish );
  542.            printf("(in seconds) %f real, %f system, %f user\n",
  543.                (finish-start) / (double)CLK_TCK,
  544.                (tms_finish.tms_stime-tms_start.tms_stime) / (double)CLK_TCK,
  545.                (tms_finish.tms_utime-tms_start.tms_utime) / (double)CLK_TCK);
  546.            return 0;
  547.         }
  548.  
  549.         You might want to divide CLK_TCK by 1000.0 to get more
  550.         precise millisecond values.  times() returns -1 if it
  551.         cannot provide timing information.
  552.  
  553.         While Solaris 2 conforms to POSIX, SunOS 4.1 defines
  554.         times() as returning a flag instead of elapsed real time.
  555.         You can use ftime() to get elapsed real time:
  556.  
  557.         #include <stdio.h>
  558.         #include <sys/types.h>  /* for time_t */
  559.         #include <sys/timeb.h>  /* for ftime() and struct timeb */
  560.  
  561.         int main(void) {
  562.            struct timeb start, finish;
  563.            double real_secs;
  564.            ftime( &start );
  565.            /* ... do something ... */
  566.            ftime( &finish );
  567.            real_secs = finish.time - start.time;
  568.            if ( finish.millitm < start.millitm )
  569.               real_secs = (real_secs-1) +
  570.                           (1000+start.millitm-finish.millitm)/1000.0;
  571.            else
  572.               real_secs = (finish.millitm-start.millitm)/1000.0;
  573.            printf( "That took %f real seconds.", real_secs );
  574.            return 0;
  575.         }
  576.  
  577.         The ANSI C function clock() can also be used for timing.
  578.         It returns elased "processor" time, which is equivalent
  579.         to system+user time. While it also returns a clock_t
  580.         value, you must divide the difference between to calls to
  581.         clock() by CLOCKS_PER_SEC, *not* CLK_TCK.  The values are
  582.         different by orders of magnitude.  SunOS 4.1 doesn't seem
  583.         to provide CLOCKS_PER_SEC or CLK_TCK in <time.h>.  Try
  584.         10000000 and 60, respectively.
  585.  
  586.  
  587.  
  588.         Compatibility Functions
  589.         -----------------------
  590.  
  591.         /*
  592.          *      getrusage --
  593.          */
  594.  
  595.         #include <sys/resource.h>
  596.         #ifndef RUSAGE_SELF
  597.         #include <sys/procfs.h>
  598.         #endif
  599.  
  600.         #ifdef PIOCUSAGE
  601.                 int             fd;
  602.                 char            proc[SOMETHING];
  603.                 prusage_t       prusage;
  604.  
  605.                 sprintf(proc,"/proc/%d", getpid());
  606.                 if ((fd = open(proc,O_RDONLY)) == -1) {
  607.                         perror("open");
  608.                         ....
  609.                 }
  610.                 if (ioctl(fd, PIOCUSAGE, &prusage) == -1) {
  611.                         perror("ioctl");
  612.                         ...
  613.                 }
  614.                 ....
  615.         #else                   /* Again, assume BSD */
  616.                 if (getrusage(RUSAGE_SELF, &rusage) == -1) {
  617.                         perror("getrusage");
  618.                         ....
  619.                 }
  620.                 ....
  621.         #endif /* PIOCUSAGE */
  622.  
  623.  
  624.  
  625.         /*
  626.          *      setlinebuf --
  627.          *
  628.          */
  629.         
  630.         #ifdef   __STDC__
  631.                 setvbuf(stderr, NULL, _IOLBF, 0);
  632.         #else
  633.                 setlinebuf(stderr);
  634.         #endif  /* __STDC__  */
  635.  
  636.  
  637.         /*
  638.          *      gethostid 
  639.          *
  640.          *      This example has a combination of high-level
  641.          *      (SVR4) and (SI_HW_SERIAL) feature declarations.
  642.          */
  643.         
  644.         #if defined(SVR4) && defined(SI_HW_SERIAL)
  645.         long  gethostid() {
  646.                         
  647.           char buf[128];
  648.                 
  649.           if (sysinfo(SI_HW_SERIAL, buf, 128) == -1) {
  650.             perror("sysinfo");
  651.             exit(1);
  652.           }
  653.           return(strtoul(buf,NULL,0));
  654.         }
  655.         #endif /* SVR4 && SI_HW_SERIAL */
  656.  
  657.  
  658.         /*
  659.          *      getdtablesize --
  660.          *
  661.          *      Several possibilites here. Note that while one
  662.          *      can emulate getdtablesize with getrlimit on SVR4
  663.          *      or 4.3BSD (or later), these systems should be
  664.          *      POSIX.1 compliant, so sysconf is preferred.
  665.          *
  666.          */
  667.  
  668.         #ifdef  _SC_OPEN_MAX            /* POSIX -- preferred */
  669.                 if ((tableSize = sysconf(_SC_OPEN_MAX)) == -1) {
  670.                         perror("sysconf");
  671.                         ...
  672.                 }
  673.         #elif   RLIMIT_NOFILE           /* who is non POSIX but has this? */
  674.                 if (getrlimit(RLIMIT_NOFILE, &rlimit) == -1) {
  675.                         perror("getrlimit");
  676.                         exit(1);
  677.                 }
  678.                 tableSize = rlimit.rlim_max;
  679.         #else                           /* assume old BSD type */
  680.                 tableSize = getdtablesize();
  681.         #endif
  682.  
  683.  
  684. ------------------   
  685.  
  686.         /*
  687.          * gethostname  --
  688.          *
  689.          */
  690.  
  691.         #ifdef  SVR4 
  692.         #include <sys/systeminfo.h>
  693.         #endif  /* SVR4 */ 
  694.  
  695.                 ....
  696.  
  697.                 char buf[MAXHOSTNAME]
  698.  
  699.         #ifdef  SVR4
  700.                 if (sysinfo(SI_HOSTNAME, buf, sizeof(buf)) <0) {
  701.                         perror("SI_HOSTNAME");
  702.                         exit(BAD);
  703.                 }
  704.         #else   /* Assume BSD */
  705.                 if (gethostname(buf, sizeof(buf)) < 0) {
  706.                         perror("gethostname");
  707.                         exit(BAD);
  708.                 }
  709.         #endif  /* SVR4 */
  710.  
  711.         /* buf has hostname here... */
  712.  
  713.  
  714.         /*
  715.          *      usleep(delay)  --
  716.          *
  717.          *      Possible usleep replacement. Delay in microseconds.
  718.          *      Another possiblity is to use poll(2). On Solaris
  719.          *      2.x, select is just a wrapper for poll, so you
  720.          *      are better off using it directly.  If you use,
  721.          *      poll, note that it uses millisecond resolution,
  722.          *      and is not affected by the O_NDELAY and O_NONBLOCK 
  723.          *      flags.
  724.          *
  725.          *      Note that using nanosleep has portability implications,
  726.          *      even across different versions of Solaris 2.x. In
  727.          *      particular, only Solaris 2.3 has libposix4, and 
  728.          *      hence nanosleep. Select (or poll) is a better option if 
  729.          *      you need portability across those versions.
  730.          *
  731.          *      If you define USE_NANOSLEEP, be sure to link with -lposix4
  732.          *
  733.          */
  734.  
  735.         #include <unistd.h>
  736.         #include <stdlib.h>
  737.         #include <stdio.h>
  738.         #include <errno.h>
  739.         #include <time.h>
  740.         #include <sys/time.h>
  741.         #include <sys/param.h>
  742.         #include <sys/types.h>
  743.         #ifdef  USE_POLL
  744.         #include <stropts.h>
  745.         #include <poll.h>
  746.         #endif  /* USE_POLL */
  747.         
  748.         int     usleep(unsigned long int useconds)
  749.         {
  750.         #ifdef  USE_NANOSLEEP
  751.           struct timespec rqtp;
  752.         
  753.           rqtp.tv_sec  = useconds / (unsigned long)  1000000;
  754.           rqtp.tv_nsec = (useconds % (unsigned long) 1000000) * 1000 ;
  755.         
  756.           if (nanosleep(&rqtp,  (struct  timespec *) NULL) == -1)
  757.             perror("nanosleep");
  758.           return (0);
  759.         
  760.         #elif   USE_POOL
  761.           struct pollfd unused;
  762.         
  763.           if (poll(&unused,0,(useconds/1000)) == -1) 
  764.             perror("poll");
  765.           return(0);
  766.         #elif   USE_USLEEP
  767.           struct timeval delay;
  768.         
  769.           delay.tv_sec = 0;
  770.           delay.tv_usec = useconds;
  771.           if (select(0,
  772.                      (fd_set *) NULL,
  773.                      (fd_set *) NULL,
  774.                      (fd_set *) NULL,
  775.                      &delay) == -1)
  776.             perror("select");
  777.           return (0);
  778.         #endif                  /* USE_NANOSLEEP */
  779.         
  780.         
  781.         /*
  782.          *      tzsetwall -- 
  783.          */
  784.         
  785.         void tzsetwall()
  786.         {
  787.           unsetenv("TZ");
  788.           tzset();
  789.         }
  790.  
  791.         /*
  792.          *      gethostybname --
  793.          *
  794.          *      The following code was contributed by Casper H.S. Dik
  795.          *      to address the following problem:
  796.          *
  797.          *      gethostbyname() always returns null in h->aliases.
  798.          *      Now, gethostbyX can be replaced its __switch_gethostbyX
  799.          *      equivalents. However, these are missing from Solaris 2.3.
  800.          *
  801.          *      The _r functions are reentrant.  They have a different
  802.          *      calling sequence. (The __switch_getXXXbyYYY are called
  803.          *      like getXXXbyYYY, the _switch_getXXXbyYYY_r are called
  804.          *      like getXXXbyYYY_r) 
  805.          *
  806.          *      With this bit of knowledge I constructed the code that
  807.          *      follows this message. Just plug it in every program
  808.          *      that requires gethostbyname to work. (Gethostbyaddr()
  809.          *      is added for symmetry). 
  810.          *
  811.          *      You'll need to link with -lnsl -ldl.
  812.          *
  813.          *      It works for Solaris 2.2 and 2.3.  (Compiled on 2.3 or
  814.          *      2.2 it will run 2.2 and 2.3)
  815.          *
  816.          *      Note that as with __switch* _switch*_r is undocumented
  817.          *      and can be changed in the next release.
  818.          *
  819.          */
  820.         
  821.         /*
  822.          *     Proper gethostbyXX function for Solaris 2.0-2.3
  823.          *     (and later ?) 
  824.          *
  825.          *     Fixed in 2.4?
  826.          *
  827.          *     You'll need -ldl added to the link command line.
  828.          *
  829.          *     Casper Dik (casper@fwi.uva.nl)
  830.          *
  831.          */
  832.  
  833.         #include <netdb.h>
  834.         #include <dlfcn.h>
  835.         
  836.         #define HBUFSIZE 4096
  837.         
  838.         static void *dlhandle;
  839.         /* The gethostbyXXX function variables. Named after
  840.         * then .so files they appear in. nsw*.so in SunOS 5.2
  841.         * and earlier, nss_*.so in 5.3 */ 
  842.         static struct hostent *(*nswghba)(const char *, int, int),
  843.                               *(*nswghbn)(const char *),
  844.                               *(*nss_ghba)(const char *,
  845.                                            int, int,
  846.                                            struct hostent *, char *, int, int *),
  847.                               *(*nss_ghbn)(const char *,
  848.                                            struct hostent *, char *, int, int *);
  849.         
  850.         static int dlinit(void)
  851.         {
  852.           static int dlstatus = 0; /* 0 = uninited, 1 = inited & ok, -1 = error */
  853.         
  854.           if (dlstatus)
  855.             return dlstatus;
  856.         
  857.           dlstatus = -1;
  858.         
  859.           dlhandle = dlopen(0, RTLD_LAZY);
  860.         
  861.           if (dlhandle == 0)
  862.             return dlstatus;
  863.         
  864.           /* SunOS 5.0 - 5.2 */
  865.           nswghba = (struct hostent *(*)(const char *, int, int))
  866.             dlsym(dlhandle, "__switch_gethostbyaddr");
  867.         
  868.           nswghbn = (struct hostent *(*)(const char *))
  869.             dlsym(dlhandle, "__switch_gethostbyname");
  870.         
  871.           /* either both should exist or both should not exist */
  872.           if ((nswghbn == 0) != (nswghba == 0))
  873.             return dlstatus;
  874.         
  875.           if (nswghbn)
  876.             return dlstatus = 1;
  877.         
  878.           /* SunOS 5.3 - ? */
  879.           nss_ghba = (struct hostent *(*)
  880.                       (const char *, int, int, struct hostent *, char *, int , int *))
  881.             dlsym(dlhandle, "_switch_gethostbyaddr_r");
  882.         
  883.           nss_ghbn = (struct hostent *(*)
  884.                       (const char *, struct hostent *, char *, int , int *))
  885.             dlsym(dlhandle, "_switch_gethostbyname_r");
  886.         
  887.           /* these two must exist when we get here */
  888.           if (nss_ghbn != 0 && nss_ghba != 0)
  889.             dlstatus = 1;
  890.         
  891.           return dlstatus;
  892.         }
  893.         
  894.         struct hostent *
  895.         gethostbyname(const char *name) {
  896.         
  897.           static struct hostent hp;
  898.           static char buf[HBUFSIZE];
  899.         
  900.           if (dlinit() == -1)
  901.             return 0;
  902.         
  903.           if (nswghbn)
  904.             return nswghbn(name);
  905.           else
  906.             return nss_ghbn(name, &hp, buf, sizeof(buf), &h_errno);
  907.         }
  908.         
  909.         struct hostent *
  910.         gethostbyaddr(const char *addr, int len, int type) {
  911.           static struct hostent hp;
  912.           static char buf[HBUFSIZE];
  913.         
  914.           if (dlinit() == -1)
  915.             return 0;
  916.         
  917.           if (nswghba)
  918.             return nswghba(addr, len, type);
  919.           else
  920.             return nss_ghba(addr,
  921.                             len, type, &hp, buf, sizeof(buf), &h_errno);
  922.         }
  923.  
  924.  
  925. ------------------   
  926. strptime
  927. -----------------
  928.  
  929. /*
  930.  * Copyright (c) 1994 Powerdog Industries.  All rights reserved.
  931.  *
  932.  * Redistribution and use in source and binary forms, without
  933.  * modification, are permitted provided that the following conditions
  934.  * are met:
  935.  * 1. Redistributions of source code must retain the above copyright
  936.  *    notice, this list of conditions and the following disclaimer.
  937.  * 2. Redistributions in binary form must reproduce the above copyright
  938.  *    notice, this list of conditions and the following disclaimer
  939.  *    in the documentation and/or other materials provided with the
  940.  *    distribution.
  941.  * 3. All advertising materials mentioning features or use of this
  942.  *    software must display the following acknowledgement:
  943.  *      This product includes software developed by Powerdog Industries.
  944.  * 4. The name of Powerdog Industries may not be used to endorse or
  945.  *    promote products derived from this software without specific prior
  946.  *    written permission.
  947.  *
  948.  * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
  949.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  950.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  951.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
  952.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  953.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  954.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  955.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  956.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  957.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  958.  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  959.  */
  960.  
  961. #ifndef lint
  962. static char copyright[] =
  963. "@(#) Copyright (c) 1994 Powerdog Industries.  All rights reserved.";
  964. static char sccsid[] = "@(#)strptime.c  0.1 (Powerdog) 94/03/27";
  965. #endif /* not lint */
  966.  
  967. #include <time.h>
  968. #include <ctype.h>
  969. #include <locale.h>
  970. #include <string.h>
  971.  
  972. #define asizeof(a)      (sizeof (a) / sizeof ((a)[0]))
  973.  
  974. #ifndef sun
  975. struct dtconv {
  976.         char    *abbrev_month_names[12];
  977.         char    *month_names[12];
  978.         char    *abbrev_weekday_names[7];
  979.         char    *weekday_names[7];
  980.         char    *time_format;
  981.         char    *sdate_format;
  982.         char    *dtime_format;
  983.         char    *am_string;
  984.         char    *pm_string;
  985.         char    *ldate_format;
  986. };
  987. #endif
  988.  
  989. static struct dtconv    En_US = {
  990.         { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  991.           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
  992.         { "January", "February", "March", "April",
  993.           "May", "June", "July", "August",
  994.           "September", "October", "November", "December" },
  995.         { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
  996.         { "Sunday", "Monday", "Tuesday", "Wednesday",
  997.           "Thursday", "Friday", "Saturday" },
  998.         "%H:%M:%S",
  999.         "%m/%d/%y",
  1000.         "%a %b %e %T %Z %Y",
  1001.         "AM",
  1002.         "PM",
  1003.         "%A, %B, %e, %Y"
  1004. };
  1005.  
  1006. #ifdef SUNOS4
  1007. extern int      strncasecmp();
  1008. #endif
  1009.  
  1010. char    *
  1011. strptime(char *buf, char *fmt, struct tm *tm)
  1012. {
  1013.         char    c,
  1014.                 *ptr;
  1015.         int     i,
  1016.                 len;
  1017.  
  1018.         ptr = fmt;
  1019.         while (*ptr != 0) {
  1020.                 if (*buf == 0)
  1021.                         break;
  1022.  
  1023.                 c = *ptr++;
  1024.  
  1025.                 if (c != '%') {
  1026.                         if (isspace(c))
  1027.                                 while (*buf != 0 && isspace(*buf))
  1028.                                         buf++;
  1029.                         else if (c != *buf++)
  1030.                                 return 0;
  1031.                         continue;
  1032.                 }
  1033.  
  1034.                 c = *ptr++;
  1035.                 switch (c) {
  1036.                 case 0:
  1037.                 case '%':
  1038.                         if (*buf++ != '%')
  1039.                                 return 0;
  1040.                         break;
  1041.  
  1042.                 case 'C':
  1043.                         buf = strptime(buf, En_US.ldate_format, tm);
  1044.                         if (buf == 0)
  1045.                                 return 0;
  1046.                         break;
  1047.  
  1048.                 case 'c':
  1049.                         buf = strptime(buf, "%x %X", tm);
  1050.                         if (buf == 0)
  1051.                                 return 0;
  1052.                         break;
  1053.  
  1054.                 case 'D':
  1055.                         buf = strptime(buf, "%m/%d/%y", tm);
  1056.                         if (buf == 0)
  1057.                                 return 0;
  1058.                         break;
  1059.  
  1060.                 case 'R':
  1061.                         buf = strptime(buf, "%H:%M", tm);
  1062.                         if (buf == 0)
  1063.                                 return 0;
  1064.                         break;
  1065.  
  1066.                 case 'r':
  1067.                         buf = strptime(buf, "%I:%M:%S %p", tm);
  1068.                         if (buf == 0)
  1069.                                 return 0;
  1070.                         break;
  1071.  
  1072.                 case 'T':
  1073.                         buf = strptime(buf, "%H:%M:%S", tm);
  1074.                         if (buf == 0)
  1075.                                 return 0;
  1076.                         break;
  1077.  
  1078.                 case 'X':
  1079.                         buf = strptime(buf, En_US.time_format, tm);
  1080.                         if (buf == 0)
  1081.                                 return 0;
  1082.                         break;
  1083.  
  1084.                 case 'x':
  1085.                         buf = strptime(buf, En_US.sdate_format, tm);
  1086.                         if (buf == 0)
  1087.                                 return 0;
  1088.                         break;
  1089.  
  1090.                 case 'j':
  1091.                         if (!isdigit(*buf))
  1092.                                 return 0;
  1093.  
  1094.                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
  1095.                                 i *= 10;
  1096.                                 i += *buf - '0';
  1097.                         }
  1098.                         if (i > 365)
  1099.                                 return 0;
  1100.  
  1101.                         tm->tm_yday = i;
  1102.                         break;
  1103.  
  1104.                 case 'M':
  1105.                 case 'S':
  1106.                         if (*buf == 0 || isspace(*buf))
  1107.                                 break;
  1108.  
  1109.                         if (!isdigit(*buf))
  1110.                                 return 0;
  1111.  
  1112.                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
  1113.                                 i *= 10;
  1114.                                 i += *buf - '0';
  1115.                         }
  1116.                         if (i > 59)
  1117.                                 return 0;
  1118.  
  1119.                         if (c == 'M')
  1120.                                 tm->tm_min = i;
  1121.                         else
  1122.                                 tm->tm_sec = i;
  1123.  
  1124.                         if (*buf != 0 && isspace(*buf))
  1125.                                 while (*ptr != 0 && !isspace(*ptr))
  1126.                                         ptr++;
  1127.                         break;
  1128.  
  1129.                 case 'H':
  1130.                 case 'I':
  1131.                 case 'k':
  1132.                 case 'l':
  1133.                         if (!isdigit(*buf))
  1134.                                 return 0;
  1135.  
  1136.                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
  1137.                                 i *= 10;
  1138.                                 i += *buf - '0';
  1139.                         }
  1140.                         if (c == 'H' || c == 'k') {
  1141.                                 if (i > 23)
  1142.                                         return 0;
  1143.                         } else if (i > 11)
  1144.                                 return 0;
  1145.  
  1146.                         tm->tm_hour = i;
  1147.  
  1148.                         if (*buf != 0 && isspace(*buf))
  1149.                                 while (*ptr != 0 && !isspace(*ptr))
  1150.                                         ptr++;
  1151.                         break;
  1152.  
  1153.                 case 'p':
  1154.                         len = strlen(En_US.am_string);
  1155.                         if (strncasecmp(buf, En_US.am_string, len) == 0) {
  1156.                                 if (tm->tm_hour > 12)
  1157.                                         return 0;
  1158.                                 if (tm->tm_hour == 12)
  1159.                                         tm->tm_hour = 0;
  1160.                                 buf += len;
  1161.                                 break;
  1162.                         }
  1163.  
  1164.                         len = strlen(En_US.pm_string);
  1165.                         if (strncasecmp(buf, En_US.pm_string, len) == 0) {
  1166.                                 if (tm->tm_hour > 12)
  1167.                                         return 0;
  1168.                                 if (tm->tm_hour != 12)
  1169.                                         tm->tm_hour += 12;
  1170.                                 buf += len;
  1171.                                 break;
  1172.                         }
  1173.  
  1174.                         return 0;
  1175.  
  1176.                 case 'A':
  1177.                 case 'a':
  1178.                         for (i = 0; i < asizeof(En_US.weekday_names); i++) {
  1179.                                 len = strlen(En_US.weekday_names[i]);
  1180.                                 if (strncasecmp(buf,
  1181.                                                 En_US.weekday_names[i],
  1182.                                                 len) == 0)
  1183.                                         break;
  1184.  
  1185.                                 len = strlen(En_US.abbrev_weekday_names[i]);
  1186.                                 if (strncasecmp(buf,
  1187.                                                 En_US.abbrev_weekday_names[i],
  1188.                                                 len) == 0)
  1189.                                         break;
  1190.                         }
  1191.                         if (i == asizeof(En_US.weekday_names))
  1192.                                 return 0;
  1193.  
  1194.                         tm->tm_wday = i;
  1195.                         buf += len;
  1196.                         break;
  1197.  
  1198.                 case 'd':
  1199.                 case 'e':
  1200.                         if (!isdigit(*buf))
  1201.                                 return 0;
  1202.  
  1203.                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
  1204.                                 i *= 10;
  1205.                                 i += *buf - '0';
  1206.                         }
  1207.                         if (i > 31)
  1208.                                 return 0;
  1209.  
  1210.                         tm->tm_mday = i;
  1211.  
  1212.                         if (*buf != 0 && isspace(*buf))
  1213.                                 while (*ptr != 0 && !isspace(*ptr))
  1214.                                         ptr++;
  1215.                         break;
  1216.  
  1217.                 case 'B':
  1218.                 case 'b':
  1219.                 case 'h':
  1220.                         for (i = 0; i < asizeof(En_US.month_names); i++) {
  1221.                                 len = strlen(En_US.month_names[i]);
  1222.                                 if (strncasecmp(buf,
  1223.                                                 En_US.month_names[i],
  1224.                                                 len) == 0)
  1225.                                         break;
  1226.  
  1227.                                 len = strlen(En_US.abbrev_month_names[i]);
  1228.                                 if (strncasecmp(buf,
  1229.                                                 En_US.abbrev_month_names[i],
  1230.                                                 len) == 0)
  1231.                                         break;
  1232.                         }
  1233.                         if (i == asizeof(En_US.month_names))
  1234.                                 return 0;
  1235.  
  1236.                         tm->tm_mon = i;
  1237.                         buf += len;
  1238.                         break;
  1239.  
  1240.                 case 'm':
  1241.                         if (!isdigit(*buf))
  1242.                                 return 0;
  1243.  
  1244.                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
  1245.                                 i *= 10;
  1246.                                 i += *buf - '0';
  1247.                         }
  1248.                         if (i < 1 || i > 12)
  1249.                                 return 0;
  1250.  
  1251.                         tm->tm_mon = i - 1;
  1252.  
  1253.                         if (*buf != 0 && isspace(*buf))
  1254.                                 while (*ptr != 0 && !isspace(*ptr))
  1255.                                         ptr++;
  1256.                         break;
  1257.  
  1258.                 case 'Y':
  1259.                 case 'y':
  1260.                         if (*buf == 0 || isspace(*buf))
  1261.                                 break;
  1262.  
  1263.                         if (!isdigit(*buf))
  1264.                                 return 0;
  1265.  
  1266.                         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
  1267.                                 i *= 10;
  1268.                                 i += *buf - '0';
  1269.                         }
  1270.                         if (c == 'Y')
  1271.                                 i -= 1900;
  1272.                         if (i < 0)
  1273.                                 return 0;
  1274.  
  1275.                         tm->tm_year = i;
  1276.  
  1277.                         if (*buf != 0 && isspace(*buf))
  1278.                                 while (*ptr != 0 && !isspace(*ptr))
  1279.                                         ptr++;
  1280.                         break;
  1281.                 }
  1282.         }
  1283.  
  1284.         return buf;
  1285. }
  1286.  
  1287. -----------------------------------------------------------
  1288.  
  1289. 4)* TOPIC: BSD/Solaris 1/POSIX Signal Primer
  1290.  
  1291. [Last modified: 24 May 94]
  1292.  
  1293.  
  1294. The most common problem encountered when porting BSD/Solaris 1
  1295. signal code is that Solaris 2 (and SVR4) handles interrupted
  1296. systems calls differently than does BSD. In Solaris 2 (SVR4),
  1297. system calls are interrupted and return EINTR, unless the call is
  1298. read, write, or some other call that returns the number of bytes
  1299. read/written (unless 0 bytes have been read/written, in which
  1300. case the call returns EINTR). 
  1301.  
  1302. On the other hand, system calls are restarted on BSD/Solaris 1
  1303. systems. The signal calls can be made to restart by specifying a
  1304. SA_RESTART with sigaction().  Note, however, that code that
  1305. relies on restartable system calls is generally considered bad
  1306. practice. The following code is provided for illustrative
  1307. purposes only. It is recommended that you remove these
  1308. dependencies. Sigaction is the preferred (POSIX) way of
  1309. installing signal handlers.  
  1310.  
  1311.  
  1312.  
  1313.         The BSD/Solaris 1 code 
  1314.  
  1315.                 omask = sigblock(sigmask(SIGXXX));
  1316.                 do_stuff_while_SIGXXX_blocked();
  1317.                 (void)sigsetmask(omask);
  1318.         
  1319.         can be emulated by
  1320.  
  1321.                 sigset_t block, oblock;
  1322.                 struct   sigaction act, oact;
  1323.                 ....
  1324.                 (void)sigemptyset(&block);
  1325.                 (void)sigaddset(&block, SIGXXX);
  1326.                 if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0)
  1327.                         perror("sigprocmask");
  1328.                 do_stuff_while_SIGXXX_blocked();
  1329.                 (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL);
  1330.         #ifdef  SA_RESTART                      /* make restartable */
  1331.                 act.sa_flags = SA_RESTART;
  1332.         #endif  /* SA_RESTART */
  1333.                 if (sigaction(SIGXXX, &act, &oact) < 0)
  1334.                        return(SIG_ERR);
  1335.  
  1336.  
  1337.         Note that this (emulating) construct is also available on
  1338.         Solaris 1 (sans SA_RESTART), so should work on either
  1339.         Solaris 1 or SVR4.
  1340.  
  1341.         Another possibility would be to emulate BSD signal(2)
  1342.         semantics as follows:
  1343.  
  1344.         Sigfunc *bsdsignal(int signo, Sigfunc *alarm_catcher)
  1345.         {
  1346.  
  1347.          struct sigaction act;
  1348.          act.sa_handler = alarm_catcher;
  1349.          sigemptyset(&act.sa_mask);
  1350.          act.sa_flags = SA_RESTART;
  1351.          if(sigaction(signo, &act,NULL) == -1) {
  1352.            perror("signal:");
  1353.            return(SIG_ERR);
  1354.         }
  1355.  
  1356. Another problem revolves around the use of setjmp and longjmp.
  1357. With 4.3+BSD  the setjmp and longjmp save and restore the signal
  1358. mask. The default behavior for SVR4 is not to save and restore
  1359. the signal mask. Note that these calls are MT-Unsafe.
  1360.  
  1361. The POSIX.1 interface allows you to do either, by using a second
  1362. argument, savemask, for sigsetjmp. To cause the signal mask to be
  1363. saved and restored (emulating setjmp/longjmp behavior), use a
  1364. nonzero savemask.  For example,
  1365.  
  1366.  
  1367.                 #include        <stdio.h>
  1368.                 #include        <stdlib.h>
  1369.                 #include        <setjmp.h>
  1370.                 
  1371.                 sigjmp_buf      env;
  1372.                 int             savemask;
  1373.                 
  1374.                 ....
  1375.                 
  1376.                 savemask = 1;
  1377.                 #ifdef  HAS_SIGSETJMP
  1378.                         sigsetjmp(env, savemask);
  1379.                 #endif  HAS_SIGSETJMP
  1380.  
  1381.                 ...
  1382.  
  1383. In this case, the sigsetjmp saves the current signal mask of the
  1384. process in the saved environment (sigjmp_buf). Now, if the
  1385. environment was saved by a call to sigsetjmp with a nonzero
  1386. savemask, then a subsequent siglongjmp call will restore the
  1387. saved signal mask.    
  1388.  
  1389. Finally, be careful with signal handling code when you are doing
  1390. a vfork [Editor's Note: The following observation and example in
  1391. section 7. (i). comes courtesy of Paul Eggert
  1392. (eggert@twinsun.com). DM]. In Solaris 2, if a vfork'ed child
  1393. adjusts signal handling before exec'ing, signal handling is
  1394. munged in the parent in ways that lead to unreliable results; the
  1395. parent can dump core in some cases.  This bug affects some widely
  1396. distributed programs, so when building a program that adjusts
  1397. signal handlers between `vfork' and `exec', be careful to
  1398. override its configuration to use `fork' instead (see section
  1399. 7. (i) below for more detail).  
  1400.  
  1401. To summarize, some basic rules are:
  1402.  
  1403.         (i).    Limit signal handling code to the POSIX interface
  1404.                 whenever possible. 
  1405.  
  1406.         (ii).   Use sigaction to install signal handlers whenever
  1407.                 possible. Use Standard C's signal() only for
  1408.                 portability to non-POSIX systems. 
  1409.  
  1410.         (iii).  Avoid code that relies on restartable system calls. 
  1411.  
  1412.         (iv).   The main difference between SVR4 sigset() (not
  1413.                 POSIX) and SunOS 4.x/BSD signal() is that system
  1414.                 calls will return EINTR with sigset() but will be
  1415.                 restarted on BSD/SunOS 4.x. On SVR4 EINTR is only
  1416.                 returned when no bytes have been read/written.     
  1417.  
  1418.     (v).    Watch your use of vfork.
  1419.  
  1420. -----------------------------------------------------------------------------
  1421.  
  1422. 5) TOPIC: Waiting for Children to Exit
  1423.  
  1424. [Last modified: 26 October 93]
  1425.  
  1426.  
  1427. waitpid(2) is the preferred (POSIX) interface. Wait3 can be
  1428. replaced by waitpid (when you don't need the rusage). For
  1429. example, the BSD segment  
  1430.         
  1431.         while((id = wait(&stat)) >=0 && id != pid);
  1432.  
  1433. can be approximated using the POSIX waidpid(2) interface by code
  1434. of the form: 
  1435.  
  1436.         int status;
  1437.         int options;                    /* e.g., WNOHANG */
  1438.         ....
  1439.         options = WNOHANG;
  1440.         if (waitpid((pid_t) -1, &status, options) == -1)
  1441.                 perror("waitpid");
  1442.         }
  1443.  
  1444.  
  1445. Note here that if you execute a signal(SIGCHLD, SIG_IGN) or
  1446. sigset(SIGCHLD, SIG_IGN), Solaris will discard all child exit
  1447. statuses and reap the child processes without giving the parent a
  1448. chance to wait. That is, waitpid(2) will return -1 with an ECHILD. 
  1449.  
  1450.  
  1451. Another possibility is emulate the BSD wait(2) call with SVR4's
  1452. waitid(2). The code fragment below is an example. In this case,
  1453. we wait for a particular child in our process group ((pid_t) 0)
  1454. to exit (WEXITED).
  1455.  
  1456.  
  1457.         #ifdef  SVR4
  1458.         #include <sys/types.h>
  1459.         #include <sys/wait.h>
  1460.                 siginfo_t       stat;
  1461.                 int             retcode;
  1462.         #else
  1463.                 union   wait    stat;
  1464.         #endif
  1465.  
  1466.         .....
  1467.  
  1468.         #ifdef  SVR4
  1469.               while (retcode = waitid(P_ALL,(pid_t) 0, &stat, WEXITED)) {
  1470.                 if (retcode < 0) {
  1471.                   perror("waitid");
  1472.                   exit(1);
  1473.                 }
  1474.                 if (stat.si_pid == pid)
  1475.                   break;
  1476.               }
  1477.         #else           /* BSD */
  1478.                while((id = wait(&stat)) >=0 && id != pid);
  1479.         #endif  /* SVR4 */
  1480.  
  1481.  
  1482.  
  1483. -----------------------------------------------------------------------------
  1484.  
  1485. 6) TOPIC: Dealing With Shadow Password Files
  1486.  
  1487. [Last modified: 19 August 93]
  1488.  
  1489. The following code segment outlines how to handle shadow password
  1490. files. In the outline below, <passwd> is the clear text password.
  1491. Note that shadow passwords are part of SVR4, so again we have the
  1492. conflict between using high level system definitions (e.g., SVR4)
  1493. and feature definitions (for systems other than SVR4). I'll use
  1494. feature a feature definition (HAVE_SHADOW_H) to illustrate this.
  1495.  
  1496.  
  1497.         #ifdef  HAVE_SHADOW_H
  1498.         #include <shadow.h>
  1499.             register struct spwd    *sp;
  1500.         #endif  /* HAVE_SHADOW_H */
  1501.  
  1502.              .....
  1503.                 
  1504.         #ifdef  HAVE_SHADOW_H
  1505.             if ((sp = getspnam(<username>)) == NULL)
  1506.                <no password entry for username>
  1507.             if (sp->sp_pwdp == NULL)
  1508.                <NULL password for username>
  1509.             if (strcmp (crypt (<passwd>, sp->sp_pwdp), sp->sp_pwdp) != 0)
  1510.         #else 
  1511.             if ((pw = getpwnam(<username>)) == NULL)
  1512.                <no password entry for username>
  1513.             if (pw->pw_passwd == NULL)
  1514.                <NULL password for username>
  1515.             if (strcmp (crypt (<passwd>, pw->pw_passwd), pw->pw_passwd) != 0)
  1516.         #endif  /* HAVE_SHADOW_H */
  1517.                <incorrect password for username>
  1518.                        
  1519.  
  1520. -----------------------------------------------------------------------------
  1521.  
  1522. 7)  TOPIC: Some Compatibility Problems
  1523.  
  1524. [Last modified: 02 September 93]
  1525.  
  1526.         (i).     vfork doesn't work in Solaris 2
  1527.  
  1528.                 [Editor's Note: The following observation and
  1529.                 example comes courtesy of Paul Eggert
  1530.                 (eggert@twinsun.com). DM] 
  1531.  
  1532.                 In Solaris 2, if a vfork'ed child adjusts signal
  1533.                 handling before exec'ing, signal handling is munged in
  1534.                 the parent in ways that lead to unreliable results;
  1535.                 the parent can dump core in some cases.  This bug
  1536.                 affects some widely distributed programs, so when
  1537.                 building a program that adjusts signal handlers
  1538.                 between `vfork' and `exec', be careful to override its
  1539.                 configuration to use `fork' instead. 
  1540.  
  1541.                 Sun doesn't consider this behavior to be a bug,
  1542.                 so it's not likely to be fixed. 
  1543.  
  1544.                 Here's an illustration of the bug.  This program
  1545.                 works fine in SunOS 4.1.x, but dumps core in
  1546.                 Solaris 2.x. 
  1547.  
  1548.                         #include <signal.h>
  1549.                         #include <unistd.h>
  1550.  
  1551.                         #ifdef SIGLOST          /* must be SunOS 4.1.x */
  1552.                         #include <vfork.h>
  1553.                         #endif
  1554.  
  1555.                         int signalled;
  1556.  
  1557.                         void catch (sig)
  1558.                              int sig;
  1559.                         {
  1560.                              signalled = 1;
  1561.                         }
  1562.  
  1563.                         int main()
  1564.                         {
  1565.                              signal (SIGINT, catch);
  1566.                              if (vfork () == 0) {               /* child */
  1567.                                  signal (SIGINT, SIG_IGN);
  1568.                                  execlp ("sleep", "sleep", "10", (char *) 0);
  1569.                              }
  1570.         
  1571.                             /* parent here */
  1572.  
  1573.                              kill (getpid (), SIGINT);
  1574.                              return signalled != 1;
  1575.                         }
  1576.  
  1577.  
  1578.         (ii).   chown(2) does not allow uid/gid values greater
  1579.                 than 60002 on Solaris 2.[0-3]. Check /usr/include/limits.h, 
  1580.                 which contains:
  1581.  
  1582.                 #define UID_MAX         60002   
  1583.  
  1584.  
  1585. -----------------------------------------------------------------------------
  1586.  
  1587. 8)* TOPIC: Other Resources
  1588.  
  1589. [Last modified: 27 September 93]
  1590.  
  1591. Porting to Solaris 2
  1592. --------------------
  1593.  
  1594. A excellent text on this subject is  "Solaris Porting Guide",
  1595. SunSoft ISV Engineering, et. al., Prentice Hall, 1993. ISBN
  1596. 0-13-030396-8. 
  1597.  
  1598. Solaris 2 General FAQ
  1599. ---------------------
  1600.  
  1601. The official Solaris 2 Frequently Answered Questions is
  1602. maintained by Ian Darwin, ian@sq.com, and is posted once or twice 
  1603. a month to various newsgroups including comp.unix.solaris and
  1604. comp.answers.
  1605.  
  1606. General
  1607. -------
  1608.  
  1609. "Internetworking with TCP/IP: Volume III Client-Server Programming
  1610. & Applications (AT&T TLI Edition)", Douglas E. Comer & David L.
  1611. Stevens, Prentice-Hall. ISBN 0-13-474230-3. Nice reference for
  1612. TLI programming, etc.
  1613.  
  1614. "Networking Applications on UNIX System V", Mike Padovano, ISBN
  1615. 013-613555. A good reference for System V.
  1616.  
  1617. "UNIX, POSIX, and Open Systems: The Open Standards Puzzle", John
  1618. S. Quarterman and Susanne Wilhelm, Addison-Wesley, 1993. ISBN
  1619. 0-201-52772-3. Another nice modern reference.
  1620.  
  1621. "UNIX System V Network Programming", Steve Rago, ISBN
  1622. 0-201-56318-5. Another good System V reference.
  1623.  
  1624. "Advanced Programming in the UNIX Environment", W. Richard
  1625. Stevens, Addison Wesley, 1992, ISBN 0-201-56317-1, is a nice, in
  1626. depth text covering large parts of this topic.
  1627.  
  1628. ANSI C
  1629. ------
  1630.  
  1631. A very nice text here is "The Standard C Library", P.J. Plauger,
  1632. Prentice Hall, 1992, ISBN 0-13-131509-9.
  1633.  
  1634. Another example of the many texts here is "C,  a Reference
  1635. Manual", Harbison and Steele, Prentice Hall. ISBN 0-13-110933-2.  
  1636.  
  1637. POSIX
  1638. -----
  1639.  
  1640. A nice reference text on the POSIX interface is "POSIX
  1641. Programmer's Guide", Donald Levine, O'Reily & Associates, 1991.
  1642. ISBN 0-937175-73-0. 
  1643.  
  1644.  
  1645. ACKNOWLEDGMENTS
  1646.  
  1647. I would like to thank everyone who contributed to this, and I
  1648. hope that it clarifies some of these issues. I would especially 
  1649. acknowledge the contributions of Casper H.S. Dik and J.G. Vons in
  1650. helping me organize my thoughts on all this.
  1651.  
  1652. Thanks to:
  1653.  
  1654.         Jamshid Afshar          <jamshid@ses.com>
  1655.         Pedro Acebes Bayon      <pacebes@tid.es>
  1656.         Ian Darwin              <ian@sq.com>
  1657.         Casper H.S. Dik         <casper@fwi.uva.nl>
  1658.         Paul Eggert             <eggert@twinsun.com>
  1659.         Stephen L Favor         <xcpslf@atom.oryx.com>
  1660.         Charles Francois        <cbf@gotham.east.sun.com>
  1661.         Pete Hartman            <pwh@bradley.bradley.edu>
  1662.         Guy Harris              <guy@auspex.com>
  1663.         Jens-Uwe Mager          <jum@anubis.han.de>
  1664.         Thomas Maslen           <maslen@eng.sun.com>
  1665.         Richard M. Mathews      <richard@astro.west.sun.com>
  1666.         Davin Milun             <milun@cs.buffalo.edu>
  1667.         Paul Pomes              <Paul-Pomes@uiuc.edu>
  1668.         Andrew Roach            <andrewr@ultrix.sun.com>
  1669.         Kevin Ruddy             <smiles@powerdog.com> 
  1670.         M C Srivas              <M._C._Srivas@transarc.com>
  1671.     Dan Stromberg        <strombrg@hydra.acs.uci.edu>
  1672.         Larry W. Virden         <lwv26@cas.org>
  1673.         J.G. Vons               <vons%ulysse@crbca1.sinet.slb.com>
  1674.         Peter Wemm              <peter@DIALix.oz.au>
  1675.         christos@deshaw.com
  1676.         jorgens@pvv.unit.no
  1677.         Malte                   <malte@techfak.uni-bielefeld.de>
  1678.  
  1679. ----- End of Solaris 2 Porting FAQ -- Maintained by David Meyer meyer@ns.uoregon.edu --
  1680.  
  1681.  
  1682.  
  1683.         David M. Meyer 503/346-1747
  1684.         meyer@cambium.uoregon.edu
  1685.         Fri Jul 16 14:59:28 1993
  1686.  
  1687.         $Header: /net/network-services/disk1/home/meyer/FAQ/RCS/porting-FAQ,v 1.60 1994/09/13 14:00:21 meyer Exp meyer $
  1688.  
  1689.  
  1690.  
  1691.