int main(int argc, char *argv[]) { int ch, daemon = 0, s; struct passwd *pw; struct sockaddr_in sin; pid_t pid; while ((ch = getopt(argc, argv, "c:df:hp:u:")) != -1) { switch (ch) { case 'c': chrootdir = optarg; break; case 'd': daemon = 1; break; case 'f': filesdir = optarg; break; case 'p': port = atoi(optarg); break; case 'u': user = optarg; break; case '?': case 'h': usage(); break; } } if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) err(1, "socket"); memset(&sin, 0, sizeof(sin)); sin.sin_addr.s_addr = INADDR_ANY; sin.sin_family = AF_INET; sin.sin_port = htons(port); if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) err(1, "bind"); if (listen(s, 5) < 0) err(1, "listen"); if ((pw = getpwnam(user)) == NULL) err(1, "getpwnam"); if (chroot(chrootdir) < 0) err(1, "chroot"); if (chdir("/") < 0) err(1, "chdir"); if(setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) err(1, "can't drop privileges"); endpwent(); if (daemon) { switch (pid = fork()) { case -1: err(1, "cannot fork"); case 0: break; default: printf("pid: %d\n", pid); exit(0); } } for (;;) { int c; ssize_t n; char buf[1024]; struct sockaddr_in cin; socklen_t len = sizeof(cin); if ((c = accept(s, (struct sockaddr *)&cin, &len)) < 0) err(1, "accept"); pid = fork(); if (pid < 0) err(1, "fork"); if (pid = 0) continue; while ((n = recv(c, buf, sizeof(buf), 0)) > 0) { if (n > 0) buf[n-1] = '\0'; handlecommand(c, buf); memset(buf, 0, sizeof(buf)); } //return; } }
static void idle(struct net_device *dev) { unsigned long flags; int state; /* FIXME This is initialized to shut the warning up, but I need to * think this through again. */ struct xmitQel *q = NULL; int oops; int i; int base = dev->base_addr; spin_lock_irqsave(&txqueue_lock, flags); if(QInIdle) { spin_unlock_irqrestore(&txqueue_lock, flags); return; } QInIdle = 1; spin_unlock_irqrestore(&txqueue_lock, flags); /* this tri-states the IRQ line */ (void) inb_p(base+6); oops = 100; loop: if (0>oops--) { printk("idle: looped too many times\n"); goto done; } state = inb_p(base+6); if (state != inb_p(base+6)) goto loop; switch(state) { case 0xfc: /* incoming command */ if (debug & DEBUG_LOWER) printk("idle: fc\n"); handlefc(dev); break; case 0xfd: /* incoming data */ if(debug & DEBUG_LOWER) printk("idle: fd\n"); handlefd(dev); break; case 0xf9: /* result ready */ if (debug & DEBUG_LOWER) printk("idle: f9\n"); if(!mboxinuse[0]) { mboxinuse[0] = 1; qels[0].cbuf = rescbuf; qels[0].cbuflen = 2; qels[0].dbuf = resdbuf; qels[0].dbuflen = 2; qels[0].QWrite = 0; qels[0].mailbox = 0; enQ(&qels[0]); } inb_p(dev->base_addr+1); inb_p(dev->base_addr+0); if( wait_timeout(dev,0xf9) ) printk("timed out idle f9\n"); break; case 0xf8: /* ?? */ if (xmQhd) { inb_p(dev->base_addr+1); inb_p(dev->base_addr+0); if(wait_timeout(dev,0xf8) ) printk("timed out idle f8\n"); } else { goto done; } break; case 0xfa: /* waiting for command */ if(debug & DEBUG_LOWER) printk("idle: fa\n"); if (xmQhd) { q=deQ(); memcpy(ltdmacbuf,q->cbuf,q->cbuflen); ltdmacbuf[1] = q->mailbox; if (debug>1) { int n; printk("ltpc: sent command "); n = q->cbuflen; if (n>100) n=100; for(i=0;i<n;i++) printk("%02x ",ltdmacbuf[i]); printk("\n"); } handlecommand(dev); if(0xfa==inb_p(base+6)) { /* we timed out, so return */ goto done; } } else { /* we don't seem to have a command */ if (!mboxinuse[0]) { mboxinuse[0] = 1; qels[0].cbuf = rescbuf; qels[0].cbuflen = 2; qels[0].dbuf = resdbuf; qels[0].dbuflen = 2; qels[0].QWrite = 0; qels[0].mailbox = 0; enQ(&qels[0]); } else { printk("trouble: response command already queued\n"); goto done; } } break; case 0Xfb: /* data transfer ready */ if(debug & DEBUG_LOWER) printk("idle: fb\n"); if(q->QWrite) { memcpy(ltdmabuf,q->dbuf,q->dbuflen); handlewrite(dev); } else { handleread(dev); /* non-zero mailbox numbers are for commmands, 0 is for GETRESULT requests */ if(q->mailbox) { memcpy(q->dbuf,ltdmabuf,q->dbuflen); } else { /* this was a result */ mailbox[ 0x0f & ltdmabuf[0] ] = ltdmabuf[1]; mboxinuse[0]=0; } } break; } goto loop; done: QInIdle=0; /* now set the interrupts back as appropriate */ /* the first read takes it out of tri-state (but still high) */ /* the second resets it */ /* note that after this point, any read of base+6 will trigger an interrupt */ if (dev->irq) { inb_p(base+7); inb_p(base+7); } return; }