home *** CD-ROM | disk | FTP | other *** search
- /* $Id: util.c,v 4.4.4.1 1992/02/23 21:25:39 sob PATCH_4 sob $
- *
- * $Log: util.c,v $
- * Revision 4.4.4.1 1992/02/23 21:25:39 sob
- * Patch level 4
- *
- * Revision 4.4.3.1 1992/02/01 03:09:32 sob
- * Release 4.4 Patchlevel 3
- *
- * Revision 4.4 1991/09/09 20:27:37 sob
- * release 4.4
- *
- *
- *
- */
- /* This software is Copyright 1991 by Stan Barber.
- *
- * Permission is hereby granted to copy, reproduce, redistribute or otherwise
- * use this software as long as: there is no monetary profit gained
- * specifically from the use or reproduction of this software, it is not
- * sold, rented, traded or otherwise marketed, and this copyright notice is
- * included prominently in any copy made.
- *
- * The author make no claims as to the fitness or correctness of this software
- * for any use whatsoever, and it is provided as is. Any use of this software
- * is at the user's own risk.
- */
-
- #include "EXTERN.h"
- #include "common.h"
- #include "final.h"
- #include "INTERN.h"
- /*#include "util.h"*/
-
- #include "util.h"
-
- /***OS2: util.h uses "struct tm", which is defined in time.h ***
-
- *** to avoid the fork/exec-combination, we use spawn. ***
- *** but we need process.h for this call. ***
-
- *** because the mkdir-command does not work correctly, ***
- *** we replace it with a system call, but we need ***
- *** the include file "OS2.H" to do that ***/
-
- #include "process.h"
- #include "os2.h"
-
-
- void
- util_init()
- {
- ;
- }
-
- /* fork and exec a shell command */
-
- int
- doshell(shl,s)
- char *s, *shl;
- {
- int status, pid, w;
- char *shell;
-
- #ifdef SIGTSTP
- sigset(SIGTSTP,SIG_DFL);
- sigset(SIGTTOU,SIG_DFL);
- sigset(SIGTTIN,SIG_DFL);
- #endif
- if (shl != Nullch)
- { change_sl2bsl(shl);
- shell = shl;
- }
- else
- if ((shell = getenv("SHELL")) == Nullch || !*shell)
- shell = PREFSHELL;
- change_bsl2sl(shell);
-
- /*** OS2: fork's are not yet implemented in emx 0.8d. But here
- the vfork is used in combination with an execl-call.
- So lets use the spawnl-function instead. */
-
- /* if ((pid = vfork()) == 0) {
- #ifdef SERVER
- int i; */
-
- /* This is necessary to keep bourne shell from puking */
-
- /* for (i = 3; i < 10; ++i)
- close(i); */
- /* #endif * SERVER */
-
- /* if (*s)
- execl(shell, shell, "-c", s, Nullch);
- else
- execl(shell, shell, Nullch, Nullch, Nullch);
- _exit(127);
- } */
-
- /*** OS2: and now the new call: */
-
- /*** OS2: We'll have to use /c and not -c ***/
- if (*s)
- pid = spawnl(P_NOWAIT, shell, shell, "/c", s, Nullch);
- else
- pid = spawnl(P_NOWAIT, shell, shell, Nullch, Nullch, Nullch);
-
- /*** OS2: end of fork/exec - substitution **
-
- *** put fingers crossed ....****/
-
-
- signal(SIGINT, SIG_IGN);
- #ifdef SIGQUIT
- signal(SIGQUIT, SIG_IGN);
- #endif
- termlib_reset();
- waiting = TRUE;
- while ((w = wait(&status)) != pid)
- if (w == -1 && errno != EINTR)
- break;
- if (w == -1)
- status = -1;
- termlib_init();
- waiting = FALSE;
- sigset(SIGINT, int_catcher); /* always catch interrupts */
- #ifdef SIGQUIT
- signal(SIGQUIT, SIG_DFL);
- #endif
- #ifdef SIGTSTP
- sigset(SIGTSTP,stop_catcher);
- sigset(SIGTTOU,stop_catcher);
- sigset(SIGTTIN,stop_catcher);
- #endif
-
- return status;
- }
-
- static char nomem[] = "rn: out of memory!\n";
-
- /* paranoid version of malloc */
-
- char *
- safemalloc(size)
- MEM_SIZE size;
- {
- char *ptr;
- char *malloc();
-
- ptr = malloc(size ? size : (MEM_SIZE)1);
- if (ptr == Nullch) {
- fputs(nomem,stdout) ; FLUSH;
- sig_catcher(0);
- }
- return ptr;
- }
-
- /* paranoid version of realloc */
-
- char *
- saferealloc(where,size)
- char *where;
- MEM_SIZE size;
- {
- char *ptr;
- char *realloc();
-
- ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
- if (ptr == Nullch) {
- fputs(nomem,stdout) ; FLUSH;
- sig_catcher(0);
- }
- return ptr;
- }
-
- /* safe version of string copy */
-
- char *
- safecpy(to,from,len)
- char *to;
- register char *from;
- register int len;
- {
- register char *dest = to;
-
- if (from != Nullch)
- for (len--; len && (*dest++ = *from++); len--) ;
- *dest = '\0';
- return to;
- }
-
- /* safe version of string concatenate, with \n deletion and space padding */
-
- char *
- safecat(to,from,len)
- char *to;
- register char *from;
- register int len;
- {
- register char *dest = to;
-
- len--; /* leave room for null */
- if (*dest) {
- while (len && *dest++) len--;
- if (len) {
- len--;
- *(dest-1) = ' ';
- }
- }
- if (from != Nullch)
- while (len && (*dest++ = *from++)) len--;
- if (len)
- dest--;
- if (*(dest-1) == '\n')
- dest--;
- *dest = '\0';
- return to;
- }
-
- /* copy a string up to some (non-backslashed) delimiter, if any */
-
- char *
- cpytill(to,from,delim)
- register char *to, *from;
- register int delim;
- {
- for (; *from; from++,to++) {
- if (*from == '\\' && from[1] == delim)
- from++;
- else if (*from == delim)
- break;
- *to = *from;
- }
- *to = '\0';
- return from;
- }
-
- /* return ptr to little string in big string, NULL if not found */
-
- char *
- instr(big, little, case_matters)
- char *big, *little;
- int case_matters;
- {
- register char *t, *s, *x;
-
- for (t = big; *t; t++) {
- for (x=t,s=little; *s; x++,s++) {
- if (!*x)
- return Nullch;
- if (case_matters == TRUE) {
- if(*s != *x)
- break;
- } else {
- register char c,d;
- if (isupper(*s))
- c = tolower(*s);
- else
- c = *s;
- if (isupper(*x))
- d = tolower(*x);
- else
- d = *x;
- if ( c != d )
- break;
- }
- }
- if (!*s)
- return t;
- }
- return Nullch;
- }
-
- /* effective access */
-
- #ifdef SETUIDGID
- int
- eaccess(filename, mod)
- char *filename;
- int mod;
- {
- int protection, euid;
-
- mod &= 7; /* remove extraneous garbage */
- if (stat(filename, &filestat) < 0)
- return -1;
- euid = geteuid();
- if (euid == ROOTID)
- return 0;
- protection = 7 & (filestat.st_mode >>
- (filestat.st_uid == euid ? 6 :
- (filestat.st_gid == getegid() ? 3 : 0)
- ));
- if ((mod & protection) == mod)
- return 0;
- errno = EACCES;
- return -1;
- }
- #endif
-
- /*
- * Get working directory
- */
- #ifndef GETWD
- #ifdef GETCWD
- char *
- getwd(np)
- char *np;
- {
- char * name;
- extern char * getcwd();
- name = getcwd(np,512);
- return(name);
- }
- #else
- char *
- getwd(np) /* shorter but slower */
- char *np;
- {
- FILE *popen();
- FILE *pipefp = popen("/bin/pwd","r");
-
- if (pipefp == Nullfp) {
- printf("Can't run /bin/pwd\n") ; FLUSH;
- finalize(1);
- }
- fgets(np,512,pipefp);
- np[strlen(np)-1] = '\0'; /* wipe out newline */
- pclose(pipefp);
- return np;
- }
- #endif
- #endif
- /* just like fgets but will make bigger buffer as necessary */
-
- char *
- get_a_line(original_buffer,buffer_length,fp)
- char *original_buffer;
- register int buffer_length;
- FILE *fp;
- {
- register int bufix = 0;
- register int nextch;
- register char *some_buffer_or_other = original_buffer;
-
- do {
- if (bufix >= buffer_length) {
- buffer_length *= 2;
- if (some_buffer_or_other == original_buffer) {
- /* currently static? */
- some_buffer_or_other = safemalloc((MEM_SIZE)buffer_length+1);
- strncpy(some_buffer_or_other,original_buffer,buffer_length/2);
- /* so we must copy it */
- }
- else { /* just grow in place, if possible */
- some_buffer_or_other = saferealloc(some_buffer_or_other,
- (MEM_SIZE)buffer_length+1);
- }
- }
- if ((nextch = getc(fp)) == EOF)
- return Nullch;
- some_buffer_or_other[bufix++] = (char) nextch;
- } while (nextch && nextch != '\n');
- some_buffer_or_other[bufix] = '\0';
- len_last_line_got = bufix;
- return some_buffer_or_other;
- }
-
- /* copy a string to a safe spot */
-
- char *
- savestr(str)
- char *str;
- {
- register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));
-
- strcpy(newaddr,str);
- return newaddr;
- }
-
- int
- makedir(dirname,nametype)
- register char *dirname;
- int nametype;
- {
- #ifdef MAKEDIR
-
- register char *end;
- register char *s;
- char tmpbuf[1024];
- register char *tbptr = tmpbuf+5;
- /*** OS2: we'll need the following variable, to extract
- the directory name out of the tmpbuf-string, which
- includes the "mkdir "-command. ***/
- register char *tmpdirname = tmpbuf+6;
- unsigned long create_return = 0;
-
- for (end = dirname; *end; end++) ; /* find the end */
- if (nametype == MD_FILE) { /* not to create last component? */
- for (--end; end != dirname && *end != '/'; --end) ;
- if (*end != '/')
- return 0; /* nothing to make */
- *end = '\0'; /* isolate file name */
- }
- strcpy(tmpbuf,"mkdir");
-
- s = end;
- for (;;) {
- if (stat(dirname,&filestat) >= 0 && (filestat.st_mode & S_IFDIR)) {
- /* does this much exist as a dir? */
- *s = '/'; /* mark this as existing */
- break;
- }
- s = rindex(dirname,'/'); /* shorten name */
- if (!s) /* relative path! */
- break; /* hope they know what they are doing */
- *s = '\0'; /* mark as not existing */
- }
-
- /*** OS2: That's a bit of a problem, this routine will try to
- make a string like
- "mkdir c:\usr\news\haen\comp c:\usr\news\haen\comp\os ...."
- and try to make more than one directory at one. But this
- will not work with a API-Call, so we will call the
- DosCreateDir every time, when orignially the sprintf
- would be called. ***/
-
- for (s=dirname; s <= end; s++) { /* this is grody but efficient */
- if (!*s) { /* something to make? */
- /*** ok not sprintf, but DosCreateDir ***/
- /* sprintf(tbptr," %s",dirname); */
- if ((create_return = DosCreateDir(dirname,0)) != 0)
- return create_return;
- tbptr += strlen(tbptr); /* make it, sort of */
- *s = '/'; /* mark it made */
- }
- }
- if (nametype == MD_DIR) /* don't need final slash unless */
- *end = '\0'; /* a filename follows the dir name */
-
- /*** OS2: Sorry, but the doshell, which executes a "mkdir filename"
- does not work under OS/2, although we have a mkdir-command.
- So we'll remove "mkdir " out of "tmpbuf" and use
- an OS2-system call. The mkdir and so also the doshell
- returns negative return values on failure, but DosCreateDir
- returns positive values. So we must invert it. ********/
- /** This is now obsolete, see above **/
-
- /* return (tbptr==tmpbuf+5 ? 0 : doshell(sh,tmpbuf)); */
- /* return (tbptr==tmpbuf+5 ? 0 : -DosCreateDir(tmpdirname,0)); */
- /*** OS2: if DosCreateDir didn't fail, we can return 0***/
- return 0;
-
- /* exercise our faith */
- #else
- sprintf(cmd_buf,"%s %s %d", filexp(DIRMAKER), dirname, nametype);
- return doshell(sh,cmd_buf);
- #endif
- }
-
- #ifdef SETENV
- static bool firstsetenv = TRUE;
- extern char **environ;
-
- void
- setenv(nam,val)
- char *nam, *val;
- {
- register int i=envix(nam); /* where does it go? */
-
- if (!environ[i]) { /* does not exist yet */
- if (firstsetenv) { /* need we copy environment? */
- int j;
- #ifndef lint
- char **tmpenv = (char**) /* point our wand at memory */
- safemalloc((MEM_SIZE) (i+2) * sizeof(char*));
- #else
- char **tmpenv = Null(char **);
- #endif /* lint */
-
- firstsetenv = FALSE;
- for (j=0; j<i; j++) /* copy environment */
- tmpenv[j] = environ[j];
- environ = tmpenv; /* tell exec where it is now */
- }
- #ifndef lint
- else
- environ = (char**) saferealloc((char*) environ,
- (MEM_SIZE) (i+2) * sizeof(char*));
- /* just expand it a bit */
- #endif /* lint */
- environ[i+1] = Nullch; /* make sure it's null terminated */
- }
- environ[i] = safemalloc((MEM_SIZE) strlen(nam) + strlen(val) + 2);
- /* this may or may not be in */
- /* the old environ structure */
- sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
- }
-
- int
- envix(nam)
- char *nam;
- {
- register int i, len = strlen(nam);
-
- for (i = 0; environ[i]; i++) {
- if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
- break; /* strnEQ must come first to avoid */
- } /* potential SEGV's */
- return i;
- }
- #endif
-
- void
- notincl(feature)
- char *feature;
- {
- printf("\nNo room for feature \"%s\" on this machine.\n",feature) ; FLUSH;
- }
-
- char *
- getval(nam,def)
- char *nam,*def;
- {
- char *val;
-
- if ((val = getenv(nam)) == Nullch || !*val)
- val = def;
- return val;
- }
-
- /* grow a static string to at least a certain length */
-
- void
- growstr(strptr,curlen,newlen)
- char **strptr;
- int *curlen;
- int newlen;
- {
- if (newlen > *curlen) { /* need more room? */
- if (*curlen)
- *strptr = saferealloc(*strptr,(MEM_SIZE)newlen);
- else
- *strptr = safemalloc((MEM_SIZE)newlen);
- *curlen = newlen;
- }
- }
-
- void
- setdef(buffer,dflt)
- char *buffer,*dflt;
- {
- #ifdef STRICTCR
- if (*buffer == ' ')
- #else
- if (*buffer == ' ' || *buffer == '\n')
- #endif
- {
- if (*dflt == '^' && isupper(dflt[1]))
- *buffer = Ctl(dflt[1]);
- else
- *buffer = *dflt;
- }
- }
-
- #ifdef SERVER
- int nntp_get(buf, len)
- char *buf;
- int len;
- {
- int n;
- #ifdef HAVESIGHOLD
- sighold(SIGINT);
- #endif
- n = get_server(buf, len);
- #ifdef HAVESIGHOLD
- sigrelse(SIGINT);
- #endif
- return n;
- }
- #endif
-
- #if defined(USETHREADS) && !defined(STRFTIME)
- /*
- * strftime: print formatted information about a given time.
- * Adapted from the routine by Eric R. Smith, Michal Jaegermann,
- * Arnold Robins, and Paul Close.
- */
-
- /* Configuration choices for %x and %X */
-
- #undef LOCAL_DDMMYY /* choose DD/MM/YY instead of MM/DD/YY */
- #undef LOCAL_DOTTIME /* choose HH.MM.SS instead of HH:MM:SS */
-
- static char *mth_name[] = {
- "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December"
- };
-
- static char *day_name[] = {
- "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
- "Saturday"
- };
-
- #ifdef TZSET
- extern char *tzname[];
- #else
- # ifndef TM_ZONE
- char tznm[16] = "";
- # endif
- #endif
-
- size_t
- strftime(str, maxsize, fmt, ts)
- char *str;
- size_t maxsize;
- char *fmt;
- struct tm *ts;
- {
- size_t num = 0, len;
- char ch;
- char *putstr, *s;
- char tmpbuf[80];
-
- if (maxsize-- <= 0)
- return 0;
-
- for (;;) {
- if (!(ch = *fmt++))
- break;
- if (num == maxsize) {
- num = 0;
- break;
- }
- if (ch != '%') {
- *str++ = ch;
- num++;
- continue;
- }
- /* assume the finished product will be sprintf'ed into tmpbuf */
- putstr = tmpbuf;
-
- switch (ch = *fmt++) {
- case 'A':
- case 'a':
- if (ts->tm_wday < 0 || ts->tm_wday > 6)
- putstr = "?";
- else
- if (ch == 'A')
- putstr = day_name[ts->tm_wday];
- else
- sprintf(tmpbuf, "%-.3s", day_name[ts->tm_wday]);
- break;
- case 'B':
- case 'b':
- case 'h':
- if (ts->tm_mon < 0 || ts->tm_mon > 11)
- putstr = "?";
- else if (ch == 'B')
- putstr = mth_name[ts->tm_mon];
- else
- sprintf(tmpbuf, "%-.3s", mth_name[ts->tm_mon]);
- break;
- case 'C':
- strftime(tmpbuf, sizeof tmpbuf, "%A, %B %e, %Y", ts);
- break;
- case 'c':
- strftime(tmpbuf, sizeof tmpbuf, "%x %X", ts);
- break;
- case 'D':
- #ifndef LOCAL_DDMMYY
- case 'x':
- #endif
- strftime(tmpbuf, sizeof tmpbuf, "%m/%d/%y", ts);
- break;
- case 'd':
- sprintf(tmpbuf, "%02d", ts->tm_mday);
- break;
- case 'e': /* day of month, blank padded */
- sprintf(tmpbuf, "%2d", ts->tm_mday);
- break;
- case 'H':
- sprintf(tmpbuf, "%02d", ts->tm_hour);
- break;
- case 'I':
- {
- int n;
-
- n = ts->tm_hour;
- if (n == 0)
- n = 12;
- else if (n > 12)
- n -= 12;
- sprintf(tmpbuf, "%02d", n);
- break;
- }
- case 'j':
- sprintf(tmpbuf, "%03d", ts->tm_yday + 1);
- break;
- case 'm':
- sprintf(tmpbuf, "%02d", ts->tm_mon + 1);
- break;
- case 'M':
- sprintf(tmpbuf, "%02d", ts->tm_min);
- break;
- case 'p':
- putstr = (ts->tm_hour < 12) ? "AM" : "PM";
- break;
- case 'r':
- strftime(tmpbuf, sizeof tmpbuf, "%I:%M:%S %p", ts);
- break;
- case 'R':
- strftime(tmpbuf, sizeof tmpbuf, "%H:%M", ts);
- break;
- case 'S':
- sprintf(tmpbuf, "%02d", ts->tm_sec);
- break;
- case 'T':
- #ifndef LOCAL_DOTTIME
- case 'X':
- #endif
- strftime(tmpbuf, sizeof tmpbuf, "%H:%M:%S", ts);
- break;
- case 'U': /* week of year - starting Sunday */
- sprintf(tmpbuf, "%02d", (ts->tm_yday - ts->tm_wday + 10) / 7);
- break;
- case 'W': /* week of year - starting Monday */
- sprintf(tmpbuf, "%02d", (ts->tm_yday - ((ts->tm_wday + 6) % 7)
- + 10) / 7);
- break;
- case 'w':
- sprintf(tmpbuf, "%d", ts->tm_wday);
- break;
- case 'y':
- sprintf(tmpbuf, "%02d", ts->tm_year % 100);
- break;
- #ifdef LOCAL_DOTTIME
- case 'X':
- strftime(tmpbuf, sizeof tmpbuf, "%H.%M.%S", ts);
- break;
- #endif
- #ifdef LOCAL_DDMMYY
- case 'x':
- strftime(tmpbuf, sizeof tmpbuf, "%d/%m/%y", ts);
- break;
- #endif
- case 'Y':
- sprintf(tmpbuf, "%d", ts->tm_year + 1900);
- break;
- case 'Z':
- #ifdef TZSET
- sprintf(tmpbuf, "%s", tzname[ts->tm_isdst]);
- #else
- # ifdef TM_ZONE
- /*** OS2: hell wie mer sin...: because timezones are not
- implemented in emx 0.8d, the component tm_zone
- of the "struct tm" in time.h does not exist.
- Hmm,... let's default to GMT ***/
- /* sprintf(tmpbuf, "%s", ts->tm_zone); */
- sprintf(tmpbuf, "%s", "GMT");
- # else
- if (*tznm == '\0') {
- char *timezone();
- struct timeval tv;
- struct timezone tz;
-
- (void) gettimeofday(&tv, &tz);
- strcpy(tznm, timezone(tz.tz_minuteswest, ts->tm_isdst));
- }
- sprintf(tmpbuf, "%s", tznm);
- # endif
- #endif
- break;
- case '%':
- case '\0':
- putstr = "%";
- break;
- case 'n': /* same as \n */
- putstr = "\n";
- break;
- case 't': /* same as \t */
- putstr = "\t";
- break;
- default:
- sprintf(tmpbuf, "%%%c", ch);
- break;
- }
- len = strlen(putstr);
- num += len;
- if (num > maxsize) {
- len -= num - maxsize;
- num = 0;
- ch = '\0';
- }
- strncpy(str, putstr, len);
- str += len;
- if (!ch)
- break;
- }
- *str = '\0';
- return num;
- }
- #endif /* USETHREADS && no STRFTIME */
-