/* by Christian R. Shelton January 9, 2000 * (C) 2000 Christian R. Shelton * a modification of xlassie (whose copyright appears below) * * No warrentee is implied or offered. You may distribute and modify the * code as you wish * * compile as: * gcc -o xpress xpress.c -L/usr/X11/lib -lX11 -lXext -lnsl * (or maybe add -lsocket depending on the machine) */ /* Copyright (C) 1998 Trent Piepho * (C) 1999 Trent Piepho * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., 675 * Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PORT 6006 #define HOST "www.dipbounced.com" #define FONTNAME "-*-utopia-medium-r-normal--40-*-*-*-*-*-iso8859-1" #define TIME_INTERVAL 60 /* X related globals */ Display *dpy; Window win; GC gc; XFontStruct *font; int Ascent=33,Descent=0; int Width=55,Height=33; XColor FgXColor,HiXColor; Pixmap ShapeMask; /* shape stuff */ GC ShapeGC; /* shape stuff */ int MaskWidth,MaskHeight; /* shape stuff */ /* app-default related globals */ char *FgColor="Black",*BgColor="White",*HiColor="Red"; char *FontName=FONTNAME; char *DisplayName=NULL; char *AppName; int Number = -10; int Interval=TIME_INTERVAL; char SpoolFile[256]; char Command[256]; char Username[32]; char Suffix[100]; char Password[32]; int Passflag = 0; char Game[32]; char Power[32]; char *Geometry=NULL; int Options=0; #define BELL_MODE 0x01 #define SHAPED_WINDOW 0x02 #define HILIGHT_MAIL 0x04 void usage(); void update(); void handler(int); void parse_options(int argc,char *argv[]); void init(int argc,char *argv[]); int count_mail(); void update() { static int old_number=-1; char str[32]; static int oldw=-1,oldh=-1; int w,h; if (Number<0) sprintf(str,"?"); else sprintf(str,"%d",Number); w = (Width-XTextWidth(font,str,strlen(str)))/2; h = (Height+Ascent-Descent)/2; if(Options&SHAPED_WINDOW) { if(Number!=old_number || oldw!=w || oldh!=h) { old_number=Number; oldw=w; oldh=h; /* these next 3 lines clear the pixmap, is there a cleaner way? */ XSetFunction(dpy,ShapeGC,GXclear); XFillRectangle(dpy,ShapeMask,ShapeGC,0,0,MaskWidth,MaskHeight); XSetFunction(dpy,ShapeGC,GXset); XDrawString(dpy,ShapeMask,ShapeGC,0,Ascent,str,strlen(str)); XShapeCombineMask(dpy, win, ShapeBounding, w, h-Ascent, ShapeMask, ShapeSet); }; } else { XClearWindow(dpy,win); }; if(Options&HILIGHT_MAIL) { XSetForeground(dpy,gc,Number?HiXColor.pixel:FgXColor.pixel); }; XDrawString(dpy,win,gc,w,h,str,strlen(str)); } void handler(int nothing) { int old; old = Number; count_mail(); if(old==Number) return; update(); if(Options&BELL_MODE && Number>old) XBell(dpy,100); XFlush(dpy); } void font_height(void) { int foo,bar,baz; XCharStruct extents; XTextExtents(font,"0123456789",10,&foo,&bar,&baz,&extents); Ascent=extents.ascent; Descent=extents.descent; } void usage(void) { fprintf(stderr,"XPress v0.5b\t by Christian R. Shelton \n"); fprintf(stderr,"XPress is a modified version of\n"); fprintf(stderr,"XLassie v1.4\tby Trent Piepho \n\n"); fprintf(stderr,"Usage: xpress [-h] | [-options]\n"); fprintf(stderr,"where options include:\n"); fprintf(stderr," -h print usage\n"); fprintf(stderr," -name Set app name\n"); fprintf(stderr," -suffix Set window title suffix\n"); fprintf(stderr," -fg foreground color [%s]\n",FgColor); fprintf(stderr," -bg background color [%s]\n",BgColor); fprintf(stderr," -update update monitor every number seconds\n"); fprintf(stderr," -bell ring bell when press count becomes positive arrives\n"); fprintf(stderr," -display X server to connect to\n"); fprintf(stderr," -shape Use a shaped window\n"); fprintf(stderr," -command Command to execute when clicked on\n"); fprintf(stderr," -hilight [color] Use a different foreground color when\n" " there is press [%s]\n",HiColor); fprintf(stderr," -username Set username (default: prompt for it)\n"); fprintf(stderr," -password Set password (default: prompt for it)\n"); fprintf(stderr," -game Set game (default: prompt for it)\n"); fprintf(stderr," -power Set power (default: prompt for it)\n"); fprintf(stderr,"[note: if the game string is the single character '*', the total of all press for all games will be displayed]\n"); } void parse_options(int argc,char *argv[]) { int i; int intervalused=0; for(i=1;iflags = PSize; xsh->width = Width; xsh->height = Height; g=XWMGeometry(dpy,screen,Geometry,NULL,0,xsh,&x,&y,&Width,&Height,&g); if(g&XValue) { xsh->x=x; xsh->flags|=USPosition; }; if(g&YValue) { xsh->y=y; xsh->flags|=USPosition; }; if(g&WidthValue) {xsh->width=Width; xsh->flags|=USSize; } else {Width = xsh->width; }; if(g&HeightValue) {xsh->height=Height; xsh->flags|=USSize; } else {Height = xsh->height; }; buf = (char *)malloc(strlen(Game)+strlen(Power)+2); sprintf(buf,"%s:%s ",Game,Power,Suffix); XStringListToTextProperty(&buf,1,&winName); free(buf); wmh->initial_state=NormalState; wmh->input=False; wmh->flags = StateHint | InputHint; classh->res_name = (AppName==NULL)?"xpress":AppName; classh->res_class = "XBiff"; win=XCreateSimpleWindow(dpy,RootWindow(dpy,screen),x,y,Width,Height,0, BlackPixel(dpy,screen),WhitePixel(dpy,screen)); XSetWMProperties(dpy,win,&winName,NULL,argv,argc,xsh,wmh,classh); gc=XCreateGC(dpy,win,0,NULL); XAllocNamedColor(dpy,DefaultColormap(dpy,screen),FgColor,&color,&tmp); XSetForeground(dpy,gc,color.pixel); FgXColor=color; XAllocNamedColor(dpy,DefaultColormap(dpy,screen),BgColor,&color,&tmp); XSetBackground(dpy,gc,color.pixel); XSetWindowBackground(dpy,win,color.pixel); if(Options&HILIGHT_MAIL) XAllocNamedColor(dpy,DefaultColormap(dpy,screen), HiColor,&HiXColor,&tmp); XSetFont(dpy,gc,font->fid); if(Options&SHAPED_WINDOW) { MaskWidth = Width; MaskHeight = Height; ShapeMask = XCreatePixmap(dpy,win,MaskWidth,MaskHeight,1); ShapeGC = XCreateGC(dpy,ShapeMask,0,NULL); XSetFont(dpy,ShapeGC,font->fid); }; } int main(int argc,char *argv[]) { XEvent xev; struct itimerval itv; struct sigaction sig; struct passwd* pwd; char *mail; pwd = getpwuid(getuid()); mail=getenv("MAIL"); if(mail==NULL) { sprintf(SpoolFile,"/var/spool/mail/%s",pwd->pw_name); } else { strcpy(SpoolFile,mail); }; Command[0] = 0; Username[0] = 0; Password[0] = 0; Game[0] = 0; Power[0] = 0; Suffix[0] = 0; init(argc,argv); count_mail(); XSelectInput(dpy,win,ExposureMask|ButtonPressMask|StructureNotifyMask); XMapWindow(dpy,win); if(Options&BELL_MODE && Number) XBell(dpy,100); sig.sa_handler=handler; sigemptyset(&sig.sa_mask); sig.sa_flags=SA_RESTART; sigaction(SIGALRM,&sig,NULL); itv.it_interval.tv_sec=Interval; itv.it_interval.tv_usec=0; itv.it_value = itv.it_interval; setitimer(ITIMER_REAL,&itv,NULL); for(;;) { XNextEvent(dpy,&xev); switch(xev.type) { case Expose: while(XCheckTypedEvent(dpy,Expose,&xev)); update(); break; case ButtonPress: if (Command[0] != 0) system(Command); break; case ConfigureNotify: Width = xev.xconfigure.width; Height = xev.xconfigure.height; update(); break; case DestroyNotify: XCloseDisplay(dpy); exit(0); default: }; }; } int writen(int fd, char *ptr, int nbytes) { int nleft, nwritten; fd_set rfds; struct timeval tv; nleft = nbytes; while(nleft>0) { nwritten = write(fd,ptr,nleft); if (nwritten<=0) { if (errno==EAGAIN || errno==EINTR || errno==ENOSPC) { FD_ZERO(&rfds); FD_SET(fd,&rfds); tv.tv_sec = Interval/2; tv.tv_usec = 0; if (select(fd+1,NULL,&rfds,NULL,&tv)>0) { return nwritten; } } } nleft -= nwritten; ptr += nwritten; } return nbytes-nleft; } int readline(int fd, char *ptr, int maxlen) { int n,rc; char c; fd_set rfds; struct timeval tv; for(n=1;n0) { /* timeout? */ perror("nope"); *ptr = 0; return 0; } printf("yup... more data\n"); } } } *ptr = 0; return n; } int count_mail() { int fd; struct sockaddr_in serv_addr; struct hostent *hostp; char buffer[100]; char *num; int i; fd_set rfs; struct timeval tv; int tempnum; bzero((char *)&serv_addr, sizeof(serv_addr)); if ((serv_addr.sin_addr.s_addr = inet_addr(HOST)) == -1) { if((hostp = gethostbyname(HOST)) == NULL) { if (Number == -10) { fprintf(stderr,"Could not find host %s\n",HOST); exit(1); } Number = -5; return; } if (hostp->h_addrtype != AF_INET) { if (Number == -10) { fprintf(stderr,"Could not find host %s\n",HOST); exit(1); } Number = -5; return; } serv_addr.sin_family = hostp->h_addrtype; bcopy((char*)hostp->h_addr,(char*)&serv_addr.sin_addr, sizeof(serv_addr.sin_addr)); } else { serv_addr.sin_family=AF_INET; } serv_addr.sin_port = htons(PORT); if ((fd = socket(serv_addr.sin_family,SOCK_STREAM,0)) < 0) { if (Number == -10) { fprintf (stderr,"Could not open a socket\n"); exit(1); } Number = -5; return; } if (connect(fd,(struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { if (Number == -10) { fprintf(stderr,"Could not connect\n"); exit(1); } Number = -5; close(fd); return; } writen(fd,Username,strlen(Username)); writen(fd,"\n",1); writen(fd,Password,strlen(Password)); writen(fd,"\n",1); writen(fd,Game,strlen(Game)); writen(fd,"\n",1); if (!strcmp(Game,"*")) { Number = 0; while(readline(fd,buffer,99)) { printf("%s\n",buffer); num = strrchr(buffer,':'); if (num && *num) { num++; tempnum = atoi(num); if (tempnum>0) Number+=tempnum; } } } else { writen(fd,Power,strlen(Power)); writen(fd,"\n",1); readline(fd,buffer,100); printf("%s\n",buffer); Number = atoi(buffer); } printf("--------------\n"); if (Number==-1) { fprintf(stderr,"Wrong Password\n"); exit(1); } else if (Number==-2) { fprintf(stderr,"%s is not playing %s in game %s\n",Username,Power,Game); exit(1); } else if (Number==-3) { // No pressflag file Number = 0; } else if (Number < 0) { fprintf(stderr,"Unknown Error\n"); exit(1); } close(fd); }