home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / sys / hp / 14452 < prev    next >
Encoding:
Text File  |  1993-01-01  |  20.9 KB  |  910 lines

  1. Newsgroups: comp.sys.hp
  2. Path: sparky!uunet!think.com!rpi!utcsri!helios.physics.utoronto.ca!alchemy.chem.utoronto.ca!news
  3. From: system@alchemy.chem.utoronto.ca (System Admin (Mike Peterson))
  4. Subject: BSD to HP-UX porting tricks (LONG) (last updated: 13-Nov-1992)
  5. Message-ID: <1993Jan1.060005.15498@alchemy.chem.utoronto.ca>
  6. Sender: news@alchemy.chem.utoronto.ca (USENET news)
  7. Organization: University of Toronto Chemistry Department
  8. Date: Fri, 1 Jan 1993 06:00:05 GMT
  9. Lines: 899
  10.  
  11.     HP TRICKS (home-grown and from news postings)
  12.     =============================================
  13.  
  14. Things to watch out for:
  15.  
  16. TIOCNOTTY     - this is not available on HP-UX (use setsid()); trying
  17.         to open '/dev/tty' will also fail with status -1.
  18. setpgrp       - this doesn't get rid of the controlling terminal
  19.         if you use -lBSD (use setsid()).
  20. BSD signals   - you almost certainly want them if your program came from
  21.         a BSD system (e.g. Sun); this breaks 'setpgrp' among other
  22.         things (see 'man bsdproc' and notes below).
  23. /etc/utmp     - contains all sorts of records, not just current logins;
  24.         old login records are found if file is read blindly.
  25. setproctitle  - doesn't work as expected (see notes below for a version
  26.         that really does work on HP-UX).
  27.  
  28.  
  29. getwd:
  30. ------
  31.  
  32. /* Replace 'SIZEOFARG-1' with the declared size of "arg", minus 1 */
  33.  
  34. #ifdef __hpux
  35. #include <unistd.h>
  36. #define getwd(arg)    getcwd(arg, (size_t) SIZEOFARG-1)
  37. #else
  38. char    *getwd();
  39. #endif
  40.  
  41.  
  42. getrusage:
  43. ----------
  44.  
  45. From: scot@pawnee.ugrad.ee.ufl.edu (Scott Miller)
  46. Newsgroups: comp.sys.hp
  47. Subject: Re: Where is getrusage()? (Summary)
  48. Organization: UF EE Department
  49.  
  50. getrusage() is in the syscall includes
  51.  
  52. Here is the code fragment I used:
  53.  
  54. #ifdef hpux
  55. #include <sys/syscall.h>
  56. #define getrusage(a, b)  syscall(SYS_GETRUSAGE, a, b)
  57. #endif /* hpux */
  58.  
  59.  
  60. srandom, random:
  61. ----------------
  62.  
  63. For a conversion to a "better" generator, use:
  64.  
  65. #define srandom srand48
  66. #define random lrand48
  67.  
  68. For a simple conversion, use:
  69.  
  70. From: mjo@snclib.snc.edu (Mike O'Connor)
  71. Newsgroups: comp.sys.hp
  72. Subject: Re: random and srandom on HP9000/720 with HPUX-8.07
  73.  
  74. #define srandom srand
  75. #define random rand
  76.  
  77.  
  78. getdtablesize:
  79. --------------
  80.  
  81. /*
  82.  * getdtablesize ()
  83.  *
  84.  * Returns the maximum number of file descriptors allowed.
  85.  */
  86.  
  87. #include <unistd.h>
  88.  
  89.     int
  90. getdtablesize ()
  91. {
  92.     return(sysconf(_SC_OPEN_MAX));
  93. }
  94.  
  95.  
  96. usleep:
  97. -------
  98.  
  99. /*
  100.  *  NAME:
  101.  *      usleep     -- This is the precision timer for Test Set
  102.  *                    Automation. It uses the select(2) system
  103.  *                    call to delay for the desired number of
  104.  *                    micro-seconds. This call returns ZERO
  105.  *                    (which is usually ignored) on successful
  106.  *                    completion, -1 otherwise. 
  107.  *
  108.  *  ALGORITHM:
  109.  *      1) We range check the passed in microseconds and log a
  110.  *         warning message if appropriate. We then return without
  111.  *         delay, flagging an error. 
  112.  *      2) Load the Seconds and micro-seconds portion of the
  113.  *         interval timer structure.
  114.  *      3) Call select(2) with no file descriptors set, just the
  115.  *         timer, this results in either delaying the proper
  116.  *         ammount of time or being interupted early by a signal.
  117.  *
  118.  *  HISTORY:
  119.  *      Added when the need for a subsecond timer was evident.
  120.  *
  121.  *  AUTHOR:
  122.  *      Michael J. Dyer                   Telephone:   AT&T 414.647.4044
  123.  *      General Electric Medical Systems        GE DialComm  8 *767.4044
  124.  *      P.O. Box 414  Mail Stop 12-27         Sect'y   AT&T 414.647.4584
  125.  *      Milwaukee, Wisconsin  USA 53201                      8 *767.4584
  126.  *      internet:  mike@sherlock.med.ge.com     GEMS WIZARD e-mail: DYER
  127.  */
  128.  
  129. #include <unistd.h>
  130. #include <stdlib.h>
  131. #include <stdio.h>
  132. #include <errno.h>
  133. #include <time.h>
  134. #include <sys/time.h>
  135. #include <sys/param.h>
  136. #include <sys/types.h>
  137.  
  138. int     usleep( unsigned long int microSeconds )
  139. {
  140.         unsigned int            Seconds, uSec;
  141.         int                     nfds, readfds, writefds, exceptfds;
  142.         struct  timeval         Timer;
  143.  
  144.         nfds = readfds = writefds = exceptfds = 0;
  145.  
  146.         if( (microSeconds == (unsigned long) 0) 
  147.                 || microSeconds > (unsigned long) 4000000 )
  148.         {
  149.                 errno = ERANGE;         /* value out of range */
  150.                 perror( "usleep time out of range ( 0 -> 4000000 ) " );
  151.                 return -1;
  152.         }
  153.  
  154.         Seconds = microSeconds / (unsigned long) 1000000;
  155.         uSec    = microSeconds % (unsigned long) 1000000;
  156.  
  157.         Timer.tv_sec            = Seconds;
  158.         Timer.tv_usec           = uSec;
  159.  
  160.         if( select( nfds, &readfds, &writefds, &exceptfds, &Timer ) < 0 )
  161.         {
  162.                 perror( "usleep (select) failed" );
  163.                 return -1;
  164.         }
  165.  
  166.         return 0;
  167. }
  168.  
  169.  
  170. flock:
  171. ------
  172.  
  173. /*
  174.  * flock (fd, operation)
  175.  *
  176.  * This routine performs some file locking like the BSD 'flock'
  177.  * on the object described by the int file descriptor 'fd',
  178.  * which must already be open.
  179.  *
  180.  * The operations that are available are:
  181.  *
  182.  * LOCK_SH  -  get a shared lock.
  183.  * LOCK_EX  -  get an exclusive lock.
  184.  * LOCK_NB  -  don't block (must be ORed with LOCK_SH or LOCK_EX).
  185.  * LOCK_UN  -  release a lock.
  186.  *
  187.  * Return value: 0 if lock successful, -1 if failed.
  188.  *
  189.  * Note that whether the locks are enforced or advisory is
  190.  * controlled by the presence or absence of the SETGID bit on
  191.  * the executable.
  192.  *
  193.  * Note that there is no difference between shared and exclusive
  194.  * locks, since the 'lockf' system call in SYSV doesn't make any
  195.  * distinction.
  196.  *
  197.  * The file "<sys/file.h>" should be modified to contain the definitions
  198.  * of the available operations, which must be added manually (see below
  199.  * for the values).
  200.  */
  201.  
  202. #include <unistd.h>
  203. #include <sys/file.h>
  204. #include <errno.h>
  205.  
  206. #ifndef LOCK_SH
  207. #define LOCK_SH 1
  208. #endif
  209. #ifndef LOCK_EX
  210. #define LOCK_EX 2
  211. #endif
  212. #ifndef LOCK_NB
  213. #define LOCK_NB 4
  214. #endif
  215. #ifndef LOCK_UN
  216. #define LOCK_UN 8
  217. #endif
  218.  
  219. extern int errno;
  220.  
  221.     int
  222. flock (int fd, int operation)
  223. {
  224.     int i;
  225.  
  226.     switch (operation) {
  227.  
  228.     /* LOCK_SH - get a shared lock */
  229.     case LOCK_SH:
  230.     /* LOCK_EX - get an exclusive lock */
  231.     case LOCK_EX:
  232.         i = lockf (fd, F_LOCK, 0);
  233.         break;
  234.  
  235.     /* LOCK_SH|LOCK_NB - get a non-blocking shared lock */
  236.     case LOCK_SH|LOCK_NB:
  237.     /* LOCK_EX|LOCK_NB - get a non-blocking exclusive lock */
  238.     case LOCK_EX|LOCK_NB:
  239.         i = lockf (fd, F_TLOCK, 0);
  240.         if (i == -1)
  241.             if ((errno == EAGAIN) || (errno == EACCES))
  242.                 errno = EWOULDBLOCK;
  243.         break;
  244.  
  245.     /* LOCK_UN - unlock */
  246.     case LOCK_UN:
  247.         i = lockf (fd, F_ULOCK, 0);
  248.         break;
  249.  
  250.     /* Default - can't decipher operation */
  251.     default:
  252.         i = -1;
  253.         errno = EINVAL;
  254.         break;
  255.     }
  256.  
  257.     return (i);
  258. }
  259.  
  260. /*
  261.  * An alternative version was posted by James Gritton
  262.  * (gritton@byu.edu) in comp.sys.hp.
  263.  * As far as I can tell, it works the same as the above
  264.  * except for the "errno" values returned (and it defaults
  265.  * an invalid operation to "unlock").
  266.  * The definitions of LOCK_xx should be put into <sys/file.h> and/or
  267.  * <fcntl.h>.
  268.  * Note: this was typed in, so it may not work as given.
  269.  */
  270.  
  271. /*
  272.  *#include <fcntl.h>
  273.  *#define LOCK_SH 1
  274.  *#define LOCK_EX 2
  275.  *#define LOCK_NB 4
  276.  *#define LOCK_UN 8
  277.  *
  278.  *    int
  279.  *flock (int fd, int operation)
  280.  *{
  281.  *    struct flock fl;
  282.  *
  283.  *    switch (operation & ~LOCK_NB) {
  284.  *    case LOCK_SH:
  285.  *        fl.l_type = F_RDLCK;
  286.  *        break;
  287.  *    case LOCK_EX:
  288.  *        fl.l_type = F_WRLCK;
  289.  *        break;
  290.  *    default:
  291.  *        fl.l_type = F_UNLCK;
  292.  *        break;
  293.  *    }
  294.  *
  295.  *    fl.l_whence = SEEK_SET;
  296.  *    fl.l_start = fl.l_len = 0L;
  297.  *
  298.  *    return fcntl (fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &fl);
  299.  *}
  300.  */
  301.  
  302.  
  303. getclktck:
  304. ----------
  305.  
  306. /*
  307.  * getclktck ()
  308.  *
  309.  * Returns the value of CLK_TCK (timer resolution).
  310.  */
  311.  
  312. #include <unistd.h>
  313.  
  314.     int
  315. getclktck ()
  316. {
  317.     return(sysconf(_SC_CLK_TCK));
  318. }
  319.  
  320.  
  321. getloadavg (works on a wide variety of systems):
  322. ------------------------------------------------
  323.  
  324. /*
  325.  * getloadavg (ave, n)
  326.  *
  327.  * This routine returns 'n' double precision floats containing
  328.  * the load averages in 'ave'; at most 3 values will be returned.
  329.  *
  330.  * Return value: 0 if successful, -1 if failed (and all load
  331.  * averages are returned as 0).
  332.  */
  333.  
  334. #include <sys/types.h>
  335. #include <stdio.h>
  336. #include <nlist.h>
  337. #include <errno.h>
  338.  
  339. extern int errno;
  340.  
  341. #define STRSIZ    512            /* Sprintf buffer size */
  342. static char errstr[STRSIZ];        /* Global sprintf buffer */
  343.  
  344. int ugetloads(float *a);
  345. static void mperror(char *s);
  346. static char *syserr();
  347.  
  348. #define merror(a1)        fprintf(stderr,"%s",a1)
  349. #define merror1(fmt,a1)        { sprintf(errstr,fmt,a1); merror(errstr); }
  350.  
  351. struct    nlist nl[] = {
  352. #ifdef stardent
  353. # define unixpath "/unix"
  354.     { "avenrun" },
  355. #else
  356. #ifdef __hpux
  357. # define unixpath "/hp-ux"
  358. #ifdef __hppa       /* series 700 & 800 */
  359.     { "avenrun" },
  360. #else               /* series 300 & 400 */
  361.     { "_avenrun" },
  362. #endif
  363. #else
  364. # define unixpath "/vmunix"
  365.     { "_avenrun" },
  366. #endif
  367. #endif
  368.     { 0 },
  369. };
  370.  
  371. #ifndef RISCos
  372.     int
  373. getloadavg (double *a, int na)
  374. {
  375.     int i, nreturn;
  376.     static int kmem = -1;
  377. #if defined(vax) || defined(__hpux)
  378.     double avenrun[3];
  379. #else
  380.     long avenrun[3];
  381. #endif
  382. #ifdef NOKMEM
  383.     float aves[3];
  384. #endif /* NOKMEM */
  385.  
  386.     nreturn = na;
  387.     if ( nreturn < 0 )
  388.         nreturn = 0;
  389.     if ( nreturn > 3 )
  390.         nreturn = 3;
  391.  
  392. #ifdef NOKMEM
  393. /* Use 'uptime' output for BSD-like systems with no /dev/kmem */
  394.  
  395.     i = ugetloads(aves);
  396.     if( i == -1 ){
  397.         merror("ugetloads failed\n");
  398.         goto failed;
  399.     }
  400.     for (i = 0; i < nreturn; i++)
  401.         a[i] = aves[i];
  402.  
  403. #else /*NOKMEM*/
  404.  
  405.     if(kmem == -1) {
  406. #ifdef sgi
  407. # include <sys/sysmp.h>
  408.     nl[0].n_value = sysmp(MP_KERNADDR, MPKA_AVENRUN) & 0x7fffffff;
  409. #else
  410.         nlist(unixpath, nl);
  411.         if (nl[0].n_type==0) {
  412.             merror1("%s: No namelist\n", unixpath);
  413.             goto failed;
  414.         }
  415. #ifdef stardent
  416.         nl[0].n_value &= 0x7fffffff;
  417. #endif
  418. #endif
  419.         if((kmem = open("/dev/kmem", 0)) == -1) {
  420.             mperror("Can't open(/dev/kmem)");
  421.             goto failed;
  422.         }
  423.     }
  424.     if( lseek(kmem, (off_t)nl[0].n_value, 0) == -1 ){
  425.         mperror("Can't lseek in kmem");
  426.         goto failed;
  427.     }
  428.     if( read(kmem, (char *)avenrun, sizeof(avenrun)) != sizeof(avenrun) ){
  429.         mperror("Can't read kmem");
  430.         goto failed;
  431.     }
  432.     for (i = 0; i < nreturn; i++)
  433. #if defined(sun) || defined(sequent)
  434.         a[i] = avenrun[i] / FSCALE;
  435. #else 
  436. #ifdef sgi
  437.         a[i] = avenrun[i] / 1024;
  438. #else
  439. #if defined(BSD4_2) || defined(__hpux)
  440.         a[i] = avenrun[i];
  441. #else 
  442. #ifdef stardent
  443.         a[i] = (double)avenrun[i] / (1<<16);
  444. #else
  445.         a[i] = avenrun[i] / 1024;
  446. #endif /*stardent*/
  447. #endif /*BSD4_2*/
  448. #endif /*sgi*/
  449. #endif /*sun*/
  450. #endif /*NOKMEM*/
  451.     return(0); 
  452. failed:;
  453.     for (i = 0; i < nreturn; i++)
  454.         a[i] = 0;
  455.     return(-1);
  456. }
  457. #else /*RISCos*/
  458. #include <sys/fixpoint.h>
  459.     static
  460. getloadavg (double *a, int na)
  461. {
  462.     int i, nreturn;
  463.     static int kmem = -1;
  464.     fix avenrun[3];
  465.  
  466.     nreturn = na;
  467.     if ( nreturn < 0 )
  468.         nreturn = 0;
  469.     if ( nreturn > 3 )
  470.         nreturn = 3;
  471.  
  472.     if(kmem == -1) {
  473.         nlist("/unix", nl);
  474.         if (nl[0].n_type==0) {
  475.             merror("/unix: No namelist\n");
  476.             goto failed;
  477.         }
  478.         if((kmem = open("/dev/kmem", 0)) == -1) {
  479.             mperror("Can't open(/dev/kmem)");
  480.             goto failed;
  481.         }
  482.     }
  483.     if( lseek(kmem, (off_t)nl[0].n_value, 0) == -1 ){
  484.         mperror("Can't lseek in kmem");
  485.         goto failed;
  486.     }
  487.     if( read(kmem, (char *)avenrun, sizeof(avenrun)) != sizeof(avenrun) ){
  488.         mperror("Can't read kmem");
  489.         goto failed;
  490.     }
  491.     for (i = 0; i < nreturn; i++)
  492.             a[i] = (int) FIX_TO_INT(avenrun[i]) + .5;
  493.     return(0);
  494. failed:;
  495.     for (i = 0; i < nreturn; i++)
  496.         a[i] = 0;
  497.     return(-1);
  498. }
  499. #endif /* RISCOS */
  500.  
  501. /* ugetloads(ls)
  502.  * float ld[3];
  503.  *
  504.  * Puts the 1, 5, and 15 minute load averages in the float
  505.  * array passed to it.  This program calls upon uptime(1)
  506.  * which could have different ways of printing ie. with bsd4.2
  507.  * "   9:34pm  up 11 hrs,  3 users,  load average: 0.25, 0.22, 0.24  "
  508.  *                                notice the commas -- ^ --- ^.
  509.  * while bsd4.1 does not print commas.  The BSD41 define will 
  510.  * take care of this if that is your system, it defaults to
  511.  * the 4.2 version.
  512.  *
  513.  * Author:
  514.  *  John Bien
  515.  *  {ihnp4 | ucbvax | decvax}!trwrb!jsb
  516.  *
  517.  * This routine taken from comp.sources.unix: Volume 4, Issue 78
  518.  */
  519.  
  520. FILE *popen();
  521.  
  522. ugetloads(ld)
  523. float ld[3];
  524. {
  525.     FILE *stream;
  526.     int i;
  527.  
  528.     if((stream = popen("uptime","r")) == NULL)
  529.     return(-1);
  530.  
  531. #ifdef BSD41
  532.     i = fscanf(stream,"%*[^l] load average: %f %f %f", &ld[0],&ld[1],&ld[2]);
  533. #else
  534.     i = fscanf(stream,"%*[^l] load average: %f, %f, %f", &ld[0],&ld[1],&ld[2]);
  535. #endif /* BSD41 */
  536.     pclose(stream);
  537.     return i == 3 ? 0 : -1;
  538. }
  539.  
  540. /* Routine to print messages to stderr, appending the system error message */
  541.  
  542.     static void
  543. mperror(char *s)
  544. {
  545.     char *p;
  546.     char str[STRSIZ];    /* must have own internal buffer */
  547.  
  548.     if( (p=index(s,'\n')) != NULL )
  549.         *p = '\0';
  550.     sprintf(str,"%s: %s\n", s, syserr());
  551.     if( p )
  552.         *p = '\n';
  553.     merror(str);
  554. }
  555.  
  556. /* Routine to get the last system error message */
  557.  
  558. extern int sys_nerr;
  559. extern char *sys_errlist[];
  560.  
  561.     static char *
  562. syserr()
  563. {
  564.     static char buf[80];
  565.  
  566.     if (errno >= 0 && errno < sys_nerr)
  567.         return(sys_errlist[errno]);
  568.     sprintf(buf,"Unknown error %d", errno);
  569.     return(buf);
  570. }
  571.  
  572.  
  573. Dissociate from controlling terminal:
  574. -------------------------------------
  575.  
  576. From: jhd@irfu.se (Jan D.)
  577. Organization: Swedish Institute of Space Physics, Uppsala, Sweden
  578.  
  579. The code above should look like this on HP-UX (POSIX ?):
  580.  
  581.     #include <unistd.h>    /* For _SC_OPEN_MAX */
  582.  
  583.     long    tblsiz = sysconf(_SC_OPEN_MAX);
  584.  
  585.      if (fork())
  586.          exit(0);
  587.  
  588.     setsid();    /* Disassociate from controlling terminal */
  589.      for (c = 0; c < tblsiz; c++)
  590.          (void) close(c);
  591.      (void) open("/", O_RDONLY);
  592.      (void) dup2(0, 1);
  593.      (void) dup2(0, 2);
  594.  
  595.  
  596. Here's the deal regarding '-lBSD':
  597.  
  598. setpgrp() (in libc) is equivalent to setsid().
  599. setpgrp(pid, pgrp) (in -lBSD) is equivalent to POSIX setpgid(pid, pgrp).
  600. setpgrp2(pid, pgrp) is also equivalent to POSIX setpgid(pid, pgrp).
  601.  
  602. If you don't link with -lBSD you can replace setsid() in with setpgrp()
  603. if you wan't. They both will get rid of the controlling terminal.
  604.  
  605. setpgrp(pid, pgrp) (-lBSD style), setpgid(pid, pgrp)
  606. and setpgrp2(pid, pgrp) will NOT remove the controlling terminal.
  607.  
  608. Thus: The only way (I know of) in HP-UX to remove the controlling terminal
  609. is with setsid() or setpgrp() in libc. The only way in POSIX to get
  610. rid of the controlling terminal is with setsid().
  611.  
  612.  
  613. setlinebuf:
  614. -----------
  615.  
  616. /*
  617.  * setlinebuf (FILE *fp)
  618.  *
  619.  * Routine to set line buffering on "fp".
  620.  */
  621.  
  622. #include <stdio.h>
  623.  
  624.     int
  625. setlinebuf (FILE *fp)
  626. {
  627.     (void) setvbuf (fp, NULL, _IOLBF, 0);
  628.     return(0);
  629. }
  630.  
  631.  
  632. alloca:
  633. -------
  634.  
  635. /*
  636.     alloca -- (mostly) portable public-domain implementation -- D A Gwyn
  637.  
  638.     last edit:    86/05/30    rms
  639.        include config.h, since on VMS it renames some symbols.
  640.        Use xmalloc instead of malloc.
  641.  
  642.     This implementation of the PWB library alloca() function,
  643.     which is used to allocate space off the run-time stack so
  644.     that it is automatically reclaimed upon procedure exit, 
  645.     was inspired by discussions with J. Q. Johnson of Cornell.
  646.  
  647.     It should work under any C implementation that uses an
  648.     actual procedure stack (as opposed to a linked list of
  649.     frames).  There are some preprocessor constants that can
  650.     be defined when compiling for your specific system, for
  651.     improved efficiency; however, the defaults should be okay.
  652.  
  653.     The general concept of this implementation is to keep
  654.     track of all alloca()-allocated blocks, and reclaim any
  655.     that are found to be deeper in the stack than the current
  656.     invocation.  This heuristic does not reclaim storage as
  657.     soon as it becomes invalid, but it will do so eventually.
  658.  
  659.     As a special case, alloca(0) reclaims storage without
  660.     allocating any.  It is a good idea to use alloca(0) in
  661.     your main control loop, etc. to force garbage collection.
  662. */
  663. #ifndef lint
  664. static char    SCCSid[] = "@(#)alloca.c    1.1";    /* for the "what" utility */
  665. #endif
  666.  
  667. #ifdef emacs
  668. #include "config.h"
  669. #ifdef static
  670. /* actually, only want this if static is defined as ""
  671.    -- this is for usg, in which emacs must undefine static
  672.    in order to make unexec workable
  673.    */
  674. #ifndef STACK_DIRECTION
  675. you
  676. lose
  677. -- must know STACK_DIRECTION at compile-time
  678. #endif /* STACK_DIRECTION undefined */
  679. #endif static
  680. #else
  681. #define xmalloc malloc
  682. #endif emacs
  683.  
  684. #if defined(X3J11) || defined(__STDC__)
  685. typedef void    *pointer;        /* generic pointer type */
  686. #else
  687. typedef char    *pointer;        /* generic pointer type */
  688. #endif
  689.  
  690. #define    NULL    0            /* null pointer constant */
  691.  
  692. extern void    free();
  693. extern pointer    xmalloc();
  694.  
  695. /*
  696.     Define STACK_DIRECTION if you know the direction of stack
  697.     growth for your system; otherwise it will be automatically
  698.     deduced at run-time.
  699.  
  700.     STACK_DIRECTION > 0 => grows toward higher addresses
  701.     STACK_DIRECTION < 0 => grows toward lower addresses
  702.     STACK_DIRECTION = 0 => direction of growth unknown
  703. */
  704.  
  705. #ifndef STACK_DIRECTION
  706. #define    STACK_DIRECTION    0        /* direction unknown */
  707. #endif
  708.  
  709. #if STACK_DIRECTION != 0
  710.  
  711. #define    STACK_DIR    STACK_DIRECTION    /* known at compile-time */
  712.  
  713. #else    /* STACK_DIRECTION == 0; need run-time code */
  714.  
  715. static int    stack_dir;        /* 1 or -1 once known */
  716. #define    STACK_DIR    stack_dir
  717.  
  718. static void
  719. find_stack_direction (/* void */)
  720. {
  721.   static char    *addr = NULL;    /* address of first
  722.                    `dummy', once known */
  723.   auto char    dummy;        /* to get stack address */
  724.  
  725.   if (addr == NULL)
  726.     {                /* initial entry */
  727.       addr = &dummy;
  728.  
  729.       find_stack_direction ();    /* recurse once */
  730.     }
  731.   else                /* second entry */
  732.     if (&dummy > addr)
  733.       stack_dir = 1;        /* stack grew upward */
  734.     else
  735.       stack_dir = -1;        /* stack grew downward */
  736. }
  737.  
  738. #endif    /* STACK_DIRECTION == 0 */
  739.  
  740. /*
  741.     An "alloca header" is used to:
  742.     (a) chain together all alloca()ed blocks;
  743.     (b) keep track of stack depth.
  744.  
  745.     It is very important that sizeof(header) agree with malloc()
  746.     alignment chunk size.  The following default should work okay.
  747. */
  748.  
  749. #ifndef    ALIGN_SIZE
  750. #define    ALIGN_SIZE    sizeof(double)
  751. #endif
  752.  
  753. typedef union hdr
  754. {
  755.   char    align[ALIGN_SIZE];    /* to force sizeof(header) */
  756.   struct
  757.     {
  758.       union hdr *next;        /* for chaining headers */
  759.       char *deep;        /* for stack depth measure */
  760.     } h;
  761. } header;
  762.  
  763. /*
  764.     alloca( size ) returns a pointer to at least `size' bytes of
  765.     storage which will be automatically reclaimed upon exit from
  766.     the procedure that called alloca().  Originally, this space
  767.     was supposed to be taken from the current stack frame of the
  768.     caller, but that method cannot be made to work for some
  769.     implementations of C, for example under Gould's UTX/32.
  770. */
  771.  
  772. static header *last_alloca_header = NULL; /* -> last alloca header */
  773.  
  774. pointer
  775. alloca (size)            /* returns pointer to storage */
  776.      unsigned    size;        /* # bytes to allocate */
  777. {
  778.   auto char    probe;        /* probes stack depth: */
  779.   register char    *depth = &probe;
  780.  
  781. #if STACK_DIRECTION == 0
  782.   if (STACK_DIR == 0)        /* unknown growth direction */
  783.     find_stack_direction ();
  784. #endif
  785.  
  786.                 /* Reclaim garbage, defined as all alloca()ed storage that
  787.                    was allocated from deeper in the stack than currently. */
  788.  
  789.   {
  790.     register header    *hp;    /* traverses linked list */
  791.  
  792.     for (hp = last_alloca_header; hp != NULL;)
  793.       if (STACK_DIR > 0 && hp->h.deep > depth
  794.       || STACK_DIR < 0 && hp->h.deep < depth)
  795.     {
  796.       register header    *np = hp->h.next;
  797.  
  798.       free ((pointer) hp);    /* collect garbage */
  799.  
  800.       hp = np;        /* -> next header */
  801.     }
  802.       else
  803.     break;            /* rest are not deeper */
  804.  
  805.     last_alloca_header = hp;    /* -> last valid storage */
  806.   }
  807.  
  808.   if (size == 0)
  809.     return NULL;        /* no allocation required */
  810.  
  811.   /* Allocate combined header + user data storage. */
  812.  
  813.   {
  814.     register pointer    new = xmalloc (sizeof (header) + size);
  815.     /* address of header */
  816.  
  817.     ((header *)new)->h.next = last_alloca_header;
  818.     ((header *)new)->h.deep = depth;
  819.  
  820.     last_alloca_header = (header *)new;
  821.  
  822.     /* User storage begins just after header. */
  823.  
  824.     return (pointer)((char *)new + sizeof(header));
  825.   }
  826. }
  827.  
  828.  
  829. setproctitle:
  830. -------------
  831.  
  832. From: Tor Lillqvist (tml@tik.vtt.fi),
  833.       Technical Research Centre of Finland,
  834.       Laboratory for Information Processing (VTT/TIK).
  835.  
  836. Q: How can I write to the argv[] strings in a program so that the
  837.    altered strings show up in 'ps'?
  838.  
  839. A: In HP-UX you can't do it by clobbering the argv strings, but with the
  840.    undocumented pstat syscall.  This code is from sendmail 5.65c (routine
  841.    conf.c). Modify to your taste (especially remove the " (sendmail)").
  842.  
  843. /*
  844. **  SETPROCTITLE -- set process title for ps
  845. **
  846. **    Parameters:
  847. **        fmt -- a printf style format string.
  848. **        a, b, c -- possible parameters to fmt.
  849. **
  850. **    Returns:
  851. **        none.
  852. **
  853. **    Side Effects:
  854. **        Clobbers argv of our main procedure so ps(1) will
  855. **        display the title.
  856. */
  857.  
  858. /*VARARGS1*/
  859. void
  860. #ifdef __STDC__
  861. setproctitle(const char *fmt, ...)
  862. #else /* !__STDC__ */
  863. setproctitle(fmt, va_alist)
  864.     const char *fmt;
  865. va_dcl
  866. #endif /* __STDC__ */
  867. {
  868. #if defined(SETPROCTITLE) && !defined(SYSV)
  869.     va_list    args;
  870.     register char *p;
  871.     register int i;
  872. #if defined(__hpux) && defined(PSTAT_SETCMD)
  873.     union pstun un;
  874. #else
  875.     extern char **Argv;
  876.     extern char *LastArgv;
  877. #endif
  878.     char buf[MAXLINE];
  879.  
  880. # ifdef __STDC__
  881.     va_start(args, fmt);
  882. # else /* !__STDC__ */
  883.     va_start(args);
  884. # endif /* __STDC__ */
  885.     (void) vsprintf(buf, fmt, args);
  886.     va_end(args);
  887.  
  888. #if defined(__hpux) && defined(PSTAT_SETCMD)
  889.     (void) sprintf(buf + strlen(buf), " (sendmail)");
  890.     un.pst_command = buf;
  891.     pstat(PSTAT_SETCMD, un, strlen(buf), 0, 0);
  892. #else
  893.     /* make ps print "(sendmail)" */
  894.     p = Argv[0];
  895.     *p++ = '-';
  896.  
  897.     i = strlen(buf);
  898.     if (i > LastArgv - p - 2)
  899.     {
  900.         i = LastArgv - p - 2;
  901.         buf[i] = '\0';
  902.     }
  903.     (void) strcpy(p, buf);
  904.     p += i;
  905.     while (p < LastArgv)
  906.         *p++ = ' ';
  907. #endif
  908. #endif /* SETPROCTITLE && !SYSV */
  909. }
  910.