home *** CD-ROM | disk | FTP | other *** search
- /*
- * util.c - Various support functions.
- *
- * (C) 1994 Mikael Nordqvist (d91mn@efd.lth.se, mech@df.lth.se)
- */
-
- #include <ctype.h>
- #include <string.h>
- #include <stdio.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <sys/wait.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <sys/soundcard.h>
-
- #include "mod.h"
- #include "message.h"
-
- extern struct mod_info M;
- extern char quit;
- extern int seqfd, mixerfd;
-
- SEQ_DECLAREBUF();
-
- /*
- * Wordswapping functions
- */
-
- unsigned short SWAPSHORT(char *a)
- {
- return (((*(unsigned short *)a&0xff)<<8)|((*(unsigned short *)a>>8)&0xff));
- }
-
- unsigned long SWAPLONG(char *a)
- {
- return (SWAPSHORT(a)<<16 | SWAPSHORT(a+2));
- }
-
- /*
- * Removes nonprintable characters and trailing spaces from a string.
- */
-
- void fix_string(char *s)
- {
- char *a;
-
- a=s;
- while(*s) {
- if(*s >= 32 && *s <=126)
- s++;
- else
- *s++=' ';
- }
-
- for(--s; s >=a; --s) {
- if(*s == ' ')
- *s=0;
- else
- break;
- }
- }
-
- /* Fills out a string with spaces, or truncates it if its too long. */
-
- char *fill_string(char *s, int len)
- {
- static char buf[128];
- int i;
-
- strcpy(buf, s);
-
- i=strlen(s);
- if(i > len)
- i=len;
-
- for(; i < len; ++i)
- buf[i]=' ';
-
- buf[i]=0;
- return buf;
- }
-
- /*
- * This is seqbuf_dump() used by the SEQ_DUMPBUF macro.
- */
-
- void seqbuf_dump()
- {
- int thisone=0; /* No need to initialize, but it removes a warning */
- fd_set wset;
-
- while(_seqbufptr) {
- FD_ZERO(&wset);
- FD_SET(seqfd, &wset);
- if(select(seqfd+1, 0, &wset, 0, 0) >= 0) {
- if((thisone=write(seqfd, _seqbuf, _seqbufptr)) == -1)
- error("Unable to write(sequencer)");
-
- if(thisone < _seqbufptr) {
- memmove(_seqbuf, &(_seqbuf[thisone]), _seqbufptr-thisone);
- _seqbufptr-=thisone;
- }
- else
- _seqbufptr=0;
- }
- else {
- if(errno != EINTR)
- error("select() in seqbuf_dump failed (errno=%d)\n", errno);
- }
- }
- }
-
- /*
- * Changes the master volume by amount. amount=0 mutes/demutes
- */
-
- void change_mastervolume(int amount)
- {
- static int muted=100;
- int current;
-
- if(mixerfd == -1)
- return;
-
- if(ioctl(mixerfd, SOUND_MIXER_READ_SYNTH, ¤t) == -1)
- return;
-
- /* Take average of left/right */
- current=((current&0xff)+((current>>8)&0xff))/2;
- if(amount == 0) {
- if(!current)
- current=muted;
- else {
- muted=current;
- current=0;
- }
- }
- else {
- current=MIN(MAX(0, current+amount), 100);
- }
- current=current|(current<<8);
-
- if(ioctl(mixerfd, SOUND_MIXER_WRITE_SYNTH, ¤t) == -1)
- return;
- }
-
-
- /*
- * Takes track-data and returns the corresponding track-index.
- * This is where identical tracks are found.
- */
-
- int get_track_idx(struct event *e)
- {
- int i;
-
- for(i=0; i < M.nr_tracks; ++i)
- if(!bcmp(e, M.tracks[i], sizeof(struct event)*64))
- return i;
-
- M.tracks[M.nr_tracks]=(struct event *)malloc(sizeof(struct event)*64);
- memcpy((void *)M.tracks[M.nr_tracks], (void *)e, sizeof(struct event)*64);
- return M.nr_tracks++;
- }
-
-
- /* Allows reading of a small amounts of bytes from a file, n <= 10. Buffers
- * data to minimize number of read()-calls.
- * n = 0 Init.
- * n = -1 Cleanup (only needed if you need the read-ahead flushed).
- * The function returns true if all bytes could be read, false otherwise.
- */
-
- int get_bytes(int fd, char *dest, int n)
- {
- static char buf[1024];
- static int bufpos, lastbufpos, nomore;
- int thisone;
-
- if(n == -1) {
- if(lseek(fd, -(lastbufpos-bufpos+1), SEEK_CUR) == -1)
- error("Seek() failed.\n");
- return 1;
- }
-
- if(!n) {
- bufpos=0;
- lastbufpos=read(fd, buf, 1024);
- if(!lastbufpos || lastbufpos == -1) {
- return 0;
- }
- else {
- if(lastbufpos != 1024)
- nomore=1;
- else
- nomore=0;
- --lastbufpos;
- return 1;
- }
- }
-
- if(bufpos+n-1 <= lastbufpos) {
- memcpy(dest, &buf[bufpos], n);
- bufpos+=n;
- }
- else {
- return 0;
- }
-
- if(bufpos > 1010 && !nomore) {
- memmove(buf, &buf[bufpos], 1024-bufpos);
- if((thisone=read(fd, &buf[1024-bufpos], bufpos)) == 0 ||
- thisone == -1 || thisone != bufpos) {
- nomore=1;
- if(thisone <= 0)
- thisone=0;
- lastbufpos=1024-bufpos+thisone-1;
- }
- bufpos=0;
- }
- return 1;
- }
-
-
- /*
- * Writes a string to a filedescriptor
- */
-
- void safe_read(int fd, struct mod_message *buf, int len)
- {
- int sofar, thisone;
-
- sofar=0;
- do {
- thisone=read(fd, ((char *)buf)+sofar, len-sofar);
- if(thisone >= 0) {
- sofar+=thisone;
- if(!thisone)
- debug("safe_read(): 0\n");
- }
- else {
- if(errno != EAGAIN) {
- debug("Error reading pipe %d (seq=%d) (errno=%d)\n",
- fd, seqfd, errno);
- }
- else
- debug("safe_read() returned EAGAIN, retrying...\n");
- }
- }
- while(sofar < len);
- }
-
-
- /*
- * Writes a string to a filedescriptor
- */
-
- void safe_write(int fd, struct mod_message *buf, int len)
- {
- int sofar, thisone;
-
- sofar=0;
- do {
- thisone=write(fd, ((char *)buf)+sofar, len-sofar);
- if(thisone >= 0) {
- sofar+=thisone;
- if(!thisone)
- debug("safe_write(): 0\n");
- }
- else {
- if(errno != EAGAIN)
- error("Error writing pipe (%d)\n", errno);
- error("safe_write() would block...\n");
- }
- }
- while(sofar < len);
- }
-
-
- /* Returns < 0 if we got SIG_QUIT otherwise exitstatus of command */
-
- int my_system(char *a)
- {
- int p, status;
-
- switch(p=fork()) {
- case -1:
- error("Fork failed in my_system.");
- break;
- case 0:
- exit(system(a));
- break;
- default:
- while(1) {
- if(waitpid(p, &status, 0) >= 0) {
- if(WIFEXITED(status)) {
- if(quit == QUIT_SIGNAL)
- return -1;
- else
- return WEXITSTATUS(status);
- }
- else {
- debug("Huh??!! system()-problems\n");
- return 1;
- }
- }
- else {
- if(errno != EINTR && errno != ERESTARTSYS) {
- error("Huh??!! waitpid()-problems\n");
- }
- }
- }
- }
- error("Never reached");
- return 0; /* Remove warning */
- }
-
-
- /* Escapes characters for the shell */
-
- char *escape_name(char *s, int a)
- {
- static char buf1[PATH_MAX+1], buf2[PATH_MAX+1];
- char *d;
-
- d=(a ? buf2 : buf1);
- while(*s) {
- if(!((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') ||
- (*s >= '0' && *s <= '9') || *s == '.' || *s == '/' || *s == '-'
- || *s == '_'))
- *d++='\\';
- *d++=*s++;
- }
- *d=0;
- return (a ? buf2 : buf1);
- }
-