int realpath_main(int argc, char **argv) { int retval = EXIT_SUCCESS; #if PATH_MAX > (BUFSIZ+1) RESERVE_CONFIG_BUFFER(resolved_path, PATH_MAX); # define resolved_path_MUST_FREE 1 #else #define resolved_path bb_common_bufsiz1 # define resolved_path_MUST_FREE 0 #endif if (--argc == 0) { bb_show_usage(); } do { argv++; if (realpath(*argv, resolved_path) != NULL) { puts(resolved_path); } else { retval = EXIT_FAILURE; bb_perror_msg("%s", *argv); } } while (--argc); #if ENABLE_FEATURE_CLEAN_UP && resolved_path_MUST_FREE RELEASE_CONFIG_BUFFER(resolved_path); #endif bb_fflush_stdout_and_exit(retval); }
static int check_utc(void) { int utc = 0; FILE *f = fopen(ADJTIME_PATH, "r"); if (f) { RESERVE_CONFIG_BUFFER(buffer, 128); while (fgets(buffer, sizeof(buffer), f)) { int len = strlen(buffer); while (len && isspace(buffer[len - 1])) len--; buffer[len] = 0; if (strncmp(buffer, "UTC", 3) == 0) { utc = 1; break; } } fclose(f); RELEASE_CONFIG_BUFFER(buffer); } return utc; }
static size_t bb_full_fd_action(int src_fd, int dst_fd, const size_t size2) { int status; size_t xread, wrote, total, size = size2; if (src_fd < 0) { return -1; } if (size == 0) { /* If size is 0 copy until EOF */ size = ULONG_MAX; } { RESERVE_CONFIG_BUFFER(buffer,BUFSIZ); total = 0; wrote = 0; status = -1; while (total < size) { xread = BUFSIZ; if (size < (total + BUFSIZ)) xread = size - total; xread = bb_full_read(src_fd, buffer, xread); if (xread > 0) { if (dst_fd < 0) { /* A -1 dst_fd means we need to fake it... */ wrote = xread; } else { wrote = bb_full_write(dst_fd, buffer, xread); } if (wrote < xread) { bb_perror_msg(bb_msg_write_error); break; } total += wrote; } else if (xread < 0) { bb_perror_msg(bb_msg_read_error); break; } else if (xread == 0) { /* All done. */ status = 0; break; } } RELEASE_CONFIG_BUFFER(buffer); } if (status == 0 || total) return total; /* Some sortof error occured */ return -1; }
static uint8_t *hash_file(const char *filename, uint8_t hash_algo) { int src_fd = strcmp(filename, "-") == 0 ? STDIN_FILENO : open(filename, O_RDONLY); if (src_fd == -1) { bb_perror_msg("%s", filename); return NULL; } else { uint8_t *hash_value; RESERVE_CONFIG_UBUFFER(hash_value_bin, 20); hash_value = hash_fd(src_fd, -1, hash_algo, hash_value_bin) != -2 ? hash_bin_to_hex(hash_value_bin, hash_algo == HASH_MD5 ? 16 : 20) : NULL; RELEASE_CONFIG_BUFFER(hash_value_bin); close(src_fd); return hash_value; } }
static int send_pack(int sock, struct in_addr *src_addr, struct in_addr *dst_addr, struct sockaddr_ll *ME, struct sockaddr_ll *HE) { int err; struct timeval now; RESERVE_CONFIG_UBUFFER(buf, 256); struct arphdr *ah = (struct arphdr *) buf; unsigned char *p = (unsigned char *) (ah + 1); ah->ar_hrd = htons(ME->sll_hatype); ah->ar_hrd = htons(ARPHRD_ETHER); ah->ar_pro = htons(ETH_P_IP); ah->ar_hln = ME->sll_halen; ah->ar_pln = 4; ah->ar_op = cfg & advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); memcpy(p, &ME->sll_addr, ah->ar_hln); p += ME->sll_halen; memcpy(p, src_addr, 4); p += 4; if (cfg & advert) memcpy(p, &ME->sll_addr, ah->ar_hln); else memcpy(p, &HE->sll_addr, ah->ar_hln); p += ah->ar_hln; memcpy(p, dst_addr, 4); p += 4; gettimeofday(&now, NULL); err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE)); if (err == p - buf) { last = now; sent++; if (!(cfg & unicasting)) brd_sent++; } RELEASE_CONFIG_BUFFER(buf); return err; }
static int show_clock(int utc) { struct tm *ptm; time_t t; RESERVE_CONFIG_BUFFER(buffer, 64); t = read_rtc(utc); ptm = localtime(&t); /* Sets 'tzname[]' */ safe_strncpy(buffer, ctime(&t), 64); if (buffer[0]) buffer[strlen(buffer) - 1] = 0; //printf("%s %.6f seconds %s\n", buffer, 0.0, utc ? "" : (ptm->tm_isdst ? tzname[1] : tzname[0])); printf( "%s %.6f seconds\n", buffer, 0.0); RELEASE_CONFIG_BUFFER(buffer); return 0; }
int mdev_main(int argc, char *argv[]) { if (argc > 1) { if (argc == 2 && !strcmp(argv[1],"-s")) { RESERVE_CONFIG_BUFFER(temp,PATH_MAX); strcpy(temp,"/sys/block"); find_dev(temp); strcpy(temp,"/sys/class"); find_dev(temp); if(ENABLE_FEATURE_CLEAN_UP) RELEASE_CONFIG_BUFFER(temp); return 0; } else bb_show_usage(); } /* hotplug support goes here */ return 0; }
/* If size is 0 copy until EOF */ static ssize_t bb_full_fd_action(int src_fd, int dst_fd, const size_t size) { ssize_t read_total = 0; RESERVE_CONFIG_BUFFER(buffer,BUFSIZ); while ((size == 0) || (read_total < size)) { size_t read_try; ssize_t read_actual; if ((size == 0) || (size - read_total > BUFSIZ)) { read_try = BUFSIZ; } else { read_try = size - read_total; } read_actual = safe_read(src_fd, buffer, read_try); if (read_actual > 0) { if ((dst_fd >= 0) && (bb_full_write(dst_fd, buffer, (size_t) read_actual) != read_actual)) { bb_perror_msg(bb_msg_write_error); /* match Read error below */ break; } } else if (read_actual == 0) { if (size) { bb_error_msg("Unable to read all data"); read_total = -1; } break; } else { /* read_actual < 0 */ bb_perror_msg("Read error"); read_total = -1; break; } read_total += read_actual; } RELEASE_CONFIG_BUFFER(buffer); return(read_total); }
int pipe_progress_main(int argc, char **argv) { RESERVE_CONFIG_BUFFER(buf, PIPE_PROGRESS_SIZE); time_t t = time(NULL); size_t len; while ((len = fread(buf, 1, PIPE_PROGRESS_SIZE, stdin)) > 0) { time_t new_time = time(NULL); if (new_time != t) { t = new_time; fputc('.', stderr); } fwrite(buf, len, 1, stdout); } fputc('\n', stderr); if (ENABLE_FEATURE_CLEAN_UP) RELEASE_CONFIG_BUFFER(buf); return 0; }
int arping_main(int argc, char **argv) { const char *device = "eth0"; int ifindex; char *source = NULL; char *target; s = xsocket(PF_PACKET, SOCK_DGRAM, 0); // Drop suid root privileges xsetuid(getuid()); { unsigned opt; char *_count, *_timeout; /* Dad also sets quit_on_reply. * Advert also sets unsolicited. */ opt_complementary = "Df:AU"; opt = getopt32(argc, argv, "DUAqfbc:w:i:s:", &_count, &_timeout, &device, &source); cfg |= opt & 0x3f; /* set respective flags */ if (opt & 0x40) /* -c: count */ count = xatou(_count); if (opt & 0x80) /* -w: timeout */ timeout = xatoul_range(_timeout, 0, INT_MAX/2000); //if (opt & 0x100) /* -i: interface */ if (strlen(device) > IF_NAMESIZE) { bb_error_msg_and_die("interface name '%s' is too long", device); } //if (opt & 0x200) /* -s: source */ } argc -= optind; argv += optind; if (argc != 1) bb_show_usage(); target = *argv; xfunc_error_retval = 2; { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, IFNAMSIZ - 1); if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { bb_error_msg_and_die("interface %s not found", device); } ifindex = ifr.ifr_ifindex; if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) { bb_error_msg_and_die("SIOCGIFFLAGS"); } if (!(ifr.ifr_flags & IFF_UP)) { bb_error_msg_and_die("interface %s is down", device); } if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { bb_error_msg("interface %s is not ARPable", device); return (cfg & dad ? 0 : 2); } } if (!inet_aton(target, &dst)) { len_and_sockaddr *lsa; lsa = xhost_and_af2sockaddr(target, 0, AF_INET); memcpy(&dst, &lsa->sin.sin_addr.s_addr, 4); if (ENABLE_FEATURE_CLEAN_UP) free(lsa); } if (source && !inet_aton(source, &src)) { bb_error_msg_and_die("invalid source address %s", source); } if (!(cfg & dad) && (cfg & unsolicited) && src.s_addr == 0) src = dst; if (!(cfg & dad) || src.s_addr) { struct sockaddr_in saddr; int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); if (device) { if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1) bb_error_msg("warning: interface %s is ignored", device); } memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; if (src.s_addr) { saddr.sin_addr = src; xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); } else if (!(cfg & dad)) { socklen_t alen = sizeof(saddr); saddr.sin_port = htons(1025); saddr.sin_addr = dst; if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1) bb_perror_msg("warning: setsockopt(SO_DONTROUTE)"); xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) { bb_error_msg_and_die("getsockname"); } src = saddr.sin_addr; } close(probe_fd); } me.sll_family = AF_PACKET; me.sll_ifindex = ifindex; me.sll_protocol = htons(ETH_P_ARP); xbind(s, (struct sockaddr *) &me, sizeof(me)); { socklen_t alen = sizeof(me); if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) { bb_error_msg_and_die("getsockname"); } } if (me.sll_halen == 0) { bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device); return (cfg & dad ? 0 : 2); } he = me; memset(he.sll_addr, -1, he.sll_halen); if (!(cfg & quiet)) { printf("ARPING to %s from %s via %s\n", inet_ntoa(dst), inet_ntoa(src), device ? device : "unknown"); } if (!src.s_addr && !(cfg & dad)) { bb_error_msg_and_die("no src address in the non-DAD mode"); } { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_RESTART; sa.sa_handler = (void (*)(int)) finish; sigaction(SIGINT, &sa, NULL); sa.sa_handler = (void (*)(int)) catcher; sigaction(SIGALRM, &sa, NULL); } catcher(); while (1) { sigset_t sset, osset; RESERVE_CONFIG_UBUFFER(packet, 4096); struct sockaddr_ll from; socklen_t alen = sizeof(from); int cc; cc = recvfrom(s, packet, 4096, 0, (struct sockaddr *) &from, &alen); if (cc < 0) { bb_perror_msg("recvfrom"); continue; } sigemptyset(&sset); sigaddset(&sset, SIGALRM); sigaddset(&sset, SIGINT); sigprocmask(SIG_BLOCK, &sset, &osset); recv_pack(packet, cc, &from); sigprocmask(SIG_SETMASK, &osset, NULL); RELEASE_CONFIG_BUFFER(packet); } }
static void doSyslogd(void) { struct sockaddr_un sunx; socklen_t addrLength; /*BRCM begin*/ /* * In CMS, we don't need the pidfile. Don't write it out to save some DRAM. * FILE *pidfile; * char pidfilename[30]; */ /* All the access to /dev/log will be redirected to /var/log/log * * which is TMPFS, memory file system. **/ #define BRCM_PATH_LOG "/var/log/log" /*BRCM end*/ int sock_fd; fd_set fds; /* Set up signal handlers. */ signal(SIGINT, quit_signal); signal(SIGTERM, quit_signal); signal(SIGQUIT, quit_signal); signal(SIGHUP, SIG_IGN); signal(SIGCHLD, SIG_IGN); #ifdef SIGCLD signal(SIGCLD, SIG_IGN); #endif signal(SIGALRM, domark); alarm(MarkInterval); /* Create the syslog file so realpath() can work. */ /*BRCM begin*/ /* if (realpath (_PATH_LOG, lfile) != NULL) { */ if (realpath (BRCM_PATH_LOG, lfile) != NULL) { /*BRCM end*/ unlink (lfile); } memset(&sunx, 0, sizeof(sunx)); sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, lfile, sizeof(sunx.sun_path)); if ((sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { /*BRCM begin*/ /* bb_perror_msg_and_die("Couldn't get file descriptor for socket " _PATH_LOG); */ bb_error_msg_and_die ("Couldn't get file descriptor for socket " BRCM_PATH_LOG); /*BRCM end*/ } addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path); if (bind(sock_fd, (struct sockaddr *) &sunx, addrLength) < 0) { /*BRCM begin*/ /* bb_perror_msg_and_die("Could not connect to socket " _PATH_LOG); */ bb_error_msg_and_die ("Could not connect to socket " BRCM_PATH_LOG); /*BRCM end*/ } if (chmod(lfile, 0666) < 0) { /*BRCM begin*/ /* bb_perror_msg_and_die("Could not set permission on " _PATH_LOG); */ bb_error_msg_and_die ("Could not set permission on " BRCM_PATH_LOG); /*BRCM end*/ } #ifdef CONFIG_FEATURE_IPC_SYSLOG if (circular_logging == TRUE) { ipcsyslog_init(); } #endif #ifdef CONFIG_FEATURE_REMOTE_LOG if (doRemoteLog == TRUE) { init_RemoteLog(); } #endif /*BRCM begin*/ if (localLogLevel < LOG_EMERG) localLogLevel = LOG_DEBUG; if (remoteLogLevel < LOG_EMERG) remoteLogLevel = LOG_ERR; /* change to priority emerg to be consistent with klogd */ /* logMessage(LOG_SYSLOG | LOG_INFO, "syslogd started: " BB_BANNER); */ logMessage (LOG_SYSLOG | LOG_EMERG, "BCM96345 started: " BB_BANNER); /* * In CMS, we don't need the pid file, so don't write one and save some DRAM. * sprintf (pidfilename, "%s%s.pid", _PATH_VARRUN, "syslogd"); * if ((pidfile = fopen (pidfilename, "w")) != NULL) { * fprintf (pidfile, "%d\n", getpid ()); * (void) fclose (pidfile); * } * else { * logMessage ((LOG_SYSLOG | LOG_ERR),("Failed to create pid file %s", pidfilename)); * } */ /*BRCM end*/ for (;;) { FD_ZERO(&fds); FD_SET(sock_fd, &fds); if (select(sock_fd + 1, &fds, NULL, NULL, NULL) < 0) { if (errno == EINTR) { /* alarm may have happened. */ continue; } bb_perror_msg_and_die("select error"); } if (FD_ISSET(sock_fd, &fds)) { int i; RESERVE_CONFIG_BUFFER(tmpbuf, MAXLINE + 1); memset(tmpbuf, '\0', MAXLINE + 1); if ((i = recv(sock_fd, tmpbuf, MAXLINE, 0)) > 0) { serveConnection(tmpbuf, i); } else { bb_perror_msg_and_die("UNIX socket error"); } RELEASE_CONFIG_BUFFER(tmpbuf); } /* FD_ISSET() */ } /* for main loop */ }
int arping_main(int argc, char **argv) { char *device = "eth0"; int ifindex; char *source = NULL; char *target; s = socket(PF_PACKET, SOCK_DGRAM, 0); ifindex = errno; // Drop suid root privileges xsetuid(getuid()); { unsigned long opt; char *_count, *_timeout, *_device; /* Dad also sets quit_on_reply. * Advert also sets unsolicited. */ bb_opt_complementally = "Df:AU"; opt = bb_getopt_ulflags(argc, argv, "DUAqfbc:w:i:s:", &_count, &_timeout, &_device); cfg |= opt & 63; /* set respective flags */ if (opt & 64) /* count */ count = atoi(_count); if (opt & 128) /* timeout */ timeout = atoi(_timeout); if (opt & 256) { /* interface */ if (strlen(_device) > IF_NAMESIZE) { bb_error_msg_and_die("Interface name `%s' must be less than %d", _device, IF_NAMESIZE); } device = _device; } if (opt & 512) /* source */ source = optarg; } argc -= optind; argv += optind; if (argc != 1) bb_show_usage(); target = *argv; if (s < 0) { bb_default_error_retval = ifindex; bb_perror_msg_and_die("socket"); } bb_default_error_retval = 2; { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, IFNAMSIZ - 1); if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { bb_error_msg_and_die("Interface %s not found", device); } ifindex = ifr.ifr_ifindex; if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) { bb_error_msg_and_die("SIOCGIFFLAGS"); } if (!(ifr.ifr_flags & IFF_UP)) { bb_error_msg_and_die("Interface %s is down", device); } if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { bb_error_msg("Interface %s is not ARPable", device); exit(cfg&dad ? 0 : 2); } } if (!inet_aton(target, &dst)) { struct hostent *hp; hp = gethostbyname2(target, AF_INET); if (!hp) { bb_error_msg_and_die("invalid or unknown target %s", target); } memcpy(&dst, hp->h_addr, 4); } if (source && !inet_aton(source, &src)) { bb_error_msg_and_die("invalid source address %s", source); } if (!(cfg&dad) && cfg&unsolicited && src.s_addr == 0) src = dst; if (!(cfg&dad) || src.s_addr) { struct sockaddr_in saddr; int probe_fd = socket(AF_INET, SOCK_DGRAM, 0); /* maybe use bb_xsocket? */ if (probe_fd < 0) { bb_error_msg_and_die("socket"); } if (device) { if (setsockopt (probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1) bb_error_msg("WARNING: interface %s is ignored", device); } memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; if (src.s_addr) { saddr.sin_addr = src; if (bind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) { bb_error_msg_and_die("bind"); } } else if (!(cfg&dad)) { int on = 1; socklen_t alen = sizeof(saddr); saddr.sin_port = htons(1025); saddr.sin_addr = dst; if (setsockopt (probe_fd, SOL_SOCKET, SO_DONTROUTE, (char *) &on, sizeof(on)) == -1) bb_perror_msg("WARNING: setsockopt(SO_DONTROUTE)"); if (connect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) { bb_error_msg_and_die("connect"); } if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) { bb_error_msg_and_die("getsockname"); } src = saddr.sin_addr; } close(probe_fd); }; me.sll_family = AF_PACKET; me.sll_ifindex = ifindex; me.sll_protocol = htons(ETH_P_ARP); if (bind(s, (struct sockaddr *) &me, sizeof(me)) == -1) { bb_error_msg_and_die("bind"); } { socklen_t alen = sizeof(me); if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) { bb_error_msg_and_die("getsockname"); } } if (me.sll_halen == 0) { bb_error_msg("Interface \"%s\" is not ARPable (no ll address)", device); exit(cfg&dad ? 0 : 2); } he = me; memset(he.sll_addr, -1, he.sll_halen); if (!(cfg&quiet)) { printf("ARPING to %s from %s via %s\n", inet_ntoa(dst), inet_ntoa(src), device ? device : "unknown"); } if (!src.s_addr && !(cfg&dad)) { bb_error_msg_and_die("no src address in the non-DAD mode"); } { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_RESTART; sa.sa_handler = (void (*)(int)) finish; sigaction(SIGINT, &sa, NULL); sa.sa_handler = (void (*)(int)) catcher; sigaction(SIGALRM, &sa, NULL); } catcher(); while (1) { sigset_t sset, osset; RESERVE_CONFIG_UBUFFER(packet, 4096); struct sockaddr_ll from; socklen_t alen = sizeof(from); int cc; if ((cc = recvfrom(s, packet, 4096, 0, (struct sockaddr *) &from, &alen)) < 0) { bb_perror_msg("recvfrom"); continue; } sigemptyset(&sset); sigaddset(&sset, SIGALRM); sigaddset(&sset, SIGINT); sigprocmask(SIG_BLOCK, &sset, &osset); recv_pack(packet, cc, &from); sigprocmask(SIG_SETMASK, &osset, NULL); RELEASE_CONFIG_BUFFER(packet); } }
static void doSyslogd(void) { struct sockaddr_un sunx; socklen_t addrLength; int sock_fd; fd_set fds; /* Set up signal handlers. */ signal(SIGINT, quit_signal); signal(SIGTERM, quit_signal); signal(SIGQUIT, quit_signal); signal(SIGHUP, SIG_IGN); signal(SIGCHLD, SIG_IGN); #ifdef SIGCLD signal(SIGCLD, SIG_IGN); #endif signal(SIGALRM, domark); alarm(MarkInterval); /* Create the syslog file so realpath() can work. */ if (realpath(_PATH_LOG, lfile) != NULL) { unlink(lfile); } memset(&sunx, 0, sizeof(sunx)); sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, lfile, sizeof(sunx.sun_path)); if ((sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { bb_perror_msg_and_die("Couldn't get file descriptor for socket " _PATH_LOG); } addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path); if (bind(sock_fd, (struct sockaddr *) &sunx, addrLength) < 0) { bb_perror_msg_and_die("Could not connect to socket " _PATH_LOG); } if (chmod(lfile, 0666) < 0) { bb_perror_msg_and_die("Could not set permission on " _PATH_LOG); } #ifdef CONFIG_FEATURE_IPC_SYSLOG if (circular_logging == TRUE) { ipcsyslog_init(); } #endif #ifdef CONFIG_FEATURE_REMOTE_LOG if (doRemoteLog == TRUE) { init_RemoteLog(); } #endif logMessage(LOG_SYSLOG | LOG_INFO, "syslogd started: " BB_BANNER); for (;;) { FD_ZERO(&fds); FD_SET(sock_fd, &fds); if (select(sock_fd + 1, &fds, NULL, NULL, NULL) < 0) { if (errno == EINTR) { /* alarm may have happened. */ continue; } bb_perror_msg_and_die("select error"); } if (FD_ISSET(sock_fd, &fds)) { int i; RESERVE_CONFIG_BUFFER(tmpbuf, MAXLINE + 1); memset(tmpbuf, '\0', MAXLINE + 1); if ((i = recv(sock_fd, tmpbuf, MAXLINE, 0)) > 0) { serveConnection(tmpbuf, i); } else { bb_perror_msg_and_die("UNIX socket error"); } RELEASE_CONFIG_BUFFER(tmpbuf); } /* FD_ISSET() */ } /* for main loop */ }
/* mknod in /dev based on a path like "/sys/block/hda/hda1" */ static void make_device(char *path) { char *device_name,*s; int major,minor,type,len,fd; int mode=0660; uid_t uid=0; gid_t gid=0; RESERVE_CONFIG_BUFFER(temp,PATH_MAX); /* Try to read major/minor string */ snprintf(temp, PATH_MAX, "%s/dev", path); fd = open(temp, O_RDONLY); len = read(fd, temp, PATH_MAX-1); if (len<1) goto end; temp[len] = 0; close(fd); /* Determine device name, type, major and minor */ device_name = strrchr(path, '/') + 1; type = strncmp(path+5, "block/" ,6) ? S_IFCHR : S_IFBLK; major = minor = 0; for (s = temp; *s; s++) { if (*s == ':') { major = minor; minor = 0; } else { minor *= 10; minor += (*s) - '0'; } } /* If we have a config file, look up permissions for this device */ if (ENABLE_FEATURE_MDEV_CONF) { char *conf,*pos,*end; /* mmap the config file */ if (-1!=(fd=open("/etc/mdev.conf",O_RDONLY))) { len=lseek(fd,0,SEEK_END); conf=mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0); if (conf) { int line=0; /* Loop through lines in mmaped file*/ for (pos=conf;pos-conf<len;) { int field; char *end2; line++; /* find end of this line */ for(end=pos;end-conf<len && *end!='\n';end++); /* Three fields: regex, uid:gid, mode */ for (field=3;field;field--) { /* Skip whitespace */ while (pos<end && isspace(*pos)) pos++; if (pos==end || *pos=='#') break; for (end2=pos; end2<end && !isspace(*end2) && *end2!='#'; end2++); switch(field) { /* Regex to match this device */ case 3: { char *regex=strndupa(pos,end2-pos); regex_t match; regmatch_t off; int result; /* Is this it? */ xregcomp(&match,regex,REG_EXTENDED); result=regexec(&match,device_name,1,&off,0); regfree(&match); /* If not this device, skip rest of line */ if(result || off.rm_so || off.rm_eo!=strlen(device_name)) goto end_line; break; } /* uid:gid */ case 2: { char *s2; /* Find : */ for(s=pos;s<end2 && *s!=':';s++); if(s==end2) goto end_line; /* Parse UID */ uid=strtoul(pos,&s2,10); if(s!=s2) { struct passwd *pass; pass=getpwnam(strndupa(pos,s-pos)); if(!pass) goto end_line; uid=pass->pw_uid; } s++; /* parse GID */ gid=strtoul(s,&s2,10); if(end2!=s2) { struct group *grp; grp=getgrnam(strndupa(s,end2-s)); if(!grp) goto end_line; gid=grp->gr_gid; } break; } /* mode */ case 1: { mode=strtoul(pos,&pos,8); if(pos!=end2) goto end_line; goto found_device; } } pos=end2; } end_line: /* Did everything parse happily? */ if (field && field!=3) bb_error_msg_and_die("Bad line %d",line); /* Next line */ pos=++end; } found_device: munmap(conf,len); } close(fd); } } sprintf(temp, "%s/%s", DEV_PATH, device_name); umask(0); if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST) bb_perror_msg_and_die("mknod %s failed", temp); if (ENABLE_FEATURE_MDEV_CONF) chown(temp,uid,gid); end: RELEASE_CONFIG_BUFFER(temp); }