/* Copyright 2004 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include char *setupFile() { struct stat sbuf; char path[512]; int fd; struct utsname utsbuf; char *buf = NULL; uname(&utsbuf); snprintf(path,512,"/lib/modules/%s/modules.dep",utsbuf.release); if (!stat(path,&sbuf)) { fd = open(path,O_RDONLY); buf = mmap(0,sbuf.st_size,PROT_READ,MAP_SHARED,fd,0); close(fd); } return buf; } int isAvailable(char *modulename) { char mod_name[100]; static char *buf = NULL; if (!buf) { buf = setupFile(); if (!buf) return 0; } snprintf(mod_name,100,"/%s.ko:",modulename); if (strstr(buf,mod_name)) return 1; snprintf(mod_name,100,"/%s.ko.gz:",modulename); if (strstr(buf,mod_name)) return 1; return 0; } void waitForConnection(struct device **devlist) { int sock, fd, socklen, x; struct sockaddr_un addr; FILE *tmp; sock = socket(PF_UNIX, SOCK_STREAM, 0); if (sock == -1) return; memset(addr.sun_path,'\0',sizeof(addr.sun_path)); sprintf(addr.sun_path, "akudzu_config_socket"); addr.sun_family= AF_UNIX; addr.sun_path[0] = '\0'; if (bind(sock, &addr, sizeof(struct sockaddr_un)) == -1) return; if (listen(sock, 1) == -1) return; fd = accept(sock, &addr, &socklen); if (fd == -1) return; tmp = fdopen(fd,"w"); for (x = 0; devlist[x]; x++) { devlist[x]->writeDevice(tmp,devlist[x]); fflush(tmp); } fclose(tmp); close(sock); } int main(int argc, char **argv) { char *bus = NULL, *class = NULL; int x, rc, isdaemon = 0; enum deviceBus probeBus = BUS_UNSPEC & ~BUS_SERIAL; enum deviceClass probeClass = CLASS_UNSPEC & ~CLASS_FLOPPY & ~CLASS_HD & ~CLASS_CDROM; poptContext context; struct device **devs; struct poptOption options[] = { POPT_AUTOHELP { "bus", 'b', POPT_ARG_STRING, &bus, 0, "probe only the specified 'bus'", NULL }, { "class", 'c', POPT_ARG_STRING, &class, 0, "probe only for the specified 'class'", NULL }, { "daemon", 'd', POPT_ARG_NONE, &isdaemon, 0, NULL, NULL }, { 0, 0, 0, 0, 0, 0 } }; context = poptGetContext("kmodule", argc, (const char **)argv, options, 0); while ((rc = poptGetNextOpt(context)) > 0) { } if (( rc < -1)) { fprintf(stderr, "%s: %s\n", poptBadOption(context, POPT_BADOPTION_NOALIAS), poptStrerror(rc)); exit(-1); } if (bus) { for (x=0; bus[x]; x++) bus[x] = toupper(bus[x]); for (x=0; buses[x].string && strcmp(buses[x].string,bus); x++); if (buses[x].string) probeBus = buses[x].busType; } if (class) { for (x=0; class[x]; x++) class[x] = toupper(class[x]); for (x=0; classes[x].string && strcmp(classes[x].string,class); x++); if (classes[x].string) probeClass = classes[x].classType; } initializeBusDeviceList(probeBus); devs = probeDevices(probeClass, probeBus, PROBE_ALL|PROBE_NOLOAD|PROBE_SAFE); if (!devs) return 0; for (x = 0; devs[x]; x++) { if (devs[x]->driver && isAvailable(devs[x]->driver)) { int i; for (i = 0; classes[i].classType; i++) if (devs[x]->type == classes[i].classType) { break; } printf("%s %s\n",classes[i].string,devs[x]->driver); } } fflush(stdout); if (isdaemon) { daemon(0,0); waitForConnection(devs); } return 0; }