home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / trn / part06 / util.c < prev   
Encoding:
C/C++ Source or Header  |  1991-12-02  |  14.3 KB  |  714 lines

  1. /* $Id: util.c,v 4.4 1991/09/09 20:27:37 sob Exp sob $
  2.  *
  3.  * $Log: util.c,v $
  4.  * Revision 4.4  1991/09/09  20:27:37  sob
  5.  * release 4.4
  6.  *
  7.  *
  8.  * 
  9.  */
  10. /* This software is Copyright 1991 by Stan Barber. 
  11.  *
  12.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  13.  * use this software as long as: there is no monetary profit gained
  14.  * specifically from the use or reproduction of this software, it is not
  15.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  16.  * included prominently in any copy made. 
  17.  *
  18.  * The author make no claims as to the fitness or correctness of this software
  19.  * for any use whatsoever, and it is provided as is. Any use of this software
  20.  * is at the user's own risk. 
  21.  */
  22.  
  23. #include "EXTERN.h"
  24. #include "common.h"
  25. #include "final.h"
  26. #include "INTERN.h"
  27. #include "util.h"
  28.  
  29. #ifdef TZSET
  30. #include <time.h>
  31. #else
  32. #include <sys/time.h>
  33. #include <sys/timeb.h>
  34. #endif
  35.  
  36. void
  37. util_init()
  38. {
  39.     ;
  40. }
  41.     
  42. /* fork and exec a shell command */
  43.  
  44. int
  45. doshell(shl,s)
  46. char *s, *shl;
  47. {
  48.     int status, pid, w;
  49.     char *shell;
  50.  
  51. #ifdef SIGTSTP
  52.     sigset(SIGTSTP,SIG_DFL);
  53.     sigset(SIGTTOU,SIG_DFL);
  54.     sigset(SIGTTIN,SIG_DFL);
  55. #endif
  56.     if (shl != Nullch)
  57.     shell = shl;
  58.     else if ((shell = getenv("SHELL")) == Nullch || !*shell)
  59.     shell = PREFSHELL;
  60.     if ((pid = vfork()) == 0) {
  61. #ifdef SERVER
  62.         int i;
  63.  
  64.     /* This is necessary to keep bourne shell from puking */
  65.  
  66.         for (i = 3; i < 10; ++i)
  67.                 close(i);
  68. #endif /* SERVER */
  69.  
  70.     if (*s)
  71.         execl(shell, shell, "-c", s, Nullch);
  72.     else
  73.         execl(shell, shell, Nullch, Nullch, Nullch);
  74.     _exit(127);
  75.     }
  76.     signal(SIGINT, SIG_IGN);
  77. #ifdef SIGQUIT
  78.     signal(SIGQUIT, SIG_IGN);
  79. #endif 
  80.     waiting = TRUE;
  81.     while ((w = wait(&status)) != pid)
  82.     if (w == -1 && errno != EINTR)
  83.         break;
  84.     if (w == -1)
  85.     status = -1;
  86.     waiting = FALSE;
  87.     sigset(SIGINT, int_catcher);    /* always catch interrupts */
  88. #ifdef SIGQUIT
  89.     signal(SIGQUIT, SIG_DFL);
  90. #endif 
  91. #ifdef SIGTSTP
  92.     sigset(SIGTSTP,stop_catcher);
  93.     sigset(SIGTTOU,stop_catcher);
  94.     sigset(SIGTTIN,stop_catcher);
  95. #endif
  96.     return status;
  97. }
  98.  
  99. static char nomem[] = "rn: out of memory!\n";
  100.  
  101. /* paranoid version of malloc */
  102.  
  103. char *
  104. safemalloc(size)
  105. MEM_SIZE size;
  106. {
  107.     char *ptr;
  108.     char *malloc();
  109.  
  110.     ptr = malloc(size ? size : (MEM_SIZE)1);
  111.     if (ptr == Nullch) {
  112.     fputs(nomem,stdout) FLUSH;
  113.     sig_catcher(0);
  114.     }
  115.     return ptr;
  116. }
  117.  
  118. /* paranoid version of realloc */
  119.  
  120. char *
  121. saferealloc(where,size)
  122. char *where;
  123. MEM_SIZE size;
  124. {
  125.     char *ptr;
  126.     char *realloc();
  127.  
  128.     ptr = realloc(where,size?size:1);    /* realloc(0) is NASTY on our system */
  129.     if (ptr == Nullch) {
  130.     fputs(nomem,stdout) FLUSH;
  131.     sig_catcher(0);
  132.     }
  133.     return ptr;
  134. }
  135.  
  136. /* safe version of string copy */
  137.  
  138. char *
  139. safecpy(to,from,len)
  140. char *to;
  141. register char *from;
  142. register int len;
  143. {
  144.     register char *dest = to;
  145.  
  146.     if (from != Nullch) 
  147.     for (len--; len && (*dest++ = *from++); len--) ;
  148.     *dest = '\0';
  149.     return to;
  150. }
  151.  
  152. /* safe version of string concatenate, with \n deletion and space padding */
  153.  
  154. char *
  155. safecat(to,from,len)
  156. char *to;
  157. register char *from;
  158. register int len;
  159. {
  160.     register char *dest = to;
  161.  
  162.     len--;                /* leave room for null */
  163.     if (*dest) {
  164.     while (len && *dest++) len--;
  165.     if (len) {
  166.         len--;
  167.         *(dest-1) = ' ';
  168.     }
  169.     }
  170.     if (from != Nullch)
  171.     while (len && (*dest++ = *from++)) len--;
  172.     if (len)
  173.     dest--;
  174.     if (*(dest-1) == '\n')
  175.     dest--;
  176.     *dest = '\0';
  177.     return to;
  178. }
  179.  
  180. /* copy a string up to some (non-backslashed) delimiter, if any */
  181.  
  182. char *
  183. cpytill(to,from,delim)
  184. register char *to, *from;
  185. register int delim;
  186. {
  187.     for (; *from; from++,to++) {
  188.     if (*from == '\\' && from[1] == delim)
  189.         from++;
  190.     else if (*from == delim)
  191.         break;
  192.     *to = *from;
  193.     }
  194.     *to = '\0';
  195.     return from;
  196. }
  197.  
  198. /* return ptr to little string in big string, NULL if not found */
  199.  
  200. char *
  201. instr(big, little, case_matters)
  202. char *big, *little;
  203. int case_matters;
  204. {
  205.     register char *t, *s, *x;
  206.  
  207.     for (t = big; *t; t++) {
  208.     for (x=t,s=little; *s; x++,s++) {
  209.         if (!*x)
  210.         return Nullch;
  211.         if (case_matters == TRUE) {
  212.         if(*s != *x)
  213.             break;
  214.         } else {
  215.         register char c,d;
  216.         if (isupper(*s)) 
  217.             c = tolower(*s);
  218.         else
  219.             c = *s;
  220.         if (isupper(*x)) 
  221.             d = tolower(*x);
  222.         else
  223.             d = *x;
  224.         if ( c != d )
  225.             break;
  226.        }
  227.     }
  228.     if (!*s)
  229.         return t;
  230.     }
  231.     return Nullch;
  232. }
  233.  
  234. /* effective access */
  235.  
  236. #ifdef SETUIDGID
  237. int
  238. eaccess(filename, mod)
  239. char *filename;
  240. int mod;
  241. {
  242.     int protection, euid;
  243.     
  244.     mod &= 7;                /* remove extraneous garbage */
  245.     if (stat(filename, &filestat) < 0)
  246.     return -1;
  247.     euid = geteuid();
  248.     if (euid == ROOTID)
  249.     return 0;
  250.     protection = 7 & (filestat.st_mode >>
  251.       (filestat.st_uid == euid ? 6 :
  252.         (filestat.st_gid == getegid() ? 3 : 0)
  253.       ));
  254.     if ((mod & protection) == mod)
  255.     return 0;
  256.     errno = EACCES;
  257.     return -1;
  258. }
  259. #endif
  260.  
  261. /*
  262.  * Get working directory
  263.  */
  264. #ifndef GETWD
  265. #ifdef GETCWD
  266. char *
  267. getwd(np)
  268. char *np;
  269. {
  270.     char * name;
  271.     extern char * getcwd();
  272.     name = getcwd(np,512);
  273.     return(name);
  274. }
  275. #else
  276. char *
  277. getwd(np)            /* shorter but slower */
  278. char *np;
  279. {
  280.     FILE *popen();
  281.     FILE *pipefp = popen("/bin/pwd","r");
  282.  
  283.     if (pipefp == Nullfp) {
  284.     printf("Can't run /bin/pwd\n") FLUSH;
  285.     finalize(1);
  286.     }
  287.     fgets(np,512,pipefp);
  288.     np[strlen(np)-1] = '\0';    /* wipe out newline */
  289.     pclose(pipefp);
  290.     return np;
  291. }
  292. #endif
  293. #endif
  294. /* just like fgets but will make bigger buffer as necessary */
  295.  
  296. char *
  297. get_a_line(original_buffer,buffer_length,fp)
  298. char *original_buffer;
  299. register int buffer_length;
  300. FILE *fp;
  301. {
  302.     register int bufix = 0;
  303.     register int nextch;
  304.     register char *some_buffer_or_other = original_buffer;
  305.  
  306.     do {
  307.     if (bufix >= buffer_length) {
  308.         buffer_length *= 2;
  309.         if (some_buffer_or_other == original_buffer) {
  310.                     /* currently static? */
  311.         some_buffer_or_other = safemalloc((MEM_SIZE)buffer_length+1);
  312.         strncpy(some_buffer_or_other,original_buffer,buffer_length/2);
  313.                     /* so we must copy it */
  314.         }
  315.         else {            /* just grow in place, if possible */
  316.         some_buffer_or_other = saferealloc(some_buffer_or_other,
  317.             (MEM_SIZE)buffer_length+1);
  318.         }
  319.     }
  320.     if ((nextch = getc(fp)) == EOF)
  321.         return Nullch;
  322.     some_buffer_or_other[bufix++] = (char) nextch;
  323.     } while (nextch && nextch != '\n');
  324.     some_buffer_or_other[bufix] = '\0';
  325.     len_last_line_got = bufix;
  326.     return some_buffer_or_other;
  327. }
  328.  
  329. /* copy a string to a safe spot */
  330.  
  331. char *
  332. savestr(str)
  333. char *str;
  334. {
  335.     register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));
  336.  
  337.     strcpy(newaddr,str);
  338.     return newaddr;
  339. }
  340.  
  341. int
  342. makedir(dirname,nametype)
  343. register char *dirname;
  344. int nametype;
  345. {
  346. #ifdef MAKEDIR
  347.     register char *end;
  348.     register char *s;
  349.     char tmpbuf[1024];
  350.     register char *tbptr = tmpbuf+5;
  351.  
  352.     for (end = dirname; *end; end++) ;    /* find the end */
  353.     if (nametype == MD_FILE) {        /* not to create last component? */
  354.     for (--end; end != dirname && *end != '/'; --end) ;
  355.     if (*end != '/')
  356.         return 0;            /* nothing to make */
  357.     *end = '\0';            /* isolate file name */
  358.     }
  359.     strcpy(tmpbuf,"mkdir");
  360.  
  361.     s = end;
  362.     for (;;) {
  363.     if (stat(dirname,&filestat) >= 0 && (filestat.st_mode & S_IFDIR)) {
  364.                     /* does this much exist as a dir? */
  365.         *s = '/';            /* mark this as existing */
  366.         break;
  367.     }
  368.     s = rindex(dirname,'/');    /* shorten name */
  369.     if (!s)                /* relative path! */
  370.         break;            /* hope they know what they are doing */
  371.     *s = '\0';            /* mark as not existing */
  372.     }
  373.     
  374.     for (s=dirname; s <= end; s++) {    /* this is grody but efficient */
  375.     if (!*s) {            /* something to make? */
  376.         sprintf(tbptr," %s",dirname);
  377.         tbptr += strlen(tbptr);    /* make it, sort of */
  378.         *s = '/';            /* mark it made */
  379.     }
  380.     }
  381.     if (nametype == MD_DIR)        /* don't need final slash unless */
  382.     *end = '\0';            /*  a filename follows the dir name */
  383.  
  384.     return (tbptr==tmpbuf+5 ? 0 : doshell(sh,tmpbuf));
  385.                     /* exercise our faith */
  386. #else
  387.     sprintf(cmd_buf,"%s %s %d", filexp(DIRMAKER), dirname, nametype);
  388.     return doshell(sh,cmd_buf);
  389. #endif
  390. }
  391.  
  392. #ifdef SETENV
  393. static bool firstsetenv = TRUE;
  394. extern char **environ;
  395.  
  396. void
  397. setenv(nam,val)
  398. char *nam, *val;
  399. {
  400.     register int i=envix(nam);        /* where does it go? */
  401.  
  402.     if (!environ[i]) {            /* does not exist yet */
  403.     if (firstsetenv) {        /* need we copy environment? */
  404.         int j;
  405. #ifndef lint
  406.         char **tmpenv = (char**)    /* point our wand at memory */
  407.         safemalloc((MEM_SIZE) (i+2) * sizeof(char*));
  408. #else
  409.         char **tmpenv = Null(char **);
  410. #endif /* lint */
  411.     
  412.         firstsetenv = FALSE;
  413.         for (j=0; j<i; j++)        /* copy environment */
  414.         tmpenv[j] = environ[j];
  415.         environ = tmpenv;        /* tell exec where it is now */
  416.     }
  417. #ifndef lint
  418.     else
  419.         environ = (char**) saferealloc((char*) environ,
  420.         (MEM_SIZE) (i+2) * sizeof(char*));
  421.                     /* just expand it a bit */
  422. #endif /* lint */
  423.     environ[i+1] = Nullch;    /* make sure it's null terminated */
  424.     }
  425.     environ[i] = safemalloc((MEM_SIZE) strlen(nam) + strlen(val) + 2);
  426.                     /* this may or may not be in */
  427.                     /* the old environ structure */
  428.     sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
  429. }
  430.  
  431. int
  432. envix(nam)
  433. char *nam;
  434. {
  435.     register int i, len = strlen(nam);
  436.  
  437.     for (i = 0; environ[i]; i++) {
  438.     if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
  439.         break;            /* strnEQ must come first to avoid */
  440.     }                    /* potential SEGV's */
  441.     return i;
  442. }
  443. #endif
  444.  
  445. void
  446. notincl(feature)
  447. char *feature;
  448. {
  449.     printf("\nNo room for feature \"%s\" on this machine.\n",feature) FLUSH;
  450. }
  451.  
  452. char *
  453. getval(nam,def)
  454. char *nam,*def;
  455. {
  456.     char *val;
  457.  
  458.     if ((val = getenv(nam)) == Nullch || !*val)
  459.     val = def;
  460.     return val;
  461. }
  462.  
  463. /* grow a static string to at least a certain length */
  464.  
  465. void
  466. growstr(strptr,curlen,newlen)
  467. char **strptr;
  468. int *curlen;
  469. int newlen;
  470. {
  471.     if (newlen > *curlen) {        /* need more room? */
  472.     if (*curlen)
  473.         *strptr = saferealloc(*strptr,(MEM_SIZE)newlen);
  474.     else
  475.         *strptr = safemalloc((MEM_SIZE)newlen);
  476.     *curlen = newlen;
  477.     }
  478. }
  479.  
  480. void
  481. setdef(buffer,dflt)
  482. char *buffer,*dflt;
  483. {
  484. #ifdef STRICTCR
  485.     if (*buffer == ' ')
  486. #else
  487.     if (*buffer == ' ' || *buffer == '\n')
  488. #endif
  489.     {
  490.     if (*dflt == '^' && isupper(dflt[1]))
  491.         *buffer = Ctl(dflt[1]);
  492.     else
  493.         *buffer = *dflt;
  494.     }
  495. }
  496.  
  497. #ifdef SERVER
  498. int nntp_get(buf, len)
  499. char *buf;
  500. int  len;
  501. {
  502.      int n;
  503. #ifdef HAVESIGHOLD
  504.      sighold(SIGINT);
  505. #endif
  506.      n = get_server(buf, len);
  507. #ifdef HAVESIGHOLD
  508.      sigrelse(SIGINT);
  509. #endif
  510.      return n;
  511. }
  512. #endif
  513.  
  514. #ifndef STRFTIME
  515. /*
  516.  * strftime: print formatted information about a given time.
  517.  * Adapted from the routine by Eric R. Smith, Michal Jaegermann,
  518.  * Arnold Robins, and Paul Close.
  519.  */
  520.  
  521. /* Configuration choices for %x and %X */
  522.  
  523. #undef LOCAL_DDMMYY    /* choose DD/MM/YY instead of MM/DD/YY */
  524. #undef LOCAL_DOTTIME    /* choose HH.MM.SS instead of HH:MM:SS */
  525.  
  526. static char *mth_name[] = {
  527.     "January", "February", "March", "April", "May", "June",
  528.     "July", "August", "September", "October", "November", "December"
  529. };
  530.  
  531. static char *day_name[] = {
  532.     "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
  533.     "Saturday"
  534. };
  535.  
  536. #ifdef TZSET
  537. extern char *tzname[];
  538. #endif
  539.  
  540. int
  541. strftime(str, maxsize, fmt, ts)
  542. char *str;
  543. int maxsize;
  544. char *fmt;
  545. struct tm *ts;
  546. {
  547.     int num = 0, len;
  548.     char ch;
  549.     char *putstr, *s;
  550.     char tmpbuf[80];
  551.  
  552.     if (maxsize-- <= 0)
  553.     return 0;
  554.  
  555.     for (;;) {
  556.     if (!(ch = *fmt++))
  557.         break;
  558.     if (num == maxsize) {
  559.         num = 0;
  560.         break;
  561.     }
  562.     if (ch != '%') {
  563.         *str++ = ch;
  564.         num++;
  565.         continue;
  566.     }
  567.     /* assume the finished product will be sprintf'ed into tmpbuf */
  568.     putstr = tmpbuf;
  569.  
  570.     switch (ch = *fmt++) {
  571.     case 'A':
  572.     case 'a':
  573.         if (ts->tm_wday < 0 || ts->tm_wday > 6)
  574.         putstr = "?";
  575.         else
  576.         if (ch == 'A')
  577.             putstr = day_name[ts->tm_wday];
  578.         else
  579.             sprintf(tmpbuf, "%-.3s", day_name[ts->tm_wday]);
  580.         break;
  581.     case 'B':
  582.     case 'b':
  583.     case 'h':
  584.         if (ts->tm_mon < 0 || ts->tm_mon > 11)
  585.         putstr = "?";
  586.         else if (ch == 'B')
  587.         putstr = mth_name[ts->tm_mon];
  588.         else
  589.         sprintf(tmpbuf, "%-.3s", mth_name[ts->tm_mon]);
  590.         break;
  591.     case 'C':
  592.         strftime(tmpbuf, sizeof tmpbuf, "%A, %B %e, %Y", ts);
  593.         break;
  594.     case 'c':
  595.         strftime(tmpbuf, sizeof tmpbuf, "%x %X", ts);
  596.         break;
  597.     case 'D':
  598. #ifndef LOCAL_DDMMYY
  599.     case 'x':
  600. #endif
  601.         strftime(tmpbuf, sizeof tmpbuf, "%m/%d/%y", ts);
  602.         break;
  603.     case 'd':
  604.         sprintf(tmpbuf, "%02d", ts->tm_mday);
  605.         break;
  606.     case 'e':    /* day of month, blank padded */
  607.         sprintf(tmpbuf, "%2d", ts->tm_mday);
  608.         break;
  609.     case 'H':
  610.         sprintf(tmpbuf, "%02d", ts->tm_hour);
  611.         break;
  612.     case 'I':
  613.     {
  614.         int n;
  615.  
  616.         n = ts->tm_hour;
  617.         if (n == 0)
  618.         n = 12;
  619.         else if (n > 12)
  620.         n -= 12;
  621.         sprintf(tmpbuf, "%02d", n);
  622.         break;
  623.     }
  624.     case 'j':
  625.         sprintf(tmpbuf, "%03d", ts->tm_yday + 1);
  626.         break;
  627.     case 'm':
  628.         sprintf(tmpbuf, "%02d", ts->tm_mon + 1);
  629.         break;
  630.     case 'M':
  631.         sprintf(tmpbuf, "%02d", ts->tm_min);
  632.         break;
  633.     case 'p':
  634.         putstr = (ts->tm_hour < 12) ? "AM" : "PM";
  635.         break;
  636.     case 'r':
  637.         strftime(tmpbuf, sizeof tmpbuf, "%I:%M:%S %p", ts);
  638.         break;
  639.     case 'R':
  640.         strftime(tmpbuf, sizeof tmpbuf, "%H:%M", ts);
  641.         break;
  642.     case 'S':
  643.         sprintf(tmpbuf, "%02d", ts->tm_sec);
  644.         break;
  645.     case 'T':
  646. #ifndef LOCAL_DOTTIME
  647.     case 'X':
  648. #endif
  649.         strftime(tmpbuf, sizeof tmpbuf, "%H:%M:%S", ts);
  650.         break;
  651.     case 'U':    /* week of year - starting Sunday */
  652.         sprintf(tmpbuf, "%02d", (ts->tm_yday - ts->tm_wday + 10) / 7);
  653.         break;
  654.     case 'W':    /* week of year - starting Monday */
  655.         sprintf(tmpbuf, "%02d", (ts->tm_yday - ((ts->tm_wday + 6) % 7)
  656.             + 10) / 7);
  657.         break;
  658.     case 'w':
  659.         sprintf(tmpbuf, "%d", ts->tm_wday);
  660.         break;
  661.     case 'y':
  662.         sprintf(tmpbuf, "%02d", ts->tm_year % 100);
  663.         break;
  664. #ifdef LOCAL_DOTTIME
  665.     case 'X':
  666.         strftime(tmpbuf, sizeof tmpbuf, "%H.%M.%S", ts);
  667.         break;
  668. #endif
  669. #ifdef LOCAL_DDMMYY
  670.     case 'x':
  671.         strftime(tmpbuf, sizeof tmpbuf, "%d/%m/%y", ts);
  672.         break;
  673. #endif
  674.     case 'Y':
  675.         sprintf(tmpbuf, "%d", ts->tm_year + 1900);
  676.         break;
  677.     case 'Z':
  678. #ifdef TZSET
  679.         sprintf(tmpbuf, "%s", tzname[ts->tm_isdst]);
  680. #else
  681.         sprintf(tmpbuf, "%s", ts->tm_zone);
  682. #endif
  683.         break;
  684.     case '%':
  685.     case '\0':
  686.         putstr = "%";
  687.         break;
  688.     case 'n':    /* same as \n */
  689.         putstr = "\n";
  690.         break;
  691.     case 't':    /* same as \t */
  692.         putstr = "\n";
  693.         break;
  694.     default:
  695.         sprintf(tmpbuf, "%%%c", ch);
  696.         break;
  697.     }
  698.     len = strlen(putstr);
  699.     num += len;
  700.     if (num > maxsize) {
  701.         len -= num - maxsize;
  702.         num = 0;
  703.         ch = '\0';
  704.     }
  705.     strncpy(str, putstr, len);
  706.     str += len;
  707.     if (!ch)
  708.         break;
  709.     }
  710.     *str = '\0';
  711.     return num;
  712. }
  713. #endif /* no STRFTIME */
  714.