wmtv: Remaining changes from debian package versions 0.6.5-8 through 13.

(I couldn't find the patches separately in, e.g., a bug report.)

Patches by Nicolas Boullis <Boullis.Nicolas@libertysurf.fr>.

Corresponding entries from debian/changelog:

0.6.5-8
=======
  * Drop privileges to access files, and then regain privileges.
    (Closes: #120825)
  * A new user's configuration file is automatically created when needed.
  * Cleaned up a few possible buffer overflows.

0.6.5-9
=======
  * The program does not need any more to be setuid root.
    (Closes: #120832)

0.6.5-10
========
  * Trying to change channel while the TV is off does nothing, and does
    not segfault anymore.
  * Corrected strange behavior when the mouse was moved out of a pressed
    button.

0.6.5-11
========
  * Corrected a bug introduced in version 0.6.5-9, causing the program to
    segfault while reverting from fullscreen back to normal mode.
    (Closes: #128409)

0.6.5-12
========
  * Catch SIGCHLD signals to remove zombies. (Closes: #129435)

0.6.5-13
========
  * Added missing #include in wmtv.c.
  * Automatically restarts the TV when the external application finishes.
  * In fullscreen mode, the left and right arrow keys now behave as
    specified in the README file and in the manpage. (Closes: #133301)
  * Added the ability to pass some parameters to the external
    application.
This commit is contained in:
Doug Torrance 2016-02-01 00:45:14 -05:00 committed by Carlos R. Mafra
parent 2090a44629
commit b2d150eb6d

View file

@ -29,6 +29,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include <signal.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/types.h> #include <sys/types.h>
@ -82,6 +83,9 @@
#define COMPOSITE 1 #define COMPOSITE 1
#define SVIDEO 2 #define SVIDEO 2
#ifndef GLOBALCONFFILE
#define GLOBALCONFFILE "/etc/wmtvrc"
#endif
/* Global Variables */ /* Global Variables */
int tfd; int tfd;
@ -111,6 +115,8 @@ int dcret;
int tml; int tml;
int fswidth = 0; int fswidth = 0;
int fsheight = 0; int fsheight = 0;
pid_t child_pid = -1;
int restart = FALSE;
unsigned long ccrfreq; unsigned long ccrfreq;
unsigned long rfreq; unsigned long rfreq;
@ -127,6 +133,9 @@ long ftune[MAXCHAN];
char *progname; char *progname;
char *dev = "/dev/video"; char *dev = "/dev/video";
char *sysConfFile = GLOBALCONFFILE;
char *usrConfFile;
int wmtv_mask_width = 64; int wmtv_mask_width = 64;
int wmtv_mask_height = 64; int wmtv_mask_height = 64;
char wmtv_mask_bits[64*64]; char wmtv_mask_bits[64*64];
@ -195,21 +204,89 @@ void GrabImage(void);
void ParseRCFile(const char *, rckeys *); void ParseRCFile(const char *, rckeys *);
void ParseRCFile2(const char *); void ParseRCFile2(const char *);
void WriteRCFile(const char *); void WriteRCFile(const char *, rckeys *);
void InitConfig(void); void InitConfig(void);
void InitPalette(void); void InitPalette(void);
void Usage(void); void Usage(void);
void Version(void); void Version(void);
void
sigchld_handler(int i)
{
pid_t pid;
pid = waitpid((pid_t)-1, NULL, WNOHANG);
while (pid>(pid_t)0) {
if (pid == child_pid) {
child_pid = -1;
restart = TRUE;
}
pid = waitpid((pid_t)-1, NULL, WNOHANG);
}
}
void
init_signal()
{
struct sigaction sa;
sa.sa_handler = &sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGCHLD, &sa, NULL);
}
char *
expand_format(char *format, char *letters, char **expansions)
{
char *string;
unsigned int string_pos = 0;
unsigned int size;
size = strlen(format)+1;
string = (char *)malloc(size*sizeof(char));
for (; *format != '\0'; format++) {
if (*format == '%') {
format++;
if (*format != '%') {
unsigned int i;
for (i = 0; letters[i] != '\0'; i++) {
if (letters[i] == *format)
break;
}
if (letters[i] != '\0') {
unsigned int expansion_size;
expansion_size = strlen(expansions[i]);
while (string_pos+expansion_size+1 > size) {
size *= 2;
string = realloc(string, size*sizeof(char));
}
memcpy(string+string_pos, expansions[i], expansion_size);
string_pos += expansion_size;
continue;
}
else {
format--;
}
}
}
while (string_pos+1+1 > size) {
size *= 2;
string = realloc(string, size*sizeof(char));
}
string[string_pos] = *format;
string_pos++;
}
string[string_pos] = '\0';
return string;
}
/* main function */ /* main function */
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int i, c, opind; int c, opind;
int pressed_button = -1;
/* pid_t pid; */ /* pid_t pid; */
char cfile[128];
static struct option long_options[] = { static struct option long_options[] = {
{"display", 1, 0, 'd'}, {"display", 1, 0, 'd'},
{"geometry", 1, 0, 'g'}, {"geometry", 1, 0, 'g'},
@ -222,8 +299,18 @@ main(int argc, char *argv[])
progname = strdup(argv[0]); progname = strdup(argv[0]);
strncpy(cfile, (char *)getenv("HOME"), sizeof(char)*128); {
strcat(cfile, "/.wmtvrc"); char *home = getenv("HOME");
if (home == NULL) {
fprintf(stderr, "wmtv: $HOME should be set.\n");
exit(1);
}
usrConfFile = (char *)malloc(sizeof(char)*(strlen(home)+8+1));
strcpy(usrConfFile, home);
strcat(usrConfFile, "/.wmtvrc");
}
while (1) { while (1) {
opind = 0; opind = 0;
@ -277,9 +364,21 @@ main(int argc, char *argv[])
AddMouseRegion (SCANRB, 35, 48, 47, 59); /* Right Preset/Scan Button */ AddMouseRegion (SCANRB, 35, 48, 47, 59); /* Right Preset/Scan Button */
AddMouseRegion (FULLSB, 5, 5, 59, 44); /* Toggle FullScreen */ AddMouseRegion (FULLSB, 5, 5, 59, 44); /* Toggle FullScreen */
init_signal();
/* wmtv main loop */ /* wmtv main loop */
while (1) while (1)
{ {
if (restart) {
TVOn();
if (ntfb_status == SETOFF) {
ntfb_status = SETON;
RedrawWindow();
XFlush(display);
}
restart = FALSE;
continue;
}
while (XPending(display)) while (XPending(display))
{ {
XNextEvent(display, &Event); XNextEvent(display, &Event);
@ -302,8 +401,8 @@ main(int argc, char *argv[])
RetScreen(); RetScreen();
} }
else { else {
i = CheckMouseRegion (Event.xbutton.x, Event.xbutton.y); pressed_button = CheckMouseRegion (Event.xbutton.x, Event.xbutton.y);
switch (i) { switch (pressed_button) {
case NTFB: case NTFB:
ButtonDown(NTFB); ButtonDown(NTFB);
t_lc = Event.xbutton.time; t_lc = Event.xbutton.time;
@ -325,7 +424,7 @@ main(int argc, char *argv[])
break; break;
} }
} }
else else if (ntfb_status == SETON)
ChanDown(); ChanDown();
break; break;
case SCANRB: case SCANRB:
@ -344,7 +443,7 @@ main(int argc, char *argv[])
break; break;
} }
} }
else else if (ntfb_status == SETON)
ChanUp(); ChanUp();
break; break;
case FULLSB: case FULLSB:
@ -371,8 +470,7 @@ main(int argc, char *argv[])
} }
break; break;
case ButtonRelease: case ButtonRelease:
i = CheckMouseRegion (Event.xbutton.x, Event.xbutton.y); switch (pressed_button) {
switch (i) {
case NTFB: case NTFB:
ButtonUp(NTFB); ButtonUp(NTFB);
if (but_pressed) { if (but_pressed) {
@ -383,9 +481,11 @@ main(int argc, char *argv[])
} }
if (ntfb_status == SETOFF) { if (ntfb_status == SETOFF) {
if (child_pid == -1) {
ntfb_status = SETON; ntfb_status = SETON;
TVOn(); TVOn();
} }
}
else if (ntfb_status == SETON) { else if (ntfb_status == SETON) {
if (!btime) { if (!btime) {
ntfb_status = SETUNE; ntfb_status = SETUNE;
@ -403,7 +503,7 @@ main(int argc, char *argv[])
if (!btime) { if (!btime) {
ftune[cchannel] = (rfreq - ccrfreq); ftune[cchannel] = (rfreq - ccrfreq);
/* fprintf(stderr, "wmtv: finetune offset = %ld\n", ftune[cchannel]); */ /* fprintf(stderr, "wmtv: finetune offset = %ld\n", ftune[cchannel]); */
WriteRCFile(cfile); WriteRCFile(usrConfFile, wmtv_keys);
ntfb_status = SETON; ntfb_status = SETON;
DrawPresetChan(cchannel); DrawPresetChan(cchannel);
} }
@ -437,19 +537,39 @@ main(int argc, char *argv[])
{ {
if ((ntfb_status == SETON) || (ntfb_status == SETUNE)) { if ((ntfb_status == SETON) || (ntfb_status == SETUNE)) {
if (exe) { if (exe) {
pid_t pid;
char *command;
char *letters = "#nf";
char *(expansions[3]);
ntfb_status = SETOFF; ntfb_status = SETOFF;
TVOff(); TVOff();
expansions[0] = malloc(3*sizeof(char));
snprintf(expansions[0], 3, "%d", cchannel+1);
expansions[1] = comment[cchannel];
expansions[2] = malloc(15*sizeof(char));
snprintf(expansions[2], 15, "%ld", rfreq);
command = expand_format(exe, letters, expansions);
/* system(exe); */ /* system(exe); */
if (fork() == (pid_t) 0) { child_pid = fork();
if (child_pid == (pid_t) 0) {
char *argv[4]; char *argv[4];
setuid(getuid()); /* Drop the privileges */
argv[0] = "sh"; argv[0] = "sh";
argv[1] = "-c"; argv[1] = "-c";
argv[2] = exe; argv[2] = command;
argv[3] = NULL; argv[3] = NULL;
execv("/bin/sh", argv); execv("/bin/sh", argv);
exit(-1); exit(-1);
} }
free(expansions[0]);
free(expansions[2]);
free(command);
pid = waitpid(child_pid, NULL, WNOHANG);
if (pid != 0) {
child_pid = -1;
restart = TRUE;
}
/* printf("Returned pid:\n"); */
#if 0 #if 0
pid = fork(); pid = fork();
@ -554,12 +674,10 @@ main(int argc, char *argv[])
ChanDown(); ChanDown();
break; break;
case XK_Right: case XK_Right:
if (isource == TELEVISION) VolumeUp();
FineTuneUp();
break; break;
case XK_Left: case XK_Left:
if (isource == TELEVISION) VolumeDown();
FineTuneDown();
break; break;
case XK_m: case XK_m:
if (!mute) { if (!mute) {
@ -642,7 +760,6 @@ TVOn(void)
int rx, ry; int rx, ry;
char *p; char *p;
XWindowAttributes winattr; XWindowAttributes winattr;
if (!XGetWindowAttributes (display, iconwin, &winattr)) { if (!XGetWindowAttributes (display, iconwin, &winattr)) {
@ -656,6 +773,18 @@ TVOn(void)
fprintf(stderr, "wmtv: error translating coordinates\n"); fprintf(stderr, "wmtv: error translating coordinates\n");
} }
/* This part was taken from xawtv's source code */
switch (system("v4l-conf -q")) {
case -1: /* can't run */
fprintf(stderr,"could'nt start v4l-conf\n");
break;
case 0: /* ok */
break;
default: /* non-zero return */
fprintf(stderr,"v4l-conf had some trouble, "
"trying to continue anyway\n");
}
/* End of "stolen" part */
InitConfig(); InitConfig();
GetFrameBuffer(); GetFrameBuffer();
InitPalette(); InitPalette();
@ -716,7 +845,7 @@ TVOn(void)
if (vaud.flags & VIDEO_AUDIO_MUTE) { if (vaud.flags & VIDEO_AUDIO_MUTE) {
vaud.flags &= ~VIDEO_AUDIO_MUTE; /* Unmute */ vaud.flags &= ~VIDEO_AUDIO_MUTE; /* Unmute */
vaud.volume = (0xFFFF/2)+1; vaud.volume = 0xFFFF;
} }
if (isource == TELEVISION) { if (isource == TELEVISION) {
@ -787,9 +916,11 @@ void
VolumeUp(void) VolumeUp(void)
{ {
if(vchn.flags & VIDEO_VC_AUDIO) { if(vchn.flags & VIDEO_VC_AUDIO) {
if (vaud.volume <= 0xFFFF) { if ((vaud.flags & VIDEO_AUDIO_VOLUME) == 0)
fprintf(stderr, "Warning: v4l device does not support volume control.\n");
else if (vaud.volume <= 0xEEEE) {
vaud.audio = tvsource; vaud.audio = tvsource;
vaud.volume += (0xFFFF/10); vaud.volume += 0x1111;
if (ioctl(tfd, VIDIOCSAUDIO, &vaud) < 0) if (ioctl(tfd, VIDIOCSAUDIO, &vaud) < 0)
perror("ioctl VIDIOCSAUDIO"); perror("ioctl VIDIOCSAUDIO");
} }
@ -802,9 +933,11 @@ void
VolumeDown(void) VolumeDown(void)
{ {
if (vchn.flags & VIDEO_VC_AUDIO) { if (vchn.flags & VIDEO_VC_AUDIO) {
if (vaud.volume > 0) { if ((vaud.flags & VIDEO_AUDIO_VOLUME) == 0)
fprintf(stderr, "Warning: v4l device does not support volume control.\n");
else if (vaud.volume >= 0x1111) {
vaud.audio = tvsource; vaud.audio = tvsource;
vaud.volume -= (0xFFFF/10); vaud.volume -= 0x1111;
if (ioctl(tfd, VIDIOCSAUDIO, &vaud) < 0) if (ioctl(tfd, VIDIOCSAUDIO, &vaud) < 0)
perror("ioctl VIDIOCSAUDIO"); perror("ioctl VIDIOCSAUDIO");
} }
@ -1038,8 +1171,16 @@ ParseRCFile2(const char *filename)
if (menu) { if (menu) {
ftune[i]=0; ftune[i]=0;
if(sscanf(temp, " %s %n(%ld) %n", name, &len, &ftune[i], &len)>=1) { if(sscanf(temp, " %s %n(%ld) %n", name, &len, &ftune[i], &len)>=1) {
char *pos;
cname[i]=strdup(name); cname[i]=strdup(name);
comment[i]=temp[len]?strdup(temp+len):"\n"; comment[i]=temp[len]?strdup(temp+len):"";
/* Remove the end-of-line symbol */
for (pos = comment[i]; *pos != '\0'; pos++) {
if (*pos == '\n') {
*pos = '\0';
break;
}
}
} }
if(++i>=MAXCHAN) if(++i>=MAXCHAN)
break; break;
@ -1056,28 +1197,27 @@ ParseRCFile2(const char *filename)
/* WriteRCFile function */ /* WriteRCFile function */
void void
WriteRCFile(const char *filename) WriteRCFile(const char *filename, rckeys *keys)
{ {
long i; long i;
char temp[128];
FILE *fp; FILE *fp;
int key;
if ((fp = fopen(filename, "r+")) == NULL) { if ((fp = fopen(filename, "w")) == NULL) {
fprintf(stderr, "wmtv: %s\n", strerror(errno)); fprintf(stderr, "wmtv: %s\n", strerror(errno));
return; return;
} }
while (fgets(temp, 128, fp)) { for (key=0; keys[key].label; key++)
if (*temp != '\n' && strchr(temp, '[')) { if (*keys[key].var)
fseek(fp, 0L, SEEK_CUR); /* required between read and write */ fprintf(fp, "%s = %s\n", keys[key].label, *keys[key].var);
fprintf(fp, "\n[channel]\n");
for (i = 0; i <= maxpst; i++) for (i = 0; i <= maxpst; i++)
fprintf(fp, "%s (%ld)\t%s", cname[i], ftune[i], comment[i]); fprintf(fp, "%s (%ld)\t%s\n", cname[i], ftune[i], comment[i]);
break;
}
}
i=ftell(fp);
fclose(fp); fclose(fp);
truncate(filename, i);
} }
@ -1128,17 +1268,13 @@ void
InitConfig(void) InitConfig(void)
{ {
int i; int i;
char temp[128];
strncpy(temp, (char *)getenv("HOME"), (sizeof(char)*128)); ParseRCFile(usrConfFile, wmtv_keys);
strcat(temp, "/.wmtvrc"); ParseRCFile2(usrConfFile);
ParseRCFile(temp, wmtv_keys);
ParseRCFile2(temp);
if (norcfile) { if (norcfile) {
strcpy(temp, "/etc/wmtvrc"); ParseRCFile(sysConfFile, wmtv_keys);
ParseRCFile(temp, wmtv_keys); ParseRCFile2(sysConfFile);
ParseRCFile2(temp);
if (norcfile) { if (norcfile) {
fprintf(stderr, "wmtv: error - config file not found\n"); fprintf(stderr, "wmtv: error - config file not found\n");
@ -1272,17 +1408,20 @@ InitConfig(void)
void void
GetFrameBuffer(void) GetFrameBuffer(void)
{ {
#if 0
void *baseaddr = NULL; void *baseaddr = NULL;
int evbr, erbr, flr = 0; int evbr, erbr, flr = 0;
int bankr, memr, depth; int bankr, memr, depth;
int i, n; int i, n;
int bytesperline, bytesperpixel; int bytesperline, bitsperpixel;
XPixmapFormatValues *pf; XPixmapFormatValues *pf;
#endif
if (!XGetWindowAttributes(display, DefaultRootWindow(display), &Winattr)) { if (!XGetWindowAttributes(display, DefaultRootWindow(display), &Winattr)) {
fprintf(stderr, "wmtv: error getting winattr of root\n"); fprintf(stderr, "wmtv: error getting winattr of root\n");
} }
#if 0
depth = Winattr.depth; depth = Winattr.depth;
if (XF86DGAQueryExtension(display, &evbr, &erbr)) { if (XF86DGAQueryExtension(display, &evbr, &erbr)) {
@ -1306,13 +1445,13 @@ GetFrameBuffer(void)
} }
} }
bytesperpixel = (depth+7) & 0xf8; bitsperpixel = (depth+7) & 0xf8;
bytesperline *= bytesperpixel; bytesperline *= bitsperpixel/8;
vfb.base = baseaddr; vfb.base = baseaddr;
vfb.height = Winattr.height; vfb.height = Winattr.height;
vfb.width = Winattr.width; vfb.width = Winattr.width;
vfb.depth = bytesperpixel; vfb.depth = bitsperpixel;
vfb.bytesperline = bytesperline; vfb.bytesperline = bytesperline;
if (Winattr.depth == 15) if (Winattr.depth == 15)
@ -1321,6 +1460,7 @@ GetFrameBuffer(void)
if (ioctl(tfd, VIDIOCSFBUF, &vfb) < 0) { if (ioctl(tfd, VIDIOCSFBUF, &vfb) < 0) {
perror("ioctl VIDIOCSFBUF"); perror("ioctl VIDIOCSFBUF");
} }
#endif
} }