/* Cardmon: * PCMCIA card monitor utility for X11 * Written by KIMURA Takamiti, * cardmon.c 0.1 1998/02/15 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MY_FRAME_WIDTH 250 #define EMPTY_COLOR "gray40" #define ACTIVE_COLOR "antiquewhite2" #define HIBERNATE_COLOR "gold4" #define POWER_COLOR "magenta2" #define SAFE_COLOR "cyan4" #define CONFIG_FILE "/usr/local/lib/xpccard/config" #define SERVER_NAME "/var/tmp/.pccardd" #define CLIENT_NAME "/tmp/.xpccard" #define CMD_NR_SLOTS "S\n" #define CMD_GET_INFO "N%d\n" #define CMD_PWR_ON "P%d\n" #define CMD_PWR_OFF "Q%d\n" #define MAX_PC_SLOT 4 #define MAX_INFO_LEN 64 #define MAX_CARD_NAME MAX_INFO_LEN * 2 #define MAX_NAME_FEILD 5 #define NA "N/A" struct SlotFrame { Widget pwrbutton; Widget drvbutton; Widget label; Widget sep; }; static struct SlotFrame slotFrame[MAX_PC_SLOT]; static XtAppContext appContext; static Widget top, frame; static Pixel statColor[4], PowerColor, SafeColor; static int SOCKET; static int nr_slot = 0; static int slen, clen; static char *myname; static struct sockaddr_un saddr, caddr; struct CardInfo { int stat; char manuf[MAX_INFO_LEN+4]; char vers[MAX_INFO_LEN+4]; char drv[MAX_INFO_LEN+4]; char name[MAX_CARD_NAME+4]; }; static struct CardInfo cardInfo[MAX_PC_SLOT]; struct CardAlias { char *alias; char *manuf; char *vers; char *buff; struct CardAlias *next; }; static struct CardAlias *aliasTop = NULL; static struct CardAlias *aliasPrev; static int openSocket(void); static void closeSocket(void); static int communicate(char *, char *, int); static int ismatch(char *, char*); static char *nameAlias(struct CardAlias *, struct CardInfo *); static int parseCardName(char *, struct CardInfo *); static int shellWord(char **, char **); static int readConfig(char *); static void freeAliasArray(struct CardAlias **); static void sigHandl(int); /* Xm, Xt */ static void getMyColor(void); static void powerButton(Widget, XtPointer, XtPointer); static void drvButton(Widget, XtPointer, XtPointer); static void statChanged(Widget, int *, XtInputId *); static int widgetYsize(Widget *); static int widgetXsize(Widget *); static int makeSlotFrame(int); /* ======================================= */ main(argc, argv) int argc; char **argv; { int r, i, n; int minY, maxY, minX; char cmd[64], ansbuf[BUFSIZ]; Arg av[10]; if ((myname = strrchr(*argv, '/')) == NULL) { myname = *argv; } else { myname++; } if (openSocket() < 0) { perror("openSocket"); exit(1); } if ((r = communicate(CMD_NR_SLOTS, ansbuf, BUFSIZ)) > 0) { nr_slot = atoi(ansbuf); } if (nr_slot == 0) { fprintf(stderr, "No card slots found\n"); closeSocket(); exit(0); } readConfig(CONFIG_FILE); /* dumpalias() */ for(i = 0; i < nr_slot; i++) { sprintf(cmd, "N%d\n", i); if ((r = communicate(cmd, ansbuf, BUFSIZ)) > 0) { parseCardName(ansbuf, &cardInfo[i]); /* dumpname(i); */ } } signal(SIGHUP, sigHandl); signal(SIGINT, sigHandl); signal(SIGTERM, sigHandl); signal(SIGQUIT, sigHandl); XtSetLanguageProc(NULL, NULL, NULL); top = XtOpenApplication(&appContext, "XPccard", NULL, 0, &argc, argv, NULL, sessionShellWidgetClass, NULL, 0); if (!top) { fprintf(stderr, "%s: cannot start X session\n", myname); closeSocket(); exit(1); } if (argc > 1) { fprintf(stderr, "Usage: %s [X-Toolkit options]\n", myname); closeSocket(); exit(1); } getMyColor(); XtSetArg(av[0], XmNwidth, MY_FRAME_WIDTH); frame = XmCreateForm(top, "frame", av, 1); XtManageChild(frame); for(i = maxY = 0; i < nr_slot; i++) { maxY += makeSlotFrame(i); } if (nr_slot > 1) { minY = maxY / nr_slot + 2; maxY += 2; } else minY = maxY; minX = 6 + widgetXsize(&slotFrame[0].pwrbutton) + widgetXsize(&slotFrame[0].drvbutton); n = 0; XtSetArg(av[n], XmNminHeight, minY); n++; XtSetArg(av[n], XmNmaxHeight, maxY); n++; XtSetArg(av[n], XmNminWidth, minX); n++; XtSetArg(av[n], XmNmaxWidth, MY_FRAME_WIDTH * 2); n++; XtSetValues(top, av, n); XtAppAddInput(appContext, SOCKET, (caddr_t)XtInputReadMask, (XtInputCallbackProc)statChanged, NULL); XtRealizeWidget(top); XtAppMainLoop(appContext); } static int openSocket() { umask(077); if ((SOCKET = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { return(-1); } bzero((char *)&caddr, sizeof(caddr)); caddr.sun_family = AF_UNIX; sprintf(caddr.sun_path, "%s%06d", CLIENT_NAME, getpid()); clen = SUN_LEN(&caddr); if (bind(SOCKET, (struct sockaddr *)&caddr, clen) < 0) { return(-1); } bzero((char *)&saddr, sizeof(saddr)); saddr.sun_family = AF_UNIX; strcpy(saddr.sun_path, SERVER_NAME); slen = SUN_LEN(&saddr); return(1); } static void closeSocket() { close(SOCKET); unlink(caddr.sun_path); } static int communicate(cmd, ansbuf, buflen) char *cmd, *ansbuf; int buflen; { struct timeval timeout; fd_set fds; int n, k; n = strlen(cmd); if (n) { if (sendto(SOCKET, cmd, n, 0, (struct sockaddr *)&saddr, slen) != n) { perror("send"); exit(1); } } if (buflen == 0) return(0); FD_ZERO(&fds); FD_SET(SOCKET, &fds); timeout.tv_sec = 1; timeout.tv_usec = 0; n = 0; if (select(FD_SETSIZE, &fds, NULL, NULL, &timeout) > 0) { if (FD_ISSET(SOCKET, &fds)) { k = 0; if ((n = recvfrom(SOCKET, ansbuf, buflen, 0, NULL, &k)) < 0) { perror("recvfrom"); exit(1); } } } *(ansbuf + n) = 0; return(n); } static int ismatch(key, str) char *key, *str; { int r; regex_t exp; if ((r = regcomp(&exp, key, REG_EXTENDED | REG_NOSUB)) == 0) { r = regexec(&exp, str, (size_t)0, NULL, 0); regfree(&exp); } return(r == 0); } static char *nameAlias(array, card) struct CardAlias *array; struct CardInfo *card; { while(array != NULL) { if (ismatch(array->manuf, card->manuf) && ismatch(array->vers, card->vers)) { return(array->alias); } array = array->next; } return(NULL); } static int parseCardName(buf, card) char *buf; struct CardInfo *card; { char *a[MAX_NAME_FEILD]; char *p, *r, *s; int i, n, slot; if ((p = strdup(buf)) == NULL) { return(-1); } s = p + strlen(buf) - 1; while(s > p && *s == ' ') *s-- = 0; for(s = p, i = 0; i < MAX_NAME_FEILD; i++) { while(*s && *s == ' ') s++; a[i] = s; if (*s == 0) continue; while(*s && *s != '~') s++; if (i < MAX_NAME_FEILD - 1 && *s == '~') { r = s - 1; *s++ = 0; while(r > a[i] && *r == ' ') *r-- = 0; } } slot = atoi(a[0]); card->stat = atoi(a[4]); strncpy(card->manuf, *a[1] ? a[1] : NA, MAX_INFO_LEN); strncpy(card->vers, *a[2] ? a[2] : NA, MAX_INFO_LEN); strncpy(card->drv, *a[3] ? a[3] : (card->stat == 2 ? "???" : NA), MAX_INFO_LEN); switch (card->stat) { case 0: strcpy(card->name, "Empty"); break; case 2: strcpy(card->name, "Hibernating Card"); break; default: if ((s = nameAlias(aliasTop, card)) == NULL) { sprintf(card->name, "%s (%s)", card->manuf, card->vers); } else { strncpy(card->name, s, MAX_CARD_NAME); } break; } free(p); return(slot); } static int shellWord(dst, src) char **dst, **src; { int quote, n; char *d, *s; d = *dst; s = *src; while (*s && (*s == ' ' || *s == '\t')) s++; quote = n = 0; while (*s) { if (quote == 0 && (*s == ' ' || *s == '\t')) break; switch(*s) { case '"': if (quote) quote = 0; else quote = 2; s++; break; case '\\': s++; if (*s == 0) break; default: *d++ = *s++; n++; break; } } *d = 0; *dst = ++d; *src = s; return(n); } static int readConfig(file) char *file; { FILE *fp; int n, i, cnt, line, len; char buff[1024]; char *s, *p, *a[10], *dst; struct CardAlias *alp; if ((fp = fopen(file, "r")) == NULL) { return(-1); } line = cnt = 0; while(fgets(buff, sizeof(buff), fp) != NULL) { line++; *(buff + strlen(buff) - 1) = 0; s = buff; while(*s && (*s == ' ' || *s == '\t')) s++; if (*s == 0 || *s == '#') continue; if ((dst = malloc(strlen(s))) == NULL) { return(-1); } n = 0; p = dst; len = 0; while (*s) { a[n++] = p; len += shellWord(&p, &s); } if (n == 4 && strcmp(a[0], "alias") == 0) { alp = (struct CardAlias *)malloc(sizeof(struct CardAlias)); alp->buff = dst; alp->alias = a[1]; alp->manuf = a[2]; alp->vers = a[3]; if (aliasTop == NULL) aliasTop = alp; else { aliasPrev->next = alp; alp->next = NULL; } aliasPrev = alp; cnt++; } else { fprintf(stderr, "readConfig() #%d: illegal format.\n", line); free(dst); continue; } } fclose(fp); return(cnt); } static void freeAliasArray(array) struct CardAlias **array; { struct CardAlias *p, *chan; p = *array; while(p != NULL) { chan = p->next; free(p->buff); free(p); p = chan; } *array = NULL; } static void sigHandl(sig) int sig; { switch(sig) { case SIGINT : case SIGTERM : case SIGQUIT : closeSocket(); freeAliasArray(&aliasTop); XCloseDisplay(XtDisplay(top)); exit(0); case SIGHUP : freeAliasArray(&aliasTop); readConfig(CONFIG_FILE); break; } } /* --- for debug --- dumpname(n) int n; { printf("\nslot = %d\n", n); printf("stat = %d\n", cardInfo[n].stat); printf("manuf = %s\n", cardInfo[n].manuf); printf("vers = %s\n", cardInfo[n].vers); printf("drv = %s\n", cardInfo[n].drv); printf("name = %s\n", cardInfo[n].name); } dumpalias(head) { while(head != NULL) { printf("\nalias = %s\n", head->alias); printf("manuf = %s\n", head->manuf); printf("vers = %s\n", head->vers); head = head->next; } } */ static void getMyColor() { int n = 0; Colormap cmap; XColor closest, exact; cmap = DefaultColormap(XtDisplay(top), DefaultScreen(XtDisplay(top))); /* empty color */ XAllocNamedColor(XtDisplay(top), cmap, EMPTY_COLOR, &closest, &exact); statColor[n++] = closest.pixel; /* active color */ XAllocNamedColor(XtDisplay(top), cmap, ACTIVE_COLOR, &closest, &exact); statColor[n++] = closest.pixel; /* hibernate color */ XAllocNamedColor(XtDisplay(top), cmap, HIBERNATE_COLOR, &closest, &exact); statColor[n++] = closest.pixel; /* power color */ XAllocNamedColor(XtDisplay(top), cmap, POWER_COLOR, &closest, &exact); PowerColor = closest.pixel; /* safe color */ XAllocNamedColor(XtDisplay(top), cmap, SAFE_COLOR, &closest, &exact); SafeColor = closest.pixel; } static int widgetYsize(w) Widget *w; { Arg av[1]; int n = 0; XtSetArg(av[0], XmNheight, &n); XtGetValues(*w, av, 1); return(n); } static int widgetXsize(w) Widget *w; { Arg av[1]; int n = 0; XtSetArg(av[0], XmNwidth, &n); XtGetValues(*w, av, 1); return(n); } static void powerButton(w, client, call) Widget w; XtPointer client, call; { int slot = (int)client; char cmd[8]; int n = 0; Arg av[10]; switch (cardInfo[slot].stat) { case 0: /* empty */ return; case 1: /* active */ sprintf(cmd, CMD_PWR_OFF, slot); break; case 2: /* hibernate */ sprintf(cmd, CMD_PWR_ON, slot); XtSetArg(av[n], XmNtopShadowColor, PowerColor); n++; XtSetArg(av[n], XmNbottomShadowColor, PowerColor); n++; XtSetArg(av[n], XmNbackground, PowerColor); n++; XtSetValues(slotFrame[slot].drvbutton, av, n); break; } communicate(cmd, NULL, 0); } static void drvButton(w, client, call) Widget w; XtPointer client, call; { /* not implemented. */ } static void statChanged(client, socket, xid) Widget client; int *socket; XtInputId *xid; { int n, k, slot; char ansbuf[BUFSIZ]; struct CardInfo card; XmString cstr; Arg av[10]; Pixel c; k = 0; n = recvfrom(*socket, ansbuf, BUFSIZ, 0, NULL, &k); if (n == 0) return; *(ansbuf + n) = 0; slot = parseCardName(ansbuf, &card); if (card.stat == 2) cardInfo[slot].stat = card.stat; else cardInfo[slot] = card; n = 0; cstr = XmStringCreateLocalized(cardInfo[slot].name); XtSetArg(av[n], XmNlabelString, cstr); n++; XtSetArg(av[n], XmNbackground, statColor[cardInfo[slot].stat]); n++; XtSetValues(slotFrame[slot].label, av, n); XmStringFree(cstr); n = 0; cstr = XmStringCreateLocalized(cardInfo[slot].drv); XtSetArg(av[n], XmNlabelString, cstr); n++; c = cardInfo[slot].stat == 1 ? PowerColor : SafeColor; XtSetArg(av[n], XmNbackground, c); n++; XtSetArg(av[n], XmNtopShadowColor, c); n++; XtSetArg(av[n], XmNbottomShadowColor, c); n++; XtSetValues(slotFrame[slot].drvbutton, av, n); XmStringFree(cstr); switch(cardInfo[slot].stat) { case 1: XtSetSensitive(slotFrame[slot].pwrbutton, True); XtSetSensitive(slotFrame[slot].drvbutton, True); break; case 0: XtSetSensitive(slotFrame[slot].pwrbutton, False); case 2: XtSetSensitive(slotFrame[slot].drvbutton, False); break; } } static int makeSlotFrame(num) int num; { int n, y; Arg av[40]; XmString cstr; Pixel c; char name[4], msg[256]; y = 1; /* make power button */ n = 0; sprintf(msg, " %d ", num); cstr = XmStringCreateLocalized(msg); XtSetArg(av[n], XmNlabelString, cstr); n++; XtSetArg(av[n], XmNborderWidth, 1); n++; XtSetArg(av[n], XmNsensitive, cardInfo[num].stat); n++; XtSetArg(av[n], XmNhighlightThickness, 0); n++; XtSetArg(av[n], XmNleftAttachment, XmATTACH_FORM); n++; XtSetArg(av[n], XmNleftOffset, 2); n++; XtSetArg(av[n], XmNtopOffset, y); n++; if (num == 0) { XtSetArg(av[n], XmNtopAttachment, XmATTACH_FORM); n++; } else { XtSetArg(av[n], XmNtopAttachment, XmATTACH_WIDGET); n++; XtSetArg(av[n], XmNtopWidget, slotFrame[num-1].sep); n++; XtSetArg(av[n], XmNtopOffset, 0); n++; } sprintf(name, "P%d", num); slotFrame[num].pwrbutton = XmCreatePushButton(frame, name, av, n); XtManageChild(slotFrame[num].pwrbutton); y += widgetYsize(&slotFrame[num].pwrbutton); XmStringFree(cstr); /* make label */ n = 0; cstr = XmStringCreateLocalized(cardInfo[num].name); XtSetArg(av[n], XmNlabelString, cstr); n++; XtSetArg(av[n], XmNbackground, statColor[cardInfo[num].stat]); n++; /* XtSetArg(av[n], XmNsensitive, cardInfo[num].stat); n++; */ XtSetArg(av[n], XmNborderWidth, 2); n++; XtSetArg(av[n], XmNshadowThickness, 1); n++; XtSetArg(av[n], XmNalignment, XmALIGNMENT_BEGINNING); n++; XtSetArg(av[n], XmNrightAttachment, XmATTACH_FORM); n++; XtSetArg(av[n], XmNrightOffset, 2); n++; XtSetArg(av[n], XmNleftAttachment, XmATTACH_WIDGET); n++; XtSetArg(av[n], XmNleftWidget, slotFrame[num].pwrbutton); n++; XtSetArg(av[n], XmNleftOffset, 40); n++; if (num == 0) { XtSetArg(av[n], XmNtopAttachment, XmATTACH_FORM); n++; XtSetArg(av[n], XmNtopOffset, 1); n++; } else { XtSetArg(av[n], XmNtopAttachment, XmATTACH_WIDGET); n++; XtSetArg(av[n], XmNtopWidget, slotFrame[num-1].sep); n++; XtSetArg(av[n], XmNtopOffset, 0); n++; } *name = 'L'; slotFrame[num].label = XmCreateLabel(frame, name, av, n); XtManageChild(slotFrame[num].label); XmStringFree(cstr); /* make drv button */ n = 0; sprintf(msg, " %s ", cardInfo[num].drv); cstr = XmStringCreateLocalized(msg); XtSetArg(av[n], XmNlabelString, cstr); n++; XtSetArg(av[n], XmNsensitive, cardInfo[num].stat); n++; XtSetArg(av[n], XmNborderWidth, 1); n++; c = cardInfo[num].stat == 1 ? PowerColor : SafeColor; XtSetArg(av[n], XmNbackground, c); n++; XtSetArg(av[n], XmNtopShadowColor, c); n++; XtSetArg(av[n], XmNbottomShadowColor, c); n++; XtSetArg(av[n], XmNhighlightThickness, 0); n++; XtSetArg(av[n], XmNleftAttachment, XmATTACH_WIDGET); n++; XtSetArg(av[n], XmNleftWidget, slotFrame[num].pwrbutton); n++; XtSetArg(av[n], XmNleftOffset, 0); n++; XtSetArg(av[n], XmNrightAttachment, XmATTACH_WIDGET); n++; XtSetArg(av[n], XmNrightWidget, slotFrame[num].label); n++; XtSetArg(av[n], XmNrightOffset, 0); n++; if (num == 0) { XtSetArg(av[n], XmNtopAttachment, XmATTACH_FORM); n++; XtSetArg(av[n], XmNtopOffset, 1); n++; } else { XtSetArg(av[n], XmNtopAttachment, XmATTACH_WIDGET); n++; XtSetArg(av[n], XmNtopWidget, slotFrame[num-1].sep); n++; XtSetArg(av[n], XmNtopOffset, 0); n++; } *name = 'D'; slotFrame[num].drvbutton = XmCreatePushButton(frame, name, av, n); XtManageChild(slotFrame[num].drvbutton); XmStringFree(cstr); XtAddCallback(slotFrame[num].pwrbutton, XmNactivateCallback, powerButton, (XtPointer)num); XtAddCallback(slotFrame[num].drvbutton, XmNactivateCallback, drvButton, (XtPointer)num); /* make separator */ n = 0; XtSetArg(av[n], XmNorientation, XmHORIZONTAL); n++; XtSetArg(av[n], XmNseparatorType, XmNO_LINE); n++; XtSetArg(av[n], XmNtopAttachment, XmATTACH_WIDGET); n++; XtSetArg(av[n], XmNtopWidget, slotFrame[num].pwrbutton); n++; XtSetArg(av[n], XmNtopOffset, 0); n++; *name = 'S'; slotFrame[num].sep = XmCreateSeparator(frame, name, av, n); XtManageChild(slotFrame[num].sep); y += widgetYsize(&slotFrame[num].sep); return(y); }