+ * Networking/Socket stuff
+ */
+
+/* This should really be part of the newlib _reent structure */
+int h_errno;
+
+char *inet_ntoa(struct in_addr in) {
+ static char buf[18];
+ const unsigned char *p = (void*) ∈
+ snprintf(buf,sizeof(buf),"%u.%u.%u.%u",p[0],p[1],p[2],p[3]);
+ return buf;
+}
+
+struct servent *getservbyname(const char *name,const char *proto) {
+ return NULL;
+}
+
+static const char *h_errlist[] = { "No Error","Unknown host", "Host name lookup failure","Unknown server error","No address associated with name" };
+
+const char *hstrerror(int err) {
+ if(err < 0 || err > 4) return "Unknown Error";
+ return h_errlist[err];
+}
+
+void herror(const char *string) {
+ fprintf(stderr,"%s: %s\n",string,hstrerror(h_errno));
+}
+
+extern int _resolve_ip(int addr, char *buf, size_t size);
+
+struct hostent *gethostbyaddr(const char *addr, int len, int type) {
+ static struct hostent hostent;
+ static char name[128];
+ static char *aliases[1];
+ static char *addr_list[1];
+ static char addr_list_buf[4];
+ int err,i;
+
+ if(type != AF_INET || len != 4) return NULL;
+ memcpy(&i,addr,4);
+ memcpy(addr_list_buf,addr,4);
+ err = _resolve_ip(i,name,sizeof(name));
+ if(err != 0) { h_errno = err; return NULL; }
+
+ hostent.h_name = name;
+ hostent.h_aliases = aliases;
+ aliases[0] = NULL;
+ hostent.h_addrtype = AF_INET;
+ hostent.h_length = sizeof(struct in_addr);
+ hostent.h_addr_list = addr_list;
+ addr_list[0] = addr_list_buf;
+
+ return &hostent;
+}
+
+extern int _resolve_hostname(const char *, char *buf, size_t *size);
+
+struct hostent *gethostbyname(const char *hostname) {
+#define MAX_ADDRS 256
+ static struct hostent hostent;
+ static char saved_hostname[128];
+ static char *addr_list[MAX_ADDRS+1];
+ static char addr_list_buf[MAX_ADDRS*sizeof(struct in_addr)];
+ static char *aliases[1];
+
+ unsigned char buf[MAX_ADDRS*sizeof(struct in_addr)];
+ size_t size = sizeof(buf);
+ int err,i,n=0;
+
+ err = _resolve_hostname(hostname,buf,&size);
+ if(err != 0) { h_errno = err; return NULL; }
+
+ memcpy(addr_list_buf,buf,size);
+ for(i=0;i<size;i += sizeof(struct in_addr)) addr_list[n++] = &addr_list_buf[i];
+ addr_list[n] = NULL;
+ strncpy(saved_hostname,hostname,sizeof(saved_hostname));
+ aliases[0] = NULL;
+
+ hostent.h_name = saved_hostname;
+ hostent.h_aliases = aliases;
+ hostent.h_addrtype = AF_INET;
+ hostent.h_length = sizeof(struct in_addr);
+ hostent.h_addr_list = addr_list;
+
+ return &hostent;
+}
+
+static struct passwd pw_passwd;
+static struct group gr_group;
+static FILE *passwd_fp;
+static FILE *group_fp;
+static char pw_name[1024];
+static char pw_password[1024];
+static char pw_gecos[1024];
+static char pw_dir[1024];
+static char pw_shell[1024];
+static char gr_name[1024];
+static char gr_passwd[1024];
+static char *gr_mem[1];
+
+static int gr_parse_body(const char *buf) {
+ if(sscanf(buf,"%[^:]:%[^:]:%hu",gr_name,gr_passwd,&gr_group.gr_gid) < 3) return -1;
+ gr_group.gr_name = gr_name;
+ gr_group.gr_passwd = gr_passwd;
+ gr_group.gr_mem = gr_mem;
+ gr_mem[0] = NULL;
+ return 0;
+}
+
+static int pw_parse_body(const char *buf) {
+ int pos;
+ if(sscanf(buf,"%[^:]:%[^:]:%d:%d:%[^:]:%[^:]:%s\n",pw_name,pw_password,&pw_passwd.pw_uid,&pw_passwd.pw_gid,pw_gecos,pw_dir,pw_shell) < 7) return -1;
+ pw_passwd.pw_name = pw_name;
+ pw_passwd.pw_passwd = pw_password;
+ pw_passwd.pw_gecos = pw_gecos;
+ pw_passwd.pw_dir = pw_dir;
+ pw_passwd.pw_shell = pw_shell;
+ pw_passwd.pw_comment = "";
+ return 0;
+}
+
+struct group *getgrnam(const char *name) {
+ FILE *fp;
+ char buf[1024];
+
+ if((fp=fopen("/etc/group","r"))==NULL) return NULL;
+ while(fgets(buf,sizeof(buf),fp)) {
+ if(buf[0] == '#') continue;
+ if(gr_parse_body(buf) < 0) {
+ fclose(fp);
+ return NULL;
+ }
+ if(strcmp(name,gr_name)==0) {
+ fclose(fp);
+ return &gr_group;
+ }
+ }
+ fclose(fp);
+ return NULL;
+}
+
+struct group *getgrgid(gid_t gid) {
+ FILE *fp;
+ char buf[1024];
+
+ if((fp=fopen("/etc/group","r"))==NULL) return NULL;
+ while(fgets(buf,sizeof(buf),fp)) {
+ if(buf[0] == '#') continue;
+ if(gr_parse_body(buf) < 0) {
+ fclose(fp);
+ return NULL;
+ }
+ if(gid == gr_group.gr_gid) {
+ fclose(fp);
+ return &gr_group;
+ }
+ }
+ fclose(fp);
+ return NULL;
+}
+
+struct group *getgrent() {
+ char buf[1024];
+ if(group_fp == NULL) return NULL;
+ if(fgets(buf,sizeof(buf),group_fp) == NULL) return NULL;
+ if(buf[0] == '#') return getgrent();
+ if(gr_parse_body(buf) < 0) return NULL;
+ return &gr_group;
+}
+
+void setgrent() {
+ if(group_fp != NULL) fclose(group_fp);
+ group_fp = fopen("/etc/group","r");
+}
+
+void endgrent() {
+ if(group_fp != NULL) fclose(group_fp);
+ group_fp = NULL;
+}
+
+struct passwd *getpwnam(const char *name) {
+ FILE *fp;
+ char buf[1024];
+
+ if((fp=fopen("/etc/passwd","r"))==NULL) return NULL;
+ while(fgets(buf,sizeof(buf),fp)) {
+ if(buf[0] == '#') continue;
+ if(pw_parse_body(buf) < 0) {
+ fclose(fp);
+ return NULL;
+ }
+ if(strcmp(name,pw_name)==0) {
+ fclose(fp);
+ return &pw_passwd;
+ }
+ }
+ fclose(fp);
+ return NULL;
+}
+
+struct passwd *getpwuid(uid_t uid) {
+ FILE *fp;
+ char buf[1024];
+
+ if((fp=fopen("/etc/passwd","r"))==NULL) return NULL;
+ while(fgets(buf,sizeof(buf),fp)) {
+ if(buf[0] == '#') continue;
+ if(pw_parse_body(buf) < 0) {
+ fclose(fp);
+ return NULL;
+ }
+ if(uid == pw_passwd.pw_uid) {
+ fclose(fp);
+ return &pw_passwd;
+ }
+ }
+ fclose(fp);
+ return NULL;
+}
+
+struct passwd *getpwent() {
+ char buf[1024];
+ if(passwd_fp == NULL) return NULL;
+ if(fgets(buf,sizeof(buf),passwd_fp) == NULL) return NULL;
+ if(buf[0] == '#') return getpwent();
+ if(pw_parse_body(buf) < 0) return NULL;
+ return &pw_passwd;
+}
+
+void setpwent() {
+ if(passwd_fp != NULL) fclose(passwd_fp);
+ passwd_fp = fopen("/etc/group","r");
+}
+
+void endpwent() {
+ if(passwd_fp != NULL) fclose(passwd_fp);
+ passwd_fp = NULL;
+}
+
+char *getpass(const char *prompt) {
+ static char buf[1024];
+ int len = 0;
+ fputs(prompt,stderr);
+ fflush(stdout);
+ if(fgets(buf,sizeof(buf),stdin)!=NULL) {
+ len = strlen(buf);
+ if(buf[len-1] == '\n') len--;
+ }
+ fputc('\n',stderr);
+ buf[len] = '\0';
+ return buf;
+}
+
+/* Argh... newlib's asprintf is totally broken... */
+int vasprintf(char **ret, const char *fmt, va_list ap) {
+ int n;
+ char *p;
+ *ret = malloc(128); /* just guess for now */
+ if(!*ret) return -1;
+ n = vsnprintf(*ret,128,fmt,ap);
+ if(n < 128) {
+ return n;
+ } else {
+ p = realloc(*ret,n+1);
+ if(!p) { free(*ret); return -1; }
+ return vsprintf(*ret = p,fmt,ap);
+ }
+}
+
+// FIXME: This needs to be in a header
+char *getlogin() {
+ return getenv("USER");
+}
+
+
+/*