From ucbvax!baden Mon Oct 17 19:59:08 1983 From: baden@ucbvax.UUCP Subject: Berkeley FP Bug on 4.2 Date: Mon, 17 Oct 83 19:59:08 EDT Status: O Berkeley FP is an implementation of the functional language, FP, due to John Backus. It was written in Franz Lisp. Owing to a change in the UNIX system calling convention, Berkley FP will *not* work under 4.2 -- core is dumped if any function applications are attempted (FP *will*, however, run under 4.1 and 4.1c). The two system calls, '(syscall 13),' in the file /usr/src/ucb/fp/fpMain.l, *must* be changed to '(sys:time)'. Scott B. Baden U. C. Berkeley (ucbvax!baden, baden@berkeley.kim) From cbosgd!qusavx!mddc!chris Mon Oct 24 21:42:46 1983 From: chris@mddc.UUCP Subject: Trying 4.2bsd and ra80s Date: Mon, 24 Oct 83 21:42:46 EDT Status: RO I've sent the follow message to ucbvax!4bsd-bugs but thought maybe there could be someone else out there who might know also. Was this a problem with 4.1 ra80s also? --- I am trying to bring up 4.2bsd on a 11/750 with ra80 & tu80. (I have brouht up 4.1 on several machinces but never on a ra80) Things are looking pretty good. I have noticed that the "disktab" tables are set up to use 242606 logical blocks(~121Mb), but the ra80 manual says there are only 236941 logical blocks. This first showed up when trying to do the "newfs ra0h ra80" command so "/usr" can be put there as suggested in the installation guide. The error is: write error 111201 I tried just using ra0g for /usr and this works ok. I also changed "disktab" as listed below and was then able the "newfs ra0h". pc#236941 and ph#105560 236961 - 131404 ------ 105560 What happen to the other 3Mbs? Is this the best way to fix the problem? Thanks, Chris Maloney Management Decisions Development Corp. Fairfield, Ohio 45014 (513)874-6464 ...{ucbvax,decvax,inhp4,mhuxi}!cbosgd!qusavx!mddc!chris (uucp) From philabs!mcvax!guido Mon Oct 24 10:52:07 1983 From: guido@mcvax.UUCP (Guido van Rossum) Subject: Error in 4.2 BSD Bourne shell quoting Date: Mon, 24 Oct 83 10:52:07 EDT Status: RO The following shell script doesn't work with the 4.2 BSD Bourne shell (sh): BIN=/bin : ${ECHO="$BIN/echo"} $ECHO $ECHO It replies with sh: /bin/echo: not found. The direct reason is that the variable ECHO has all the high order bits set (this was verified by exporting it and checking the environment from a C program). Probably the shell forgets to remove these bits (that it internally uses to remember quoted characters). Note that the following three alternatives for the second line all work: : ${ECHO="/bin/echo"} : ${ECHO=$BIN/echo} ECHO="$BIN/echo" The V7 shell on our PDP doesn't have the error. -- Guido van Rossum, {philabs,decvax}!mcvax!guido Centre for Mathematics and Computer Science, (CWI, formerly MC), Amsterdam From philabs!mcvax!jim Wed Oct 26 18:22:06 1983 From: jim@mcvax.UUCP (Jim McKie) Subject: 4.2BSD mail bug Date: Wed, 26 Oct 83 18:22:06 EDT Status: RO Well, I thought it was a bit quiet. Then I discovered that all mail destined from the outside world to someone on my machine was silently being thrown away by /bin/mail! Between the pre-release of 4.2BSD and the final release, a security hole in /bin/mail was closed, a check was put in such that only the users "root", "daemon" and "network" were allowed to use the "-r name" option, which specifies that the name of the person who sent this mail is "name", and not what you can get out of /etc/passwd using the result of getuid(). This is used by /usr/lib/sendmail to give you sensible names as the originator of remote mail. Unfortunately, the sendmail documentation is misleading, implying that it will do a setuid() to the default uid (usually daemon) before exec'ing any mailer, such as /bin/mail to do local delivery. This is not so, the setuid() will only be done if the real uid of sendmail is "root", i.e. it is running as a daemon, not when it is running as the result of being called by "rmail", when the real uid is probably that of "uucp". So /bin/mail says "sorry, no permission", but still gives 0 exit status, and sendmail logs the mail away as being successfully delivered. The fix is to either remove the tests on "root", "daemon" and "network", leaving the security hole, or to add "uucp" to the list. This latter may not always work, however, if you have people calling you up whose uid in the password file is not the same as the user "uucp". There may be other solutions. Jim McKie Mathematisch Centrum, Amsterdam ..{decvax!philabs}!mcvax!jim From sequel!phil Mon Oct 31 11:54:09 1983 From: phil@sequel.UUCP Subject: 4.2 BSD bugs in tip Date: Mon, 31 Oct 83 11:54:09 EST Status: RO 4.2 BSD tip program has bugs in how it supports ventel modems. The version of tip with 4.1c assumed the modem was set to "echo" while the 4.2 release assumes "no echo". In addition, the code that checks for legal phone numbers would not allow you to use either an '&' or '%' which are needed for the ventel. I have included my diffs to tip/acu.c and tip/aculib/ventel.c that make it work with the ventel (with echo on) and allow '&' and '%' in phone numbers. Also I rearranged the code somewhat to make dialing faster (and used <..> mode). Cheers.. % diff old.acu.c acu.c 66c66 < for (phnum = cp; any(*cp, "0123456789-*=K"); cp++) --- > for (phnum = cp; any(*cp, "0123456789-*=K&%"); cp++) 101c101 < for (phnum = cp; any(*cp, "0123456789-*="); cp++) --- > for (phnum = cp; any(*cp, "0123456789-*=&%"); cp++) % diff old.ventel.c ventel.c 7c7 < * The Ventel is expected to be strapped for "no echo". --- > * The Ventel is expected to be strapped for "echo". 16a17,25 > #define uucpdelay(num,denom) busyloop(CPUSPEED*num/denom) > #define CPUSPEED 1000000 /* VAX 780 is 1MIPS */ > #define DELAY(n) { register long N = (n); while (--N > 0); } > > busyloop(n) > { > DELAY(n); > } > 40,45c49,53 < echo("#k$\r$\n$D$I$A$L$:$ "); < for (cp = num; *cp; cp++) { < sleep(1); < write(FD, cp, 1); < } < echo("\r$\n"); --- > write(FD, " write(FD, num, strlen(num)); > write(FD, ">", 1); > if (gobble('\n') && gobble('\n') && gobble('\007')) > echo("\r$\n"); 125,128d132 < #ifdef notdef < if (boolean(value(VERBOSE))) < putchar(c); < #endif 146,156d149 < /* < * Toggle DTR to force anyone off that might have left < * the modem connected, and insure a consistent state < * to start from. < * < * If you don't have the ioctl calls to diddle directly < * with DTR, you can always try setting the baud rate to 0. < */ < ioctl(FD, TIOCCDTR, 0); < sleep(2); < ioctl(FD, TIOCSDTR, 0); 164c157 < sleep(1); --- > uucpdelay(1,10); /* sleep .1 sec */ 166c159,161 < sleep(3); --- > uucpdelay(1,10); /* sleep .1 sec */ > ioctl(fd, TIOCFLUSH, (struct sgttyb *)0); > uucpdelay(1,10); /* sleep .1 sec */ 177a173,184 > /* > * Toggle DTR to force anyone off that might have left > * the modem connected, and insure a consistent state. > * > * If you don't have the ioctl calls to diddle directly > * with DTR, you can always try setting the baud rate to 0. > */ > if (already == 0) { > ioctl(FD, TIOCCDTR, 0); > sleep(2); > ioctl(FD, TIOCSDTR, 0); > } -- Phil Hochstetler (503) 627-9811 Sequent Computer Systems ...!sequent!phil From RWS@mit-xx.ARPA Wed Nov 2 18:10:47 1983 Date: 2 Nov 1983 1715-EST From: RWS@mit-xx Subject: sundry 4.2 bugs To: unix-wizards%brl-vgr@multics Status: RO Despite claims to the contrary, the block number sign extension problem still exists. Berkeley put in a fix that should have worked, but a C compiler bug apparently keeps it from working. In /sys/sys/vm_mem.c in memall() the code swapdev : mount[c->c_mdev].m_dev, (daddr_t)(u_long)c->c_blkno should be changed to swapdev : mount[c->c_mdev].m_dev, c->c_blkno and in /sys/vax/vm_machdep.c in chgprot() the code munhash(mount[c->c_mdev].m_dev, (daddr_t)(u_long)c->c_blkno); should be changed to munhash(mount[c->c_mdev].m_dev, c->c_blkno); because the C compiler apparently incorrectly folds the (daddr_t) and (u_long) together and sign extends anyway. Simply taking out the (daddr_t)(u_long) works, although lint will probably complain about it. There is a magic number (0x3ffff8) representing USRSTACK/NBPG built in to Fastreclaim in /sys/vax/locore.s. However, USRSTACK depends on UPAGES, so this magic number has UPAGES=8 built in, which is bogus. If you change UPAGES, your system will panic: trap. The fix is to change subl3 P_SSIZE(r5),$0x3ffff8,r0 to subl3 P_SSIZE(r5),$(0x400000-UPAGES),r0 and to change subl2 $(0x3ffff8+UPAGES),r4 to subl2 $0x400000,r4 UDP checksumming is turned off, and with good cause, since bad checksums are produced on output. In /sys/netinet/udp_usrreq.c in udp_output(), the code ui->ui_ulen = htons((u_short)ui->ui_len); should be changed to ui->ui_len = htons((u_short)ui->ui_len); ui->ui_ulen = ui->ui_len; Then int udpcksum; can be changed to int udpcksum = 1; In /sys/netinet/tcp_input.c in tcp_intput(), the code sbdrop(&so->so_snd, so->so_snd.sb_cc); tp->snd_wnd -= so->so_snd.sb_cc; should be tp->snd_wnd -= so->so_snd.sb_cc; sbdrop(&so->so_snd, so->so_snd.sb_cc); In /sys/netinet/tcp_output.c in tcp_output() the code if (SEQ_GT(tp->snd_nxt, tp->snd_max)) tp->snd_max = tp->snd_nxt; if (SEQ_GT(tp->snd_nxt, tp->snd_max) && tp->t_rtt == 0) { tp->t_rtt = 1; tp->t_rtseq = tp->snd_nxt - len; } should be if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { tp->snd_max = tp->snd_nxt; if (tp->t_rtt == 0) { tp->t_rtt = 1; tp->t_rtseq = tp->snd_nxt - len; } } ------- From allegra!jdd Mon Nov 7 16:06:33 1983 From: jdd@allegra.UUCP Subject: Telnetd(8) problems in 4.2 Date: Mon, 7 Nov 83 16:06:33 EST Status: RO There are several bugs in telnetd(8) in 4.2BSD. First, it loses characters from the remote side. There's a place in telnet() where it reads bytes from the pty and stores them in netobuf[] (via *nfrontp++), to be written by a netflush(). If it can't fit them all at once (perhaps because a previous netflush() couldn't empty netobuf[]), it throws the rest away. As a result, if the network doesn't run quite as fast as you'd expected, you lose characters. (We're running on a network with a small IP packet size, so this happens frequently.) At least this is better than all of the sprintf's into netobuf[] (via nfrontp) that don't even check whether there is space remaining or not. By the mechanism above, these have a very good chance at overrunning the end of the array. Oh, and there are variables, like "pcc" and "options", that are referenced before they are used. This is at best poor coding style. I have also noticed that when telnetd(8) logs me in, it does it in such a way as not to mention me in /etc/utmp or /usr/adm/wtmp. More on this later. Cheers, John ("Barely Here") DeTreville Bell Labs, Murray Hill From allegra!jdd Mon Nov 7 18:30:58 1983 From: jdd@allegra.UUCP Subject: Problems With Ifconfig(8) in 4.2BSD Date: Mon, 7 Nov 83 18:30:58 EST Status: RO The ifconfig(8) program, used to configure network devices in 4.2BSD, has a couple of cute features relating to ARP. First, the meanings of the "arp" and "-arp" flags are reversed in the program from their definitions in the manual page. Specifying "arp" turns ARP off; specifying "-arp" turns it on. Second, when ifconfig(8) reports the configuration, it does not interpret the IFF_NOARP bit, so it doesn't tell you whether or not ARP is on. The user must know that 0x80 means IFF_NOARP. Cheers, John ("I Hate ARP") DeTreville Bell Labs, Murray Hill From RWS@mit-xx.ARPA Mon Nov 7 22:48:19 1983 Date: Mon 7 Nov 83 21:15:32-EST From: Robert W. Scheifler Subject: 4.2 UDP To: unix-wizards@BRL-VGR.ARPA Status: RO My earlier UDP bug fixes were not completely wonderful. Here is my final rewrite. In /sys/netinet/udp_usrreq.c in udp_output(), the code ui->ui_ulen = htons((u_short)ui->ui_len); should be changed to ui->ui_len = htons((u_short)ui->ui_len); ui->ui_ulen = ui->ui_len; and the code ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len) should be changed to if (udpcksum) { if (!(ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len))) ui->ui_sum = -1; } In udp_input(), the code if (udpcksum) { ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_len = htons((u_short)len); if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) { udpstat.udps_badsum++; m_freem(m); return; } } should be changed to if (udpcksum && ui->ui_sum) { ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_len = htons((u_short)len); if (in_cksum(m, len + sizeof (struct ip))) { udpstat.udps_badsum++; m_freem(m); return; } } Then int udpcksum; can be changed to int udpcksum = 1; ------- From sequent!phil Sun Nov 6 19:26:38 1983 From: phil@sequent.UUCP Subject: 4.2 BSD bug (/usr/dict/words -> /usr/lib/w2006) Date: Sun, 6 Nov 83 19:26:38 EST Status: RO Here is an interesting bug in the 4.2 BSD distribution. % diff /usr/dict/words /usr/lib/w2006 4955c4955 < consanguine --- > consanguiNe 4970,4971c4970,4971 < conservatism < conservative --- > conservadmsm > conser6ative 6389c6389 < diamagnetism --- > diamegnetism 8208d8207 < famish You will notice that some words are trashed in /usr/lib/w2006 and famish is deleted. I don't understand why the two aren't just links. Does anything reference /usr/lib/w2006? -- Phil Hochstetler (503) 627-9811 Sequent Computer Systems ...!sequent!phil From utah-cs!lepreau Wed Nov 16 01:51:22 1983 From: lepreau@utah-cs.UUCP (Jay Lepreau) Subject: Fix RCHECKing in malloc.c and other debug cleanup Date: Wed, 16 Nov 83 01:51:22 EST Status: RO Index: lib/libc/gen/malloc.c 4.2BSD Fix Description: 1. When RCHECK is defined, realloc needs to move the trailing RMAGIC and adjust the recorded ov_size when it uses the same block. Otherwise got false assertion failures. Spencer Thomas found this one. 2. botch() printout needs cleaning up: it used to print to stdout and w/o an fflush (so never saw it), and it needs to bracket the msg with \r\n's cause terminal state may be funny. 3. If one defined RCHECK but not debug you didn't get any checking. 4. minor lint in morecore(). (5. There seems to be some redundant code in morecore(), i.e. "can't happen" stuff, but why mess with working code?) Repeat-By: Inspection (these arose in Gosling's emacs for us). Fix: The new one is monet:~lepreau/malloc.c. Here's the diff too. *** /tmp/,RCSt1006961 Wed Nov 9 21:45:03 1983 --- malloc.c Wed Nov 9 21:43:41 1983 *************** *** 2,3 static char sccsid[] = "@(#)malloc.c 4.3 (Berkeley) 9/16/83"; #endif --- 2,5 ----- static char sccsid[] = "@(#)malloc.c 4.3 (Berkeley) 9/16/83"; + static char RCSid[] = + "$Header: malloc.c,v 1.3 83/11/09 21:42:24 lepreau Exp $"; #endif *************** *** 71,73 ! #ifdef debug #define ASSERT(p) if (!(p)) botch("p"); else --- 73,75 ----- ! #if defined(debug) || defined(RCHECK) #define ASSERT(p) if (!(p)) botch("p"); else *************** *** 73,74 #define ASSERT(p) if (!(p)) botch("p"); else static --- 75,77 ----- #define ASSERT(p) if (!(p)) botch("p"); else + #include static *************** *** 78,80 ! printf("assertion botched: %s\n", s); abort(); --- 81,84 ----- ! fprintf(stderr, "\r\nassertion botched: %s\r\n", s); ! (void) fflush(stderr); /* just in case user buffered it */ abort(); *************** *** 153,156 op = (union overhead *)sbrk(0); ! if ((int)op & 0x3ff) ! sbrk(1024 - ((int)op & 0x3ff)); /* take 2k unless the block is bigger than that */ --- 157,160 ----- op = (union overhead *)sbrk(0); ! if ((int)op & 0x3ff) /* if this sbrk fails next will too */ ! (void) sbrk(1024 - ((int)op & 0x3ff)); /* take 2k unless the block is bigger than that */ *************** *** 262,264 if (was_alloced && ! nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP) return(cp); --- 266,273 ----- if (was_alloced && ! nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP) { ! #ifdef RCHECK ! if (nbytes <= 0x10000) ! op->ov_size = nbytes - 1; ! *((u_int *)((caddr_t)op + nbytes - RSLOP)) = RMAGIC; ! #endif return(cp); *************** *** 264,265 return(cp); if ((res = malloc(nbytes)) == NULL) --- 273,275 ----- return(cp); + } if ((res = malloc(nbytes)) == NULL) *************** *** 268,269 bcopy(cp, res, (nbytes < onb) ? nbytes : onb); if (was_alloced) --- 278,286 ----- bcopy(cp, res, (nbytes < onb) ? nbytes : onb); + #ifdef RCHECK + else { + if (nbytes <= 0x10000) + op->ov_size = nbytes - 1; + *((u_int *)((caddr_t)op + nbytes - RSLOP)) = RMAGIC; + } + #endif if (was_alloced) From rws@mit-bold.ARPA Tue Nov 15 14:56:35 1983 From: Robert W. Scheifler Subject: wait3() does not always return in 4.2 Date: Tue, 15 Nov 83 14:56:35 EST Status: RO When doing a wait3() with WUNTRACED with a SIGCHLD handler, if the inferior stops due to a SIGTTIN, SIGTTOU, SIGTSTP, or SIGSTOP after the parent is already sleeping at PWAIT, the wait3() never returns. This is a result of the crufty old wait3(). What SHOULD have been done, since a new wait system call was added for 4.2, is that wait3() should have been the standard system call, and wait() should have been made a library routine that did wait3(status, 0, 0). However, the disgusting old 4.1 code that has wait3() setting magic condition codes and placing the extra arguments in registers still persists. The magic condition codes get clobbered when the wait3() system call gets restarted, which happens when the SIGCHLD occurs. In /sys/vax/trap.c, in syscall(), the following is done even for RESTARTSYS: locr0[PS] &= ~PSL_C; Since wait3() is indicated by all the bits being set, the restarted wait3() turns into a wait(), and you never terminate. The fix is to move the offending statement down inside the final else of the following if statement: if (u.u_eosys == RESTARTSYS) pc = opc; #ifdef notdef else if (u.u_eosys == SIMULATERTI) dorti(); #endif else if (u.u_error) { #ifndef lint bad: #endif locr0[R0] = u.u_error; locr0[PS] |= PSL_C; /* carry bit */ } else { locr0[PS] &= ~PSL_C; /* clear carry bit */ locr0[R0] = u.u_r.r_val1; locr0[R1] = u.u_r.r_val2; } From sdcsvax!greg Fri Nov 4 04:01:42 1983 From: greg@sdcsvax.UUCP (Greg Noel) Subject: 4.2BSD make Date: Fri, 4 Nov 83 04:01:42 EST Status: RO A bug has been found in the 4.2 version of make. The symptoms are various kinds of flakeyness in large makefiles or in makefiles that reference a lot of different directories for files. The problem is that after the vfork to execute the command the child would mark the parent's files as closed. If make needed to look in the directory again, it would reopen it. Eventually, make (or a child) would run out of avalilable file descriptors. The cure is to replace subroutine doclose in the file dosys.c with the following code: --------------------------- cut here ------------------------------------ doclose() /* Close open directory files before exec'ing */ { register struct dirhdr *od; /* Original code: for (od = firstod; od; od = od->nxtopendir) if (od->dirfc != NULL) { closedir(od->dirfc); od->dirfc = NULL; } We have done a vfork, so we can't do anything to stomp on our parent's address space. Unfortunately, the code above doesn't work since our parent's files remain open. And we can't just do a closedir, since it will free a dynamicly-allocated table entry. So we use this hack, calling close directly. If the interface ever changes, we are going to be out of luck. */ for (od = firstod; od; od = od->nxtopendir) if (od->dirfc != NULL) close(od->dirfc->dd_fd); } From seismo!harpo!decvax!sdchema!sdcsvax!laman Fri Nov 11 18:08:04 1983 From: laman@sdcsvax.UUCP (Mike Laman) Subject: Curses bug (Both net.sources dist. and 4.2 BSD) Date: Fri, 11 Nov 83 18:08:04 EST Status: RO There is a bug in wdeleteln(). This bug is in the curses library distributed over net.sources, and in the 4.2 BSD distribution (that sdcsvax received at least). Even though the last line of the window gets cleared internally, its "refresh" image may not. The fix is simple. Add the following two lines to the end of the wdeleteln() routine. win->_firstch[win->_maxy-1] = 0; win->_lastch[win->_maxy-1] = win->_maxx - 1; Now wrefresh() will look at the entire line. I have enclosed a little program that will show you if you have the bug. Just compile it with you curses library (termlib too) and run it. #include main() { register i; initscr(); mvaddstr(0, 20, "This program will delete line #5 after"); mvaddstr(1, 20, "writing the line number for each line."); for(i = 0; i < LINES; ++i) mvprintw(i, 0, "Line #%d", i); refresh(); addstr(" You have the bug if the BOTTOM line is not COMPLETELY blank!"); move(5, 0); deleteln(); move(LINES - 3, 0); refresh(); endwin(); } Mike Laman UUCP: {ucbvax,philabs,sdccsu3,sdcsla}!sdcsvax!laman From sdcsvax!laman Sun Nov 13 20:41:53 1983 From: laman@sdcsvax.UUCP (Mike Laman) Subject: Yet another curses bug (net.sources and 4.2 dist.) Date: Sun, 13 Nov 83 20:41:53 EST Status: RO The following bug is in the curses library distributed over net.sources, and in the 4.2 BSD distribution (that sdcsvax received at least). The bug is in makech() (in refresh.c). makech() gets called to give output for the given LINE (hint hint). It is interesting that this bug managed to get out. Here is the offending code (the simple fix follows). : : : else if (wx < lch) while (*nsp == *csp) { nsp++; if (!curwin) csp++; ++wx; } else : : : I wrote a program that added '*' to (0, 0) on stdscr then a refresh(). wx ended up with a value of over 3000! That loop walked down the line and the next, ... (all the way down the window!). The following code is the fix. Notice that the ++wx looks just perfect. It really makes one think "they" thought of it, but merely forgot to add the test. : : : else if (wx < lch) while (*nsp == *csp && wx <= lch) { nsp++; if (!curwin) csp++; ++wx; } else : : : Mike Laman UUCP: {ucbvax,philabs,sdccsu3,sdcsla}!sdcsvax!laman From sdccsu3!madden Mon Nov 7 03:09:21 1983 From: madden@sdccsu3.UUCP (Jim Madden) Subject: 4.2 IPC machine hang Date: Mon, 7 Nov 83 03:09:21 EST Status: RO Attached is a 4.2 bug report just submitted to Berkeley. Subject: 4.2 UNIX domain IPC machine hang Index: sys/uipc_socket.c 4.2BSD Description: Under 4.2 BSD, termination of a program which has invoked a listen on a UNIX domain socket will cause an interminable loop at net interrupt level if there are pending connections which have not yet been accepted. Repeat-By: Run program A below in the background. Run program B twice. Kill program A. The result should be a system hang at net interrupt level. Fix: In soclose of sys/uipc_socket.c, a pair of while loops assume that the procedure soabort will clean up the pending connection data structures in such a way that the while loop will step through all the pending cases. In point of fact, soabort contains no code to do this, so the while loop repeatedly tries to abort the same pending connection. A straight forward solution is to call sofree within the for loops themselves after calling soabort. A context diff of this change follows: *** /tmp/,RCSt1026683 Mon Nov 7 00:02:38 1983 --- uipc_socket.c Sun Nov 6 23:36:28 1983 *************** *** 142,148 int error; if (so->so_options & SO_ACCEPTCONN) { ! while (so->so_q0 != so) (void) soabort(so->so_q0); while (so->so_q != so) (void) soabort(so->so_q); --- 151,157 ----- int error; if (so->so_options & SO_ACCEPTCONN) { ! while (so->so_q0 != so) { (void) soabort(so->so_q0); /* * Somebody has to delink and free pending *************** *** 144,150 if (so->so_options & SO_ACCEPTCONN) { while (so->so_q0 != so) (void) soabort(so->so_q0); ! while (so->so_q != so) (void) soabort(so->so_q); } if (so->so_pcb == 0) --- 153,166 ----- if (so->so_options & SO_ACCEPTCONN) { while (so->so_q0 != so) { (void) soabort(so->so_q0); ! /* ! * Somebody has to delink and free pending ! * connections. This may not be the right place ! * but it works. ! */ ! sofree(so->so_q0); ! } ! while (so->so_q != so) { (void) soabort(so->so_q); sofree(so->so_q); } *************** *** 146,151 (void) soabort(so->so_q0); while (so->so_q != so) (void) soabort(so->so_q); } if (so->so_pcb == 0) goto discard; --- 162,169 ----- } while (so->so_q != so) { (void) soabort(so->so_q); + sofree(so->so_q); + } } if (so->so_pcb == 0) goto discard; Program A: #include #include #include struct sockaddr_un sun; main(argc, argv) char *argv[]; { int s; s = socket(AF_UNIX, SOCK_STREAM, 0); sun.sun_family = AF_UNIX; strcpy(sun.sun_path, "SOCK"); bind(s, &sun, 6); listen(s, 2); sleep(10000); } Progam B: #include #include #include struct sockaddr_un sun; main(argc, argv) char *argv[]; { int s; s = socket(AF_UNIX, SOCK_STREAM, 0); sun.sun_family = AF_UNIX; strcpy(sun.sun_path, "SOCK"); connect(s, &sun, 6); } Jim Madden sdcsvax!madden From sdccs6!ix900 Sat Nov 12 19:43:35 1983 From: ix900@sdccs6.UUCP (ix900) Subject: Bug in 4.2 -me macros Date: Sat, 12 Nov 83 19:43:35 EST Status: RO There's a minor bug in the -me macro package on 4.2bsd. (This is version 2.14 of the -me macros.) One of the features of -me is the use of an "-rx1" flag in nroff in order to set the line spacing to 1/8 inch when using a 12-pitch printout setting. In the macro package, there's a syntax error in the line where the number register "x" is referenced (line 908-909): .if (1m<0.1i)&(\nx!=0) \ . vs 9p The "!" is misplaced and thus messes up the conditional. (Instead of setting the vertical spacing, it sends "!=0 \ . vs 9p" to the standard output.) Change to: .if (1m<0.1i)&(\nx>0) \ . vs 9 David Sewell University of California, San Diego [...!ucbvax!sdcsvax!]!sdccsu3!sdccs6!ix900 From croft%Safe@su-score.ARPA Wed Nov 16 23:08:27 1983 Date: Wed, 16 Nov 83 17:25 PST From: Bill Croft Subject: telnetd 4.2 Fix Status: RO Index: /usr/src/etc/telnetd.c 4.2 Fix Description: Fix various telnet daemon bugs: (1) was dropping bytes when input buffers couldnt be emptied before next select. (2) binary option shouldn't put the controlling pty into RAW mode, this is a function of the slave tty. This was breaking TN from some TOPS-20 sites that default to binary mode for emacs meta key users. (3) some "fatalperror" messages were written to closed file descriptors. Repeat-By: Byte drop problem could be seen by, for example, "od /vmunix", or any program producing continuous sustained output. Fix: Apply the "diff -e" below. + diff telnetd.c_ telnetd.c 198c198 < fatalperror(f, "/bin/login", errno); --- > fatalperror(2, "/bin/login", errno); 208c208 < (void) sprintf(buf, "telnetd: %s.\n", msg); --- > (void) sprintf(buf, "telnetd: %s.\r\n", msg); 259c259 < if (nfrontp - nbackp) --- > if ((nfrontp - nbackp) || pcc > 0) 263c263 < if (pfrontp - pbackp) --- > if ((pfrontp - pbackp) || ncc > 0) 474d473 < mode(RAW, 0); 511d509 < mode(0, RAW); 543d540 < mode(RAW, 0); + diff -e telnetd.c_ telnetd.c 543d 511d 474d 263c if ((pfrontp - pbackp) || ncc > 0) From salkind@nyu.ARPA Thu Nov 17 02:18:37 1983 Date: Thu, 17 Nov 83 00:21:28 est From: Lou Salkind Subject: arff breaks on multiply segmented directories Status: RO Index: etc/arff.c 4.2BSD Description: "arff x" will only extract files in the first segment of a multiply segmented RT-11 filesystem. All the other commands seem to work, though. Repeat-By: Try "arff x" on a floppy with more than one directory segment (such as our VMS boot floppy). Watch it break. Fix: A diff -c follows of the required source changes. Also note the documentation changes at the end. --------------------------------------------------- *** /usr/src/etc/arff.c.dist Sun Jul 10 21:19:16 1983 --- /usr/src/etc/arff.c Mon Nov 14 18:09:20 1983 *************** *** 281,287 return; } for (segnum = 0; segnum != -1; ! segnum = rt_dir[segnum].rt_axhead.rt_nxtseg-1) for (last = rt_last+(segnum*2*RT_BLOCK), de = ((char *)&rt_dir[segnum])+10; de <= last; de += rt_entsiz) --- 281,287 ----- return; } for (segnum = 0; segnum != -1; ! segnum = rt_dir[segnum].rt_axhead.rt_nxtseg-1) { for (last = rt_last+(segnum*2*RT_BLOCK), de = ((char *)&rt_dir[segnum])+10; de <= last; de += rt_entsiz) *************** *** 288,294 switch (rt(de)->rt_stat) { case RT_ESEG: ! return; case RT_TEMP: case RT_FILE: --- 288,294 ----- switch (rt(de)->rt_stat) { case RT_ESEG: ! goto nxtseg; case RT_TEMP: case RT_FILE: *************** *** 298,303 case RT_NULL: break; } } rtx(name) --- 298,306 ----- case RT_NULL: break; } + nxtseg: + ; + } } rtx(name) ---------------------------------------------------- In /usr/man/man8/arff.8v, remove the line about "arff doesn't handle multi-segment directories." Also, flcopy should be changed to do a .so /usr/man/man8/arff.8v From salkind@nyu.ARPA Thu Nov 17 02:18:40 1983 Date: Thu, 17 Nov 83 00:32:33 est From: Lou Salkind Subject: gettable does not use hostname service Status: RO Index: etc/gettable.c 4.2BSD Description: Gettable uses the nicname service instead of the hostname service to get the NIC table. Repeat-By: Type the command. Fix: Replace nicname by hostname. diff -c follows. *** /usr/src/etc/gettable.c.dist Fri Aug 12 01:52:13 1983 --- /usr/src/etc/gettable.c Wed Oct 26 13:22:26 1983 *************** *** 36,42 fprintf(stderr, "usage: gettable host [ file ]\n"); exit(1); } ! sp = getservbyname("nicname", "tcp"); if (sp == NULL) { fprintf(stderr, "gettable: nicname/tcp: unknown service\n"); exit(3); --- 36,42 ----- fprintf(stderr, "usage: gettable host [ file ]\n"); exit(1); } ! sp = getservbyname("hostname", "tcp"); if (sp == NULL) { fprintf(stderr, "gettable: hostname/tcp: unknown service\n"); exit(3); *************** *** 38,44 } sp = getservbyname("nicname", "tcp"); if (sp == NULL) { ! fprintf(stderr, "gettable: nicname/tcp: unknown service\n"); exit(3); } host = *argv; --- 38,44 ----- } sp = getservbyname("hostname", "tcp"); if (sp == NULL) { ! fprintf(stderr, "gettable: hostname/tcp: unknown service\n"); exit(3); } host = *argv; *************** *** 90,96 continue; } if (equaln(buf, "ERR", 3)) { ! fprintf(stderr, "gettable: nicname error: %s", buf); continue; } fprintf(hf, "%s\n", buf); --- 90,96 ----- continue; } if (equaln(buf, "ERR", 3)) { ! fprintf(stderr, "gettable: hostname error: %s", buf); continue; } fprintf(hf, "%s\n", buf); From salkind@nyu.ARPA Thu Nov 17 02:18:43 1983 Date: Thu, 17 Nov 83 00:40:27 est From: Lou Salkind Subject: addbib goes into infinite loop To: unix-wizards@brl-vgr Status: RO Index: usr.bin/refer/addbib.c 4.2BSD Description: addbib asks you to enter an abstract, terminated by a ^D. You terminate with a ^D and the program goes into an infinite loop. Repeat-By: Try it and see (oh, the fun you will have)! Fix: Here is one possible solution. Clear the EOF indicator and check whether there is more input. A simple diff addbib.c.dist addbib.c follows: 170c170,172 < fgets(line, BUFSIZ, stdin); --- > clearerr(stdin); > if (fgets(line, BUFSIZ, stdin) == NULL) > return; From salkind@nyu.ARPA Thu Nov 17 02:19:00 1983 Date: Thu, 17 Nov 83 00:44:57 est From: Lou Salkind To: unix-wizards@brl-vgr Subject: libdbm built incorrectly Status: RO Index: usr.lib/libdbm/Makefile 4.2BSD Description: Makefile not correct, and libdbm.a binary is bad. Fix: Change the makefile as shown below and type make install. *** /usr/src/usr.lib/libdbm/Makefile.dist Sat Aug 20 15:27:45 1983 --- /usr/src/usr.lib/libdbm/Makefile Wed Oct 26 14:01:30 1983 *************** *** 2,10 # CFLAGS=-O ! libdbm.a: dbm.c ! libdbm.a: dbm.h ! ${CC} -o libdbm.a ${CFLAGS} dbm.c install: install -m 644 libdbm.a $(DESTDIR)/usr/lib --- 2,11 ----- # CFLAGS=-O ! libdbm.a: dbm.o ! mv dbm.o libdbm.a ! ! dbm.o: dbm.c dbm.h install: install -m 644 libdbm.a $(DESTDIR)/usr/lib From salkind@nyu.ARPA Thu Nov 17 02:22:16 1983 Date: Thu, 17 Nov 83 00:50:49 est From: Lou Salkind Subject: find fix for 4.2BSD To: unix-wizards@brl-vgr Status: RO Best to change the declaration of Pathname in /usr/src/usr.bin/find.c from char Pathname[200]; to char Pathname[1024]; From salkind@nyu.ARPA Thu Nov 17 03:10:18 1983 Date: Thu, 17 Nov 83 01:01:16 est From: Lou Salkind Subject: tip bug fixes, 4.2BSD To: unix-wizards@brl-vgr Status: RO Following are two bug fixes for tip. The change in hunt.c corrects a problem with tip just hanging if the line can't be opened for some reason. The change in log.c fixes a problem with #ifdef's placed incorrectly - you will get compile errors if you don't define ACULOG. By the way, has anybody else noticed that the Vadic 831 support is completely off the wall? For example, tip and uucp don't even use the same dial sequences! I have fixed tip and uucp to talk to our 831 correctly. Since I am not sure all VADIC 831 unit's work this way, I will not include the changes here. If anyone is interested let me know. --- *** hunt.c.dist Sat Jun 25 04:19:10 1983 --- hunt.c Sat Nov 5 23:46:24 1983 *************** *** 45,50 FD = open(cp, O_RDWR); } alarm(0); if (!deadfl) { ioctl(FD, TIOCEXCL, 0); ioctl(FD, TIOCHPCL, 0); --- 45,54 ----- FD = open(cp, O_RDWR); } alarm(0); + if (FD < 0) { + perror(cp); + deadfl = 1; + } if (!deadfl) { ioctl(FD, TIOCEXCL, 0); ioctl(FD, TIOCHPCL, 0); *** log.c.dist Sat Jun 25 05:08:57 1983 --- log.c Sat Nov 5 23:52:01 1983 *************** *** 4,9 #include "tip.h" static FILE *flog = NULL; /* --- 4,11 ----- #include "tip.h" + #ifdef ACULOG + static FILE *flog = NULL; /* *************** *** 45,52 loginit() { - - #ifdef ACULOG flog = fopen(value(LOG), "a"); if (flog == NULL) fprintf(stderr, "can't open log file\r\n"); --- 47,52 ----- loginit() { flog = fopen(value(LOG), "a"); if (flog == NULL) fprintf(stderr, "can't open log file %s\r\n", value(LOG)); *************** *** 49,54 #ifdef ACULOG flog = fopen(value(LOG), "a"); if (flog == NULL) ! fprintf(stderr, "can't open log file\r\n"); ! #endif } --- 49,54 ----- { flog = fopen(value(LOG), "a"); if (flog == NULL) ! fprintf(stderr, "can't open log file %s\r\n", value(LOG)); } #endif *************** *** 52,54 fprintf(stderr, "can't open log file\r\n"); #endif } --- 51,54 ----- if (flog == NULL) fprintf(stderr, "can't open log file %s\r\n", value(LOG)); } + #endif From seismo!harpo!utah-cs!lepreau Fri Nov 18 12:09:08 1983 From: lepreau@utah-cs.UUCP (Jay Lepreau) Subject: Fix for tset getting type from environment Date: Fri, 18 Nov 83 12:09:08 EST Status: O Index: ucb/tset/tset.c 4.2BSD Fix Description: rlogin nicely propogates the terminal type in the environment, but tset doesn't use it if mapping is specified. Such mapping if often necessary because users sometimes log in via telnet and not rlogin, for various reasons (such as they're coming from a non-Unix host.) Repeat-By: rlogin to another host and have your .login on that host contain a tset something like: set noglob; eval `tset -Q -s -m -m network:?t10`; set glob It will query you even tho it knows better. Fix: Fix by using any existing type from environment as starting point even if mapping is specified. (Dunno why that test on "Mapping" was there. Looks like a logic bug to me.) This fix applies to 4.1x tset also. *************** *** 850,852 /* get current idea of terminal type from environment */ ! if (!Dash_h && !Mapped && TtyType == 0) TtyType = getenv("TERM"); --- 850,852 ----- /* get current idea of terminal type from environment */ ! if (!Dash_h && TtyType == 0) TtyType = getenv("TERM"); From rws@mit-bold.ARPA Fri Nov 18 18:45:29 1983 Date: Fri, 18 Nov 83 17:07:07 est From: Robert W. Scheifler Subject: :r in adb drops arg chars in 4.2 Index: /usr/src/bin/adb/runpcs.c 4.2BSD Status: O Description: When using adb, :r foo bar foobar bletch ends up passing "foo ar oobar letch" as arguments. Repeat-By: adb /bin/echo :r foo bar bletch Fix: In runpcs.c, in doexec(), change the loop REP IF rdc()==EOR THEN break; FI ... WHILE lastc==SP ORF lastc==TB DO readchar(); OD PER lastc!=EOR DONE to be readchar(); LOOP WHILE lastc==SP ORF lastc==TB DO readchar(); OD IF lastc==EOR THEN break; FI ... POOL From decvax!dartvax!steve Sun Nov 20 15:29:47 1983 From: steve@dartvax.UUCP (Steve Campbell) Subject: Soft carrier bug in 4.?BSD dh/dm driver Date: Sun, 20 Nov 83 15:29:47 EST Status: O We recently reshuffled the ports on our VAX 750, moving our DEC DF03 dialer from a dz port to an ABLE dh/dm port. The dialer refused to work there, even with the soft carrier config flag set. The trusty breakout box showed that the dh/dm port was not raising DTR, so though the DF03 would dial, it would not go into data mode when the callee answered. The problem turns out to be in the dmopen routine in the (4.[12]BSD) dh/dm driver, dh.c. The routine tests the soft carrier flag and exits before turning on the port, so the open completes, but the control signals aren't up. The fix is just to move the test down near the normal end of dmopen. Here's the "diff new old" of the 4.1BSD version. The 4.2 code is the same except for some name changes. 687,688c687,689 < if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0) { < tp->t_state |= CARR_ON; /* This may be unnecessary, but... */ --- > if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0 || > (dhsoftCAR[dm]&(1< tp->t_state |= CARR_ON; 698c699 < if (addr->dmlstat&DML_CAR || (dhsoftCAR[dm]&(1< if (addr->dmlstat&DML_CAR) steve campbell ...decvax!dartvax!steve From seismo!romine Tue Nov 22 09:21:48 1983 Date: 22 Nov 83 08:03:33 EST (Tue) From: seismo!romine (Raleigh Romine) Subject: 4.2 fixes Status: O November 4, 1983 To all current 4.2BSD sites: A problem was recently discovered in the mail program (/bin/mail) on the 4.2BSD distribution. As this bug caused mail to be silently lost at some sites, it was felt that the 4.2BSD tape master should be updated, and the sites that have already received 4.2 should receive this notification of the problem and its fix. While updating the master, several other bug fixes were installed, and the most significant of those are also listed here. This notice should be forwarded to the appropriate system programmers or managers that are maintaining your 4.2BSD systems. If there are any questions or problems relating to these changes, they may be reported by using the sendbug program to mail them to 4bsd-bugs@berkeley or 4bsd-help@berkeley (or ucbvax!4bsd-bugs, ucbvax!4bsd-help from uucp). If necessary, you can call us at (415) 642-7780. Mike Karels Computer Systems Research Group CHANGES: The diff listings that follow are all in a common format. They start with the name of the file affected, followed by output from a diff command with the old version as first argument and the new version as second argument (i.e., the old version is marked < and the new version is marked >). Each change is preceeded by a short description of the problem. OK ----- /usr/src/bin/mail.c ----- The following change to mail.c is the most important change, and should definitely be installed at all sites. The previous problem was that mail would sometimes drop mail from uucp, or if sendmail was not setuid root, would drop much local mail. 2c2 < static char sccsid[] = "@(#)mail.c 4.18 (Berkeley) 9/9/83"; --- > static char sccsid[] = "@(#)mail.c 4.21 (Berkeley) 11/1/83"; 449,454d448 < if (strcmp(my_name, "root") && < strcmp(my_name, "daemon") && < strcmp(my_name, "network")) { < usage(); < done(); < } 609a604 > error = EX_USAGE; OK ----- /usr/src/etc/gettable.c ----- Gettable was using the wrong service name, causing it to fail. This change is important for hosts on the arpanet. 0a1 > 2c3 < static char sccsid[] = "@(#)gettable.c 4.2 (Berkeley) 8/11/83"; --- > static char sccsid[] = "@(#)gettable.c 4.3 (Berkeley) 10/5/83"; 39c40 < sp = getservbyname("nicname", "tcp"); --- > sp = getservbyname("hostnames", "tcp"); 41c42 < fprintf(stderr, "gettable: nicname/tcp: unknown service\n"); --- > fprintf(stderr, "gettable: hostnames/tcp: unknown service\n"); 93c94 < fprintf(stderr, "gettable: nicname error: %s", buf); --- > fprintf(stderr, "gettable: hostnames error: %s", buf); OK ----- /usr/src/etc/ifconfig.c ----- Ifconfig had the sense of the "-arp" and "arp" arguments backwards, and did not handle multiple requests correctly. 2c2 < static char sccsid[] = "@(#)ifconfig.c 4.3 (Berkeley) 9/16/83"; --- > static char sccsid[] = "@(#)ifconfig.c 4.5 (Berkeley) 11/2/83"; 34,35c34,37 < { "arp", IFF_NOARP, setifflags }, < { "-arp", -IFF_NOARP, setifflags }, --- > { "arp", -IFF_NOARP, setifflags }, > { "-arp", IFF_NOARP, setifflags }, > { "debug", IFF_DEBUG, setifflags }, > { "-debug", -IFF_DEBUG, setifflags }, 106c108 < ifr.ifr_flags = (flags &~ value); --- > flags &= ~value; 108c110,111 < ifr.ifr_flags |= value; --- > flags |= value; > ifr.ifr_flags = flags; 124c127 < "\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING" --- > "\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP" DONE+INS ----- /etc/disktab ----- The sizes for the RA80 disk in /etc/disktab were too large, causing write errors when running newfs. The following numbers are reduced to reflect the portion of the portion of the disk reserved by the controller. 186c186 < :pb#33440:pc#242606:\ --- > :pb#33440:pc#236964:\ 188c188 < :ph#111202:bh#4096:fh#1024: --- > :ph#105560:bh#4096:fh#1024: DONE ----- /sys/vaxuba/rk.c ----- An error in the rk07 driver caused bad-sector forwarding on the last block of a transfer to loop. 1c1 < /* rk.c 6.1 83/07/29 */ --- > /* rk.c 6.2 83/10/11 */ 626,627c626 < if (rk->rkwc == 0) { < um->um_tab.b_active = 0; --- > if (rk->rkwc == 0) 629d627 < } DONE ----- /sys/netinet/ip_output.c ----- Ip_output was not handling routes to hosts correctly. 1c1 < /* ip_output.c 6.1 83/07/29 */ --- > /* ip_output.c 6.2 83/10/22 */ 75c75 < if (ro->ro_rt->rt_flags & RTF_GATEWAY) --- > if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) DONE ----- /sys/net/route.c ----- There was a signed modulus operation done in route.c that should be unsigned: 1c1 < /* route.c 6.1 83/07/29 */ --- > /* route.c 6.2 83/10/20 */ 28c28 < register unsigned hash; --- > register u_long hash; 189c189 < int s, error = 0, hash, (*match)(); --- > int s, error = 0, (*match)(); 190a191 > u_long hash; DONE ----- /sys/vax/tu.c ----- A typo in tu.c caused crashes after I/O errors on the TU58 cassette. 1c1 < /* %M 6.1 83/07/29 */ --- > /* %M 6.2 83/10/12 */ 722c722 < timeout(tustart(), (caddr_t)0, hz * 3); --- > timeout(tustart, (caddr_t)0, hz * 3); DONE (to fmw) ----- /usr/ingres/source/ovqp/tidtest.c ----- This file was missing. It can be sent upon request, or obtained from the anonymous ftp account on ucb-arpa, or the uucppublic directory of ucbvax. DONE+INS ----- /usr/src/usr.bin/uucp/cico.c ----- Improper signal handling sometimes uucico to loop after errors. 2c2 < static char sccsid[] = "@(#)cico.c 5.2 (Berkeley) 7/19/83"; --- > static char sccsid[] = "@(#)cico.c 5.3 (Berkeley) 10/3/83"; 492a493,496 > #ifdef SIGIO > /* if using 4.2 signal mechanism, must unblock all signal handlers */ > sigsetmask(0); > #endif DONE+INS ----- /usr/src/etc/htable ----- The htable program has been much modified to handle gateways that are not directly reachable, and to allow the localgateways entries to override the default entries. As the differences are too long to list, the modified files will be available in a tar archive on ucb-arpa, in the file ~ftp/pub/htable.tar. It may be retrieved using ftp to the anonymous account on ucb-arpa. From rws@mit-bold.ARPA Tue Nov 22 12:51:15 1983 Date: Mon, 21 Nov 83 21:32:58 est From: Robert W. Scheifler Subject: mh prompter doesn't prompt Index: /usr/src/new/mh/cmds/prompter.c 4.2BSD Status: O Description: prompter doesn't prompt for To:, Cc:, Subject:. Repeat-By: Make prompter your editor and run comp. It will start reading in the body of the message. Fix: In main(), change if(field[0] != '\n' || field[1] != 0) { to i = 0; while ((field[i] == ' ') || (field[i] == '\t')) i++; if(field[i] != '\n' || field[i+1] != 0) { Stripping off leading white space should really be done in m_getfld, so all the commands don't have to repeat such code. From cbosgd!mark Mon Nov 21 23:53:00 1983 From: mark@cbosgd.UUCP Subject: libdbm is broken in 4.2 Date: Mon, 21 Nov 83 23:53:00 EST Status: O If you try to compile any program in 4.2BSD using -ldbm, you'll get the following diagnostics: _environ: ld:/usr/lib/libdbm.a: multiply defined start: /usr/lib/libdbm.a: multiply defined _moncontrol: /usr/lib/libdbm.a: multiply defined mcount: /usr/lib/libdbm.a: multiply defined It turns out the problem is the makefile, which loads (with libc) the dbm.o file and installs that as libdbm.a instead of the usual archive of object files. Here is the fix: *** 2,10 # CFLAGS=-O ! libdbm.a: dbm.c ! libdbm.a: dbm.h ! ${CC} -o libdbm.a ${CFLAGS} dbm.c install: install -m 644 libdbm.a $(DESTDIR)/usr/lib --- 2,12 ----- # CFLAGS=-O ! libdbm.a: dbm.o ! ar rv libdbm.a dbm.o ! ! dbm.o: dbm.h dbm.c ! ${CC} -c ${CFLAGS} dbm.c install: install -m 644 libdbm.a $(DESTDIR)/usr/lib From rws@mit-bold.ARPA Tue Nov 22 19:12:55 1983 Date: Tue, 22 Nov 83 15:28:32 est From: Robert W. Scheifler Subject: vv doesn't broadcast, doesn't loopback Index: /sys/vaxif/if_vv.c 4.2BSD Status: O Description: The V2LNI driver doesn't set up for broadcast correctly, and doesn't take advantage of the loopback-net. Repeat-By: Try running rwhod (for broacast) and rlogin to self (for loopback). Fix: Somewhere after the top add the declaration extern struct ifnet loif; In vvinit(), change sin->sin_addr = if_makeaddr(vs->vs_if.if_net, VV_BROADCAST); to be sin->sin_addr = if_makeaddr(vs->vs_if.if_net, 0); and change vs->vs_if.if_flags |= IFF_UP | IFF_RUNNING; to be vs->vs_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_BROADCAST; In vvoutput(), after dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr; add if ((dest == ((struct sockaddr_in *)&ifp->if_addr)->sin_addr.s_addr) && ((loif.if_flags & IFF_UP) != 0)) return(looutput(&loif, m0, dst)); (note the check to make sure the loopback is up, which other drivers don't do but should) and after if ((dest = in_lnaof(*((struct in_addr *)&dest))) >= 0x100) { error = EPERM; goto bad; } add if (dest == 0) dest = VV_BROADCAST; From rws@mit-bold.ARPA Tue Nov 22 20:11:07 1983 Date: Tue, 22 Nov 83 15:29:37 est From: Robert W. Scheifler Subject: host vs. net redirects not distinguished Index: /sys/net/route.c 4.2BSD Status: O Description: ICMP host-specific redirects are treated the same as network redirects. Repeat-By: Go through a gateway that uses ICMP_REDIRECT_HOST and then do a netstat -r. Fix: In /sys/netinet/ip_icmp.c, in icmp_input(), change rtredirect((struct sockaddr *)&icmpsrc, (struct sockaddr *)&icmpdst); to be rtredirect((struct sockaddr *)&icmpsrc, (struct sockaddr *)&icmpdst, (((code == ICMP_REDIRECT_NET) || (code == ICMP_REDIRECT_TOSNET)) ? RTF_GATEWAY : (RTF_GATEWAY|RTF_HOST))); In /sys/net/route.c, in rtredirect(), change rtredirect(dst, gateway) struct sockaddr *dst, *gateway; to be rtredirect(dst, gateway, flags) struct sockaddr *dst, *gateway; int flags; and change /* * Don't listen to the redirect if it's * for a route to an interface. */ if (rt->rt_flags & RTF_GATEWAY) { /* * Smash the current notion of the gateway to * this destination. This is probably not right, * as it's conceivable a flurry of redirects could * cause the gateway value to fluctuate wildly during * dynamic routing reconfiguration. */ rt->rt_gateway = *gateway; rtfree(rt); rtstat.rts_newgateway++; return; } to be if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) != flags) { rtfree(rt); if (flags & RTF_HOST) { rtinit(dst, gateway, flags); rtstat.rts_newgateway++; } return; } /* * Smash the current notion of the gateway to * this destination. This is probably not right, * as it's conceivable a flurry of redirects could * cause the gateway value to fluctuate wildly during * dynamic routing reconfiguration. */ rt->rt_gateway = *gateway; rtfree(rt); rtstat.rts_newgateway++; From salkind@nyu.ARPA Tue Nov 22 20:11:10 1983 Date: Tue, 22 Nov 83 16:01:23 est From: Lou Salkind Subject: sendmail bug Index: usr.lib/sendmail/src/collect.c 4.2BSD Status: O Description: If sendmail encounters end of file before a newline character, it can go into an infinite loop. The reason is that the EOF condition is never explicitly checked. Repeat-By: Certain files received with smtp will cause this. Fix: The diff -c that follows shows the fix: *** /usr/src/usr.lib/sendmail/src/collect.c.dist Mon Jul 25 23:19:55 1983 --- /usr/src/usr.lib/sendmail/src/collect.c Tue Nov 22 13:17:13 1983 *************** *** 76,82 for (; !feof(InChannel); !feof(InChannel) && !ferror(InChannel) && sfgets(buf, MAXFIELD, InChannel) != NULL) { ! register char c; extern bool isheader(); /* if the line is too long, throw the rest away */ --- 76,82 ----- for (; !feof(InChannel); !feof(InChannel) && !ferror(InChannel) && sfgets(buf, MAXFIELD, InChannel) != NULL) { ! register int c; extern bool isheader(); /* if the line is too long, throw the rest away */ *************** *** 82,88 /* if the line is too long, throw the rest away */ if (index(buf, '\n') == NULL) { ! while ((c = getc(InChannel)) != '\n') continue; /* give an error? */ } --- 82,88 ----- /* if the line is too long, throw the rest away */ if (index(buf, '\n') == NULL) { ! while ((c = getc(InChannel)) != '\n' && c != EOF) continue; /* give an error? */ } From lwa@mit-csr.ARPA Fri Nov 25 21:08:37 1983 Date: 23 Nov 1983 1415-EST (Wednesday) From: seismo!lwa@mit-csr Subject: User Telnet doesn't do netascii properly Index: /usr/src/ucb/telnet.c 4.2BSD Status: O Description: User Telnet does not properly perform the netascii conversion on data being transmitted. In particular, it sends the carriage return character alone without a following newline. The consensus among the Telnet implementers (including Jon Postel) is that should always be followed by . The result of this omission is that certain hosts drop the first character typed after a . Repeat-By: Try telnetting to a host whose server Telnet is known to ignore the next character sent after a . Fix: In the routine telnet(), after the lines: if (c == IAC) *nfrontp++ = c; *nfrontp++ = c; add the two lines: if (c == '\r') *nfrontp++ = '\n'; ------- From jim@mcvax.UUCP Sat Nov 26 13:09:32 1983 Date: 23 Nov 83 7:40:08-PST (Wed) From: seismo!decvax!genrad!security!linus!philabs!mcvax!jim@ucb-vax Subject: Re: autobauding on UNIX? Status: RO We don't have any terminals/modems/diallers/etc. on our machines, everything is attached to a Micom portselector. So we have autobaud detection in getty. Originally done by mcvax!piet, added to 4.2BSD by me. Here is a diff of the source with the original, followed by a copy of /etc/gettytab. It isn't hard to fit it into a non-4.2BSD. Jim McKie Mathematisch Centrum, Amsterdam ....mcvax!jim ====================================================================== diff -c ./gettytab.h /usr/src/local/etc/getty/gettytab.h *** ./gettytab.h Sun Jul 10 03:35:15 1983 --- /usr/src/local/etc/getty/gettytab.h Sun Sep 18 13:13:13 1983 *************** *** 97,102 #define PS gettyflags[16].value #define HC gettyflags[17].value #define UB gettyflags[18].value int getent(); long getnum(); --- 97,105 ----- #define PS gettyflags[16].value #define HC gettyflags[17].value #define UB gettyflags[18].value + #ifdef MCVAX + #define AB gettyflags[19].value + #endif MCVAX int getent(); long getnum(); diff -c ./init.c /usr/src/local/etc/getty/init.c *** ./init.c Sun Jul 10 03:35:16 1983 --- /usr/src/local/etc/getty/init.c Sun Sep 18 13:13:13 1983 *************** *** 80,84 { "ps", 0 }, /* do port selector speed select */ { "hc", 1 }, /* don't set hangup on close */ { "ub", 0 }, /* unbuffered output */ { 0 } }; --- 80,87 ----- { "ps", 0 }, /* do port selector speed select */ { "hc", 1 }, /* don't set hangup on close */ { "ub", 0 }, /* unbuffered output */ + #ifdef MCVAX + { "ab", 0 }, /* auto-baud detect with '\r' */ + #endif MCVAX { 0 } }; diff -c ./main.c /usr/src/local/etc/getty/main.c *** ./main.c Tue Aug 2 01:07:07 1983 --- /usr/src/local/etc/getty/main.c Sun Sep 18 13:13:13 1983 *************** *** 128,133 ioctl(0, TIOCSETD, &ldisp); if (HC) ioctl(0, TIOCHPCL, 0); if (PS) { tname = portselector(); continue; --- 128,141 ----- ioctl(0, TIOCSETD, &ldisp); if (HC) ioctl(0, TIOCHPCL, 0); + #ifdef MCVAX + if (AB) { + extern char *autobaud(); + + tname = autobaud(); + continue; + } + #endif MCVAX if (PS) { tname = portselector(); continue; diff -c ./subr.c /usr/src/local/etc/getty/subr.c *** ./subr.c Thu Jul 7 12:32:55 1983 --- /usr/src/local/etc/getty/subr.c Tue Oct 11 10:09:55 1983 *************** *** 406,408 sleep(2); /* wait for connection to complete */ return (type); } --- 406,463 ----- sleep(2); /* wait for connection to complete */ return (type); } + + #ifdef MCVAX + /* + * This auto-baud speed select machanism is written for the Micom 600 + * portselector. Selection is done by looking at how the character '\r' + * is garbled at the different speeds. + */ + #include + + char * + autobaud() + { + int rfds; + struct timeval timeout; + char c, *type = "2400-baud"; + int null = 0; + + ioctl(0, TIOCFLUSH, &null); + rfds = 1 << 0; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + if(select(32, &rfds, (int *)0, (int *)0, &timeout) <= 0) + return(type); + if(read(0, &c, sizeof(char)) != sizeof(char)) + return(type); + timeout.tv_sec = 0; + timeout.tv_usec = 20; + (void) select(32, (int *)0, (int *)0, (int *)0, &timeout); + ioctl(0, TIOCFLUSH, &null); + switch(c&0377){ + + case 0200: /* 300-baud */ + type = "300-baud"; + break; + + case 0346: /* 1200-baud */ + type = "1200-baud"; + break; + + case 015: /* 2400-baud */ + case 0215: + type = "2400-baud"; + break; + + default: /* 4800-baud */ + type = "4800-baud"; + break; + + case 0377: /* 9600-baud */ + type = "9600-baud"; + break; + } + return(type); + } + #endif MCVAX =========================================================================== /etc/gettytab =========================================================================== # # Mathematisch Centrum gettytab. # # # The default gettytab entry, used to set defaults for all other # entries, and in cases where getty is called with no table name # default:\ :ap:er=^H:kl=^X:in=\177:sp#2400:cd#3:im=\r\n%h\r\n\007: # # Auto-baud speed detect entry for Micom 600. # Special code in getty will switch this out # to one of the other entries. # A|Auto-baud:\ :ab:sp#2400:f0#040: # # Other general speed tables. These can be cycled-round # by using "break" (watch on the Micom!). # The names "SPEED-baud" are also known to the special # code in getty for auto-baud. # B|300-baud:\ :nx=9600-baud:cd@:sp#300: C|1200-baud:\ :nx=300-baud:cd@:sp#1200: D|2400-baud:\ :nx=1200-baud: E|4800-baud:\ :nx=2400-baud:cd@:sp#4800: F|9600-baud:\ :nx=4800-baud:cd@:sp#9600: # # Fixed-speed dialup lines. # H|Dialup-1200:\ :cd@:sp#1200: L|Dialup-300:\ :cd@:sp#300: # # Console Decwriter-III # c|Console|Console Decwriter III:\ :cd@:fd#1:ht: From umcp-cs!chris Sat Nov 26 16:14:48 1983 Date: 24 Nov 83 5:14:29-PST (Thu) Subject: Autobaud routine Status: RO Ok, enough people have asked for it that I'll post it. Since I announced it on net.unix-wizards, and this goes out to ARPAnet sites (whereas net.sources doesn't), I'm posting it here; to keep it short, I'm just posting the autobauding routines, not the whole of getty. Notes: 1) The "time_out" is to get around the fact that when someone dials in via our Gandalf switch, logging out leaves the line connected, and even if the user hangs up the phone, the Gandalf just doesn't let go until we drop DTR. 2) Won't run as-is on 4.2 since signals have changed; also, since all system calls get restarted (or do they?) you'd probably have to use setjmp/longjmp in the "a_zap" routine. 3) Don't forget to cut off the ".signature". (Is there any way to tell inews not to grab it? I suppose I could 'mv' it temporarily....) Chris ---------------------------begin autobaud------------------------ /* * Drop data terminal ready for one second. This is important for Gandalf * lines which must be told to disconnect. This affects all autobauding * lines after a 60 second timeout. */ time_out () { /* 2-Feb-1983 FLB */ puts ("\r\r\n\nTimeout\r\r\n\n"); sleep (2); tmode.sg_ispeed = tmode.sg_ospeed = B0; stty (0, &tmode); sleep (3); exit (0); } /* * Try to figure out what speed the terminal is set to based on what * a carriage-return looks like at 2400 baud. This doesn't distinguish * all speeds, but gets the good ones at least. 5/18/82 FLB */ struct autobaud { int s_speed; char *s_string; } a_tab[] = { B110, "\3\000\000\000", B300, "\3\200\200\000", B300, "\3\200\000\000", B300, "\3\000\200\000", B600, "\3\000\376\000", B1200, "\2\346\200", B1200, "\2\346\340", B1800, "\2\000\376", B1800, "\2\000\377", B2400, "\1\15", B2400, "\1\215", B4800, "\1\361", /* needed for Gandalf */ B4800, "\1\362", B4800, "\1\363", /* needed for Gandalf */ B4800, "\1\371", /* needed for Gandalf */ B4800, "\1\375", /* needed for Gandalf */ B4800, "\1\376", /* needed for Gandalf */ B9600, "\1\377", /* needed for Gandalf */ B110, "\1\0", /* so a ``break'' will let you escape */ 0, 0 }; auto_baud () { register struct autobaud *tp; struct sgttyb ttyb; char buf[10]; int i; ttyb.sg_ispeed = ttyb.sg_ospeed = B2400; ttyb.sg_flags = ANYP|RAW; stty (0, &ttyb); for (;;) { signal (SIGALRM, time_out); /* 2-Feb-1983 FLB */ alarm (60); /* 2-Feb-1983 FLB */ input (buf); for (tp = a_tab; tp -> s_speed; tp++) for (i = 0; buf[i] == tp -> s_string[i] && i < sizeof buf; i++) if (i == *buf) { signal (SIGALRM, time_out); /* 2-Feb-1983 FLB */ alarm (60); /* 2-Feb-1983 FLB */ return (tp -> s_speed); } stty (0, &ttyb); } } a_zap () {} input (s) char *s; { register char *cp = s + 1; read (0, cp, 1); cp++; signal (SIGALRM, a_zap); alarm (1); while (read (0, cp, 1) > 0) cp++; *s = (cp - s) - 1; } -- In-Real-Life: Chris Torek, Univ of MD Comp Sci UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris.umcp-cs@CSNet-Relay From sdchema!donn Wed Nov 23 15:06:06 1983 From: donn@sdchema.UUCP Subject: 4.2 BSD f77 compiler bug (1) Date: Wed, 23 Nov 83 15:06:06 EST Status: O Subject: Bug in f77 loop optimizer generates incorrect code (serious!) Index: /usr/src/usr.bin/f77/src/f77pass1/exec.c 4.2BSD Description: This problem occurs in the f77 compiler supplied on a tape made on 8/23/83. In f77 DO loops, a variable loop limit is squirreled away in a local variable so that it cannot be altered during the course of the loop. (This is because the standard says that DO loop initializations, limits and increments are only evaluated once, when the loop is first entered.) Unfortunately the loop limit is saved in a temporary variable which may be reallocated when subroutine arguments are evaluated in the loop. (Since f77 requires that arguments be passed to subroutines by reference rather than by value, these temporaries are used to give an address to the output of an expression.) This leads to loops which are executed an unpredictable number of times, clearly a major error. The problem is mitigated slightly by the fact that unless the loop is complicated, the loop limit quantity will migrate into register from its place on the stack, and after this it is safe from being clobbered. Repeat-By: Copy the following f77 program into the file bug1.f: -------------------------------------------------------------- program bug1 integer i, j, k, l, m, n, o j = 2 k = 3 l = 4 m = 5 n = 6 o = 7 do 20 i=1,k j = j + l l = i + j j = l * j l = j - l m = l * i n = l * m o = m - l m = o + 3 n = o / m o = j + n call dummy( i+1, j+2, l+3 ) write(unit=6,fmt=10) i 10 format('Loop pass ', i3) 20 continue stop end subroutine dummy( a, b, c ) integer a, b, c return end -------------------------------------------------------------- Notice that the expected output is: Loop pass 1 Loop pass 2 Loop pass 3 In fact this program goes into an infinite loop, counting up to infinity. To see why, compile again using the command: f77 -d14 -S -O bug1.f F77pass1 will print the debugging comment that offset -4 is being reused. If you look at the assembler output file bug1.s, you should see that the loop limit is stored at -4(fp), and that the call to dummy() clobbers -4(fp) with the value of i+1... hence the infinite loop. Fix: The best fix I can find is to cause the loop limit to be put in a TADDR-type temporary rather than a TTEMP temporary. TTEMP stack temporaries can be re-used quickly, while TADDR temporaries are not recycled until the end of a routine. The loop increment is also a TTEMP temporary, so for safety I have also made that a TADDR temporary. The changes to src/f77pass1/exec.c are: *************** *** 444,450 if( CONSTLIMIT ) ctlstack->domax = DOLIMIT; else ! ctlstack->domax = (expptr) mktemp(dotype, PNULL); if( CONSTINCR ) { --- 461,467 ----- if( CONSTLIMIT ) ctlstack->domax = DOLIMIT; else ! ctlstack->domax = (expptr) mkaltemp(dotype, PNULL); if( CONSTINCR ) { *************** *** 455,461 } else { ! ctlstack->dostep = (expptr) mktemp(dotype, PNULL); ctlstack->dostepsign = VARSTEP; } --- 472,478 ----- } else { ! ctlstack->dostep = (expptr) mkaltemp(dotype, PNULL); ctlstack->dostepsign = VARSTEP; } Donn Seeley UCSD Chemistry Dept. RRCF ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@noscvax From sdchema!donn Wed Nov 23 15:08:09 1983 From: donn@sdchema.UUCP Subject: 4.2 BSD f77 compiler bug (2) Date: Wed, 23 Nov 83 15:08:09 EST Subject: Computed GOTOs can cause f77 to dump core Status: O Index: /usr/src/usr.bin/f77/src/f77pass1/regalloc.c 4.2BSD Description: This problem occurs in the f77 compiler supplied on a tape made on 8/23/83. While compiling a program with 'f77 -O ...' that contains a computed GOTO, f77 stops with a 'Termination code 11' or 'Termination code 132' and a core dump of f77pass1 is left behind. This only occurs with a certain very large program which I have that is generated with a ratfor-like pre- processor and contains zillions of gotos and DO loops. Repeat-By: The program that causes this is much too large to send by mail or news, but it is available on request. I have tried replicating the problem with smaller programs, to no avail. The program contains the line: GOTO(16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),COMBO Fix: Fortunately the error is fairly obvious. Running dbx on f77pass1 shows that it dies with the PC in the routine alreg() of regalloc.c. At that point it is in code that handles computed GOTOs; it is running through a list of all the labels used by the computed GOTO statement. If it finds that a label is outside of the current DO loop, it flags it and breaks the loop. If it runs through the list and finds no such branches, it should just fall out. Unfortunately the test for the last label at the top of the for loop has an off-by-one error and skips off the end into never-never land. This test IS handled correctly in very similar code earlier in the same routine, so it is clear what the correct code should be (in src/f77pass1/regalloc.c): *************** *** 835,841 case SKCMGOTO: lp = (struct Labelblock **) sp->ctlinfo; ! for (i = 0; i <= sp->label; i++, lp++) if (!locallabel((*lp)->labelno)) { gensetall(sp); --- 861,867 ----- case SKCMGOTO: lp = (struct Labelblock **) sp->ctlinfo; ! for (i = 0; i < sp->label; i++, lp++) if (!locallabel((*lp)->labelno)) { gensetall(sp); Donn Seeley UCSD Chemistry Dept. RRCF ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@noscvax From sdchema!donn Wed Nov 23 23:23:43 1983 From: donn@sdchema.UUCP Subject: 4.2 BSD f77 compiler bug (3) Date: Wed, 23 Nov 83 23:23:43 EST Status: O This isn't really a 'bug' if you are an old-time Fortran hacker... so I'm not passing it on to Berkeley. It is, however, quite surprising to the uninitiated. Does anyone know of a Fortran compiler that doesn't do this? To see the 'bug', compile and run the following program: --------------------------------------------------------------------------- c c This program changes the value of constants passed as subroutine c arguments! c program con c c The routine 'screw' is called with constant arguments -- the c VALUE OF THE CONSTANT is changed by 'screw'. c call screw(99) call screw(101) call screw(103) c c The routine 'print' is also called with constant arguments here -- c it is necessary to do the printing in a subroutine since c only function arguments are affected by the bug/feature. c call print(98) call print(99) call print(100) call print(101) call print(102) call print(103) stop end c c This routine screws up its argument. c subroutine screw(i) integer i i = (i + 3) * i return end c c This routine prints its argument. c subroutine print(i) integer i write(6, 10) i 10 format(1x,i10) return end --------------------------------------------------------------------------- The trick is, of course, that all constants of the same value are stored in the same address for the purpose of being passed to subroutines. Nothing prevents subroutines from altering these stored constants. Donn Seeley UCSD Chemistry Dept. RRCF ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@noscvax From sdchema!donn Wed Nov 30 01:38:28 1983 From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: 4.2 BSD f77 compiler bug (4) Date: Wed, 30 Nov 83 01:38:28 EST Status: O Subject: f77 optimizer misses redundant register moves Index: /usr/src/usr.bin/f77/src/f77pass1/regalloc.c 4.2BSD Description: This problem occurs in the f77 compiler supplied on a tape made on 8/23/83. The f77 compiler generates code which contains instructions like 'movl r10,r10' when optimizing embedded loops. Since these instructions are easy to find, it seems strange that they are missed; and in fact the reason for this appears to be that the register optimization code in alreg() is buggy. Repeat-By: Copy out the following f77 program and call it 'bug3.f': ---------------------------------------------------------------------- program bug3 integer i, j, k, l, m, n i = 1 j = 2 k = 3 l = 4 m = 5 n = 6 do 20 i = 1, 10 do 10 j = 1, 10 k = m * j l = n * i m = i * k n = j * l 10 continue 20 continue stop end ---------------------------------------------------------------------- Compile the program with 'f77 -O -S -c bug3.f'. This program will have code in it that looks like this: ---------------------------------------------------------------------- movl $1,v.2-v.1(r11) movl $2,v.3-v.1(r11) movl $3,v.4-v.1(r11) movl $4,v.5-v.1(r11) movl $5,v.6-v.1(r11) movl $6,v.7-v.1(r11) movl v.3-v.1(r11),r10 movl v.2-v.1(r11),r9 movl v.4-v.1(r11),r8 movl v.5-v.1(r11),r7 movl v.6-v.1(r11),r6 movl $1,r9 L17: movl r10,r10 /*** Redundant ***/ movl $1,r10 L22: mull3 r10,r6,r8 mull3 r9,v.7-v.1(r11),r7 mull3 r8,r9,r6 mull3 r7,r10,v.7-v.1(r11) aobleq $10,r10,L22 movl r6,r6 /*** Redundant ***/ movl r7,r7 /*** Redundant ***/ movl r8,r8 /*** Redundant ***/ movl r10,r10 /*** Redundant ***/ acbl $10,$1,r9,L17 movl r6,v.6-v.1(r11) movl r7,v.5-v.1(r11) movl r8,v.4-v.1(r11) movl r9,v.2-v.1(r11) movl r10,v.3-v.1(r11) pushl $0 pushal L25 calls $2,_s_stop ret ---------------------------------------------------------------------- (I have prettied up the output considerably here...) The redundant moves are marked by comments. Fix: The second pass through the slots in alreg() (in regalloc.c) has code to look at the slots just before and just after embedded DO loops for redundant moves. It appears not to work correctly -- one obvious problem is that it will fail to delete redundant moves which are 'protected' by some other statement. It seems to me that the 'brute force' approach is much simpler -- since the loop over slots must look at all assignment slots in the current DO loop anyway, why not check for redundant assigments there? My solution was to move the slot deletion code down to the assignment case: *************** *** 782,803 case SKDOHEAD: docount++; globalbranch = YES; - sp1 = sp->prev; - while (sp1) - if (regtoreg(sp1)) - { - ap = (Addrp) sp1->expr->exprblock.leftp; - sp2 = sp1->prev; - for (i = toplcv + 2; i <= toptrack; i++) - if (regtab[i] && (regnum[i] == ap->memno)) - { - deleteslot(sp1); - break; - } - sp1 = sp2; - } - else - sp1 = NULL; break; case SKEQ: --- 808,813 ----- case SKDOHEAD: docount++; globalbranch = YES; break; case SKEQ: *************** *** 816,821 regdefined[i] = YES; } linearcode = NO; break; case SKARIF: --- 826,847 ----- regdefined[i] = YES; } linearcode = NO; + + /* + * Eliminate redundant register moves. + */ + if (regtoreg(sp)) + { + ap = (Addrp) sp->expr->exprblock.leftp; + sp1 = sp->prev; + for (i = toplcv + 1; i <= toptrack; i++) + if (regtab[i] && (regnum[i] == ap->memno)) + { + deleteslot(sp); + sp = sp1; + break; + } + } break; case SKARIF: *************** *** 1792,1800 if ((r->tag == TADDR) && (r->addrblock.vstg == STGREG) && (r->addrblock.memno == l->addrblock.memno)) - return YES; - if ((r->tag == TEXPR) && - (r->exprblock.opcode == OPADDR)) return YES; return NO; --- 1818,1823 ----- if ((r->tag == TADDR) && (r->addrblock.vstg == STGREG) && (r->addrblock.memno == l->addrblock.memno)) return YES; return NO; Notice the last diff -- this eliminates some odd code in regtoreg(), the routine which detects redundant moves, whose purpose seemed unclear but definitely wrong for what I am doing. The new compiler emits the following code for the same program: ---------------------------------------------------------------------- movl $1,v.2-v.1(r11) movl $2,v.3-v.1(r11) movl $3,v.4-v.1(r11) movl $4,v.5-v.1(r11) movl $5,v.6-v.1(r11) movl $6,v.7-v.1(r11) movl v.3-v.1(r11),r10 movl v.2-v.1(r11),r9 movl v.4-v.1(r11),r8 movl v.5-v.1(r11),r7 movl v.6-v.1(r11),r6 movl $1,r9 L17: movl $1,r10 L22: mull3 r10,r6,r8 mull3 r9,v.7-v.1(r11),r7 mull3 r8,r9,r6 mull3 r7,r10,v.7-v.1(r11) aobleq $10,r10,L22 acbl $10,$1,r9,L17 movl r6,v.6-v.1(r11) movl r7,v.5-v.1(r11) movl r8,v.4-v.1(r11) movl r9,v.2-v.1(r11) movl r10,v.3-v.1(r11) pushl $0 pushal L25 calls $2,_s_stop ret ---------------------------------------------------------------------- The new version of the compiler omits precisely the redundant instructions. It sometimes simplifies more complicated expressions in DO loop headers by causing the compiler to realize that it can eliminate a stack variable, too. Sometimes, though, it seems to miss the fact that it has the same element in register twice. I'm open to suggestions about how to fix this. Donn Seeley UCSD Chemistry Dept. RRCF ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@noscvax From seismo!philabs!linus!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Sun Nov 27 22:06:13 1983 From: donn@sdchema.UUCP Subject: 4.2 BSD f77 compiler bug (5) Date: Sun, 27 Nov 83 22:06:13 EST Status: O Subject: f77 won't put REAL variables in register Index: usr.bin/f77/src/f77pass1/regalloc.c 4.2BSD Description: This problem occurs in the f77 compiler supplied on a tape made on 8/23/83. The new f77 compiler will put INTEGERs in register but not REALs even though the VAX allows REAL (4-byte floating point) values to appear in general registers. This adds unnecessary overhead to programs which do lots of computations with REAL values (that is to say, virtually all typical f77 programs). Repeat-By: Clip out the following f77 program and put it in a file named bug4.f: -------------------------------------------------------------------- program bug4 integer i real a, b, c a = 2.0 b = 1.0 c = 0.999 do 100 i = 1, 1000000 a = (a + b) * c 100 continue stop end -------------------------------------------------------------------- Compile this program with the command 'f77 -S -O -c bug4.f'. The assembler output shows that REAL variables are not put in register while integer values are. The following is a pretty-printed version of the assembler file, where variables of the form 'v.4-v.1(r11)' are written '{variable}' and addresses of constants of the form 'L25' are written '{constant}' (you can get the pretty-printer by sending mail to me asking for it): -------------------------------------------------------------------- .globl _MAIN_ .set LF1,0 _MAIN_: .word LWM1 subl2 $LF1,sp jmp L12 L13: movl {0x4100},{a} movl {0x4080},{b} movl {0xbe77407f},{c} movl {i},r10 movl $1,r10 L17: addf3 {b},{a},r0 mulf3 {c},r0,{a} aobleq $1000000,r10,L17 movl r10,{i} pushl $0 pushal {00,00} calls $2,_s_stop ret .align 1 _bug4_: .word LWM1 L12: moval v.1,r11 jmp L13 -------------------------------------------------------------------- Notice that the INTEGER variable 'i' is put in register 10 but the only time that a register is used for a REAL is when it is necessary to hold the intermediate result of an expression computation; ordinary REAL variables are not assigned registers when DO loops are optimized. Fix: A simple change can be made to the compiler to cause it to assign REAL variables to registers -- in fact the change is so simple it is suspicious; why didn't anyone do this before? But I have been unable to find any evidence that this change is harmful, and all of the programs I have tested the new version of the compiler on have worked correctly. The change is in f77/src/f77pass1/regalloc.c: -------------------------------------------------------------------- *************** *** 31,36 #define VARTABSIZE 1009 #define TABLELIMIT 12 #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) #define ISREGTYPE(x) ONEOF(x, MSKREGTYPES) --- 34,42 ----- #define VARTABSIZE 1009 #define TABLELIMIT 12 + #if HERE==VAX + #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) | M(TYREAL) + #else #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) #endif *************** *** 32,37 #define TABLELIMIT 12 #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) #define ISREGTYPE(x) ONEOF(x, MSKREGTYPES) --- 38,44 ----- #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) | M(TYREAL) #else #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) + #endif #define ISREGTYPE(x) ONEOF(x, MSKREGTYPES) -------------------------------------------------------------------- Notice that the change does not affect DOUBLE PRECISION variables (it would probably take a lot more work to get them in register). After changing the compiler in this way, the code that is generated for 'bug4.f' changes to this: -------------------------------------------------------------------- .globl _MAIN_ .set LF1,0 _MAIN_: .word LWM1 subl2 $LF1,sp jmp L12 L13: movl {0x4100},{a} movl {0x4080},{b} movl {0xbe77407f},{c} movl {a},r10 movl {b},r9 movl {c},r8 movl {i},r7 movl $1,r7 L17: addf3 r9,r10,r0 mulf3 r8,r0,r10 aobleq $1000000,r7,L17 movl r7,{i} movl r10,{a} pushl $0 pushal {00,00} calls $2,_s_stop ret .align 1 _bug4_: .word LWM1 L12: moval v.1,r11 jmp L13 -------------------------------------------------------------------- I timed the old and new versions of 'bug4' and observed the following values ('time' is the 'user' time returned by the C-shell 'time' command): -------------------------------------------------------------------- Version Time (sec) Type of System Old 32.2 VAX11/750, no FPA New 29.0 VAX11/750, no FPA Old 11.7 VAX11/750 with FPA New 8.7 VAX11/750 with FPA -------------------------------------------------------------------- On systems with no FPA, the operand fetch time is much smaller than the actual computation time for floating point operations -- notice that the improvement is independent of using an FPA, being approx. 3 seconds in both cases. Still the improvement is 10% even without an FPA (closer to 25% if you have one). One oddity -- I notice that the compiler invariably translates floating point assignment operations to 'movl' instructions instead of 'movf' instructions. I think this is because 'movl' is faster than 'movf' and the compiler guarantees that nothing depends on side effects of assignments, but I haven't pinned this down for sure yet. Donn Seeley UCSD Chemistry Dept. RRCF ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@noscvax From lwa@mit-csr.ARPAd Wed Nov 30 12:09:53 1983 Date: 30 Nov 1983 1035-EST (Wednesday) From: seismo!lwa@mit-csr Subject: Bug in rip_output() Status: O Index: /sys/netinet/raw_ip.c 4.2BSD Description: When performing raw internet output, the ip_off field in the internet header is never completely cleared. Although the ip_output routine later zeroes everything but the IP_DF flag, this flag may still be randomly set (depending on the previous contents of the mbuf used to hold the ip header). As a result, raw output packets larger than the maximum local net packet size may be rejected as "too large". Repeat-By: Try repeatedly sending packets larger than the maximum local net packet size using the raw interface. Some will be rejected as too large. Fix: Add the following line to the rip_output() routine in the file /sys/netinet/raw_ip.c: ip = mtod(m, struct ip *); /* add the following line */ ip->ip_off = 0; /* end of addition */ ip->ip_p = so->so_proto->pr_protocol; -Larry Allen ------- From rws@mit-bold.ARPA Thu Dec 1 18:46:10 1983 Date: Thu, 1 Dec 83 12:57:58 est From: Robert W. Scheifler Subject: icmp_input() doesn't pullup Status: O Index: /sys/netinet/ip_icmp.c 4.2BSD Description: icmp_input() assumes that both the IP and ICMP headers are in the first mbuf, which they needn't be. Repeat-By: Well, first you should give superuser access to raw ICMP. All the code is there, but the protosw doesn't give access, so change the ICMP protosw in in_proto.c to { SOCK_RAW, PF_INET, IPPROTO_ICMP, PR_ATOMIC|PR_ADDR, icmp_input, rip_output, 0, 0, raw_usrreq, 0, 0, 0, 0, }, Then write yourself a "ping" program to send ICMP ECHOs and look for ICMP ECHOREPLYs. Watch it work over a real network. Watch it fail over the loopback-net to yourself, with ECHO packets apparently being zeroed out. Fix: In icmp_input(), add the code if ((m->m_off > MMAXOFF || m->m_len < (sizeof (struct icmp) + hlen)) && (m = m_pullup(m, (sizeof(struct icmp) + hlen))) == 0) { icmpstat.icps_tooshort++; return; } ip = mtod(m, struct ip *); before the lines m->m_len -= hlen; m->m_off += hlen; and remove the comment /* need routine to make sure header is in this mbuf here */ From utah-cs!lepreau Tue Nov 29 21:12:52 1983 From: lepreau@utah-cs.UUCP (Jay Lepreau) Subject: scandir() calls realloc too much and is not pessimistic enuf Date: Tue, 29 Nov 83 21:12:52 EST Status: O Index: lib/libc/gen/scandir.c 4.2BSD Fix Description: 1. If the arraysz estimate proved low, scandir does a realloc assuming the worst, but it never recomputes the new arraysz, so it keeps calling realloc all the rest of the way thru the dir. (This isn't as bad as it sounds, for realloc is smart enuf not to do anything if the same size is requested.) 2. scandir is overly optimistic about the worst case: the directory could grow on it (unless there's some synchrony out there I don't know about), leading to an infinite loop. It should restat the directory. Repeat-By: Well, *I* noticed it from that nifty gprof output showing hundreds of realloc calls. Obvious from inspection too. Fix: *************** *** 60,61 if (++nitems >= arraysz) { names = (struct direct **)realloc((char *)names, --- 62,66 ----- if (++nitems >= arraysz) { + if (fstat(dirp->dd_fd, &stb) < 0) + return(-1); /* just might have grown */ + arraysz = stb.st_size/12; names = (struct direct **)realloc((char *)names, *************** *** 61,63 names = (struct direct **)realloc((char *)names, ! (stb.st_size/12) * sizeof(struct direct *)); if (names == NULL) --- 66,68 ----- names = (struct direct **)realloc((char *)names, ! arraysz * sizeof(struct direct *)); if (names == NULL) From salkind@nyu.ARPA Fri Dec 2 14:11:11 1983 Date: Thu, 1 Dec 83 23:59:31 est From: Lou Salkind Subject: system memory computed incorrectly Status: O Index: sys/vax/machdep.c 4.2BSD Description: The amount of physical memory the system uses is not computed correctly. This is because the kernel makes the (incorrect) assumption that 2*nbuf = bufpages. By default, nbuf is set to bufpages/2 where bufpages is a function of the physical memory available. If bufpages is odd, you lose. Repeat-By: Actually, I noticed this problem when patching in my own values of bufpages and nbuf. Fix: Apply the following one line change: *** dist/machdep.c Sun Oct 2 14:57:38 1983 --- machdep.c Thu Dec 1 23:39:13 1983 *************** *** 167,173 * allocated real memory. */ ncmap = (physmem*NBPG - ((int)v &~ 0x80000000) + ! (nbuf * (MAXBSIZE - 2 * CLBYTES))) / (NBPG*CLSIZE + sizeof (struct cmap)); valloclim(cmap, struct cmap, ncmap, ecmap); if ((((int)(ecmap+1))&~0x80000000) > SYSPTSIZE*NBPG) --- 167,173 ----- * allocated real memory. */ ncmap = (physmem*NBPG - ((int)v &~ 0x80000000) + ! nbuf*MAXBSIZE - bufpages*CLBYTES) / (NBPG*CLSIZE + sizeof (struct cmap)); valloclim(cmap, struct cmap, ncmap, ecmap); if ((((int)(ecmap+1))&~0x80000000) > SYSPTSIZE*NBPG) From steveh@hammer.UUCP Mon Dec 5 12:07:20 1983 From: steveh@hammer.UUCP (Stephen Hemminger) Subject: dmf driver doesn't wake on output selects. Date: Mon, 5 Dec 83 12:07:20 EST Status: O Index: vaxuba/dmf.c 4.2BSD (and 4.1c) Description: With the 4.2/4.1c select(2) a program should block until a state change on any one of N file descriptors. If one of these happens to be the terminal on a dmf device, then it will never wakeup on output queue draining. Repeat-By: Most noticeable in telnet. Output from remote will not finish until a character is typed. Fix: Add selwakeup() in near wakeup in dmfstart(). *** dmf.fix Mon Dec 5 08:48:33 1983 --- dmf.4.2 Fri Jul 29 07:33:35 1983 *************** *** 517,532 * water mark, wake up the sleepers. * (steve@tek) and wake up any selects */ ! if (tp->t_outq.c_cc<=TTLOWAT(tp)) { ! if(tp->t_state&TS_ASLEEP) { ! tp->t_state &= ~TS_ASLEEP; ! wakeup((caddr_t)&tp->t_outq); ! } ! if(tp->t_wsel) { ! selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); ! tp->t_wsel = 0; ! tp->t_state &= ~TS_WCOLL; ! } } --- 516,524 ----- * If there are sleepers, and output has drained below low * water mark, wake up the sleepers. */ ! if ((tp->t_state&TS_ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) { ! tp->t_state &= ~TS_ASLEEP; ! wakeup((caddr_t)&tp->t_outq); } From salkind@nyu.ARPA Fri Dec 9 17:29:50 1983 Date: Fri, 9 Dec 83 13:07:12 est From: Lou Salkind Subject: _brk routine not supplied for franz rawhlisp Status: O Subject: _brk routine not supplied for franz rawhlisp Index: ucb/lisp/franz/vax 4.2BSD Description: rawhlisp can not be built from the distributed sources (several important franz applications need this). Repeat-By: In the vax directory, type make rawhlisp. You will get _brk undefined. Fix: 1) make a symbolic link to /usr/src/lib/libc/vax/sys/SYS.h in the franz/h directory 2) install the following in vax/hbrk.c --- /* special brk for hlisp */ #include "SYS.h" #define SYS_brk 17 .globl curbrk ENTRY(_brk) chmk $SYS_brk jcs err movl 4(ap),curbrk clrl r0 ret err: jmp cerror --- 3) apply the following changes to Makefile: --- 82c82 < VaxObj = bigmath.o qfuncl.o vax.o --- > VaxObj = bigmath.o qfuncl.o vax.o hbrk.o 117a118,120 > > hbrk.o: hbrk.c > cc -I../h -E ${ProfFlag2} hbrk.c | as -o hbrk.o --- From jsq@ut-sally.UUCP Sat Dec 10 16:28:16 1983 From: jsq@ut-sally.UUCP (John Quarterman) Subject: TCP connections hanging forever in FIN_WAIT_2 state Date: Sat, 10 Dec 83 16:28:16 EST Status: O Subject: TCP connections hanging forever in FIN_WAIT_2 state Index: sys/netinet/tcp_input.c 4.2BSD Description: TCP connections with TOPS-20 systems occassionally hang in FIN_WAIT_2 state. When this happens, the connection *never* closes and such hung connections accumulate. Repeat-By: If you have frequent TCP connections with a TOPS-20 host, you will notice, using netstat, connections in FIN_WAIT_2 state accumulating. If you have frequent TOPS-20 traffic, all your incoming network pty ports will eventually be eaten up. Fix: Add the line marked with +, 533, to /sys/netinet/tcp_input.c. This kludge does not agree complete with the TCP spec, but it does solve the problem. /* * In FIN_WAIT_1 STATE in addition to the processing * for the ESTABLISHED state if our FIN is now acknowledged * then enter FIN_WAIT_2. */ case TCPS_FIN_WAIT_1: if (ourfinisacked) { /* * If we can't receive any more * data, then closing user can proceed. */ if (so->so_state & SS_CANTRCVMORE) soisdisconnected(so); tp->t_state = TCPS_FIN_WAIT_2; + tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; } break; -- John Quarterman, CS Dept., University of Texas, Austin, Texas {ihnp4,seismo,ctvax}!ut-sally!jsq, jsq@ut-sally.{ARPA,UUCP} From shannon@sun.uucp Fri Dec 9 04:29:39 1983 From: shannon@sun.uucp (Bill Shannon) Subject: 4.2bsd awk bug Date: Fri, 9 Dec 83 04:29:39 EST Status: O Index: bin/awk 4.2BSD [Fix] Description: Awk doesn't allow you to replace fields. This bug was introduced when the indirect-through-zero bugs in awk were fixed. Repeat-By: The following command echo 1 2 3 | awk '{$1 = NF; print}' should give 3 2 3 if it works. If it's broken it will give 1 2 3 Fix: Install the following fix: --- awk.def 7a8 > #define isnull(x) ((x) == EMPTY || (x) == NULL) --- tran.c 139c139 < if ((vp->tval & FLD) && vp->nval == 0) --- > if ((vp->tval & FLD) && isnull(vp->nval)) 154c154 < if ((vp->tval & FLD) && vp->nval == 0) --- > if ((vp->tval & FLD) && isnull(vp->nval)) From jeff@fluke.UUCP Fri Dec 9 18:37:14 1983 From: jeff@fluke.UUCP (Jeff Stearns) Subject: sendmail bug #2 (and fix) Date: Fri, 9 Dec 83 18:37:14 EST Status: O Subject: Sendmail can drop incoming mail from Berknet. Index: usr.lib/sendmail/src/{deliver,srvrsmtp}.c 4.2BSD Description: The mail connection between Berknet and sendmail can be flakey. Incoming mail may be lost. Complaints from MAILER-DAEMON may or may not be generated. N.B. this problem is related but not identical to the `bug' fixed in version 4.21 (11/1/83) of /bin/mail. Repeat-By: The following command should deliver the arbitrary message read from STDIN. Instead, the message is neither accepted nor returned; there are vague complaints of "Bad usage" and the message is lost. % /usr/lib/sendmail -v -T10-11 -oee -r -h 1 Fix: ----- /usr/src/usr.lib/sendmail/deliver.c ----- 1370c1371,1391 > /* > * FLUKE jps 5-Dec-83 - Surely Eric had not intended > * the degenerate comparison statement. An > * assignment statement looks reasonable to me. > * > * We were led to this statement while tracking > * down problems with mail received via Berknet. > * Berknet mmail would invoke a command such as: > * /usr/lib/sendmail -oee -r FROM -h 1 TO > * FROM = sender's name > * TO = recipient's name > * The mail would not be delivered. There would > * be hints of a response from MAILER-DAEMON, but > * it would never be returned. > * > * Including the sendmail flags `-v -d10-11' will > * produce more helpful information. > * > */ > ErrorMode = EM_MAIL; --- < ErrorMode == EM_MAIL; =============================================================================== ----- /usr/src/usr.lib/sendmail/srvrsmtp.c ----- 289c290,294 > /* > * FLUKE jps 5-Dec-83 - For a discussion of > * this change, see comments in deliver.c > */ > ErrorMode = EM_MAIL; --- < ErrorMode == EM_MAIL; Jeff Stearns, John Fluke Mfg. Co., Inc. P.O. Box C9090, Everett WA 98043 ...!decvax!microsoft!fluke!jeff From rws@mil-bold.ARPA Tue Dec 13 13:21:34 1983 Date: Mon, 12 Dec 83 22:47:22 est From: Robert W. Scheifler Subject: panic: Reserved operand Status: O Index: /sys/vax/asm.sed 4.2BSD Description: For example, after a non-recoverable machine check, and panic: mchk, you get trap type 2, code = 0, pc = 80000d76 panic: Reserved operand a number of times and then panic: KSP not valid The problem is caused by REIing back to the interrupt stack at priority level 0, which causes a reserved operand fault on the VAX. Repeat-By: Cause a panic and have disk interrupts go off while waiting for bufs to go out in boot(). Fix: The fix is almost there. In 4.1, in panic(), there was an spl0() that caused this problem. In 4.2 the spl was moved into boot() and changed to an spl1(). However, asm.sed turns an spl1() into the same thing as an spl0(), and you still lose. So change s/calls $0,_spl1/mfpr $18,r0\ mtpr $0,$18/ to be s/calls $0,_spl1/mfpr $18,r0\ mtpr $1,$18/ (Actually, I think any value between 1 and 11 would work.) From mogul@navaho.ARPA Dec 13 14:31:10 1983 Date: Mon, 12 Dec 83 18:31:28 pst From: Jeff Mogul Subject: Serious 4.2 kernel bug causes files and directories to be mangled Status: O Index: kernel 4.2BSD Description: Symptom: files get trashed, with text mysteriously appearing at random places in random files. Sometimes, directories become corrupted (by the way, fsck core dumps if you ask it to try to fix these.) One process is writing output to a file (usually, to a terminal or pseudo-terminal). Somewhere on the system, another process opens a file (any file). The output from the first process ends up in the file opened by the second process. This bug is so obviously similar to the 4.1BSD mx2.c mxclose() bug that it took me only a few minutes to find the superficial cause: iput() is being called with an inode whose i_count is already less than 1. Thus, at some later point the inode shows up both allocated and free, and gets allocated a second time. The disaster is inevitable once this occurs. I installed a bugcheck in iput() and quickly found that the real problem is that closef() (in sys/kern_descrip.c) is being called with a file argument whose f_count field is already zero. Since nobody checks that this count is positive, the inode referenced by f_data is passed to iput() for a second time. By installing another bugcheck in closef() I verified this hypothesis. However, after a week of placing debugging code into parts of the kernel (and reading a lot of it) I have not been able to find where the reference count is going wrong. Two possible theories are: (1) Something is copying a struct file * but is not bumping the reference count (2) There's a race going on somewhere. Theory #2 had some initial support from a possible bug between closef() and ino_close(). Both set f_count to zero, and ino_close may block (if I've understood things) between the point where it zeros the count and the point where closef() zeros the count. If another process allocates the (now apparently free) file in the interim, the potential for disaster is obvious. However, in spite of a few traps I set this race is not leaving the traces I would have expected. Even so, this looks like it might be a bug in certain circumstances. the line in ino_close() that sets the count to 0 is crypticly commented "/* XXX Should catch */", which I interpret to be an indication of trouble. The reorganization of the code between 4.1BSD and 4.2BSD is significant; this particular race could not occur in the 4.1BSD code. One other "fact": when closef() is called with f_count == 0, f_data->i_number is apparently always that of /dev/ttyp? Since we always use telnet (rarely, rlogin) because the system has no serial lines, these are the only "slow" output devices on the system. Repeat-by: First, install the two panic()s given in the next section, or your files will be trashed. Then, run the system and login via telnet connections. Our 750 with a user community of about 8 (a development machine) crashes about twice a day. I can't repeat it any more reliably than that. Fix: To prevent files from being trashed, in sys/kern_descrip.c, in closef(), just before the line (*fp->f_ops->fo_close)(fp); insert: if (fp->f_count < 1) panic("closef: starting count < 1"); and, to be safe (since a related bug has already popped up once before) in sys/ufs_inode.c, in iput() before the first line, insert: if (ip->i_count < 1) panic("iput: starting count < 1"); This WON'T solve the problem; it will simply keep your files intact. From salkind@cmcl2.UUCP Mon Dec 12 16:54:45 1983 From: salkind@cmcl2.UUCP (Lou Salkind) Subject: Re: Tar bug, runs out of files Date: Mon, 12 Dec 83 16:54:45 EST Status: O The 4.2 bsd version of tar has a similar (yet different) bug. Here is the fix: *** /usr/src/bin/tar.c.dist Sun Sep 25 21:05:06 1983 --- /usr/src/bin/tar.c Mon Dec 12 16:46:52 1983 *************** *** 532,537 if (strlen(longname) >= NAMSIZ) { fprintf(stderr, "tar: %s: file name too long\n", longname); return; } strcpy(dblock.dbuf.name, longname); --- 532,538 ----- if (strlen(longname) >= NAMSIZ) { fprintf(stderr, "tar: %s: file name too long\n", longname); + close(infile); return; } strcpy(dblock.dbuf.name, longname); From mile@brl-vgr.ARPA Wed Dec 14 10:09:29 1983 Date: Wed, 14 Dec 83 3:55:38 EST From: Michael John Muuss Subject: Fix for 20% loss of ICMP Packets Status: O Index: sys/netinet/ip_icmp.c 4.2BSD Description: When using a "ping" program to send ICMP_ECHO packets onto the network, a steady 20% of them are lost, regardless of interface, including the software loopback driver. The problem is that ip_icmp is incorrectly looking in the sequence number and ID field of the ICMP header, as if this was an "error advice" packet much like ICMP_REDIRECT. Repeat-By: Ping the loopback device. Ping program availible on request. (Pitty that one was not included with 4.2) Fix: A little code has to be rearranged in ip_icmp.c, around line 200+. ******* ORIGINAL CODE ******* goto free; /* not yet implemented: ignore */ #endif case ICMP_REDIRECT: case ICMP_ECHOREPLY: case ICMP_TSTAMPREPLY: case ICMP_IREQREPLY: if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) { icmpstat.icps_badlen++; goto free; } /* * Short circuit routing redirects to force * immediate change in the kernel's routing * tables. The message is also handed to anyone * listening on a raw socket (e.g. the routing * daemon for use in updating it's tables). */ if (icp->icmp_type == ICMP_REDIRECT) { icmpsrc.sin_addr = icp->icmp_ip.ip_dst; icmpdst.sin_addr = icp->icmp_gwaddr; rtredirect((struct sockaddr *)&icmpsrc, (struct sockaddr *)&icmpdst); } icmpsrc.sin_addr = ip->ip_src; icmpdst.sin_addr = ip->ip_dst; raw_input(dtom(icp), &icmproto, (struct sockaddr *)&icmpsrc, (struct sockaddr *)&icmpdst); return; default: goto free; ********** Correct code ********** goto free; /* not yet implemented: ignore */ #endif case ICMP_REDIRECT: /* Make sure it includes "error advice" (ie, front of * packet which advice applies to). */ if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) { icmpstat.icps_badlen++; goto free; } /* * Short circuit routing redirects to force * immediate change in the kernel's routing * tables. The message is also handed to anyone * listening on a raw socket (e.g. the routing * daemon for use in updating it's tables). */ icmpsrc.sin_addr = icp->icmp_ip.ip_dst; icmpdst.sin_addr = icp->icmp_gwaddr; rtredirect((struct sockaddr *)&icmpsrc, (struct sockaddr *)&icmpdst); /* fall through */ case ICMP_ECHOREPLY: case ICMP_TSTAMPREPLY: case ICMP_IREQREPLY: icmpsrc.sin_addr = ip->ip_src; icmpdst.sin_addr = ip->ip_dst; raw_input(dtom(icp), &icmproto, (struct sockaddr *)&icmpsrc, (struct sockaddr *)&icmpdst); return; default: goto free; From mike@brl-vgr.ARPA Fri Dec 16 12:11:00 1983 Date: Thu, 15 Dec 83 19:56:11 EST From: Michael John Muuss Subject: Sign bit smeared in TIOCLGET Status: O Index: sys/sys/tty.c 4.2BSD Description: If the high bit of the "local flags" is set, TIOCLGET smears that bit across the high halfword of the int by the >>16. Credit for finding this goes to Doug Gwyn, . Repeat-By: Set the bit with TIOCLSET, and read it back with TIOCLGET. Fix: Mask the data. See diff -c listing below. *** tty.c~ Thu Dec 15 19:47:12 1983 --- tty.c Thu Dec 15 19:48:14 1983 *************** break; case TIOCLGET: ! *(int *)data = tp->t_flags >> 16; break; /* should allow SPGRP and GPGRP only if tty open for reading */ -------------- break; case TIOCLGET: ! *(int *)data = (tp->t_flags >> 16) & 0xFFFF; break; /* should allow SPGRP and GPGRP only if tty open for reading */ From sheppard@parsec.UUCP Thu Dec 15 22:52:02 1983 From: sheppard@parsec.UUCP Newsgroups: net.sources Subject: 4.1c dmf driver works on ports 0/1 - (nf) Date: Thu, 15 Dec 83 22:52:02 EST Status: O This version of the dmf driver is based on version 4.16, date 82/12/17, Berkeley 4.1c. It fixes ports 0 and 1 to where they are usable without a full set of RS232 lines. The fixes actually appeared in an earlier version of dmf.c, 4.3, which was posted to this group back in September by sbcs!perry. All I did was to incorporate them into a later (better?) version of the driver. Dtr and dsr (pins 6 and 20) must still be jumpered in the connector that plugs into the dmf distribution panel for it to work. We've been using it for some time now, and it appears to work well. Andy Sheppard Parsec Scientific Computer Corporation ----------------------- cut on the dotted line ------------------------- /* dmf.c 4.16 82/12/17 */ #include "dmf.h" #if NDMF > 0 /* * DMF32 driver * * TODO: * test with modem * load as much as possible into silo * get correct numbers for receive silo parameter timeout * use auto XON/XOFF * test reset code * optimize for efficient DMA and dynamically * decide between silo and DMA mode * * Modified by A. Sheppard, Parsec Scientific Computer Corporation * to work correctly on "modem" ports (0, 1) without a full set of * RS232 lines. Original fixes by RJ Spanbauer, SUNY/Stony Brook. * * Remember: dtr and dsr (pins 6 and 20) must be jumpered in order * for this to work. */ #include "../machine/pte.h" #include "bk.h" #include "../h/param.h" #include "../h/conf.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/ioctl.h" #include "../h/tty.h" #include "../h/map.h" #include "../h/buf.h" #include "../h/vm.h" #include "../h/bk.h" #include "../h/clist.h" #include "../h/file.h" #include "../h/uio.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" /* * Definition of the driver for the auto-configuration program. */ int dmfprobe(), dmfattach(), dmfrint(), dmfxint(); struct uba_device *dmfinfo[NDMF]; u_short dmfstd[] = { 0 }; struct uba_driver dmfdriver = { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo }; /* * In this driver, "dmf" (unqualified) refers to the async portion * of the dmf32, "dmfc" to the combo portion, "dmfs" to the sync * portion, "dmfl" to the lp portion, and "dmfd" to the dr portion. */ struct dmfdevice { short dmfccsr0; /* combo csr 0 */ short dmfccsr1; /* combo csr 1 */ short dmfs[4]; short dmfcsr; /* control-status register */ short dmflpr; /* line parameter register */ short dmfrbuf; /* receiver buffer (ro) */ union { u_short dmfirw; /* indirect register word */ u_char dmfirc[2]; /* " " bytes */ } dmfun; short dmfl[2]; short dmfd[4]; }; #define dmfrsp dmfrbuf /* receive silo parameter register (wo) */ #define dmftbuf dmfun.dmfirc[0] /* transmit buffer */ #define dmftsc dmfun.dmfirc[0] /* transmit silo count */ #define dmfrms dmfun.dmfirc[1] /* receive modem status */ #define dmflcr dmfun.dmfirc[0] /* line control register */ #define dmftms dmfun.dmfirc[1] /* transmit modem status */ #define dmftba dmfun.dmfirw /* transmit buffer address */ #define dmftcc dmfun.dmfirw /* transmit character count */ /* bits in dmfcsr */ #define DMF_TI 0100000 /* transmit interrupt */ #define DMF_TIE 0040000 /* transmit interrupt enable */ #define DMF_NXM 0020000 /* non-existant memory */ #define DMF_LIN 0003400 /* transmit line number */ #define DMF_RI 0000200 /* receiver interrupt */ #define DMF_RIE 0000100 /* receiver interrupt enable */ #define DMF_CLR 0000040 /* master reset */ #define DMF_IAD 0000037 /* indirect address register */ #define DMFIR_TBUF 000 /* select tbuf indirect register */ #define DMFIR_LCR 010 /* select lcr indirect register */ #define DMFIR_TBA 020 /* select tba indirect register */ #define DMFIR_TCC 030 /* select tcc indirect register */ /* bits in dmflpr */ #define BITS6 (01<<3) #define BITS7 (02<<3) #define BITS8 (03<<3) #define TWOSB 0200 #define PENABLE 040 /* DEC manuals incorrectly say this bit causes generation of even parity. */ #define OPAR 0100 #define DMF_IE (DMF_TIE|DMF_RIE) #define DMF_SILOCNT 32 /* size of DMF output silo (per line) */ /* bits in dmfrbuf */ #define DMF_DSC 0004000 /* data set change */ #define DMF_PE 0010000 /* parity error */ #define DMF_FE 0020000 /* framing error */ #define DMF_DO 0040000 /* data overrun */ /* bits in dmfrms */ #define DMF_USRR 0004 /* user modem signal (pin 25) */ #define DMF_SR 0010 /* secondary receive */ #define DMF_CTS 0020 /* clear to send */ #define DMF_CAR 0040 /* carrier detect */ #define DMF_RNG 0100 /* ring */ #define DMF_DSR 0200 /* data set ready */ /* bits in dmftms */ #define DMF_USRW 0001 /* user modem signal (pin 18) */ #define DMF_DTR 0002 /* data terminal ready */ #define DMF_RATE 0004 /* data signal rate select */ #define DMF_ST 0010 /* secondary transmit */ #define DMF_RTS 0020 /* request to send */ #define DMF_BRK 0040 /* pseudo break bit */ #define DMF_PREEMPT 0200 /* preempt output */ /* flags for modem control */ #define DMF_ON (DMF_DTR|DMF_RTS) #define DMF_OFF 0 /* bits in dmflcr */ #define DMF_MIE 0040 /* modem interrupt enable */ #define DMF_FLUSH 0020 /* flush transmit silo */ #define DMF_RBRK 0010 /* real break bit */ #define DMF_RE 0004 /* receive enable */ #define DMF_AUTOX 0002 /* auto XON/XOFF */ #define DMF_TE 0001 /* transmit enable */ #define DMFLCR_ENA (DMF_RE|DMF_TE) /* bits in dm lsr, copied from dh.c */ #define DML_USR 0001000 /* usr modem sig, not a real DM bit */ #define DML_DSR 0000400 /* data set ready, not a real DM bit */ #define DML_RNG 0000200 /* ring */ #define DML_CAR 0000100 /* carrier detect */ #define DML_CTS 0000040 /* clear to send */ #define DML_SR 0000020 /* secondary receive */ #define DML_ST 0000010 /* secondary transmit */ #define DML_RTS 0000004 /* request to send */ #define DML_DTR 0000002 /* data terminal ready */ #define DML_LE 0000001 /* line enable */ /* * Local variables for the driver */ char dmf_speeds[] = { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 }; struct tty dmf_tty[NDMF*8]; char dmfsoftCAR[NDMF]; #ifndef lint int ndmf = NDMF*8; /* used by iostat */ #endif int dmfact; /* mask of active dmf's */ int dmfstart(), ttrstrt(); #ifdef DMFDMA /* * The clist space is mapped by the driver onto each UNIBUS. * The UBACVT macro converts a clist space address for unibus uban * into an i/o space address for the DMA routine. */ int dmf_ubinfo[MAXNUBA]; /* info about allocated unibus map */ static int cbase[MAXNUBA]; /* base address in unibus map */ #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) #endif /* * Routine for configuration to set dmf interrupt. */ /*ARGSUSED*/ dmfprobe(reg, ctlr) caddr_t reg; int ctlr; { register int br, cvec; /* these are ``value-result'' */ register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg; #ifdef lint br = 0; cvec = br; br = cvec; dmfxint(0); dmfrint(0); dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(); #endif br = 0x15; cvec = (uba_hd[numuba].uh_lastiv -= 4*8); dmfaddr->dmfccsr0 = cvec >> 2; /* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */ return (sizeof (struct dmfdevice)); } /* * Routine called to attach a dmf. */ dmfattach(ui) struct uba_device *ui; { dmfsoftCAR[ui->ui_unit] = ui->ui_flags; } /* * Open a DMF32 line, mapping the clist onto the uba if this * is the first dmf on this uba. Turn on this dmf if this is * the first use of it. */ /*ARGSUSED*/ dmfopen(dev, flag) dev_t dev; { register struct tty *tp; register int unit, dmf; register struct dmfdevice *addr; register struct uba_device *ui; int s; unit = minor(dev); dmf = unit >> 3; if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) return (ENXIO); tp = &dmf_tty[unit]; if (tp->t_state&TS_XCLUDE && u.u_uid!=0) return (EBUSY); addr = (struct dmfdevice *)ui->ui_addr; tp->t_addr = (caddr_t)addr; tp->t_oproc = dmfstart; tp->t_state |= TS_WOPEN; /* * While setting up state for this uba and this dmf, * block uba resets which can clear the state. */ s = spl5(); #ifdef DMFDMA if (dmf_ubinfo[ui->ui_ubanum] == 0) { dmf_ubinfo[ui->ui_ubanum] = uballoc(ui->ui_ubanum, (caddr_t)cfree, nclist*sizeof(struct cblock), 0); cbase[ui->ui_ubanum] = dmf_ubinfo[ui->ui_ubanum]&0x3ffff; } #endif if ((dmfact&(1<dmfcsr |= DMF_IE; dmfact |= (1<dmfrsp = 1; /* DON'T KNOW WHAT TO SET IT TO YET */ } splx(s); /* * If this is first open, initialze tty state to default. */ if ((tp->t_state&TS_ISOPEN) == 0) { ttychars(tp); if (tp->t_ispeed == 0) { tp->t_ispeed = B300; tp->t_ospeed = B300; tp->t_flags = ODDP|EVENP|ECHO; } dmfparam(unit); } /* * Wait for carrier, then process line discipline specific open. */ if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) || (dmfsoftCAR[dmf] & (1<<(unit&07)))) tp->t_state |= TS_CARR_ON; s = spl5(); while ((tp->t_state & TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; sleep((caddr_t)&tp->t_rawq, TTIPRI); } splx(s); return ((*linesw[tp->t_line].l_open)(dev, tp)); } /* * Close a DMF32 line. */ /*ARGSUSED*/ dmfclose(dev, flag) dev_t dev; int flag; { register struct tty *tp; register unit; unit = minor(dev); tp = &dmf_tty[unit]; (*linesw[tp->t_line].l_close)(tp); (void) dmfmctl(unit, DMF_BRK, DMBIC); if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) (void) dmfmctl(unit, DMF_OFF, DMSET); ttyclose(tp); } dmfread(dev, uio) dev_t dev; struct uio *uio; { register struct tty *tp; tp = &dmf_tty[minor(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio)); } dmfwrite(dev, uio) dev_t dev; struct uio *uio; { register struct tty *tp; tp = &dmf_tty[minor(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio)); } /* * DMF32 receiver interrupt. */ dmfrint(dmf) int dmf; { register struct tty *tp; register c; register struct dmfdevice *addr; register struct tty *tp0; register struct uba_device *ui; int overrun = 0; ui = dmfinfo[dmf]; if (ui == 0 || ui->ui_alive == 0) return; addr = (struct dmfdevice *)ui->ui_addr; tp0 = &dmf_tty[dmf<<3]; /* * Loop fetching characters from the silo for this * dmf until there are no more in the silo. */ while ((c = addr->dmfrbuf) < 0) { tp = tp0 + ((c>>8)&07); if (c & DMF_DSC) { addr->dmfcsr = DMF_IE | DMFIR_TBUF | ((c>>8)&07); if (addr->dmfrms & DMF_CAR) { if ((tp->t_state & TS_CARR_ON) == 0) { wakeup((caddr_t)&tp->t_rawq); tp->t_state |= TS_CARR_ON; } } else { if (tp->t_state & TS_CARR_ON) { gsignal(tp->t_pgrp, SIGHUP); gsignal(tp->t_pgrp, SIGCONT); addr->dmfcsr = DMF_IE | DMFIR_LCR | ((c>>8)&07); addr->dmfun.dmfirw &= 0xff; flushtty(tp, FREAD|FWRITE); } tp->t_state &= ~TS_CARR_ON; } continue; } if ((tp->t_state&TS_ISOPEN)==0) { wakeup((caddr_t)tp); continue; } if (c & DMF_PE) if ((tp->t_flags&(EVENP|ODDP))==EVENP || (tp->t_flags&(EVENP|ODDP))==ODDP ) continue; if ((c & DMF_DO) && overrun == 0) { printf("dmf%d: silo overflow\n", dmf); overrun = 1; } if (c & DMF_FE) /* * At framing error (break) generate * a null (in raw mode, for getty), or a * interrupt (in cooked/cbreak mode). */ if (tp->t_flags&RAW) c = 0; else c = tp->t_intrc; #if NBK > 0 if (tp->t_line == NETLDISC) { c &= 0177; BKINPUT(c, tp); } else #endif (*linesw[tp->t_line].l_rint)(c, tp); } } /* * Ioctl for DMF32. */ /*ARGSUSED*/ dmfioctl(dev, cmd, data, flag) dev_t dev; caddr_t data; { register struct tty *tp; register int unit = minor(dev); int error; tp = &dmf_tty[unit]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) { if (cmd == TIOCSETP || cmd == TIOCSETN) dmfparam(unit); return (error); } switch (cmd) { case TIOCSBRK: (void) dmfmctl(dev, DMF_BRK, DMBIS); break; case TIOCCBRK: (void) dmfmctl(dev, DMF_BRK, DMBIC); break; case TIOCSDTR: (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS); break; case TIOCCDTR: (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC); break; case TIOCMSET: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET); break; case TIOCMBIS: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS); break; case TIOCMBIC: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC); break; case TIOCMGET: *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET)); break; default: return (ENOTTY); } return (0); } dmtodmf(bits) register int bits; { register int b; b = bits & 012; if (bits & DML_ST) b |= DMF_RATE; if (bits & DML_RTS) b |= DMF_RTS; if (bits & DML_USR) b |= DMF_USRW; return(b); } dmftodm(bits) register int bits; { register int b; b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE; if (bits & DMF_USRR) b |= DML_USR; if (bits & DMF_RTS) b |= DML_RTS; return(b); } /* * Set parameters from open or stty into the DMF hardware * registers. */ dmfparam(unit) register int unit; { register struct tty *tp; register struct dmfdevice *addr; register int lpar, lcr; int s; tp = &dmf_tty[unit]; addr = (struct dmfdevice *)tp->t_addr; /* * Block interrupts so parameters will be set * before the line interrupts. */ s = spl5(); addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE; if ((tp->t_ispeed)==0) { tp->t_state |= TS_HUPCLS; (void) dmfmctl(unit, DMF_OFF, DMSET); return; } lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8); lcr = DMFLCR_ENA; if ((tp->t_ispeed) == B134) lpar |= BITS6|PENABLE; else if (tp->t_flags & (RAW|LITOUT)) lpar |= BITS8; else { lpar |= BITS7|PENABLE; /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */ } if ((tp->t_flags&EVENP) == 0) lpar |= OPAR; if ((tp->t_ospeed) == B110) lpar |= TWOSB; lpar |= (unit&07); addr->dmflpr = lpar; addr->dmfun.dmfirw = lcr | (addr->dmftms << 8); splx(s); } /* * DMF32 transmitter interrupt. * Restart the idle line. */ dmfxint(dmf) int dmf; { register struct tty *tp; register struct dmfdevice *addr; register struct uba_device *ui; register int unit, t; #ifdef DMFDMA short cntr; #endif ui = dmfinfo[dmf]; addr = (struct dmfdevice *)ui->ui_addr; while ((t = addr->dmfcsr) & DMF_TI) { unit = dmf*8 + ((t>>8)&07); tp = &dmf_tty[unit]; tp->t_state &= ~TS_BUSY; if (t & DMF_NXM) { printf("dmf%d: NXM line %d\n", dmf, unit&7); /* SHOULD RESTART OR SOMETHING... */ } if (tp->t_state&TS_FLUSH) tp->t_state &= ~TS_FLUSH; #ifdef DMFDMA else { addr->dmfcsr = DMFIR_TBUF | DMF_IE | (unit&07); if (addr->dmftsc == 0) { /* * Do arithmetic in a short to make up * for lost 16&17 bits. */ addr->dmfcsr = DMFIR_TBA | DMF_IE | (unit&07); cntr = addr->dmftba - UBACVT(tp->t_outq.c_cf, ui->ui_ubanum); ndflush(&tp->t_outq, (int)cntr); } } #endif if (tp->t_line) (*linesw[tp->t_line].l_start)(tp); else dmfstart(tp); } } /* * Start (restart) transmission on the given DMF32 line. */ dmfstart(tp) register struct tty *tp; { register struct dmfdevice *addr; register int car, dmf, unit, nch; int s; unit = minor(tp->t_dev); dmf = unit >> 3; unit &= 07; addr = (struct dmfdevice *)tp->t_addr; /* * Must hold interrupts in following code to prevent * state of the tp from changing. */ s = spl5(); /* * If it's currently active, or delaying, no need to do anything. */ if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) goto out; /* * If there are still characters in the silo, * just reenable the transmitter. */ addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; if (addr->dmftsc) { addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; addr->dmfun.dmfirw |= DMF_TE; tp->t_state |= TS_BUSY; goto out; } /* * If there are sleepers, and output has drained below low * water mark, wake up the sleepers. */ if ((tp->t_state&TS_ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } /* * Now restart transmission unless the output queue is * empty. */ if (tp->t_outq.c_cc == 0) goto out; if (tp->t_flags & (RAW|LITOUT)) nch = ndqb(&tp->t_outq, 0); else { nch = ndqb(&tp->t_outq, 0200); /* * If first thing on queue is a delay process it. */ if (nch == 0) { nch = getc(&tp->t_outq); timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); tp->t_state |= TS_TIMEOUT; goto out; } } /* * If characters to transmit, restart transmission. */ if (nch) { #ifdef DMFDMA addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; addr->dmfun.dmfirw |= DMF_TE; car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum); addr->dmfcsr = DMF_IE | DMFIR_TBA | unit; addr->dmftba = car; addr->dmftcc = ((car>>2)&0xc000) | nch; #else register char *cp = tp->t_outq.c_cf; register int i; nch = MIN(nch, DMF_SILOCNT); addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; addr->dmfun.dmfirw |= DMF_TE; addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; for (i = 0; i < nch; i++) addr->dmftbuf = *cp++; ndflush(&tp->t_outq, nch); #endif tp->t_state |= TS_BUSY; } out: splx(s); } /* * Stop output on a line, e.g. for ^S/^Q or output flush. */ /*ARGSUSED*/ dmfstop(tp, flag) register struct tty *tp; { register struct dmfdevice *addr; register int unit, s; addr = (struct dmfdevice *)tp->t_addr; /* * Block input/output interrupts while messing with state. */ s = spl5(); if (tp->t_state & TS_BUSY) { /* * Device is transmitting; stop output * by selecting the line and disabling * the transmitter. If this is a flush * request then flush the output silo, * otherwise we will pick up where we * left off by enabling the transmitter. */ unit = minor(tp->t_dev); addr->dmfcsr = DMFIR_LCR | (unit&07) | DMF_IE; addr->dmfun.dmfirw &= ~DMF_TE; if ((tp->t_state&TS_TTSTOP)==0) { tp->t_state |= TS_FLUSH; addr->dmflcr |= DMF_FLUSH; } else tp->t_state &= ~TS_BUSY; } splx(s); } /* * DMF32 modem control */ dmfmctl(dev, bits, how) dev_t dev; int bits, how; { register struct dmfdevice *dmfaddr; register int unit, mbits, lcr; int s; unit = minor(dev); dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); unit &= 07; s = spl5(); dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; mbits = dmfaddr->dmfrms << 8; dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit; mbits |= dmfaddr->dmftms; lcr = dmfaddr->dmflcr; switch (how) { case DMSET: mbits = bits; break; case DMBIS: mbits |= bits; break; case DMBIC: mbits &= ~bits; break; case DMGET: (void) splx(s); return(mbits); } if (mbits & DMF_BRK) lcr |= DMF_RBRK; else lcr &= ~DMF_RBRK; lcr &= ~DMF_MIE; /* for local use, this bit causes only problems*/ dmfaddr->dmfun.dmfirw = ((mbits & 037) << 8) + (lcr & 0377); (void) splx(s); return(mbits); } /* * Reset state of driver if UBA reset was necessary. * Reset the csr, lpr, and lcr registers on open lines, and * restart transmitters. */ dmfreset(uban) int uban; { register int dmf, unit; register struct tty *tp; register struct uba_device *ui; register struct dmfdevice *addr; int i; #ifdef DMFDMA if (dmf_ubinfo[uban] == 0) return; dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, nclist*sizeof (struct cblock), 0); cbase[uban] = dmf_ubinfo[uban]&0x3ffff; #endif for (dmf = 0; dmf < NDMF; dmf++) { ui = dmfinfo[dmf]; if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) continue; printf(" dmf%d", dmf); addr = (struct dmfdevice *)ui->ui_addr; addr->dmfcsr = DMF_IE; addr->dmfrsp = 1; unit = dmf * 8; for (i = 0; i < 8; i++) { tp = &dmf_tty[unit]; if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { dmfparam(unit); (void) dmfmctl(unit, DMF_ON, DMSET); tp->t_state &= ~TS_BUSY; dmfstart(tp); } unit++; } } } /* stubs for interrupt routines for devices not yet supported */ dmfsrint() { printf("dmfsrint\n"); } dmfsxint() { printf("dmfsxint\n"); } dmfdaint() { printf("dmfdaint\n"); } dmfdbint() { printf("dmfdbint\n"); } dmflint() { printf("dmflint\n"); } #endif From satz@sri-joyce.ARPA Sun Dec 18 17:17:49 1983 Date: 17 Dec 83 01:57:26 PST (Sat) From: Greg Satz Subject: bugs in 4.2 and 2.9 tftp user program Status: O The tftp (trivial ftp) program doesn't work. It seems someone didn't read the fine print when reading the protocol. Index: ucb/tftp/tftp.c ucb/tftp/main.c 4.2BSD Description: The tftp program as distributed doesn't work. When trying to tftp a file, the first block of data is received and an ACK reply is sent, but subsequent data is never sent. Another symptom is getting an error packet from the remote tftp server saying last packet contained an illegal opcode. Since netascii format requires all line feeds to be preceeded by carriage return, something should be done with the carriage returns. I have only tested the get command. The only way I can get a file is to print out the value of sin.sin_port after it has been reassigned its new value. If I don't print it out, it acts like the assignment is never done. This seems like a C compile bug. Repeat-By: Run tftp and try to get or put a file. Watch it loop forever or time-out. Fix: The protocol requires that you send either a read request (RRQ) or write request (WRQ) to a host on port 69 (decimal). All further packets should be sent to the port that the tftp daemon returns not to port 69. Make the following changes to tftp.c: *** /usr/src/ucb/tftp/tftp.c_ Thu Aug 11 22:44:53 1983 --- /usr/src/ucb/tftp/tftp.c Sat Dec 17 00:10:25 1983 *************** *** 89,94 perror("tftp: recvfrom"); goto abort; } if (trace) tpacket("received", tp, n); /* should verify packet came from server */ --- 89,95 ----- perror("tftp: recvfrom"); goto abort; } + sin.sin_port = from.sin_port; if (trace) tpacket("received", tp, n); /* should verify packet came from server */ *************** *** 99,105 tp->th_msg); goto abort; } ! } while (tp->th_opcode != ACK && block != tp->th_block); if (block > 0) amount += size; block++; --- 100,106 ----- tp->th_msg); goto abort; } ! } while (tp->th_opcode != ACK || block != tp->th_block); if (block > 0) amount += size; block++; *************** *** 157,162 perror("tftp: recvfrom"); goto abort; } if (trace) tpacket("received", tp, n); /* should verify client address */ --- 158,164 ----- perror("tftp: recvfrom"); goto abort; } + sin.sin_port = from.sin_port; if (trace) tpacket("received", tp, n); /* should verify client address */ *************** *** 167,173 tp->th_msg); goto abort; } ! } while (tp->th_opcode != DATA && block != tp->th_block); size = write(fd, tp->th_data, n - 4); if (size < 0) { nak(errno + 100); --- 169,175 ----- tp->th_msg); goto abort; } ! } while (tp->th_opcode != DATA || block != tp->th_block); size = write(fd, tp->th_data, n - 4); if (size < 0) { nak(errno + 100); You need to reset the original port (69 decimal) after each command. These changes to main.c will do that: *** /usr/src/ucb/tftp/main.c_ Thu Aug 11 22:44:53 1983 --- /usr/src/ucb/tftp/main.c Sat Dec 17 00:13:53 1983 *************** *** 22,27 struct sockaddr_in sin; int f; int trace; int verbose; int connected; --- 22,28 ----- struct sockaddr_in sin; int f; + short port; int trace; int verbose; int connected; *************** *** 149,155 strcpy(hnamebuf, argv[1]); hostname = hnamebuf; } ! sin.sin_port = sp->s_port; if (argc == 3) { sin.sin_port = atoi(argv[2]); if (sin.sin_port < 0) { --- 150,156 ----- strcpy(hnamebuf, argv[1]); hostname = hnamebuf; } ! port = sin.sin_port = sp->s_port; if (argc == 3) { sin.sin_port = atoi(argv[2]); if (sin.sin_port < 0) { *************** *** 157,163 connected = 0; return; } ! sin.sin_port = htons((u_short)sin.sin_port); } connected = 1; } --- 158,164 ----- connected = 0; return; } ! port = sin.sin_port = htons((u_short)sin.sin_port); } connected = 1; } *************** *** 456,461 if (!top) putchar('\n'); for (;;) { printf("%s> ", prompt); if (gets(line) == 0) continue; --- 457,463 ----- if (!top) putchar('\n'); for (;;) { + sin.sin_port = port; printf("%s> ", prompt); if (gets(line) == 0) continue; From gwyn@brl-vld.ARPA Tue Dec 20 10:11:53 1983 Date: Tue, 20 Dec 83 5:31:28 EST From: Doug Gwyn (VLD/VMB) Subject: improved 4.2BSD signal(2) library routine Status: O /* signal -- old system call emulation for 4.2BSD (VAX version) (adapted from BRL UNIX System V emulation for 4.2BSD) last edit: 20-Dec-1983 D A Gwyn NOTE: Although this module is VAX-specific, it should be possible to adapt it to other fairly clean implementations of 4.2BSD. The difficulty lies in avoiding the automatic restart of certain system calls when the signal handler returns. I use here a trick first described by Donn Seeley of UCSD Chem. Dept. */ #include #include extern int sigvec(); extern int sigsetmask(); extern etext; extern int errno; /* # bytes to skip at the beginning of C ret_eintr() function code: */ #define OFFSET 2 /* for VAX .word reg_mask */ /* PC will be pointing at a syscall if it is to be restarted: */ typedef unsigned char opcode; /* one byte long */ #define SYSCALL 0xBC /* VAX CHMK instruction */ static int (*handler[NSIG])() = /* "current handler" memory */ { BADSIG /* initially, unknown state */ }; static int catchsig(); static int ret_eintr(); int (* signal( sig, func ) /* returns previous handler */ )() register int sig; /* signal affected */ register int (*func)(); /* new handler */ { register int (*retval)(); /* previous handler value */ struct sigvec oldsv; /* previous state */ struct sigvec newsv; /* state being set */ if ( func >= (int (*)())&etext ) /* "lint" hates this */ { errno = EFAULT; return BADSIG; /* error */ } /* cancel pending signals */ newsv.sv_handler = SIG_IGN; newsv.sv_mask = newsv.sv_onstack = 0; if ( sigvec( sig, &newsv, &oldsv ) != 0 ) return BADSIG; /* error */ /* the first time for this sig, get state from the system */ if ( (retval = handler[sig-1]) == BADSIG ) retval = oldsv.sv_handler; handler[sig-1] = func; /* keep track of state */ if ( func == SIG_DFL ) newsv.sv_handler = SIG_DFL; else if ( func != SIG_IGN ) newsv.sv_handler = catchsig; /* actual sig catcher */ if ( func != SIG_IGN /* sig already being ignored */ && sigvec( sig, &newsv, (struct sigvec *)0 ) != 0 ) return BADSIG; /* error */ return retval; /* previous handler */ } /*ARGSUSED*/ static int catchsig( sig, code, scp ) /* signal interceptor */ register int sig; /* signal number */ int code; /* code for SIGILL, SIGFPE */ register struct sigcontext *scp; /* -> interrupted context */ { struct sigvec oldsv; /* previous state */ struct sigvec newsv; /* state being set */ /* at this point, sig is blocked */ /* most UNIXes usually want the state reset to SIG_DFL */ if ( sig != SIGILL && sig != SIGTRAP ) { newsv.sv_handler = SIG_DFL; newsv.sv_mask = newsv.sv_onstack = 0; (void)sigvec( sig, &newsv, &oldsv ); } (void)sigsetmask( scp->sc_mask ); /* restore old mask */ /* at this point, sig is not blocked, usually have SIG_DFL; a longjmp may safely be taken by the user signal handler */ (void)(*handler[sig-1])( sig ); /* user signal handler */ /* must now avoid restarting certain system calls */ if ( *(opcode *)scp->sc_pc == (opcode)SYSCALL ) scp->sc_pc = (int)ret_eintr + OFFSET; /* return here restores interrupted context */ } static int ret_eintr() /* substitute for system call */ { errno = EINTR; return -1; } From mccallum@opus.ARPA Wed Dec 21 15:14:15 1983 Date: 20 Dec 83 6:38:33-PST (Tue) From: seismo!hplabs!hao!cires!nbires!opus!mccallum@ucb-vax Subject: Re: panic: munhash (4.2BSD crash) Status: RO The bug fix for the panic: munhash in 4.2/4.1c has been posted. The posted fix did not explain under what conditions the panic occurs. The problem shows up when you have a LARGE file system and use a debugger on program that resides in the part of the file system that makes the block number field use all 20 bits. The fix is as follows: Path: opus!nbires!cires!hao!hplabs!sri-unix!RWS@mit-xx From: RWS%mit-xx@sri-unix.UUCP Newsgroups: net.unix-wizards Subject: sundry 4.2 bugs Message-ID: <13280@sri-arpa.UUCP> Date: Wed, 2-Nov-83 15:15:00 MST Article-I.D.: sri-arpa.13280 Posted: Wed Nov 2 15:15:00 1983 Date-Received: Thu, 3-Nov-83 18:47:16 MST Lines: 64 Despite claims to the contrary, the block number sign extension problem still exists. Berkeley put in a fix that should have worked, but a C compiler bug apparently keeps it from working. In /sys/sys/vm_mem.c in memall() the code swapdev : mount[c->c_mdev].m_dev, (daddr_t)(u_long)c->c_blkno should be changed to swapdev : mount[c->c_mdev].m_dev, c->c_blkno and in /sys/vax/vm_machdep.c in chgprot() the code munhash(mount[c->c_mdev].m_dev, (daddr_t)(u_long)c->c_blkno); should be changed to munhash(mount[c->c_mdev].m_dev, c->c_blkno); because the C compiler apparently incorrectly folds the (daddr_t) and (u_long) together and sign extends anyway. Simply taking out the (daddr_t)(u_long) works, although lint will probably complain about it. From thomson@utcsrgv.UUCP Tue Dec 20 18:59:28 1983 From: thomson@utcsrgv.UUCP (Brian Thomson) Subject: 4.2BSD non-blocking sockets and selects Date: Tue, 20 Dec 83 18:59:28 EST Status: O Index: sys/uipc_socket.c h/socketvar.h 4.2BSD Description: If you do a select() for writing on a non-blocking SOCK_STREAM socket, and there is some send queue buffer space available, it will tell you the socket can be written. But sosend() insists that all writes to non-blocking sockets be atomic, and will return EWOULDBLOCK if there is not enough buffer space for the entire write to go in one shot. This behaviour is OK for non-stream sockets, but streams should allow partial writes. A couple of distributed utilities agree with me ... Repeat-by: Both rlogind(1) and telnetd(1) are prepared for partial socket writes. Try this: % rlogin localhost < message of the day > % cat /usr/dict/words ~^Z (i.e. suspend the rlogin locally) Stopped % jobs [1] Stopped rlogin localhost % An iostat at this point will show (unless you happen to exactly fill the send queue) that your system is being eaten alive by rlogind. Fix: Allow partial writes to non-blocking sockets unless the underlying protocol is atomic. This is consistent with the behaviour of non-blocking ttys, which are a good model for stream-oriented sockets. In file /sys/h/socketvar.h, change: #define sosendallatonce(so) \ (((so)->so_state & SS_NBIO) || ((so)->so_proto->pr_flags & PR_ATOMIC)) to #define sosendallatonce(so) \ ((so)->so_proto->pr_flags & PR_ATOMIC) In file /sys/sys/uipc_socket.c, routine sosend(), diff -c shows: *************** *** 281,286 register int space; int len, error = 0, s, dontroute; struct sockbuf sendtempbuf; if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) return (EMSGSIZE); --- 287,293 ----- register int space; int len, error = 0, s, dontroute; struct sockbuf sendtempbuf; + int sentsome = 0; if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) return (EMSGSIZE); *************** *** 324,329 goto release; } mp = ⊤ } if (uio->uio_resid == 0) { splx(s); --- 331,337 ----- goto release; } mp = ⊤ + sentsome = 1; } if (uio->uio_resid == 0) { splx(s); *************** *** 336,342 if (space <= 0 || sosendallatonce(so) && space < uio->uio_resid) { if (so->so_state & SS_NBIO) ! snderr(EWOULDBLOCK); sbunlock(&so->so_snd); sbwait(&so->so_snd); splx(s); --- 344,353 ----- if (space <= 0 || sosendallatonce(so) && space < uio->uio_resid) { if (so->so_state & SS_NBIO) ! if(sentsome) ! { splx(s); goto release; } ! else ! snderr(EWOULDBLOCK); sbunlock(&so->so_snd); sbwait(&so->so_snd); splx(s); Reservation: You should probably HOLD OFF installing this change until it gets batted about the net a bit. The original behaviour appears to have been quite deliberate, and although I do think it's wrong, I'd like to give someone in the know a chance to explain the unobvious reason that it was right in the first place! -- Brian Thomson, CSRG Univ. of Toronto {linus,ihnp4,uw-beaver,floyd,utzoo}!utcsrgv!thomson From jim@haring.UUCP Tue Dec 20 09:05:59 1983 From: jim@haring.UUCP (Jim McKie) Subject: /etc/rmt protocol botch Date: Tue, 20 Dec 83 09:05:59 EST Status: O The following is a bug report on a botch in the remote magtape protocol described in RMT(8). I found this when writing a set of routines (topen, tread, twrite, etc.) for a program to let us do remote tape-to-tape copies. Jim McKie Centrum voor Wiskunde en Informatica ..mcvax!jim --------------------------------------------------------------------------- Subject: /etc/rmt protocol botch Index: /usr/src/etc/rmt.c 4.2BSD Description: The remote magtape protocol described in RMT(8) is not followed by the module "/etc/rmt" with respect to the 'S' command. Repeat-By: Write a short program which creates a connection to the /etc/rmt on another machine then try an 'S' command - you will not get a valid response back (i.e. 'A') if the operation was successfull. /etc/rmt will send back the contents of a successfull MTIOCGET ioctl BEFORE it sends back the 'A' response. Fix: Change the two lines in the code for the 'S' command from (void) write(1, (char *)&mtget, sizeof (mtget)); goto respond; to (void) sprintf(resp, "A%d\n", rval); (void) write(1, resp, strlen(resp)); (void) write(1, (char *)&mtget, sizeof (mtget)); goto top; Another (fairly benign) bug is that all arrays declared of size 'SSIZE' should be of size 'SSIZE+1', to deal with one of the terminating conditions of the 'for' loop in the function 'gets'. From gwyn@brl-vld.ARPA Thu Dec 22 17:21:24 1983 Date: Thu, 22 Dec 83 17:07:43 EST From: Doug Gwyn (VLD/VMB) Subject: Re: 4.2BSD signal(2) replacement To: Rick Adams Status: O /* signal -- old system call emulation for 4.2BSD (VAX version) (adapted from BRL UNIX System V emulation for 4.2BSD) last edit: 22-Dec-1983 D A Gwyn NOTE: Although this module is VAX-specific, it should be possible to adapt it to other fairly clean implementations of 4.2BSD. The difficulty lies in avoiding the automatic restart of certain system calls when the signal handler returns. I use here a trick first described by Donn Seeley of UCSD Chem. Dept. */ #include #include #include extern int sigvec(); extern int sigsetmask(); extern etext; extern int errno; /* # bytes to skip at the beginning of C ret_eintr() function code: */ #define OFFSET 2 /* for VAX .word reg_mask */ /* PC will be pointing at a syscall if it is to be restarted: */ typedef unsigned char opcode; /* one byte long */ #define SYSCALL ((opcode)0xBC) /* VAX CHMK instruction */ #define IMMEDIATE ((opcode)0x8F) /* VAX immediate addressing */ static int (*handler[NSIG])() = /* "current handler" memory */ { BADSIG /* initially, unknown state */ }; static int catchsig(); static int ret_eintr(); int (* signal( sig, func ) /* returns previous handler */ )() register int sig; /* signal affected */ register int (*func)(); /* new handler */ { register int (*retval)(); /* previous handler value */ struct sigvec oldsv; /* previous state */ struct sigvec newsv; /* state being set */ if ( func >= (int (*)())&etext ) /* "lint" hates this */ { errno = EFAULT; return BADSIG; /* error */ } /* cancel pending signals */ newsv.sv_handler = SIG_IGN; newsv.sv_mask = newsv.sv_onstack = 0; if ( sigvec( sig, &newsv, &oldsv ) != 0 ) return BADSIG; /* error */ /* the first time for this sig, get state from the system */ if ( (retval = handler[sig-1]) == BADSIG ) retval = oldsv.sv_handler; handler[sig-1] = func; /* keep track of state */ if ( func == SIG_DFL ) newsv.sv_handler = SIG_DFL; else if ( func != SIG_IGN ) newsv.sv_handler = catchsig; /* actual sig catcher */ if ( func != SIG_IGN /* sig already being ignored */ && sigvec( sig, &newsv, (struct sigvec *)0 ) != 0 ) return BADSIG; /* error */ return retval; /* previous handler */ } /*ARGSUSED*/ static int catchsig( sig, code, scp ) /* signal interceptor */ register int sig; /* signal number */ int code; /* code for SIGILL, SIGFPE */ register struct sigcontext *scp; /* -> interrupted context */ { register opcode *pc; /* for snooping instructions */ struct sigvec oldsv; /* previous state */ struct sigvec newsv; /* state being set */ /* at this point, sig is blocked */ /* most UNIXes usually want the state reset to SIG_DFL */ if ( sig != SIGILL && sig != SIGTRAP ) { newsv.sv_handler = SIG_DFL; newsv.sv_mask = newsv.sv_onstack = 0; (void)sigvec( sig, &newsv, &oldsv ); } (void)sigsetmask( scp->sc_mask ); /* restore old mask */ /* at this point, sig is not blocked, usually have SIG_DFL; a longjmp may safely be taken by the user signal handler */ (void)(*handler[sig-1])( sig ); /* user signal handler */ /* must now avoid restarting certain system calls */ pc = (opcode *)scp->sc_pc; if ( *pc++ == SYSCALL && (*pc == SYS_read || *pc == SYS_write || *pc == SYS_ioctl || *pc++ == IMMEDIATE && (*pc == SYS_wait || *pc == SYS_readv || *pc == SYS_writev) ) ) scp->sc_pc = (int)ret_eintr + OFFSET; /* return here restores interrupted context */ } static int ret_eintr() /* substitute for system call */ { errno = EINTR; return -1; } From jaap@haring.UUCP Sun Dec 25 21:01:09 1983 From: jaap@haring.UUCP (Jaap Akkerhuis) Subject: lprm doesn't work at all at 4.2bsd (and vplotf as well) Date: Sun, 25 Dec 83 21:01:09 EST Status: O Lprm didn't work correctly, when we got our distribution for the VAX. Index: usr.lib/lprm 4.2BSD Description: You would get after: $ print /etc/passwd $ lpq lp is ready & printing Rank Owner Job Files Total Size active jaap 219 /etc/passwd 5790 bytes $ lprm jaap dfa219mcvax dequeued cfa219mcvax dequeued /usr/lib/lpd: mcvax: unknown printer lprm: lp: cannot restart printer daemon (Assumed is that the log file is /dev/console, and you are doing this on the console...) Caused by: rmjob tries to restart the daemon with startdaemon(host), instead of startdaemon(printer). Fixed by: change the call startdeamon(host) into startdeamon(printer) in rmjob.c Since we are talking about the spooler things, here is another one: Index: usr.bin/lpr/vplotf.c Description: The vplotf filter produces a square instaed of a circle Fixed by: The definition of labs(a) needs some more brackets, else an if statement will do something, what it is clearly not supposed to be in the routine circle(). So this is the right define: #define labs(a) ((a) >= 0 ? (a) : -(a)) By the way, has anybody an just as elegant algorithm for generating an arc as the one for a circle? jaap akkerhuis, with thanks to guido (mcvax!guido) From rws@mit-bold.ARP Mon Jan 2 16:11:00 1984 Newsgroups: net.unix-wizards Subject: 3rd party copies don't work in 4.2 rcp Date: Mon, 2 Jan 84 16:11:00 EST Status: O From: Robert W. Scheifler Description: rcp (version 4.8) doesn't work for 3rd party copies. In forking rsh it uses -L instead of -l, and uses the wrong user name at the destination. Even with this fix, I don't think this form of copy has the right semantics in terms of who must be equivalent to whom. I would have thought that if I could do rcp host1.name1:foo /tmp/foo rcp /tmp/foo host2.name2:foo then I should be able to do rcp host1.name1:foo host2.name2:foo but that isn't the case. The current implementation requires that name1@host1 (not me) be in the .rhosts of name2@host2. Repeat-By: Try doing one. Fix: Here is a 'diff old new' 105c105 < (void) sprintf(buf, "rsh %s -L %s -n %s %s '%s:%s'", --- > (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s.%s:%s'", 107c107 < src, argv[argc - 1], targ); --- > src, argv[argc - 1], tuser, targ); 109c109 < (void) sprintf(buf, "rsh %s -n %s %s '%s:%s'", --- > (void) sprintf(buf, "rsh %s -n %s %s '%s.%s:%s'", 111c111 < src, argv[argc - 1], targ); --- > src, argv[argc - 1], tuser, targ); From lepreau@utah-cs.UUCP Fri Jan 6 06:05:25 1984 From: lepreau@utah-cs.UUCP (Jay Lepreau) Subject: ctime doesn't handle negative times in 4.2 Date: Fri, 6 Jan 84 06:05:25 EST Status: O Index: lib/libc/gen/ctime.c 4.2BSD Fix Description: For negative GMT times, which in the USA can be positive local times, ctime prints out garbage. Matter of fact it is so garbaged that the year has a ^A in it! In particular, this is a problem with local times of 0. gmtime() turns out to be the culprit. Repeat-By: main() /* in timezones west of greenwich */ { int zero = 0; printf("%s", ctime(&zero)); } Fix: This happened cause the types of all the "time" variables in ctime.c have been changed from long in 4.1 to unsigned long in 4.2. Note that sys/types.h says that time_t is long, as do all the man pages. Plus I seem to remember seeing somewhere in the Unix docco that negative times are supposed to "work." And finally, 7fffffff is year 2038, and I expect Unix will be long dead by then, even if the world isn't. All you really have to change are the types in gmtime() itself: 206c206 < unsigned long *tim; --- > long *tim; 209c209 < unsigned long hms, day; --- > long hms, day; From guido@mcvax.UUCP Thu Jan 5 15:20:55 1984 From: guido@mcvax.UUCP (Guido van Rossum) Subject: C log function inaccurate (with fix) (many UNIX versions) Date: Thu, 5 Jan 84 15:20:55 EST Status: O One of my colleagues discovered that the log function the the mathematical C library is quite inaccurate. What's more, he also provided a change to one of the coefficients which much improved it. Here they are: BAD: p2 = -.963769093368686593e1; GOOD: p2 = -.963769093377840513e1; ^^^^^^^^ So now you should all go and fix your C library. I found the same coefficients in UNIX V7 as in 4.2 BSD, so I suspect they are probably in almost all other UNIXes around the world. Related question: the source states "The coefficients are #2705 from Hart & Cheney. (19.38D)". We cannot locate this reference in our institute's library. Does someone know what this references, and give us a more precise pointer? Guido van Rossum, {philabs,decvax}!mcvax!guido Centre for Mathematics and Computer Science, (CWI, formerly MC), Amsterdam (with thanks to Lambert Meertens) From mike@brl-vgr.ARPA Thu Jan 12 03:34:10 1984 Date: Thu, 12 Jan 84 2:30:54 EST From: Mike Muuss Subject: 4.2 BSD Signals: A Proposal Status: O REFRESHER. On 4.1 and earlier UNIX systems, signal handlers had several attributes: *) After a signal was caught, the handler was reset to SIG_DFL. *) If the process was executing a (kernel) sleep() at "low" priority, and a signal was processed, the system call would abort, returning an error code (-1), with errno = u.u_error = EINTR (interupted system call). On 4.2 BSD UNIX, these two aspects of signal handling were altered (along with some other, nice improvements, which are not germane). 1) The signal handler remains "installed" until explicitly changed. 2) System calls which may (kernel) sleep() at "low" priority will be silently restarted after processing an incomming signal. The signal handler will have no idea if this is happening or not. PROBLEM. Clearly, programs written for the old style signal interface will have a fair amount of difficulty coping with difference #2 above, if they depend on signals (especially timer signals) interrupting a system call. Network software which wishes to run timouts around network reads will have to longjmp() in the signal handler, rather than being able to depend on just returning, with an EINTR to be returned from the read/write sys-call that timed out. Editors and shells will have to expect their I/O to be restarted after SIGINT, etc. (You would not believe the crud that Berkeley had to do to /bin/sh to make it still capable of re-printing $PS1 after a SIGINT (^C, etc).). Certainly, change #1 is "mostly harmless"; the number of programs which will break is minimal -- the timing windows which this change fixes were something that no mortal programmer would dare depend on. However, change #2 is truely problematic: Certainly, there are advantages to the new style signal interface, and programs which are written with this style of operation in mind should work out well. However, no matter how hard we try, few of us will be able to afford the luxury of running 4.2 BSD on *all* our machines. Those of you planning on purchasing a Cray-2 (as we are), will have to contend with System-V UNIX (at least to start with). Many other vendors will be non-4.2 BSD, and it is too late to stomp them all out (pitty, no?). And somehow, those venerable old PDP-11s just keep on refusing to quit! THEREFORE, the problem of program portability rears it's ugly head. 4.2 people (true believers) will, of course, deisre to import quality software from elsewhere ("expensive, yes, extravagant, no"), without having to re-write all the signal code. Others may wish to be able to use 4.2 code on their own system ("rotsa-ruck"). Being in the former camp, I would like to offer the following solution: PROPOSED SOLUTION. In proc.h, SOUSIG (1 bit in p_flag) is defined to mean "this process is using the old signal mechanism". This piece of information is used in two ways: 1) To determine resetting of default signal handling after traps (in sys/kern_sig.c and sys/kern_xxx.c). 2) To determine restartability of interrupted ("slow") system calls (in kern_exit.c, sys_generic.c, sys_inode.c). By adding another bit to the p_flag word called SDFLSIG and assigning it function #1 (above) to this new bit, and then redefining the meaning of SOUSIG to JUST function #2 (above), +and+ by adding a new sys-call (#151, sigrestartable()) which permits the user to manipulate the state of the SOUSIG bit, then a solution can be achieved. For programs which do not use the new sys-call, standard 4.2 functionality occurs. Programs which wish to avoid having their sys-calls restarted may say: sigrestartable( 0 ); and get the 4.2 interface, with continuously installed signal handlers, but with sys-calls returning the old familiar EINTR. Calling sigrestartable() with a non-zero argument restores the 4.2 BSD style restartable sys-calls, so that one can "live in both worlds" by switching back and forth. The sys-call is as fast as getpid(), so pairs could reasonably be used around old-fashioned code if one desires to "blend" signaling style within a single program. STATUS. This evening, I installed the change I proposed above, into 2 of our 780s. Effort to change: h/proc.h 2 lines sys/init_sysent.c: 1 line sys/syscalls.c: 1 line sys/kern_sig.c 14 lines sys/kern_exec.c 1 line sys/kern_fork.c 1 line sys/kern_xxx.c 1 line To the best of my ability to test it, this new system call operates exactly as I have described above. QUESTION. What does the UNIX-community-at-large think of this strategy? If people feel that this is a reasonable solution to the 4.2 signal "problem", DPK and I will arrange to reproduce many copies of a 1-page document describing how to install this code into your 4.2 kernel, and distribute them at UNIFORvM in Washington DC next week. On the other hand, if a better proposal can be brought forth, I am willing to withdraw this proposal and implement something else, assuming that it offers a solution of similar generality, elegance, and simplicity (pardon the self-admiration). CREDIT. The motivation for addressing this problem at this time came from a program which Doug Kingston has been working on. His struggles, his requests, and his constructive feedback were instrumental in shaping the form of this solution. Together we evaluated 7 or 8 different solutions to this problem, before the present solution was arrived at. COMMENTS. Please mail your responses to this issue back to the full list. This issue is too important to discuss privately. Best, -Mike Muuss SOURCE CODE. Just in case you desire to try this change yourself, here is the code: h/proc.h (2 changes): change comment to: #define SOUSIG 0x0100000 /* old signal semantics: no restart (BRL) */ add at the bottom: #define SDFLSIG 0x2000000 /* reset signals to default handling (BRL) */ sys/init_sysent.c (2 lines from the bottom): 1, sigrestartable, /* 151 = sigrestartable (BRL) */ sys/syscalls.c (1 line from the bottom): "sigrestartable", /* 151 = sigrestartable */ sys/kern_xxx.c (3 lines from the bottom): from: p->p_flag |= SOUSIG; to: p->p_flag |= SOUSIG|SDFLSIG; sys/kern_exec.c (80% into the file): from: u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SOUSIG); to: u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SOUSIG|SDFLSIG); sys/kern_fork.c (50% into the file): from: rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SOUSIG)); to: rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SOUSIG|SDFLSIG)); sys/kern_sig.c (in psig(), 85% into the file): from: if (p->p_flag & SOUSIG) { to: if (p->p_flag & SDFLSIG) { and, after #define cantmask (mask(SIGKILL)|mask(SIGCONT)|mask(SIGSTOP)) near the front of the file, add this routine: sigrestartable() /* BRL-specific */ { register struct a { int restartable; } *uap = (struct a *)u.u_ap; /* BRL syscall to permit non-restartable signal behavior */ if( uap->restartable ) u.u_procp->p_flag &= ~SOUSIG; /* Restartable */ else u.u_procp->p_flag |= SOUSIG; /* Non-restartable */ } HAPPY HACKING! From cak@Purdue.ARPA Thu Jan 12 22:56:57 1984 Date: 8 Jan 1984 2213-EST (Sunday) From: Christopher A Kent Subject: no way to force local ether traffic onto the wire Status: O Index: sys/netinet/if_ether.c 4.2BSD fix Status: R Description: If it is desired, for testing or other purposes, to force ethernet traffic for the local host to go out onto the wire, it is not possible to do so. Changes to if_ether.c to follow that cause the ethernet traffic to use the loopback device only if it is marked IFF_UP; thus by "ifconfig lo0 down", one can force the packets to go onto the wire. Unfortunately, the ARP code must be changed, as well, since it is designed to ignore incoming packets from itself. A new type of entry, a "sticky" entry, is defined. The interface address definition routine calls the new routine arpinstall() to install a mapping entry for itself; this is a sticky entry that will not be timed out. Thus the resolution can always be done without broadcasting a packet. This feature may also be useful for networks that have simple-minded diskless stations that depend on someone knowing their IP address, using a modified ARP to do a "reverse query". Repeat-By: On an ethernet host, rlogin `hostname`. Inspecting netstat -i will show the the lo packet counts are going up, not the ether device. Fix: Apply the following diffs... *** if_ether.c.old --- if_ether.c.new *************** *** 31,36 /* at_flags field values */ #define ATF_INUSE 1 /* entry in use */ #define ATF_COM 2 /* completed entry (enaddr valid) */ #define ARPTAB_BSIZ 5 /* bucket size */ #define ARPTAB_NB 19 /* number of buckets */ --- 31,37 ----- /* at_flags field values */ #define ATF_INUSE 1 /* entry in use */ #define ATF_COM 2 /* completed entry (enaddr valid) */ + #define ATF_STICKY 4 /* may not be timed out */ #define ARPTAB_BSIZ 5 /* bucket size */ #define ARPTAB_NB 19 /* number of buckets */ *************** *** 124,129 for (i = 0; i < ARPTAB_SIZE; i++, at++) { if (at->at_flags == 0) continue; if (++at->at_timer < ((at->at_flags&ATF_COM) ? ARPT_KILLC : ARPT_KILLI)) continue; --- 125,132 ----- for (i = 0; i < ARPTAB_SIZE; i++, at++) { if (at->at_flags == 0) continue; + if (at->at_flags & ATF_STICKY) + continue; if (++at->at_timer < ((at->at_flags&ATF_COM) ? ARPT_KILLC : ARPT_KILLI)) continue; *************** *** 198,206 return (1); } ifp = &ac->ac_if; ! /* if for us, then use software loopback driver */ ! if (destip->s_addr == ! ((struct sockaddr_in *)&ifp->if_addr)-> sin_addr.s_addr) { sin.sin_family = AF_INET; sin.sin_addr = *destip; return (looutput(&loif, m, (struct sockaddr *)&sin)); --- 201,210 ----- return (1); } ifp = &ac->ac_if; ! /* if for us, then use software loopback driver if available */ ! if ((destip->s_addr == ! ((struct sockaddr_in *)&ifp->if_addr)-> sin_addr.s_addr) && ! ((loif.if_flags & IFF_UP) != 0)) { sin.sin_family = AF_INET; sin.sin_addr = *destip; return (looutput(&loif, m, (struct sockaddr *)&sin)); *************** *** 378,384 for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) { if (at->at_flags == 0) goto out; /* found an empty entry */ ! if (at->at_timer > oldest) { oldest = at->at_timer; ato = at; } --- 382,389 ----- for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) { if (at->at_flags == 0) goto out; /* found an empty entry */ ! if ((at->at_timer > oldest) && ! ((at->at_flags) & ATF_STICKY) == 0) { oldest = at->at_timer; ato = at; } *************** *** 389,392 at->at_iaddr = *addr; at->at_flags = ATF_INUSE; return (at); } --- 394,427 ----- at->at_iaddr = *addr; at->at_flags = ATF_INUSE; return (at); + } + + /* + * Install an ARP mapping. Called by device address routines to force + * a mapping in for themselves. + */ + + arpinstall(ipaddr, enaddr, sticky) + register struct in_addr *ipaddr; + u_char enaddr[6]; + { + struct arptab *at = 0; + int s = splimp(); + + ARPTAB_LOOK(at, ipaddr->s_addr); + if(at){ /* already there! */ + printf("duplicate IP address 0x%X!! overwriting "); + printf("%x %x %x %x %x %x with %x %x %x %x %x %x\n", + at->at_enaddr[0]&0xff, at->at_enaddr[1]&0xff, + at->at_enaddr[2]&0xff, at->at_enaddr[3]&0xff, + at->at_enaddr[4]&0xff, at->at_enaddr[5]&0xff, + enaddr[0]&0xff, enaddr[1]&0xff, + enaddr[2]&0xff, enaddr[3]&0xff, + enaddr[4]&0xff, enaddr[5]&0xff); + }else + at = arptnew(ipaddr); + + bcopy((caddr_t)enaddr, (caddr_t)at->at_enaddr, sizeof(at->at_enaddr)); + at->at_flags |= (ATF_COM | (sticky?ATF_STICKY:0)); + splx(s); } It is also necessary to modify the setaddr routine in the appropriate ethernet interface drivers. NOTE THAT SOME INTERFACES CAN'T HEAR THEIR OWN PACKETS, so this whole thing is useless for them. Notable among these are the 3Com 10Mb and the Xerox 3Mb ethers. We have Interlan hardware; the change for this follows: *** if_il.c.old --- if_il.c.new *************** *** 642,647 register struct ifnet *ifp; register struct sockaddr_in *sin; { ifp->if_addr = *(struct sockaddr *)sin; ifp->if_net = in_netof(sin->sin_addr); --- 644,650 ----- register struct ifnet *ifp; register struct sockaddr_in *sin; { + register struct il_softc *is = &il_softc[ifp->if_unit]; ifp->if_addr = *(struct sockaddr *)sin; ifp->if_net = in_netof(sin->sin_addr); *************** *** 646,651 ifp->if_addr = *(struct sockaddr *)sin; ifp->if_net = in_netof(sin->sin_addr); ifp->if_host[0] = in_lnaof(sin->sin_addr); sin = (struct sockaddr_in *)&ifp->if_broadaddr; sin->sin_family = AF_INET; sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); --- 649,655 ----- ifp->if_addr = *(struct sockaddr *)sin; ifp->if_net = in_netof(sin->sin_addr); ifp->if_host[0] = in_lnaof(sin->sin_addr); + arpinstall(&sin->sin_addr, is->is_stats.ils_addr, 1); sin = (struct sockaddr_in *)&ifp->if_broadaddr; sin->sin_family = AF_INET; sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); ---------- From cak@Purdue.ARPA Fri Jan 13 07:13:05 1984 Date: 11 Jan 1984 1659-EST (Wednesday) From: Christopher A Kent Subject: syslog(3) in distributed libc.a broken Status: O Index: lib/syslog.c 4.2BSD Fix Description: Attempts to use syslog(3) fail in programs that perform other network functions. Output to the log file is garbled, or correct network system call invocations fail for no apparent reason. The syslog supplied with sendmail does, however, function correctly. Inspection of the two versions shows that the C library version neglects to bind the datagram socket to any address. Recompiling the supplied libc source and reinstalling /lib/libc.a causes the problem to go away(!). Repeat-By: Compile and run the following, both with and without an argument, and inspect the syslog output. /* * demonstrate broken syslog */ #include #include #include #include #include struct sockaddr_in sin = { AF_INET }; /* socket address */ main(argc, argv) char **argv; { int s; if(fork()) exit(0); if(argc > 1) openlog("stest", LOG_PID); syslog(LOG_INFO, "starting up"); sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(77); s = socket(AF_INET, SOCK_STREAM, 0, 0); if(s < 0){ perror("socket"); exit(1); } if(bind(s, &sin, sizeof(sin)) < 0){ perror("bind"); exit(1); } syslog(LOG_INFO, "message1"); syslog(LOG_INFO, "message2"); } Fix: While the recompiled version seems to work correctly, the following diff supplies the "missing" bind, for the conservative-minded: *** syslog.c.old --- syslog.c.new *************** *** 119,124 } bzero(&SyslogAddr, sizeof SyslogAddr); SyslogAddr.sin_family = hp->h_addrtype; bcopy(hp->h_addr, (char *)&SyslogAddr.sin_addr, hp->h_length); SyslogAddr.sin_port = sp->s_port; LogStat |= LOG_DGRAM; --- 119,130 ----- } bzero(&SyslogAddr, sizeof SyslogAddr); SyslogAddr.sin_family = hp->h_addrtype; + if(bind(LogFile, &SyslogAddr, sizeof SyslogAddr, 0) < 0){ + perror("syslog: bind"); + close(LogFile); + LogFile = -1; + goto bad; + } bcopy(hp->h_addr, (char *)&SyslogAddr.sin_addr, hp->h_length); SyslogAddr.sin_port = sp->s_port; LogStat |= LOG_DGRAM; ---------- From cak@Purdue.ARPA Fri Jan 13 07:13:13 1984 Date: 11 Jan 1984 2004-EST (Wednesday) From: Christopher A Kent Subject: anonymous ftps aren't recorded in wtmp Status: O Index: etc/ftpd.c 4.2BSD Fix Description: FTP users who log in as "anonymous" or "ftp" are not recorded in wtmp. This is because the logging is done after the chroot call; thus the open of "/usr/adm/wtmp" is now relative to ~ftp. Even if it succeeds, the record is written into the wrong file. Repeat-By: ftp localhost and log in as anonymous. quit and do a last; no session is recorded. Fix: Move the log action to after the user has logged in but before the chroot() call. If the chroot fails, there will be extra log entries, but this is fairly unlikely. A diff: *** ftpd.c.old --- ftpd.c.new *************** *** 235,240 pw->pw_name, pw->pw_dir); goto bad; } if (guest && chroot(pw->pw_dir) < 0) { reply(550, "Can't set guest privileges."); goto bad; --- 235,241 ----- pw->pw_name, pw->pw_dir); goto bad; } + dologin(pw); /* before chroot for ftp */ if (guest && chroot(pw->pw_dir) < 0) { reply(550, "Can't set guest privileges."); goto bad; *************** *** 244,250 else reply(230, "Guest login ok, access restrictions apply."); logged_in = 1; - dologin(pw); seteuid(pw->pw_uid); /* * Save everything so globbing doesn't --- 245,250 ----- else reply(230, "Guest login ok, access restrictions apply."); logged_in = 1; seteuid(pw->pw_uid); /* * Save everything so globbing doesn't ---------- From dpk@brl-vgr.ARPA Fri Jan 13 08:22:54 1984 Date: Thu, 12 Jan 84 3:10:50 EST From: Doug Kingston Subject: sigrestartable.s Status: O The following is the system interface for Mike's sigrestartable system call. This is just the output of cpp cleaned up to be self-contained. Just assemble and load with programs. -Doug- --------- sigrestartable.s ---------- .globl cerror err: jmp cerror; .globl _sigrestart; .align 2; _sigrestart: .word 0; chmk $151; jcs err ret From dpk@brl-vgr.ARPA Fri Jan 13 09:18:43 1984 Date: Fri, 13 Jan 84 0:23:05 EST From: Doug Kingston Subject: 4.2BSD sigrestartable(2) man page Status: O The following is a manual page for the system call interface sigrestartable, as developed at BRL and discussed on this list. sigrestartable.2: .TH SIGRESTARTABLE 2B "11 January 1984" .UC 4 .SH NAME sigrestartable \- change system call restart behavior .SH SYNOPSIS .nf .B sigrestartable(flag); .B int flag; .SH DESCRIPTION .I Sigrestartable is used to change the system call restart behavior when a system call is interrupted by a signal. If the .I flag is one (01), then system calls will be restarted if they are interrupted by a signal and no data has been transferred yet. This is the default behavior on 4.2 BSD. .PP If the .I flag is 0, then restarting of system calls is disabled. If a system call is interrupted and no data has been transferred, the system call will return -1 with .I errno set to EINTR. Interrupted system calls that have started transfering data will return the amount of data actually transferred. This is the signal behavior found on 4.1 BSD and AT&T System V UNIX systems. .PP Note that the new 4.2 BSD signal handling semantics are not altered in any other way. Most notably, signal handlers always remain installed until explicitly changed by a subsequent sigvec(2) call, and the signal mask operates as documented in sigvec(2). Programs may switch between restartable and interruptable system call operation as often as desired in the execution of a program. .PP Issuing an sigrestartable(2) system call during the execution of a signal handler will cause the new action to take place on the \fInext\fR signal to be caught. .SH "RETURN VALUE None. .SH "SEE ALSO" sigvec(2), sigblock(2), sigpause(2), sigsetmask(2). .SH CAVEAT This is a BRL-developed system call, and may not have been adopted on all systems. Hence, while using this system call may make life easier locally, it does not enhance the portability of code to other 4.2 BSD systems. From gwyn@brl-vld.ARPA Fri Jan 13 22:21:17 1984 Date: Fri, 13 Jan 84 7:35:57 EST From: Doug Gwyn (VLD/VMB) Subject: signal(2) emulation for 4.2BSD Status: O I found the following problems in the previously posted emulation: (1) Incorrect initialization of the local handler history array; (2) Failure to update the history to SIG_DFL in the signal catcher. The following code replaces the previous submission. It does not depend on the BRL kernel modification you have been hearing about recently. Recipients of the BRL UNIX System V emulation for 4.2BSD should install corresponding corrections in the two signal.c source files and rebuild things, especially the Bourne shell. /* signal -- old system call emulation for 4.2BSD (VAX version) (adapted from BRL UNIX System V emulation for 4.2BSD) last edit: 13-Jan-1984 D A Gwyn NOTE: Although this module is VAX-specific, it should be possible to adapt it to other fairly clean implementations of 4.2BSD. The difficulty lies in avoiding the automatic restart of certain system calls when the signal handler returns. I use here a trick first described by Donn Seeley of UCSD Chem. Dept. */ #include #include #include extern int sigvec(); extern int sigsetmask(); extern etext; extern int errno; /* # bytes to skip at the beginning of C ret_eintr() function code: */ #define OFFSET 2 /* for VAX .word reg_mask */ /* PC will be pointing at a syscall if it is to be restarted: */ typedef unsigned char opcode; /* one byte long */ #define SYSCALL ((opcode)0xBC) /* VAX CHMK instruction */ #define IMMEDIATE ((opcode)0x8F) /* VAX immediate addressing */ static int (*handler[NSIG])() = /* "current handler" memory */ { BADSIG /* initially, unknown state */ }; static int inited = 0; /* for initializing above */ static int catchsig(); static int ret_eintr(); int (* signal( sig, func ) /* returns previous handler */ )() register int sig; /* signal affected */ register int (*func)(); /* new handler */ { register int (*retval)(); /* previous handler value */ struct sigvec oldsv; /* previous state */ struct sigvec newsv; /* state being set */ if ( func >= (int (*)())&etext ) /* "lint" hates this */ { errno = EFAULT; return BADSIG; /* error */ } /* cancel pending signals */ newsv.sv_handler = SIG_IGN; newsv.sv_mask = newsv.sv_onstack = 0; if ( sigvec( sig, &newsv, &oldsv ) != 0 ) return BADSIG; /* error */ /* C language provides no good way to initialize handler[] */ if ( !inited ) /* once only */ { register int i; for ( i = 1; i < NSIG; ++i ) handler[i] = BADSIG; /* initialize */ ++inited; } /* the first time for this sig, get state from the system */ if ( (retval = handler[sig-1]) == BADSIG ) retval = oldsv.sv_handler; handler[sig-1] = func; /* keep track of state */ if ( func == SIG_DFL ) newsv.sv_handler = SIG_DFL; else if ( func != SIG_IGN ) newsv.sv_handler = catchsig; /* actual sig catcher */ if ( func != SIG_IGN /* sig already being ignored */ && sigvec( sig, &newsv, (struct sigvec *)0 ) != 0 ) return BADSIG; /* error */ return retval; /* previous handler */ } /*ARGSUSED*/ static int catchsig( sig, code, scp ) /* signal interceptor */ register int sig; /* signal number */ int code; /* code for SIGILL, SIGFPE */ register struct sigcontext *scp; /* -> interrupted context */ { register opcode *pc; /* for snooping instructions */ struct sigvec newsv; /* state being set */ register int (*uhandler)() = handler[sig-1]; /* user handler */ /* at this point, sig is blocked */ /* most UNIXes usually want the state reset to SIG_DFL */ if ( sig != SIGILL && sig != SIGTRAP ) { handler[sig-1] = newsv.sv_handler = SIG_DFL; newsv.sv_mask = newsv.sv_onstack = 0; (void)sigvec( sig, &newsv, (struct sigvec *)0 ); } (void)sigsetmask( scp->sc_mask ); /* restore old mask */ /* at this point, sig is not blocked, usually have SIG_DFL; a longjmp may safely be taken by the user signal handler */ (void)(*uhandler)( sig ); /* user signal handler */ /* must now avoid restarting certain system calls */ pc = (opcode *)scp->sc_pc; if ( *pc++ == SYSCALL && (*pc == SYS_read || *pc == SYS_write || *pc == SYS_ioctl || *pc++ == IMMEDIATE && (*pc == SYS_wait || *pc == SYS_readv || *pc == SYS_writev) ) ) scp->sc_pc = (int)ret_eintr + OFFSET; /* return here restores interrupted context */ } static int ret_eintr() /* substitute for system call */ { errno = EINTR; return -1; } From rws@mit-bold.ARPA Tue Jan 17 23:11:10 1984 Date: Tue, 17 Jan 84 20:43:46 est From: Robert W. Scheifler Subject: 4.2 telnetd AYT bug Status: O Index: /src/etc/telnet.c 4.2BSD Description: When the telnet daemon receive an Are You There, it writes a ^G to the pty rather than back to the network. Repeat-By: Telnet to a 4.2 host with a user telnet that can send AYT's, and send one. See the ^G echo and show up in your input buffer, rather than ringing your bell. Fix: Change case AYT: *pfrontp++ = BELL; break; to case AYT: *nfrontp++ = BELL; break; From mrose@uci-750a.ARPA Thu Jan 19 00:19:51 1984 Date: 18 Jan 84 19:49:53 PST (Wed) From: Marshall Rose Subject: bug in syslog(3) Status: O Index: lib/libc/gen/syslog.c 4.2BSD Description: If the format string you give to syslog() contains a '%' escape other than a '%m', then the format string is truncated after that escape and the resulting output in the syslog file looks very wierd. This bug makes syslog() virtually useless if you like to put lots of information in a single line. Repeat-By: Run the following program, wait a while for some other process to send something to the syslog daemon, and then check out the file. You'll see something like this: Jan 17 17:39:12 localhost: 4222 foo: argc=1<8>4231 sendmail: connected to uci-750b Note how the syslog daemon got real confused on that one... #include main (argc, argv) char **argv; { openlog ("foo", LOG_PID); syslog (LOG_INFO, "argc=%d *argv=%s", argc, *argv); } Fix: The code that expands '%m' in the source format string prematurely embeds a null in the target format string. The solution is not to do this (obviously). Actually, a better fix would be to make the daemon work correctly regardless of the message that it received. That's not done here though. *** _syslog.c Tue Jan 17 17:27:49 1984 --- syslog.c Tue Jan 17 17:27:55 1984 *************** *** 70,76 } c = *f++; if (c != 'm') { ! *b++ = '%', *b++ = c, *b++ = '\0'; continue; } if ((unsigned)errno > sys_nerr) --- 70,76 ----- } c = *f++; if (c != 'm') { ! *b++ = '%', *b++ = c; continue; } if ((unsigned)errno > sys_nerr) From andrew@garfield.UUCP Tue Jan 17 20:26:48 1984 From: andrew@garfield.UUCP (Andrew Draskoy) Subject: bug in which (4.2bsd) Date: Tue, 17 Jan 84 20:26:48 EST Status: O Subject: Bug in 4.2bsd which csh script Index: ucb/which.csh 4.2BSD Description: The which csh script won't tell you if a command is an alias, and will not read the path from the .cshrc as documented. This is because it is exec'd with "csh -f", which does not read in the .cshrc file. Repeat-By: Type "which xxx", where xxx is any alias defined in your .cshrc If the bug is present, "which" will not tell you that it is an alias. Fix: Take the "-f" out of the top line of the script. From smk@axiom.UUCP Thu Jan 19 20:56:35 1984 From: smk@axiom.UUCP (Steven M. Kramer) Subject: fix to the tip vadic 3451 code in 4.2bsd -- and an improvement Date: Thu, 19 Jan 84 20:56:35 EST Status: O The dialer code had an error where an extra \r in the code disable the dialing attempt. I took that out. Also, our vadic look-alike doesn't look for EXACTLY the same words so a couple of mods are there (but probably not necessary for most sites). The improvement is to use the interval timer code of 4.2 rather than sleeping a WHOLE second between each character `typed'. This speeds up the process tremeddously. I found around 2/10 sec is a reasonable delay. I hope this makes it to 43 so I don't have to fix the uucp/cu code in each version of unix! *** v3451.c.orig Sat Jun 25 05:10:44 1983 --- v3451.c Thu Jan 19 15:55:01 1984 *************** *** 6,11 * Routines for calling up on a Vadic 3451 Modem */ #include "tip.h" static jmp_buf Sjbuf; --- 6,19 ----- * Routines for calling up on a Vadic 3451 Modem */ #include "tip.h" + #ifdef AXIOM + #include + /* The sleeps done here are handled not by sleep(3), but by the + fast_sleep at the botton of this file (to get better resolution). + */ + #define sleep(n) fast_sleep(n*200000) + #define sleepx fast_sleepx + #endif static jmp_buf Sjbuf; *************** *** 61,66 * brain damaged design). */ vawrite("\r", 1 + slow); vawrite("\r", 1 + slow); if (!expect("DIALING:")) { printf("Vadic failed to dial\n"); --- 69,86 ----- * brain damaged design). */ vawrite("\r", 1 + slow); + #ifdef AXIOM + /* + * This extra \r is BAD!! It cancels the call and leaves the + * 3451 in limbo (which i heard was somewhere in North Dakota). + * + * Also, the DIALING: below is wrong, it should be DIALING... + * So I fixed that + * + * 1/9/84 Steve Kramer + */ + if (!expect("DIALING...")) { + #else vawrite("\r", 1 + slow); if (!expect("DIALING:")) { #endif *************** *** 63,68 vawrite("\r", 1 + slow); vawrite("\r", 1 + slow); if (!expect("DIALING:")) { printf("Vadic failed to dial\n"); #ifdef ACULOG logent(value(HOST), num, "vadic", "failed to dial"); --- 83,89 ----- #else vawrite("\r", 1 + slow); if (!expect("DIALING:")) { + #endif printf("Vadic failed to dial\n"); #ifdef ACULOG logent(value(HOST), num, "vadic", "failed to dial"); *************** *** 174,176 return (1); return (c == '\0'); } --- 195,259 ----- return (1); return (c == '\0'); } + #ifdef AXIOM + /* We should really use the fast timer stuff because it's + unnecessary to wait a whole second between writes to + the Vadic. This code was taken from sleep(3). + */ + + #define mask(s) (1<<((s)-1)) + #define setvec(vec, a) \ + vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0 + + static int ringring; + + fast_sleep (n) + unsigned n; + { + int sleepx(), omask; + struct itimerval itv, oitv; + register struct itimerval *itp = &itv; + struct sigvec vec, ovec; + + if (n == 0) + return; + timerclear(&itp->it_interval); + timerclear(&itp->it_value); + if (setitimer(ITIMER_REAL, itp, &oitv) < 0) + return; + setvec(ovec, SIG_DFL); + omask = sigblock(0); + itp->it_value.tv_sec = n/1000000; + itp->it_value.tv_usec = n%1000000; + if (timerisset(&oitv.it_value)) { + if (timercmp(&oitv.it_value, &itp->it_value, >)) + oitv.it_value.tv_sec -= itp->it_value.tv_sec; + else { + itp->it_value = oitv.it_value; + /* + * This is a hack, but we must have time to + * return from the setitimer after the alarm + * or else it'll be restarted. And, anyway, + * sleep never did anything more than this before. + */ + oitv.it_value.tv_sec = 1; + oitv.it_value.tv_usec = 0; + } + } + setvec(vec, sleepx); + (void) sigvec(SIGALRM, &vec, &ovec); + ringring = 0; + (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0); + while (!ringring) + sigpause(omask &~ mask(SIGALRM)); + (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0); + (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0); + } + + static + sleepx() + { + + ringring = 1; + } + #endif -- --steve kramer {allegra,genrad,ihnp4,utzoo,philabs,uw-beaver}!linus!axiom!smk (UUCP) linus!axiom!smk@mitre-bedford (MIL) From arwhite@watmath.UUCP (Alex White) Mon Jan 23 12:35:33 1984 Relay-Version: version B 2.10.1a 12/4/83; site rlgvax.UUCP Posting-Version: version B 2.10.1 6/24/83; site watmath.UUCP Path: rlgvax!seismo!harpo!eagle!mit-vax!grkermit!genrad!security!linus!utzoo!watmath!arwhite From: arwhite@watmath.UUCP (Alex White) Newsgroups: net.bugs.4bsd Subject: Receiving out of band data in unix domain causes panic Message-ID: <6691@watmath.UUCP> Date: Mon, 23 Jan 84 12:35:33 EST Date-Received: Wed, 25 Jan 84 00:09:43 EST Organization: U of Waterloo, Ontario Lines: 88 Status: O Subject: Using out of band data causes panic(mfree) Index: sys/sys/uipc_usrreq.c 4.2BSD Description: Receiving data with MSG_OOB set causes panic in the unix domain. soreceive() calls pr_usrreq with a newly allocated mbuf, but the code for PRU_RCVOOB is non-existent, hence it always frees it, when it returns to soreceive that tries to free it again and panics. Repeat-By: Just do an recv with the flag MSG_OOB set in the unix domain. Fix: The following just disallows MSG_OOB in the unix domain, rather than making it work. It just causes a return of EOPNOTSUPP It hasn't been tested as I don't have an available machine... *** uipc_usrreq.c Mon Jan 23 12:25:52 1984 --- /usr/distr/4.2/usr/sys/sys/uipc_usrreq.c Sun Sep 25 21:06:43 1983 *************** *** 180,186 snd->sb_hiwat -= rcv->sb_cc - rcv->sb_hiwat; rcv->sb_hiwat = rcv->sb_cc; sbwakeup(rcv); - m = 0; #undef snd #undef rcv break; --- 180,185 ----- snd->sb_hiwat -= rcv->sb_cc - rcv->sb_hiwat; rcv->sb_hiwat = rcv->sb_cc; sbwakeup(rcv); #undef snd #undef rcv break; *************** *** 188,193 default: panic("uipc 4"); } break; case PRU_ABORT: --- 187,193 ----- default: panic("uipc 4"); } + m = 0; break; case PRU_ABORT: *************** *** 204,211 /* END UNIMPLEMENTED HOOKS */ case PRU_RCVOOB: ! /* Don't release resources below, sorecieve always does */ ! return (EOPNOTSUPP); case PRU_SENDOOB: /* Release resources below, sosend never does... */ --- 204,210 ----- /* END UNIMPLEMENTED HOOKS */ case PRU_RCVOOB: ! break; case PRU_SENDOOB: break; *************** *** 208,215 return (EOPNOTSUPP); case PRU_SENDOOB: - /* Release resources below, sosend never does... */ - error = EOPNOTSUPP; break; case PRU_SOCKADDR: --- 207,212 ----- break; case PRU_SENDOOB: break; case PRU_SOCKADDR: From arwhite@watmath.UUCP (Alex White) Mon Jan 23 16:13:27 1984 Relay-Version: version B 2.10.1a 12/4/83; site rlgvax.UUCP Posting-Version: version B 2.10.1 6/24/83; site watmath.UUCP Path: rlgvax!seismo!harpo!eagle!mit-vax!grkermit!genrad!security!linus!utzoo!watmath!arwhite From: arwhite@watmath.UUCP (Alex White) Newsgroups: net.bugs.4bsd Subject: Asm() label botch again... Message-ID: <6706@watmath.UUCP> Date: Mon, 23 Jan 84 16:13:27 EST Date-Received: Wed, 25 Jan 84 00:09:48 EST Organization: U of Waterloo, Ontario Lines: 14 Status: O Subject: Segmentation violation due to junk user interrupt stack Index: sys/vax/machdep.c 4.2BSD Description: stupid asm() botch. Repeat-By: Don't bother, not worth it. Fix: sigcleanup() has in #ifndef lint around an asm("prober") which follows an if statement, and, as is well known, the label gets emited by the C compiler in the wrong place; there are certainly other places in the code which carefully have the following line in front of that #ifndef lint, place it here as well: ; /* Avoid asm() label botch */ From rascal@verdix.UUCP (Steve Scalpone) Tue Jan 24 23:47:14 1984 Relay-Version: version B 2.10.1a 12/4/83; site rlgvax.UUCP Posting-Version: version B 2.10 5/3/83; site verdix.UUCP Path: rlgvax!seismo!harpo!ihnp4!alberta!ubc-vision!uw-beaver!tektronix!ogcvax!verdix!rascal From: rascal@verdix.UUCP (Steve Scalpone) Newsgroups: net.bugs.4bsd Subject: Bug fix for 4.2BSD sdb Message-ID: <176@verdix.UUCP> Date: Tue, 24 Jan 84 23:47:14 EST Date-Received: Fri, 27 Jan 84 10:17:54 EST Organization: Verdix Lines: 18 Status: O In sdb, like in ex, you can type a control-d and get another bit of text displayed. In sdb, this is implemented by catching EOF. Naturally, sdb doesn't ever "clearerr" before reading again, so EOF is returned again and again. This is a problem. Fix it in "sub.c" right after line 19. Add a call to "clearerr(f)". 19 if ((i = getc(f)) == EOF) { 20 *p++ = '\004'; 21 *p = '\n'; 22 } No source? Try changing your EOF character or escaping the "^D". Steve Scalpone Verdix Corporation ogcvax!verdix!rascal sequent!verdix!rascal From seismo!unix-wizards-request@BRL-VGR.ARPA Fri Jan 27 20:23:27 1984 Received: by rlgvax.UUCP; Fri, 27 Jan 84 20:23:27 EST Date: Fri, 27 Jan 84 19:49:10 est From: Lou Salkind Subject: dh soft carrier bug Posted-Date: Fri, 27 Jan 84 19:49:10 est Message-Id: <8401280049.AA29828@NYU.ARPA> Received: From nyu-gw.ARPA by BRL-VGR via smtp; 27 Jan 84 19:50 EST Received: by NYU.ARPA; Fri, 27 Jan 84 19:49:10 est Received: from BRL-VGR by SEISMO.ARPA (3.342/3.21) id AA15851; 27 Jan 84 20:17:26 EST (Fri) To: unix-wizards@brl-vgr Status: RO Subject: dh soft carrier bug Index: sys/vaxuba/dh.c 4.2BSD Description: If the soft carrier flag for a dh line is set (dhsoftCAR), and a dm modem interrupt occurs on the line, the TS_CARR_ON flag may be cleared. This causes future reads/writes to the terminal to return EIO. Repeat-By: On a line with modem control, bring down DTR to force a modem interrupt. (This really can happen!) Fix: In dmintr(), add the declaration: register int unit; and change if (addr->dmcsr&DM_CF) { tp = &dh11[(dm<<4)+(addr->dmcsr&0xf)]; to unit = addr->dmcsr & 0xf; if (addr->dmcsr&DM_CF && (dhsoftCAR[dm]&(1< Subject: minor nit in fcntl Posted-Date: Fri, 27 Jan 84 20:10:56 est Message-Id: <8401280110.AA00236@NYU.ARPA> Received: From nyu-gw.ARPA by BRL-VGR via smtp; 27 Jan 84 20:12 EST Received: by NYU.ARPA; Fri, 27 Jan 84 20:10:56 est Received: from BRL-VGR by SEISMO.ARPA (3.342/3.21) id AA16124; 27 Jan 84 20:33:48 EST (Fri) To: unix-wizards@brl-vgr Status: RO Subject: minor nit in fcntl Index: sys/sys/kern_descrip.c 4.2BSD Description: If you try fcntl(fd, F_DUPFD, NOFILE), you get the error EMFILE instead of EINVAL. Repeat-By: fcntl(fd, F_DUPFD, NOFILE); Fix: In fcntl, replace the test if (i < 0 || i > NOFILE) by if (i < 0 || i >= NOFILE) Like I said, a minor nit. From seismo!unix-wizards-request@BRL-VGR.ARPA Tue Jan 31 10:10:45 1984 Received: by rlgvax.UUCP; Tue, 31 Jan 84 10:10:45 EST Date: 30 Jan 84 21:13:19-PST (Mon) From: seismo!hplabs!hao!seismo!philabs!cmcl2!rna!dan@ucb-vax Subject: Small bug in /etc/swapon Posted-Date: 30 Jan 84 21:13:19-PST (Mon) Message-Id: <8401311459.AA29630@SEISMO.ARPA> Received: From Sri-Unix.ARPA by BRL-VGR via smtp; 31 Jan 84 9:35 EST Received: from Usenet.uucp by sri-unix.uucp with rs232; 31 Jan 84 6:28-PST Received: from BRL-VGR by SEISMO.ARPA (3.342/3.21) id AA29630; 31 Jan 84 09:59:10 EST (Tue) To: Unix-Wizards@brl-vgr Article-I.D.: rna.209 Status: RO Subject: /etc/swapon -a prints No such device: (garbage) when trying to swapon a bad entry in /etc/fstab Index: etc/swapon.c 4.2BSD Description: Missing argument to printf. Repeat-By: /etc/swapon -a with a bad swap device entry in /etc/fstab Fix: *** swapon.c.org Sun Jan 29 23:28:03 1984 --- swapon.c Sun Jan 29 23:28:36 1984 *************** *** 30,32 printf("%s: %s\n", ! sys_errlist[errno]); stat = 1; --- 30,32 ----- printf("%s: %s\n", ! sys_errlist[errno], fsp->fs_spec); stat = 1; *************** Cheers, Dan Ts'o ...cmcl2!rna!dan From seismo!unix-wizards-request@BRL-VGR.ARPA Tue Jan 31 11:12:42 1984 Received: by rlgvax.UUCP; Tue, 31 Jan 84 11:12:42 EST Date: 30 Jan 84 21:56:17-PST (Mon) From: seismo!hplabs!hao!seismo!philabs!cmcl2!rna!dan@ucb-vax Subject: Bug in ADB Posted-Date: 30 Jan 84 21:56:17-PST (Mon) Message-Id: <8401311513.AA00019@SEISMO.ARPA> Received: From Sri-Unix.ARPA by BRL-VGR via smtp; 31 Jan 84 9:46 EST Received: from Usenet.uucp by sri-unix.uucp with rs232; 31 Jan 84 6:39-PST Received: from BRL-VGR by SEISMO.ARPA (3.342/3.21) id AA00019; 31 Jan 84 10:13:56 EST (Tue) To: Unix-Wizards@brl-vgr Article-I.D.: rna.210 Status: RO Subject: Arguments after the first supplied to the :r command of ADB get the first character lopped off. Index: bin/adb/runpcs.c (maybe) 4.2BSD Description: When giving more than one argument to the :r command of ADB the first character of each subsequent argument is dropped. Repeat-By: adb /bin/echo :r hello this example /bin/echo: running hello his xample process terminated Fix: Haven't had time to wade to ADB's Bourne/A68'isms. Presumably in runpcs.c the first character gets throw away while looking for io redirections. For now, of course, supply a extra first character to be thrown away. Cheers, Dan Ts'o ...cmcl2!rna!dan From seismo!unix-wizards-request@BRL-VGR.ARPA Tue Jan 31 11:13:35 1984 Received: by rlgvax.UUCP; Tue, 31 Jan 84 11:13:35 EST Date: Tue, 31 Jan 84 09:55:16 est From: Robert W. Scheifler Subject: 4.2 ftp has 8 character passwords Posted-Date: Tue, 31 Jan 84 09:55:16 est Message-Id: <8401311455.AA03933@mit-bold.ARPA> Received: From Mit-Bold.ARPA by BRL-VGR via smtp; 31 Jan 84 9:55 EST Received: by mit-bold.ARPA (4.12/4.7) id AA03933; Tue, 31 Jan 84 09:55:16 est Received: from BRL-VGR by SEISMO.ARPA (3.342/3.21) id AA00667; 31 Jan 84 10:36:34 EST (Tue) Index: /src/ucb/ftp/getpass.c 4.2BSD Apparently-To: unix-wizards@brl-vgr Status: RO Description: User ftp truncates passwords to 8 characters, which loses completely when talking to non-Unix sites. Repeat-By: ftp to a TOPS-20, for example, and try to login to an account with a long password. Fix: Change static char pbuf[9]; to static char pbuf[51]; and if (p < &pbuf[8]) to if (p < &pbuf[50]) or some other suitably large values. (Geez, C+Unix=blech.) From arwhite@watmath.UUCP (Alex White) Tue Jan 31 10:58:39 1984 Relay-Version: version B 2.10.1a 12/4/83; site rlgvax.UUCP Posting-Version: version B 2.10.1 6/24/83; site watmath.UUCP Path: rlgvax!seismo!harpo!ulysses!burl!clyde!watmath!arwhite From: arwhite@watmath.UUCP (Alex White) Newsgroups: net.bugs.4bsd Subject: Accounting problems in 4.2 Message-ID: <6743@watmath.UUCP> Date: Tue, 31 Jan 84 10:58:39 EST Date-Received: Tue, 31 Jan 84 19:20:32 EST Organization: U of Waterloo, Ontario Lines: 46 Status: O Somebody posted something in the last month complaining about problems in accounting cpu times - I don't remember who cuz I assumed that somebody would have posted an answer and it was only several hundred messages later that I realized nobody had... Unfortunately, I think this still has the problem that only seconds of cpu are actually being recorded... This only fixes the memory usage (which we happen to account for). Subject: Accounting time quantities screwed up Index: sys/sys/kern_acct.c etc/sa.c 4.2BSD Description: Accounting records now write times out in seconds, sa still works in 60ths of seconds. Accounting entry ac_mem is incorrect as the kernel divides by SECONDS, the integrated memory usage which is in NBPG ticks. Repeat-By: Use sa -u to see what's being printed out, its wrong. Fix: I can't provide the fix to sa because we have so many changes in it to make it work on uid/gid basis that a diff listing would be horrible. However, basically, everywhere that uses a time currently divides by 60 to get rid of the old hz factor. e.g. routine col() divides by either 60 or 3600 depending on whether it wants seconds or minutes when it should be just divide by 60 for minutes. *** /sys/sys/kern_acct.c Fri Dec 2 14:09:33 1983 --- /usr/distr/4.2/sys/sys/kern_acct.c Fri Jul 29 10:07:16 1983 *************** *** 98,106 ap->ac_gid = u.u_rgid; ap->ac_mem = 0; ! /* ! * Note that ru_i?rss is in units of NBPG core tick ! */ ! if (i = (u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec)*hz + ! (u.u_ru.ru_utime.tv_usec + u.u_ru.ru_stime.tv_usec)/tick) ap->ac_mem = (u.u_ru.ru_ixrss + u.u_ru.ru_idrss + u.u_ru.ru_isrss) / i; --- 98,102 ----- ap->ac_gid = u.u_rgid; ap->ac_mem = 0; ! if (i = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec) ap->ac_mem = (u.u_ru.ru_ixrss + u.u_ru.ru_idrss + u.u_ru.ru_isrss) / i; From seismo!unix-wizards-request@BRL-VGR.ARPA Wed Feb 1 19:31:28 1984 Received: by rlgvax.UUCP; Wed, 1 Feb 84 19:31:28 EST Date: Wed, 1 Feb 84 14:41:28 pst From: Eric Holstege Subject: bug in csh Posted-Date: Wed, 1 Feb 84 14:41:28 pst Message-Id: <8402012241.AA17324@cit-vax.ARPA> Received: From brl-gateway2.ARPA by BRL-VGR via smtp; 1 Feb 84 18:13 EST Received: From Cit-Vax.ARPA by BRL via smtp; 1 Feb 84 18:07 EST Received: by cit-vax.ARPA (4.12/4.7) id AA17324; Wed, 1 Feb 84 14:41:28 pst Received: from BRL-VGR by SEISMO.ARPA (3.342/3.21) id AA02303; 1 Feb 84 18:50:29 EST (Wed) To: unix-wizards@brl Status: RO Under 4.2, if the terminal is in raw mode (for example, an editor just bombed) the first character with the high (parity) bit set will log out the csh. This is because, in the routine bgetc in sh.lex.c, a character is read from the terminal and returned as an integer. This causes sign extension of the parity bit, resulting in a negative integer. Routines calling bgetc test for < 0 to detect EOF. The fix is to chaange the two occurrences of "return(c)" in bgetc to "return(c&0177)". From ber@enea.UUCP (Bj|rn Eriksen) Wed Feb 8 20:29:15 1984 Relay-Version: version B 2.10.1a 12/4/83; site rlgvax.UUCP Posting-Version: version B 2.10.1 6/24/83 (MC830713); site enea.UUCP Path: rlgvax!seismo!philabs!mcvax!enea!ber From: ber@enea.UUCP (Bj|rn Eriksen) Newsgroups: net.bugs.4bsd Subject: Bug in 4.2 tip Message-ID: <209@enea.UUCP> Date: Wed, 8 Feb 84 20:29:15 EST Date-Received: Fri, 3 Feb 84 04:34:40 EST Organization: ENEA DATA, Sweden Lines: 20 Status: O When I was adding the "tip" (4.2 BSD) line locking routines to Kermit I came across that old uucplock-bug. In the source for tip there is a file uucplock.c which defines #define NAMESIZE 15 which is used in "ulockf" as static char tempfile[NAMESIZE]; if (pid < 0) { pid = getpid(); sprintf(tempfile, "/usr/spool/uucp/LTMP.%d", pid); } But that file name sure has more than 15 character, which caused my new Kermit to core dump in the next calloc. -- Bjorn Eriksen {philabs,decvax}!mcvax!enea!ber From eric%ucbarpa%berkeley@sri-unix.UUCP Thu Feb 2 23:45:00 1984 Relay-Version: version B 2.10.1a 12/4/83; site rlgvax.UUCP Path: rlgvax!seismo!hao!hplabs!sri-unix!eric%ucbarpa@berkeley From: eric%ucbarpa%berkeley@sri-unix.UUCP Newsgroups: net.unix-wizards Subject: Re: bug in syslog(3) Message-ID: <16353@sri-arpa.UUCP> Date: Thu, 2 Feb 84 23:45:00 EST Date-Received: Sun, 5 Feb 84 18:19:16 EST Lines: 9 Status: O From: Eric Allman For some reason that I do not understand at all, someone created a new version of syslog which was installed into libc. This version has several problems -- I recommend chucking it completely. The version in .../sendmail/lib/syslog.c works fine (to the best of my knowledge). eric From km@emory.UUCP (Ken Mandelberg) Fri Feb 3 19:06:55 1984 Relay-Version: version B 2.10.1a 12/4/83; site rlgvax.UUCP Posting-Version: version B 2.10.1 6/24/83; site emory.UUCP Path: rlgvax!seismo!hao!hplabs!zehntel!tektronix!decvax!harpo!ulysses!burl!clyde!akgua!emory!km From: km@emory.UUCP (Ken Mandelberg) Newsgroups: net.bugs.4bsd,net.lang.pascal,net.unix-wizards Subject: Bug in Pascal (Pix) on 4.2BSD Message-ID: <1277@emory.UUCP> Date: Fri, 3 Feb 84 19:06:55 EST Date-Received: Sun, 5 Feb 84 19:43:52 EST Organization: Math & Computer Science, Emory University, Atlanta Lines: 53 Status: O We have found an apparent bug in pix on 4.2 on real reads. The same problem does not occur on either pc or pix on 4.1. Has anyone fixed this yet? The bug report follows. Ken Mandelberg Dept of Math and CS Emory University {akgua,sb1,gatech}!emory!km Subject: Pi gives error on real reads Index: /usr/src/ucb/pascal/pi 4.2BSD Description: Pix blows up on the second real number read from stdin. More precisely, the first real read following the read of a real number entered with a decimal point will fail. Repeat-By: Script started on Fri Feb 3 18:36:32 1984 % cat test2.p program cnvx(input,output); var x:real; begin readln(x); writeln(x); readln(x); writeln(x); end. % pix test2.p Execution begins... 1.1 1.10000000000000e+00 1.2 standard input: Bad data found on real read Program error Do you wish to enter the debugger? n Error in "cnvx"+2 near line 7. Execution terminated abnormally. 3 statements executed in 0000.80 seconds cpu time. % script done on Fri Feb 3 18:37:43 1984 Fix: Unknown. Pc does not have the same bug, so it can be used when real reads are needed. From clyde@ut-ngp.UUCP (Clyde W. Hoover) Thu Feb 2 17:18:51 1984 Relay-Version: version B 2.10.1a 12/4/83; site rlgvax.UUCP Posting-Version: version B 2.10.1 6/24/83; site ut-ngp.UUCP Path: rlgvax!seismo!ut-sally!ut-ngp!clyde From: clyde@ut-ngp.UUCP (Clyde W. Hoover) Newsgroups: net.bugs.4bsd Subject: Man bug in 4.2 Message-ID: <274@ut-ngp.UUCP> Date: Thu, 2 Feb 84 17:18:51 EST Date-Received: Thu, 9 Feb 84 21:13:11 EST Organization: Comp. Center, Univ. of Texas at Austin Lines: 61 Status: O Subject: Man leaves processes hanging around, tty modes left scrambled Index: /usr/src/ucb/man.c 4.2BSD Description: Man does not always interact well with job control. When displaying a manual page using "more" and interrupted, processes can be left hanging. Symptoms: there is a 'sh -c' in proc wait (on more) 'more' is in stopped mode. NOTE: This only happens when using the Cshell. Cause: Man and more both trap SIGINT. Man removes temp file, and more restores terminal modes before exiting. If man exits before more, then Cshell resets the process group of the controlling terminal, then when more finally gets around to restoring tty modes, it is "in the background" and so gets stopped with SIGTTOU. The shell that fired up more is hung waiting for more to exit. Man rolls its own system() so it can use vfork; however it does NOT ignore SIGINT and SIGQUIT while waiting for the shell it invoked to exit. If interrupted, man can exit before its subprocesses do. No problem unless the subprocesses do things with the terminal - then they will get stopped with SIGTTOU. Repeat-By: Do 'man something' and interrupt at the "--More--" prompt a few times until man dies and the tty is left in noecho cbreak mode. Then do a 'ps -ax' to see the hung processes. Fix: system(s) (Last routine in man.c) char *s; { int status, pid, w; int (*saveintr)(), (*savequit)(); if ((pid = vfork()) == 0) { execl("/bin/sh", "sh", "-c", s, 0); _exit(127); } saveintr = signal (SIGINT, SIG_IGN); /* ***** FIX **** */ savequit = signal (SIGQUIT, SIG_IGN); /* ***** FIX **** */ while ((w = wait(&status)) != pid && w != -1) ; if (w == -1) status = -1; return (status); (void) signal (SIGQUIT, saveintr); /* ***** FIX **** */ (void) signal (SIGQUIT, savequit); /* ***** FIX **** */ } -- Clyde W. Hoover @ Univ. of Texas Computation Center; Austin, Texas (Shouter-To-Dead-Parrots) clyde@ut-ngp.{UUCP,ARPA} clyde@ut-sally.{UUCP,ARPA} ihnp4!ut-ngp!clyde From harpo!eagle!mhuxl!ihnp4!alberta!ubc-vision!uw-beaver!cornell!vax135!floyd!cmcl2!salkind Sun Feb 6 01:28:16 206 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site cmcl2.UUCP Path: seismo!harpo!eagle!mhuxl!ihnp4!alberta!ubc-vision!uw-beaver!cornell!vax135!floyd!cmcl2!salkind From: salkind@cmcl2.UUCP (Lou Salkind) Newsgroups: net.bugs.4bsd Subject: ar bug Message-ID: <2173@cmcl2.UUCP> Date: Mon, 13-Feb-84 13:17:15 EST Date-Received: Tue, 14-Feb-84 14:59:08 EST Organization: New York University Lines: 23 Status: O Subject: ar bug Index: bin/ar.c 4.2BSD Description: If you try to archive a file with a uid or gid greater than 32K, ar will fail when you try to read the archive back in. You will get the message "Malformed archive." Repeat-By: mkdir f chgrp 50000 f cd f cp /etc/passwd f ar r f.a passwd ar t f.a Fix: When the file header is written out, cast the uid and gid to an unsigned short. "diff ar.c.dist ar.c" follows: 510,511c510,511 < stbuf.st_uid, < stbuf.st_gid, --- > (u_short)stbuf.st_uid, > (u_short)stbuf.st_gid, From harpo!eagle!mit-vax!grkermit!genrad!decvax!linus!axiom!smk Thu Feb 16 20:28:04 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site axiom.UUCP Path: seismo!harpo!eagle!mit-vax!grkermit!genrad!decvax!linus!axiom!smk From: smk@axiom.UUCP (Steven M. Kramer) Newsgroups: net.bugs,net.news.b Subject: nasty bug in the 4.2 compatibility routines Message-ID: <489@axiom.UUCP> Date: Thu, 16-Feb-84 20:28:04 EST Article-I.D.: axiom.489 Posted: Thu Feb 16 20:28:04 1984 Date-Received: Fri, 17-Feb-84 17:43:34 EST Organization: Axiom Technology, Newton MA Lines: 119 Status: O The 4.2 compatibility routines opendir(), seekdir(), readdir(), telldir() have 2 bugs in the package. This can cause problems in 2.10 and 2.10.1 B news, anyone trying to port the 4.2 uucp to another machine without long directories, and any other utility which uses them. One bug is simply that the structure elements are messed up. The other more serious bug is due to the wrong variable being checked. The fix is below, but what happened was that I was porting the 4.2 uucp distribution (which is overall very good) to another machine. A directory would be opened, read a couple of times, then rewinddir was called and the directory was read again. You'd expect the same entries to be reread, but the seek to the beginning did not happen and the next block (there was none) could be read in, and so readdir returned 0 (EOF). This happened inbetween checking to see if work was to be done in a spool and actually doing it. I can envision many other comparable quirks popping up because of this. --steve kramer (This was a toughy to track down!) *** readdir.c.orig Thu Feb 16 20:14:24 1984 --- readdir.c Thu Feb 16 20:16:18 1984 *************** *** 42,47 dirp->dd_loc += sizeof(struct olddirect); if (dp->od_ino == 0) continue; dir.od_ino = dp->d_ino; strncpy(dir.d_name, dp->od_name, ODIRSIZ); dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ --- 42,57 ----- dirp->dd_loc += sizeof(struct olddirect); if (dp->od_ino == 0) continue; + #ifdef AXIOM + /* + * Let's get our structure elements straight. + * d_ino is the virtual inode number and od_ino is the real + * inode number we have (but don't want to see as + * such using this library). + * Steve Kramer 2/16/84 + */ + dir.d_ino = dp->od_ino; + #else dir.od_ino = dp->d_ino; #endif strncpy(dir.d_name, dp->od_name, ODIRSIZ); *************** *** 43,48 if (dp->od_ino == 0) continue; dir.od_ino = dp->d_ino; strncpy(dir.d_name, dp->od_name, ODIRSIZ); dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ dir.d_namlen = strlen(dir.d_name); --- 53,59 ----- dir.d_ino = dp->od_ino; #else dir.od_ino = dp->d_ino; + #endif strncpy(dir.d_name, dp->od_name, ODIRSIZ); dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ dir.d_namlen = strlen(dir.d_name); *** seekdir.c.orig Thu Feb 16 20:16:57 1984 --- seekdir.c Thu Feb 16 20:19:53 1984 *************** *** 25,30 return; base = loc & ~(DIRBLKSIZ - 1); offset = loc & (DIRBLKSIZ - 1); if (dirp->dd_loc != 0 && (curloc & ~(DIRBLKSIZ - 1)) == base) { dirp->dd_loc = offset; return; --- 25,43 ----- return; base = loc & ~(DIRBLKSIZ - 1); offset = loc & (DIRBLKSIZ - 1); + #ifdef AXIOM + /* + * What is intended is to avoid a seek if we are seeking to a + * location we have already buffered in core. However, there + * is a special case. If we want to go to the beginning of the + * buffer, the readdir() routine will interpret that as the + * signal to read in another buffer, which is not intended. + * The value we want to check here then, is the offset into the + * buffer we will end up in, not where we are now. + * Steve Kramer 2/16/84 + */ + if ((offset != 0) && ((curloc & ~(DIRBLKSIZ - 1)) == base)) { + #else if (dirp->dd_loc != 0 && (curloc & ~(DIRBLKSIZ - 1)) == base) { #endif dirp->dd_loc = offset; *************** *** 26,31 base = loc & ~(DIRBLKSIZ - 1); offset = loc & (DIRBLKSIZ - 1); if (dirp->dd_loc != 0 && (curloc & ~(DIRBLKSIZ - 1)) == base) { dirp->dd_loc = offset; return; } --- 39,45 ----- if ((offset != 0) && ((curloc & ~(DIRBLKSIZ - 1)) == base)) { #else if (dirp->dd_loc != 0 && (curloc & ~(DIRBLKSIZ - 1)) == base) { + #endif dirp->dd_loc = offset; return; } -- --steve kramer {allegra,genrad,ihnp4,utzoo,philabs,uw-beaver}!linus!axiom!smk (UUCP) linus!axiom!smk@mitre-bedford (MIL) From harpo!ulysses!burl!clyde!watmath!arwhite Fri Feb 17 02:03:57 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site watmath.UUCP Path: seismo!harpo!ulysses!burl!clyde!watmath!arwhite From: arwhite@watmath.UUCP (Alex White) Newsgroups: net.bugs.4bsd Subject: ps and pstat fixes to work on dumps in 4.2 Message-ID: <6927@watmath.UUCP> Date: Fri, 17-Feb-84 02:03:57 EST Article-I.D.: watmath.6927 Posted: Fri Feb 17 02:03:57 1984 Date-Received: Fri, 17-Feb-84 17:38:31 EST Organization: U of Waterloo, Ontario Lines: 770 Status: O Subject: ps and pstat don't know about page tables for core dumps Index: etc/pstat.c bin/ps.c 4.2BSD Description: ps -k vmunix.xx vmcore.xx pstat -k vmunix.xx vmcore.xx both blow up with garbage. Repeat-By: Procedure to repeat the problem. Fix: All accesses to the kernel if in a core dump must go thru the kernel page tables. Diffs follow for both ps and pstat *** ps.c Fri Feb 17 01:59:54 1984 --- /usr/distr/4.2/usr/src/bin/ps.c Sun Sep 25 21:05:05 1983 *************** *** 46,57 #define X_DMMIN 10 { "_dmmax" }, #define X_DMMAX 11 - { "_u" }, - #define X_UAREA 12 - { "_Sysmap" }, - #define X_SYSMAP 13 - { "_Syssize" }, - #define X_SYSSIZE 14 { "" }, }; --- 46,51 ----- #define X_DMMIN 10 { "_dmmax" }, #define X_DMMAX 11 { "" }, }; *************** *** 105,110 } user; #define u user.user int chkpid; int aflg, cflg, eflg, gflg, kflg, lflg, rflg, sflg, uflg, vflg, xflg; --- 99,106 ----- } user; #define u user.user + #define clear(x) ((int)x & 0x7fffffff) + int chkpid; int aflg, cflg, eflg, gflg, kflg, lflg, sflg, uflg, vflg, xflg; *************** *** 106,112 #define u user.user int chkpid; ! int aflg, cflg, eflg, gflg, kflg, lflg, rflg, sflg, uflg, vflg, xflg; char *tptr; char *gettty(), *getcmd(), *getname(), *savestr(), *alloc(), *state(); --- 102,108 ----- #define clear(x) ((int)x & 0x7fffffff) int chkpid; ! int aflg, cflg, eflg, gflg, kflg, lflg, sflg, uflg, vflg, xflg; char *tptr; char *gettty(), *getcmd(), *getname(), *savestr(), *alloc(), *state(); *************** *** 182,190 case 'l': lflg++; break; - case 'r': - rflg++; - break; case 's': sflg++; break; --- 178,183 ----- case 'l': lflg++; break; case 's': sflg++; break; *************** *** 272,280 mproc->p_stat == SSTOP)) continue; } - if (rflg && ! (mproc->p_stat == SRUN - || mproc->p_pri < PZERO)) - continue; save(); } } --- 265,270 ----- mproc->p_stat == SSTOP)) continue; } save(); } } *************** *** 323,337 int off; { ! /* ! * If this is a dump, then the kernel isn't doing the page mapping ! * for us. Simulate it. ! */ ! if (kflg && (loc & 0x80000000) != 0) { ! long v; ! long addr; ! struct pte pte; ! loc &= 0x7fffffff; v = btop(loc); if(v >= nl[X_SYSSIZE].n_value) { --- 313,319 ----- int off; { ! if (kflg) loc &= 0x7fffffff; (void) lseek(fd, (long)loc, off); } *************** *** 333,355 struct pte pte; loc &= 0x7fffffff; - v = btop(loc); - if(v >= nl[X_SYSSIZE].n_value) { - printf("address botch %x\n", loc); - return; - } - addr = (long)((struct pte *)nl[X_SYSMAP].n_value + v); - lseek(kmem, addr&0x7fffffff, 0); - if(read(kmem, (char *)&pte, sizeof(pte)) != sizeof(pte)) { - printf("Error reading kmem for pte at %x\n", addr); - return; - } - if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) { - printf("pte bad for %x\n", addr); - return; - } - loc = (long)ptob(pte.pg_pfnum) + (loc & PGOFSET); - } (void) lseek(fd, (long)loc, off); } --- 315,320 ----- if (kflg) loc &= 0x7fffffff; (void) lseek(fd, (long)loc, off); } *************** *** 397,402 fprintf(stderr, "%s: No namelist\n", nlistf); exit(1); } usrpt = (struct pte *)nl[X_USRPT].n_value; /* don't clear!! */ Usrptma = (struct pte *)nl[X_USRPTMA].n_value; klseek(kmem, (long)nl[X_NSWAP].n_value, 0); --- 362,370 ----- fprintf(stderr, "%s: No namelist\n", nlistf); exit(1); } + if (kflg) + for (nlp = nl; nlp < &nl[sizeof (nl)/sizeof (nl[0])]; nlp++) + nlp->n_value = clear(nlp->n_value); usrpt = (struct pte *)nl[X_USRPT].n_value; /* don't clear!! */ Usrptma = (struct pte *)nl[X_USRPTMA].n_value; klseek(kmem, (long)nl[X_NSWAP].n_value, 0); *************** *** 757,763 mproc->p_pid, swapf); return (0); } ! pcbpf = mproc->p_swaddr; argaddr = 0; return (1); } --- 725,731 ----- mproc->p_pid, swapf); return (0); } ! pcbpf = 0; argaddr = 0; return (1); } *************** *** 761,766 argaddr = 0; return (1); } pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1]; klseek(kmem, (long)pteaddr, 0); if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { --- 729,736 ----- argaddr = 0; return (1); } + if (kflg) + mproc->p_p0br = (struct pte *)clear(mproc->p_p0br); pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1]; klseek(kmem, (long)pteaddr, 0); if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { *************** *** 765,771 klseek(kmem, (long)pteaddr, 0); if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { printf("ps: cant read indir pte to get u for pid %d from %s\n", ! mproc->p_pid, kmemf); return (0); } klseek(mem, --- 735,741 ----- klseek(kmem, (long)pteaddr, 0); if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { printf("ps: cant read indir pte to get u for pid %d from %s\n", ! mproc->p_pid, swapf); return (0); } klseek(mem, *************** *** 883,889 } char *lhdr = ! " F UID PID PPID CP PRI NI ADDR SZ RSS WCHAN STAT TT TIME"; lpr(sp) struct savcom *sp; { --- 853,859 ----- } char *lhdr = ! " F UID PID PPID CP PRI NI ADDR SZ RSS WCHAN STAT TT TIME"; lpr(sp) struct savcom *sp; { *************** *** 894,905 ap->a_flag, ap->a_uid, ap->a_pid, lp->l_ppid, lp->l_cpu&0377, ap->a_pri-PZERO, ap->a_nice-NZERO, lp->l_addr, pgtok(ap->a_size), pgtok(ap->a_rss)); ! ! if(lp->l_wchan == (caddr_t)nl[X_UAREA].n_value) ! printf(" pause"); ! else ! printf(lp->l_wchan ? " %6x" : " ", ! (int)lp->l_wchan&~0x80000000); printf(" %4.4s ", state(ap)); ptty(ap->a_tty); ptime(ap); --- 864,870 ----- ap->a_flag, ap->a_uid, ap->a_pid, lp->l_ppid, lp->l_cpu&0377, ap->a_pri-PZERO, ap->a_nice-NZERO, lp->l_addr, pgtok(ap->a_size), pgtok(ap->a_rss)); ! printf(lp->l_wchan ? " %5x" : " ", (int)lp->l_wchan&0xfffff); printf(" %4.4s ", state(ap)); ptty(ap->a_tty); ptime(ap); *************** *** 1103,1109 return (vp->v_swrss + (ap->a_xccount ? 0 : vp->v_txtswrss)); } ! #define NMAX 16 /* sizeof loginname (should be sizeof (utmp.ut_name)) */ #define NUID 2048 /* must not be a multiple of 5 */ struct nametable { --- 1068,1074 ----- return (vp->v_swrss + (ap->a_xccount ? 0 : vp->v_txtswrss)); } ! #define NMAX 8 /* sizeof loginname (should be sizeof (utmp.ut_name)) */ #define NUID 2048 /* must not be a multiple of 5 */ struct nametable { *** pstat.c Fri Feb 17 01:52:34 1984 --- /usr/distr/4.2/usr/src/etc/pstat.c Wed Nov 2 18:51:57 1983 *************** *** 74,83 { "_nswdev" }, #define SSWDEVT 21 { "_swdevt" }, - #define X_SYSMAP 22 - { "_Sysmap" }, - #define X_SYSSIZE 23 - { "_Syssize" }, { "" } }; --- 74,79 ----- { "_nswdev" }, #define SSWDEVT 21 { "_swdevt" }, { "" } }; *************** *** 175,184 printf("no namelist\n"); exit(1); } - if (kflg && (nl[X_SYSMAP].n_value == 0 || nl[X_SYSSIZE].n_value == 0)) { - printf("No _Sysmap or _Syssize\n"); - exit(1); - } allflags = filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf; if (allflags == 0) { printf("pstat: one or more of -[aixptfsu] is required\n"); --- 171,176 ----- printf("no namelist\n"); exit(1); } allflags = filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf; if (allflags == 0) { printf("pstat: one or more of -[aixptfsu] is required\n"); *************** *** 216,222 nin = 0; ninode = getw(nl[SNINODE].n_value); xinode = (struct inode *)calloc(ninode, sizeof (struct inode)); ! klseek(fc, (int)(ainode = (struct inode *)getw(nl[SINODE].n_value)), 0); read(fc, xinode, ninode * sizeof(struct inode)); for (ip = xinode; ip < &xinode[ninode]; ip++) if (ip->i_count) --- 208,214 ----- nin = 0; ninode = getw(nl[SNINODE].n_value); xinode = (struct inode *)calloc(ninode, sizeof (struct inode)); ! lseek(fc, (int)(ainode = (struct inode *)getw(nl[SINODE].n_value)), 0); read(fc, xinode, ninode * sizeof(struct inode)); for (ip = xinode; ip < &xinode[ninode]; ip++) if (ip->i_count) *************** *** 263,269 { int word; ! klseek(fc, loc, 0); read(fc, &word, sizeof (word)); return (word); } --- 255,263 ----- { int word; ! if (kflg) ! loc &= 0x7fffffff; ! lseek(fc, loc, 0); read(fc, &word, sizeof (word)); if (kflg) word &= 0x7fffffff; *************** *** 265,270 klseek(fc, loc, 0); read(fc, &word, sizeof (word)); return (word); } --- 259,266 ----- loc &= 0x7fffffff; lseek(fc, loc, 0); read(fc, &word, sizeof (word)); + if (kflg) + word &= 0x7fffffff; return (word); } *************** *** 286,292 ntx = 0; ntext = getw(nl[SNTEXT].n_value); xtext = (struct text *)calloc(ntext, sizeof (struct text)); ! klseek(fc, (int)(atext = (struct text *)getw(nl[STEXT].n_value)), 0); read(fc, xtext, ntext * sizeof (struct text)); for (xp = xtext; xp < &xtext[ntext]; xp++) if (xp->x_iptr!=NULL) --- 282,288 ----- ntx = 0; ntext = getw(nl[SNTEXT].n_value); xtext = (struct text *)calloc(ntext, sizeof (struct text)); ! lseek(fc, (int)(atext = (struct text *)getw(nl[STEXT].n_value)), 0); read(fc, xtext, ntext * sizeof (struct text)); for (xp = xtext; xp < &xtext[ntext]; xp++) if (xp->x_iptr!=NULL) *************** *** 330,336 nproc = getw(nl[SNPROC].n_value); xproc = (struct proc *)calloc(nproc, sizeof (struct proc)); ! klseek(fc, (int)(aproc = (struct proc *)getw(nl[SPROC].n_value)), 0); read(fc, xproc, nproc * sizeof (struct proc)); np = 0; for (pp=xproc; pp < &xproc[nproc]; pp++) --- 326,332 ----- nproc = getw(nl[SNPROC].n_value); xproc = (struct proc *)calloc(nproc, sizeof (struct proc)); ! lseek(fc, (int)(aproc = (struct proc *)getw(nl[SPROC].n_value)), 0); read(fc, xproc, nproc * sizeof (struct proc)); np = 0; for (pp=xproc; pp < &xproc[nproc]; pp++) *************** *** 359,365 printf(" %6d", pp->p_pgrp); printf(" %6d", pp->p_pid); printf(" %6d", pp->p_ppid); ! klseek(fc, (long)(Usrptma+btokmx(pp->p_addr)), 0); read(fc, &apte, sizeof(apte)); printf(" %8x", ctob(apte.pg_pfnum+1) - sizeof(struct pte) * UPAGES); printf(" %4x", pp->p_rssize); --- 355,363 ----- printf(" %6d", pp->p_pgrp); printf(" %6d", pp->p_pid); printf(" %6d", pp->p_ppid); ! if (kflg) ! pp->p_addr = (struct pte *)clear((int)pp->p_addr); ! lseek(fc, (long)(Usrptma+btokmx(pp->p_addr)), 0); read(fc, &apte, sizeof(apte)); printf(" %8x", ctob(apte.pg_pfnum+1) - sizeof(struct pte) * UPAGES); printf(" %4x", pp->p_rssize); *************** *** 380,386 register char *mesg; printf("1 cons\n"); ! klseek(fc, (long)nl[SKL].n_value, 0); read(fc, dz_tty, sizeof(dz_tty[0])); mesg = " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n"; printf(mesg); --- 378,386 ----- register char *mesg; printf("1 cons\n"); ! if (kflg) ! nl[SKL].n_value = clear(nl[SKL].n_value); ! lseek(fc, (long)nl[SKL].n_value, 0); read(fc, dz_tty, sizeof(dz_tty[0])); mesg = " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n"; printf(mesg); *************** *** 382,388 printf("1 cons\n"); klseek(fc, (long)nl[SKL].n_value, 0); read(fc, dz_tty, sizeof(dz_tty[0])); ! mesg = " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n"; printf(mesg); ttyprt(&dz_tty[0], 0); if (nl[SNDZ].n_type == 0) --- 382,388 ----- nl[SKL].n_value = clear(nl[SKL].n_value); lseek(fc, (long)nl[SKL].n_value, 0); read(fc, dz_tty, sizeof(dz_tty[0])); ! mesg = " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n"; printf(mesg); ttyprt(&dz_tty[0], 0); if (nl[SNDZ].n_type == 0) *************** *** 387,393 ttyprt(&dz_tty[0], 0); if (nl[SNDZ].n_type == 0) goto dh; ! klseek(fc, (long)nl[SNDZ].n_value, 0); read(fc, &ndz, sizeof(ndz)); printf("%d dz lines\n", ndz); klseek(fc, (long)nl[SDZ].n_value, 0); --- 387,397 ----- ttyprt(&dz_tty[0], 0); if (nl[SNDZ].n_type == 0) goto dh; ! if (kflg) { ! nl[SNDZ].n_value = clear(nl[SNDZ].n_value); ! nl[SDZ].n_value = clear(nl[SDZ].n_value); ! } ! lseek(fc, (long)nl[SNDZ].n_value, 0); read(fc, &ndz, sizeof(ndz)); printf("%d dz lines\n", ndz); lseek(fc, (long)nl[SDZ].n_value, 0); *************** *** 390,396 klseek(fc, (long)nl[SNDZ].n_value, 0); read(fc, &ndz, sizeof(ndz)); printf("%d dz lines\n", ndz); ! klseek(fc, (long)nl[SDZ].n_value, 0); read(fc, dz_tty, ndz * sizeof (struct tty)); for (tp = dz_tty; tp < &dz_tty[ndz]; tp++) ttyprt(tp, tp - dz_tty); --- 394,400 ----- lseek(fc, (long)nl[SNDZ].n_value, 0); read(fc, &ndz, sizeof(ndz)); printf("%d dz lines\n", ndz); ! lseek(fc, (long)nl[SDZ].n_value, 0); read(fc, dz_tty, ndz * sizeof (struct tty)); for (tp = dz_tty; tp < &dz_tty[ndz]; tp++) ttyprt(tp, tp - dz_tty); *************** *** 397,403 dh: if (nl[SNDH].n_type == 0) goto pty; ! klseek(fc, (long)nl[SNDH].n_value, 0); read(fc, &ndz, sizeof(ndz)); printf("%d dh lines\n", ndz); klseek(fc, (long)nl[SDH].n_value, 0); --- 401,411 ----- dh: if (nl[SNDH].n_type == 0) goto pty; ! if (kflg) { ! nl[SNDH].n_value = clear(nl[SNDH].n_value); ! nl[SDH].n_value = clear(nl[SDH].n_value); ! } ! lseek(fc, (long)nl[SNDH].n_value, 0); read(fc, &ndz, sizeof(ndz)); printf("%d dh lines\n", ndz); lseek(fc, (long)nl[SDH].n_value, 0); *************** *** 400,406 klseek(fc, (long)nl[SNDH].n_value, 0); read(fc, &ndz, sizeof(ndz)); printf("%d dh lines\n", ndz); ! klseek(fc, (long)nl[SDH].n_value, 0); read(fc, dz_tty, ndz * sizeof(struct tty)); for (tp = dz_tty; tp < &dz_tty[ndz]; tp++) ttyprt(tp, tp - dz_tty); --- 408,414 ----- lseek(fc, (long)nl[SNDH].n_value, 0); read(fc, &ndz, sizeof(ndz)); printf("%d dh lines\n", ndz); ! lseek(fc, (long)nl[SDH].n_value, 0); read(fc, dz_tty, ndz * sizeof(struct tty)); for (tp = dz_tty; tp < &dz_tty[ndz]; tp++) ttyprt(tp, tp - dz_tty); *************** *** 407,412 pty: if (nl[SPTY].n_type == 0) goto pty; printf("32 pty lines\n"); klseek(fc, (long)nl[SPTY].n_value, 0); read(fc, dz_tty, 32*sizeof(struct tty)); --- 415,423 ----- pty: if (nl[SPTY].n_type == 0) goto pty; + if (kflg) { + nl[SPTY].n_value = clear(nl[SPTY].n_value); + } printf("32 pty lines\n"); lseek(fc, (long)nl[SPTY].n_value, 0); read(fc, dz_tty, 32*sizeof(struct tty)); *************** *** 408,414 if (nl[SPTY].n_type == 0) goto pty; printf("32 pty lines\n"); ! klseek(fc, (long)nl[SPTY].n_value, 0); read(fc, dz_tty, 32*sizeof(struct tty)); for (tp = dz_tty; tp < &dz_tty[32]; tp++) ttyprt(tp, tp - dz_tty); --- 419,425 ----- nl[SPTY].n_value = clear(nl[SPTY].n_value); } printf("32 pty lines\n"); ! lseek(fc, (long)nl[SPTY].n_value, 0); read(fc, dz_tty, 32*sizeof(struct tty)); for (tp = dz_tty; tp < &dz_tty[32]; tp++) ttyprt(tp, tp - dz_tty); *************** *** 449,456 putf(tp->t_state&TS_ASLEEP, 'A'); putf(tp->t_state&TS_XCLUDE, 'X'); putf(tp->t_state&TS_HUPCLS, 'H'); - putf(tp->t_state&TS_TTSTOP, 'S'); - putf(tp->t_state&TS_TBLOCK, 'Q'); printf("%6d", tp->t_pgrp); switch (tp->t_line) { --- 460,465 ----- putf(tp->t_state&TS_ASLEEP, 'A'); putf(tp->t_state&TS_XCLUDE, 'X'); putf(tp->t_state&TS_HUPCLS, 'H'); printf("%6d", tp->t_pgrp); switch (tp->t_line) { *************** *** 599,605 nf = 0; nfile = getw(nl[SNFILE].n_value); xfile = (struct file *)calloc(nfile, sizeof (struct file)); ! klseek(fc, (int)(afile = (struct file *)getw(nl[SFIL].n_value)), 0); read(fc, xfile, nfile * sizeof (struct file)); for (fp=xfile; fp < &xfile[nfile]; fp++) if (fp->f_count) --- 608,614 ----- nf = 0; nfile = getw(nl[SNFILE].n_value); xfile = (struct file *)calloc(nfile, sizeof (struct file)); ! lseek(fc, (int)(afile = (struct file *)getw(nl[SFIL].n_value)), 0); read(fc, xfile, nfile * sizeof (struct file)); for (fp=xfile; fp < &xfile[nfile]; fp++) if (fp->f_count) *************** *** 660,666 swapmap = (struct map *)calloc(nswapmap, sizeof (struct map)); nswdev = getw(nl[SNSWDEV].n_value); swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); ! klseek(fc, nl[SSWDEVT].n_value, L_SET); read(fc, swdevt, nswdev * sizeof (struct swdevt)); klseek(fc, getw(nl[SPROC].n_value), 0); read(fc, proc, nproc * sizeof (struct proc)); --- 669,675 ----- swapmap = (struct map *)calloc(nswapmap, sizeof (struct map)); nswdev = getw(nl[SNSWDEV].n_value); swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); ! lseek(fc, nl[SSWDEVT].n_value, L_SET); read(fc, swdevt, nswdev * sizeof (struct swdevt)); lseek(fc, getw(nl[SPROC].n_value), 0); read(fc, proc, nproc * sizeof (struct proc)); *************** *** 662,668 swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); klseek(fc, nl[SSWDEVT].n_value, L_SET); read(fc, swdevt, nswdev * sizeof (struct swdevt)); ! klseek(fc, getw(nl[SPROC].n_value), 0); read(fc, proc, nproc * sizeof (struct proc)); klseek(fc, getw(nl[STEXT].n_value), 0); read(fc, xtext, ntext * sizeof (struct text)); --- 671,677 ----- swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); lseek(fc, nl[SSWDEVT].n_value, L_SET); read(fc, swdevt, nswdev * sizeof (struct swdevt)); ! lseek(fc, getw(nl[SPROC].n_value), 0); read(fc, proc, nproc * sizeof (struct proc)); lseek(fc, getw(nl[STEXT].n_value), 0); read(fc, xtext, ntext * sizeof (struct text)); *************** *** 664,670 read(fc, swdevt, nswdev * sizeof (struct swdevt)); klseek(fc, getw(nl[SPROC].n_value), 0); read(fc, proc, nproc * sizeof (struct proc)); ! klseek(fc, getw(nl[STEXT].n_value), 0); read(fc, xtext, ntext * sizeof (struct text)); klseek(fc, getw(nl[SWAPMAP].n_value), 0); read(fc, swapmap, nswapmap * sizeof (struct map)); --- 673,679 ----- read(fc, swdevt, nswdev * sizeof (struct swdevt)); lseek(fc, getw(nl[SPROC].n_value), 0); read(fc, proc, nproc * sizeof (struct proc)); ! lseek(fc, getw(nl[STEXT].n_value), 0); read(fc, xtext, ntext * sizeof (struct text)); lseek(fc, getw(nl[SWAPMAP].n_value), 0); read(fc, swapmap, nswapmap * sizeof (struct map)); *************** *** 666,672 read(fc, proc, nproc * sizeof (struct proc)); klseek(fc, getw(nl[STEXT].n_value), 0); read(fc, xtext, ntext * sizeof (struct text)); ! klseek(fc, getw(nl[SWAPMAP].n_value), 0); read(fc, swapmap, nswapmap * sizeof (struct map)); swapmap->m_name = "swap"; swapmap->m_limit = (struct mapent *)&swapmap[nswapmap]; --- 675,681 ----- read(fc, proc, nproc * sizeof (struct proc)); lseek(fc, getw(nl[STEXT].n_value), 0); read(fc, xtext, ntext * sizeof (struct text)); ! lseek(fc, getw(nl[SWAPMAP].n_value), 0); read(fc, swapmap, nswapmap * sizeof (struct map)); swapmap->m_name = "swap"; swapmap->m_limit = (struct mapent *)&swapmap[nswapmap]; *************** *** 932,974 return; badrmfree: printf("bad rmfree\n"); - } - - /* - * Stolen from ps asis. - */ - klseek(fd, loc, off) - int fd; - long loc; - int off; - { - - /* - * If this is a dump, then the kernel isn't doing the page mapping - * for us. Simulate it. - */ - if (kflg && (loc & 0x80000000) != 0) { - long v; - long addr; - struct pte pte; - - loc &= 0x7fffffff; - v = btop(loc); - if(v >= nl[X_SYSSIZE].n_value) { - printf("address botch %x\n", loc); - return; - } - addr = (long)((struct pte *)nl[X_SYSMAP].n_value + v); - lseek(fd, addr&0x7fffffff, 0); - if(read(fd, (char *)&pte, sizeof(pte)) != sizeof(pte)) { - printf("Error reading kmem for pte at %x\n", addr); - return; - } - if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) { - printf("pte bad for %x\n", addr); - return; - } - loc = (long)ptob(pte.pg_pfnum) + (loc & PGOFSET); - } - (void) lseek(fd, (long)loc, off); } --- 941,944 ----- return; badrmfree: printf("bad rmfree\n"); } From harpo!ulysses!burl!clyde!watmath!arwhite Fri Feb 17 03:18:55 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site watmath.UUCP Path: seismo!harpo!ulysses!burl!clyde!watmath!arwhite From: arwhite@watmath.UUCP (Alex White) Newsgroups: net.bugs.4bsd Subject: Panic in soqremque from sonewconn Message-ID: <6928@watmath.UUCP> Date: Fri, 17-Feb-84 03:18:55 EST Article-I.D.: watmath.6928 Posted: Fri Feb 17 03:18:55 1984 Date-Received: Fri, 17-Feb-84 17:39:39 EST Organization: U of Waterloo, Ontario Lines: 24 Status: O Subject: in_pcbdetach does a sofree Index: /sys/netinet/in_pcb.c 4.2BSD Description: System dies with a panic from a garbage pointer in soqremque called from sonewconn. What happens is that sonewconn, calls tcp_usrreq which calls tcp_attach, this calls in_pcballoc which succeeds, but then tcp_newtcpcb fails due to lack of mbufs. tcp_attach hence calls in_pcbdetach to clean up. in_pcbdetach unfortunately invokes sofree which releases the socket itself. we then return back up to sonewconn. Sonewconn now tries to clean up and release the socket itself; it calls soqremq with the socket which now has a zero pointer for so_head and craps out. Superficial examination of code as in udp_usrreq, PRU_ABORT shows that it invokes in_pcbdetach and then itself calls sofree which was done in in_pcbdetach! Repeat-By: Run out of mbuf's. If you don't crash of panic: exit: m_getclr first (I have a fix for that one...) I suppose its probable that you'll hit this after a while... How to run out of mbuf's is another bug, which I haven't tracked down yet - but I suspect that it has something to do with unix domain ipc being used by hundreds of students.... From harpo!ihnp4!houxm!hocda!hou3c!burl!clyde!floyd!cmcl2!rna!dan Sat Feb 18 18:46:34 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Path: seismo!harpo!ihnp4!houxm!hocda!hou3c!burl!clyde!floyd!cmcl2!rna!dan From: dan@rna.UUCP Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: A few small bugs in 4.2bsd learn... Message-ID: <215@rna.UUCP> Date: Sat, 18-Feb-84 18:46:34 EST Article-I.D.: rna.215 Posted: Sat Feb 18 18:46:34 1984 Date-Received: Sun, 19-Feb-84 07:30:28 EST Lines: 31 Status: O Subject: Few bugs with learn Index: /usr/src/usr.bin/learn/copy.c 4.2BSD Description: 1) Typing EOT to learn causes learn to loop on error from stdin. 2) learn scripts files, eqn, vi cannot startup at all. Repeat-By: (above) Fix: 1) In the file, copy.c, add clearerr(stdin)... *** copy.c.org Tue Apr 26 03:04:22 1983 --- copy.c Sat Feb 18 18:11:11 1984 *************** *** 34,35 if (fin == stdin) { fprintf(stderr, "Type \"bye\" if you want to leave learn.\n"); --- 34,36 ----- if (fin == stdin) { + clearerr(stdin); fprintf(stderr, "Type \"bye\" if you want to leave learn.\n"); 2) chmod 755 /usr/lib/learn/files/Init /usr/lib/learn/eqn/Init \ /usr/lib/learn/vi/Init Cheers, Dan Ts'o ...cmcl2!rna!dan From harpo!ulysses!burl!clyde!watmath!arwhite Mon Feb 20 16:46:13 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site watmath.UUCP Path: seismo!harpo!ulysses!burl!clyde!watmath!arwhite From: arwhite@watmath.UUCP (Alex White) Newsgroups: net.bugs.4bsd Subject: out of mbufs bug Message-ID: <6957@watmath.UUCP> Date: Mon, 20-Feb-84 16:46:13 EST Article-I.D.: watmath.6957 Posted: Mon Feb 20 16:46:13 1984 Date-Received: Mon, 20-Feb-84 20:47:35 EST Organization: U of Waterloo, Ontario Lines: 143 Status: O Subject: Crash in PRU_ACCEPT in uipc_usrreq.c when out of mbuf's Index: sys/sys/uipc_usrreq.c 4.2BSD Description: Accept -> soaccept -> uipc_usrreq(PRU_ACCEPT) -> bcopy Bcopy dies as unp->unp_remaddr == 0 Why? Because the connect which this accept refers to, connect -> soconnect -> uipc_usrreq(PRU_CONNECT) -> unp_connect -> unp_connect2 -> m_copy; m_copy has run out of mbufs and returns zero into unp->unp_remaddr. Repeat-By: Ya gotta be kidding, it was after 18,000 requests for memory denied that we got this one. And there seem to be soooo many bugs that occur if you run out, it isn't funny; you'll never get this one a second time! you'll get hit by one of the others. However, for anybody that wants to try, I enclose changes to kern_exit.c so that when you run out of mbufs you won't panic the next time a process exits... Plea-for-help: We keep on running out of mbufs - generally ~600 mbufs allocated to socket structures, ~600 allocated to protocol control blocks, and ~100 to socket names and addresses. (However, we've also had similar crashes without the socket name and address mbufs). We have hundreds of students running a 5-process game communicating via pipes OR sockets in the unix domain. No, it doesn't seem to be legitimate running out because of too many pipes. There don't seem to be enough sitting around after the crash. I've looked at most student's programmes, and haven't found any yet which seems to cause any problems. Fix: *** uipc_usrreq.c Mon Feb 20 16:30:16 1984 --- /usr/distr/4.2/usr/sys/sys/uipc_usrreq.c Sun Sep 25 21:06:43 1983 *************** *** 371,377 case SOCK_STREAM: unp2->unp_conn = unp; ! if (sonam) { unp2->unp_remaddr = m_copy(sonam, 0, (int)M_COPYALL); if(unp2->unp_remaddr == NULL) { unp->unp_conn = 0; --- 368,374 ----- case SOCK_STREAM: unp2->unp_conn = unp; ! if (sonam) unp2->unp_remaddr = m_copy(sonam, 0, (int)M_COPYALL); soisconnected(so2); soisconnected(so); *************** *** 373,384 unp2->unp_conn = unp; if (sonam) { unp2->unp_remaddr = m_copy(sonam, 0, (int)M_COPYALL); - if(unp2->unp_remaddr == NULL) { - unp->unp_conn = 0; - unp2->unp_conn = 0; - return (ENOBUFS); - } - } soisconnected(so2); soisconnected(so); break; --- 370,375 ----- unp2->unp_conn = unp; if (sonam) unp2->unp_remaddr = m_copy(sonam, 0, (int)M_COPYALL); soisconnected(so2); soisconnected(so); break; *** kern_exit.c Fri Feb 17 05:10:18 1984 --- /usr/distr/4.2/usr/sys/sys/kern_exit.c Fri Jul 29 10:07:18 1983 *************** *** 112,124 panic("init died"); done: p->p_xstat = rv; ! if(m == 0) ! printf("No mem for rusage for pid %d\n", p->p_pid); ! else { ! p->p_ru = mtod(m, struct rusage *); ! *p->p_ru = u.u_ru; ! ruadd(p->p_ru, &u.u_cru); ! } for (q = proc; q < procNPROC; q++) if (q->p_pptr == p) { if (q->p_osptr) --- 112,122 ----- panic("init died"); done: p->p_xstat = rv; ! if (m == 0) ! panic("exit: m_getclr"); ! p->p_ru = mtod(m, struct rusage *); ! *p->p_ru = u.u_ru; ! ruadd(p->p_ru, &u.u_cru); for (q = proc; q < procNPROC; q++) if (q->p_pptr == p) { if (q->p_osptr) *************** *** 198,204 u.u_r.r_val1 = p->p_pid; u.u_r.r_val2 = p->p_xstat; p->p_xstat = 0; ! if (ru && p->p_ru) *ru = *p->p_ru; if(p->p_ru) { ruadd(&u.u_cru, p->p_ru); --- 196,202 ----- u.u_r.r_val1 = p->p_pid; u.u_r.r_val2 = p->p_xstat; p->p_xstat = 0; ! if (ru) *ru = *p->p_ru; ruadd(&u.u_cru, p->p_ru); (void) m_free(dtom(p->p_ru)); *************** *** 200,209 p->p_xstat = 0; if (ru && p->p_ru) *ru = *p->p_ru; ! if(p->p_ru) { ! ruadd(&u.u_cru, p->p_ru); ! (void) m_free(dtom(p->p_ru)); ! } p->p_ru = 0; p->p_stat = NULL; p->p_pid = 0; --- 198,205 ----- p->p_xstat = 0; if (ru) *ru = *p->p_ru; ! ruadd(&u.u_cru, p->p_ru); ! (void) m_free(dtom(p->p_ru)); p->p_ru = 0; p->p_stat = NULL; p->p_pid = 0; From harpo!ulysses!burl!clyde!floyd!cmcl2!lanl-a!unm-cvax!unmvax!lee Sun Feb 19 22:12:16 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site unmvax.UUCP Path: seismo!harpo!ulysses!burl!clyde!floyd!cmcl2!lanl-a!unm-cvax!unmvax!lee From: lee@unmvax.UUCP Newsgroups: net.bugs.4bsd Subject: 4.2 Mail bug fix Message-ID: <211@unmvax.UUCP> Date: Sun, 19-Feb-84 22:12:16 EST Article-I.D.: unmvax.211 Posted: Sun Feb 19 22:12:16 1984 Date-Received: Tue, 21-Feb-84 02:27:41 EST Organization: Univ. of New Mexico, Albuquerque Lines: 97 Status: O If a user has parends in the gecos field in /etc/passwd the Mail interface tacks a parend onto the end of his name. This makes 'r' or 'R' annoying. Repeat by: Log in as a user who has an open/close parend pair in his gecos field (or make one or whatever...) and send mail to yourself. When you enter mail you will notice something like.. unmvax 2.1 "/usr/spool/mail/lee": 4 messages > 1 genix!ldl Sun Nov 20 00:02 15/266 2 parsec!kolstad Thu Sep 15 23:29 37/1251 "Re: UUCP connect" 3 lee Sun Sep 4 22:27 14/275 "bad INTEL board" 4 stanly) Sun Feb 19 16:33 12/302 "Re: REDUCE" & To fix: cd to /usr/src/ucb/Mail and edit aux.c The following is a diff -c to show what needs changed. *** aux.original Sun Feb 19 19:58:57 1984 --- aux.c Sun Feb 19 20:02:31 1984 *************** *** 1,5 /* ! * $Header: aux.c,v 1.1 84/02/19 19:58:53 root Exp $ * $Log: aux.c,v $ * Revision 1.1 84/02/19 19:58:53 root * Initial revision --- 1,5 ----- /* ! * $Header: aux.c,v 1.2 84/02/19 20:02:02 root Exp $ * $Log: aux.c,v $ * Revision 1.2 84/02/19 20:02:02 root * Fixed the parends at the end of the name problem. *************** *** 1,6 /* * $Header: aux.c,v 1.1 84/02/19 19:58:53 root Exp $ * $Log: aux.c,v $ * Revision 1.1 84/02/19 19:58:53 root * Initial revision * --- 1,10 ----- /* * $Header: aux.c,v 1.2 84/02/19 20:02:02 root Exp $ * $Log: aux.c,v $ + * Revision 1.2 84/02/19 20:02:02 root + * Fixed the parends at the end of the name problem. + * --Lee + * * Revision 1.1 84/02/19 19:58:53 root * Initial revision * *************** *** 565,572 for (cp = name, cp2 = nbuf; c = *cp++; ) { switch (c) { case '(': ! while (*cp != ')' && *cp != 0) ! cp++; if (*cp) cp++; lastsp = 0; --- 569,592 ----- for (cp = name, cp2 = nbuf; c = *cp++; ) { switch (c) { case '(': ! /* If a user has parends in the GECOS field this ! * used to get TOTALLY messed. We just keep track ! * of how many open parends we see and keep going ! * until count is zero rather than quit at the ! * first close parend. ! * --Lee 84/02/19 ! */ ! { ! int pcount = 1; ! ! while (*cp != 0 && pcount > 0) { ! if (*cp == '(') ! ++pcount; ! else if (*cp == ')') ! --pcount; ! ++cp; ! } ! } if (*cp) cp++; lastsp = 0; --Lee (Ward) {ucbvax,parsec,gatech}!unmvax!lee From rlgvax!guy Sun Feb 19 13:26:22 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1a 12/4/83; site rlgvax.UUCP Path: seismo!rlgvax!guy From: guy@rlgvax.UUCP (Guy Harris) Newsgroups: net.unix-wizards,net.bugs.usg,net.bugs.4bsd Subject: Re: C optimizer bug? Message-ID: <1733@rlgvax.UUCP> Date: Sun, 19-Feb-84 13:26:22 EST Article-I.D.: rlgvax.1733 Posted: Sun Feb 19 13:26:22 1984 Date-Received: Sun, 19-Feb-84 14:11:54 EST References: <16773@sri-arpa.UUCP> Organization: CCI Office Systems Group, Reston, VA Lines: 223 Status: O The System III and 4.xBSD C optimizers (the 4.xBSD optimizer is a later release than the System III one) have a number of bugs, many of which have to do with improperly dealing with conversion instructions. Here is a log of the fixed ones: revision 1.5 date: 83/08/15 05:31:38; author: bin; state: Exp; lines added/del: 5/3 In generating code to extract values from fields, the compiler uses only the extv/extvz instructions. The optimizer changes all extractions of byte/word fields on byte/word boundaries to cvt{b,w}l or movz{b,w}l depending on the field being signed or unsigned. However, it does this incorrectly for word size fields on non-longword boundaries; it adds the offset into the word to the address, but adds it as if it were a byte offset, not a word offset. Fixed. ---------------------------- revision 1.4 date: 83/08/15 05:29:00; author: bin; state: Exp; lines added/del: 4/0 Fix courtesy of James T. Ellis, Microelectronics Center of North Carolina: don't fold ANYTHING with cvtfl, cvtdl, cvtgl, or cvthl!!!! ---------------------------- revision 1.3 date: 83/08/15 05:25:00; author: bin; state: Exp; lines added/del: 25/3 Previous fix meant that if the mask was 0xffff, the instructions were cvtwl and movzwl, which could be merged but weren't. Fixed to merge the instructions iff the sizes of the operands were the same. Also modified to handle masks of 0xffff as well as 0xff. ---------------------------- revision 1.2 date: 83/08/15 05:19:50; author: bin; state: Exp; lines added/del: 8/1 Fixed so as not to collapse a cvtwl xx,dest/bicl $0377,dest sequence into a movzbl xx,dest if the xx does autoincrementing or autodecrementing. The first sequence would increment or decrement the register used in xx by 2, while the second sequence would increment or decrement it by 1. Routine "autoid" added to test if an operand used autoincrement or autodecrement; routine "bicopt" modified to test for !autoid(src of cvtwl) as well as !indexa(src). and here is a "diff -c" listing of the two versions of the optimizer. Note that the line numbers pertain to the 4.1cBSD version, so they may not be exactly the same for the 4.1 or 4.2 versions. This listing can also be used, with some care, for the System III version. (The System V version doesn't have this problem, because it was totally rewritten to be retargetable to the various machines that are targets for the Software Generation Systems.) *** c21.c (original) Sun Feb 19 13:23:08 1984 --- c21.c (fixed) Sun Feb 19 13:23:11 1984 *************** *** 275,281 ** ** also byte- and word-size fields: ** extv $n*8,$8,A,B > cvtbl n+A,B ! ** extv $n*16,$16,A,B > cvtwl n+A,B ** extzv $n*8,$8,A,B > movzbl n+A,B ** extzv $n*16,$16,A,B > movzwl n+A,B */ --- 275,281 ----- ** ** also byte- and word-size fields: ** extv $n*8,$8,A,B > cvtbl n+A,B ! ** extv $n*16,$16,A,B > cvtwl 2n+A,B ** extzv $n*8,$8,A,B > movzbl n+A,B ** extzv $n*16,$16,A,B > movzwl 2n+A,B */ *************** *** 277,283 ** extv $n*8,$8,A,B > cvtbl n+A,B ** extv $n*16,$16,A,B > cvtwl n+A,B ** extzv $n*8,$8,A,B > movzbl n+A,B ! ** extzv $n*16,$16,A,B > movzwl n+A,B */ register struct node *pf; /* forward node */ register struct node *pn; /* next node (after pf) */ --- 277,283 ----- ** extv $n*8,$8,A,B > cvtbl n+A,B ** extv $n*16,$16,A,B > cvtwl 2n+A,B ** extzv $n*8,$8,A,B > movzbl n+A,B ! ** extzv $n*16,$16,A,B > movzwl 2n+A,B */ register struct node *pf; /* forward node */ register struct node *pn; /* next node (after pf) */ *************** *** 322,328 if (coff == 0) strcpy(regs[RT1], regs[RT3]); else ! sprintf(regs[RT1], "%d%s%s", coff, regs[RT3][0]=='(' ? "":"+", regs[RT3]); strcpy(regs[RT2], regs[RT4]); regs[RT3][0] = '\0'; regs[RT4][0] = '\0'; --- 322,330 ----- if (coff == 0) strcpy(regs[RT1], regs[RT3]); else ! sprintf(regs[RT1], "%d%s%s", ! (flen == 8 ? coff : 2*coff), ! (regs[RT3][0] == '(' ? "" : "+"), regs[RT3]); strcpy(regs[RT2], regs[RT4]); regs[RT3][0] = '\0'; regs[RT4][0] = '\0'; *************** *** 788,793 /* use field operations or MOVZ if possible. done as part of 'bflow'. */ register char *cp1,*cp2; int r; char src[C2_ASIZE]; if (!bixprep(p,JBCC)) return(p); if (f==0) {/* the BIC isolates low order bits */ --- 790,796 ----- /* use field operations or MOVZ if possible. done as part of 'bflow'. */ register char *cp1,*cp2; int r; + char lhssiz, subop; char src[C2_ASIZE]; if (!bixprep(p,JBCC)) return(p); if (f==0) {/* the BIC isolates low order bits */ *************** *** 804,809 delnode(p->back); } } if (p->back->op==CVT || p->back->op==MOVZ) {/* greedy, aren't we? */ splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT2]; if (equstr(src,cp2) && okio(cp1) && !indexa(cp1) --- 807,825 ----- delnode(p->back); } } + /* + * 'pos', 'siz' known; find out the size of the + * left-hand operand of what the bicl will turn into. + */ + if (pos==0) { + if (siz==8) + lhssiz = BYTE; /* movzbl */ + else if (siz==16) + lhssiz = WORD; /* movzwl */ + else + lhssiz = BYTE; /* extzvl */ + } else + lhssiz = BYTE; /* extzvl */ if (p->back->op==CVT || p->back->op==MOVZ) {/* greedy, aren't we? */ splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT2]; /* *************** *** 806,812 } if (p->back->op==CVT || p->back->op==MOVZ) {/* greedy, aren't we? */ splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT2]; ! if (equstr(src,cp2) && okio(cp1) && !indexa(cp1) && 0<=(r=isreg(cp2)) && rback->subop&0xF]>=(pos+siz) && bitsize[p->back->subop>>4]>=(pos+siz)) {/* good CVT */ --- 822,840 ----- lhssiz = BYTE; /* extzvl */ if (p->back->op==CVT || p->back->op==MOVZ) {/* greedy, aren't we? */ splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT2]; ! /* ! * If indexa(cp1) || autoid(cp1), the fold may ! * still be OK if the CVT/MOVZ has the same ! * size operand on its left size as what we ! * will turn the bicl into. ! * However, if the CVT is from a float or ! * double, forget it! ! */ ! subop = p->back->subop&0xF; /* type of LHS of CVT/MOVZ */ ! if (equstr(src,cp2) && okio(cp1) ! && subop != FFLOAT && subop != DFLOAT ! && subop != GFLOAT && subop != HFLOAT ! && ((!indexa(cp1) && !autoid(cp1)) || lhssiz == subop) && 0<=(r=isreg(cp2)) && rback->subop&0xF]>=(pos+siz) && bitsize[p->back->subop>>4]>=(pos+siz)) {/* good CVT */ *************** *** 816,823 } /* 'pos', 'siz' known; source of field is in 'src' */ splitrand(p); /* retrieve destination of BICL */ ! if (siz==8 && pos==0) { ! p->combop = T(MOVZ,U(BYTE,LONG)); sprintf(line,"%s,%s",src,lastrand); } else { p->combop = T(EXTZV,LONG); --- 844,851 ----- } /* 'pos', 'siz' known; source of field is in 'src' */ splitrand(p); /* retrieve destination of BICL */ ! if ((siz==8 || siz==16) && pos==0) { ! p->combop = T(MOVZ,U(lhssiz,LONG)); sprintf(line,"%s,%s",src,lastrand); } else { p->combop = T(EXTZV,LONG); *************** *** 1361,1366 indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */ while (*p) if (*p++=='[') return(1); return(0); } --- 1389,1401 ----- indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */ while (*p) if (*p++=='[') return(1); + return(0); + } + + autoid(p) register char *p; {/* 1-> uses autoincrement/autodecrement; 0->doesn't */ + if (*p == '-' && *(p+1) == '(') return(1); + while (*p) p++; + if (*--p == '+' && *--p == ')') return(1); return(0); } Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy From unix-wizards-request@BRL-VGR.ARPA Sat Feb 25 13:30:36 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Sat, 25 Feb 84 13:30:36 est Message-Id: <8402251830.AA00590@seismo.ARPA> Received: From Su-Coyote.ARPA by BRL-VGR via smtp; 24 Feb 84 14:21 EST From: Jeff Mogul Date: 24 Feb 1984 1116-PST (Friday) To: unix-wizards@brl-vgr Subject: fix for 4.2BSD kernel bug that trashes file systems Status: RO A few months ago, I sent a request to this list for help with a bug that was quietly trashing files and directories. I knew that the problem was a bad reference count on a file struct; I just wasn't sure how it got like that. Berkeley responded to me, with a fix that works fine. However, every few days I get a message from someone else who has the same problem, and since Berkeley has publicized this fix, I have to do so to keep my sanity. My guess is that there are oodles of apparently bizarre problems that will be solved by installing this fix. Of course, I take no responsibility if it doesn't work for you! ------- Forwarded Message Received: from UCB-VAX.ARPA by Navajo with TCP; Tue, 13 Dec 83 16:06:50 pst Received: from ucbmonet.ARPA by UCB-VAX.ARPA (4.22/4.16) id AA13058; Tue, 13 Dec 83 16:04:52 pst Received: by ucbmonet.ARPA (4.22/4.14) id AA00424; Tue, 13 Dec 83 16:06:54 pst From: karels%ucbmonet@Berkeley (Mike Karels) Message-Id: <8312140006.AA00424@ucbmonet.ARPA> Date: 13 Dec 1983 1606-PST (Tuesday) To: Jeff Mogul Subject: Re: Serious 4.2 kernel bug causes files and directories to be mangled You are right about the race in ino_close/closef, the problem can occur whenever the device close routine blocks for output to flush. We haven't seen the problem here (strangely), but it was discovered by Robert Elz. The changes that we have made follow; they have been running for a week or two on several machines without any problems, so I think there shouldn't be any problem. There are actually two changes; the first guarantees that closef will be done only once, even if interrupted, and the second catches interrupts in ino_close, which will then always return to closef. f_close can then be cleared exactly once. By the way, the ordering becomes more similar to that in 4.1. Mike Nov 18 10:06 1983 SCCS/s.kern_descrip.c: -r6.2 vs. -r6.3 Page 1 246,247d245 < closef(fp); < /* WHAT IF u.u_error ? */ 249a248,249 > closef(fp); > /* WHAT IF u.u_error ? */ Nov 18 10:06 1983 SCCS/s.sys_inode.c: -r6.1 vs. -r6.2 Page 1 294c294 < struct file *fp; --- > register struct file *fp; 296a297 > register struct file *ffp; 309d309 < fp->f_count = 0; /* XXX Should catch */ 336,337c336,337 < for (fp = file; fp < fileNFILE; fp++) { < if (fp->f_type == DTYPE_SOCKET) /* XXX */ --- > for (ffp = file; ffp < fileNFILE; ffp++) { > if (ffp == fp) 339c339,341 < if (fp->f_count && (ip = (struct inode *)fp->f_data) && --- > if (ffp->f_type == DTYPE_SOCKET) /* XXX */ > continue; > if (ffp->f_count && (ip = (struct inode *)ffp->f_data) && 352c354,363 < (*cfunc)(dev, flag, fp); --- > if (setjmp(&u.u_qsave)) { > /* > * If device close routine is interrupted, > * must return so closef can clean up. > */ > if (u.u_error == 0) > u.u_error = EINTR; /* ??? */ > return; > } > (*cfunc)(dev, flag); ------- End of Forwarded Message By the way, I strongly recommend, in sys/ufs_inode.c, in iput() adding (before the first line of code): if (ip->i_count < 1) panic("iput: starting count < 1"); This will save you from similar sorts of trashing in the future (i.e., your system will crash but your files will not be randomly trashed.) For those of you who remember a similar bug in the 4.1BSD mpx code, this same panic would also have caught the problem. -Jeff From unix-wizards-request@BRL-VGR.ARPA Sat Feb 25 23:05:32 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Sat, 25 Feb 84 23:05:32 est Received: From Mit-Bold.ARPA by BRL-VGR via smtp; 25 Feb 84 22:19 EST Received: by mit-bold.ARPA (4.12/4.7) id AA00281; Sat, 25 Feb 84 22:19:47 est Date: Sat, 25 Feb 84 22:19:47 est From: Robert W. Scheifler Message-Id: <8402260319.AA00281@mit-bold.ARPA> Subject: bug in 4.2 select() Index: /sys/sys/sys_generic.c 4.2BSD Apparently-To: unix-wizards@brl-vgr Status: RO Description: If a SIGTSTP is generated on the controlling tty of a process that is waiting in a select() on that tty, the process will mysteriously vanish. Repeat-By: Run in foreground the program: main() { int fds = 1; select(1, &fds, 0, 0, 0); } and then generate SIGTSTP from the keyboard. The process will correctly suspend, but as soon as a character becomes available for input to the terminal (i.e. as soon as you type CR to the shell), the process will vanish. Why: At the select(), the tty t_rsel gets set to the process, but no chars are available, so the process goes into state SSLEEP on &selwait. When the suspend character is typed, a psignal() on the process changes its state to SSTOP and sets p_cursig to SIGTSTP. When input chars are made available to the tty, a ttwakeup() is performed, which calls selwakeup() because t_rsel is still set. Since this is the only process that has done select() on the tty, there are no collisions, and selwakeup() simply calls setrun() on the process rather than calling wakeup(). Therein lies the bug, because this bogusly makes the process runnable, and it will run before the input chars are gobbled, and so the select() will succeed and try to return. However, p_cursig is still set to SIGTSTP, and syscall() will see it and call psig(), which will call exit() and the process will vanish. Also note another bug (which I don't propose a fix for here): select() will succeed on a tty even if the process and the tty are in different process groups. So the process will think there is data to read, and then hang trying to do the actual read. Fix: selwakeup() should make the same checks in the single process case that wakeup() makes per process in the general case. In selwakeup(), replace: setrun(p); with: { if (p->p_stat == SSLEEP) setrun(p); else unsleep(p); } [Note that the special casing of one process from multiple processes and tracking collisions doesn't seem to have helped much, since setrun() or unsleep() will do basically the same work wakeup() does in munging the hash chain.] From unix-wizards-request@BRL-VGR.ARPA Tue Feb 28 10:49:54 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Tue, 28 Feb 84 10:49:54 est Message-Id: <8402281549.AA00955@seismo.ARPA> Received: From brl-gateway2.ARPA by BRL-VGR via smtp; 26 Feb 84 20:24 EST Received: From Bbnh.ARPA by BRL via smtp; 26 Feb 84 20:18 EST Date: Sun, 26 Feb 84 20:10:44 EST From: Bob Walsh Subject: 4.2BSD bugfix netimp/if_imphost.c To: unix-wizards@brl Status: RO Problem: A vax with multiple imps seg faults upon booting. Solution: Fix netimp/if_imphost.c for reasons that the comments in the code indicate. 121,123d120 < #ifdef BUGFIXES < register struct mbuf *nextm; < #endif 126,132d122 < #ifdef BUGFIXES < /* < * see BUGFIXES below < */ < for (m = hosts; m; m = nextm) { < nextm = m->m_next; < #else 134d123 < #endif 209,211d197 < #ifdef BUGFIXES < register struct mbuf *nextm; < #endif 215,226d200 < #ifdef BUGFIXES < /* < * hostrelease may put the current m on the free list, so avoid < * traversing the free list instead of the host list. Not only is < * this wrong, but it can cause a panic if an mbuf pointing to a page < * is used since then in hostrelease(), the dtom macro does not < * produce a proper pointer to the mbuf structure. < * bw 2/26/84 < */ < for (m = hosts; m; m = nextm) { < nextm = m->m_next; < #else 228d201 < #endif bob walsh From unix-wizards-request@BRL-VGR.ARPA Tue Feb 28 10:50:04 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Tue, 28 Feb 84 10:50:04 est Message-Id: <8402281550.AA00967@seismo.ARPA> Received: From brl-gateway2.ARPA by BRL-VGR via smtp; 26 Feb 84 20:58 EST Received: From Bbnh.ARPA by BRL via smtp; 26 Feb 84 20:53 EST Date: Sun, 26 Feb 84 20:46:04 EST From: Bob Walsh Subject: 4.2BSD netimp/if_imphost.c To: unix-wizards@brl Status: RO After thinking about it a little bit, I realize my first letter contained code with hastily written comments. The code corrections are correct, but the code comments contained an incorrect analysis. I believe this diff contains code comments with a correct analysis of the source of the panic. 121,123d120 < #ifdef BUGFIXES < register struct mbuf *nextm; < #endif 126,132d122 < #ifdef BUGFIXES < /* < * see BUGFIXES below < */ < for (m = hosts; m; m = nextm) { < nextm = m->m_next; < #else 134d123 < #endif 209,211d197 < #ifdef BUGFIXES < register struct mbuf *nextm; < #endif 215,236d200 < #ifdef BUGFIXES < /* < * hostrelease may put the current m on the free list, so avoid < * traversing the free list instead of the host list. Not only is < * this wrong, but it can cause a panic: < * < * On the mbuf free list, the m_off field is zero (due to MFREE) < * and hm points to the m_next field of the mbuf. < * hm_count is m_next. < * < * m_off is h_q. m_len and m_type (0) are h_addr. < * The qcnt, timer, rfnm, and flags fields of hp are in m_dat. < * < * If hostrelease() is called on an item in the free list, then < * hm_count (m_next) is decremented, trashing the free list which < * we're following. < * < * bw 2/26/84 < */ < for (m = hosts; m; m = nextm) { < nextm = m->m_next; < #else 238d201 < #endif I'll try to be less sloppy, bob walsh From harpo!decvax!linus!utzoo!utcsrgv!utai!uthub!thomson Mon Feb 13 12:44:03 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10 beta 3/9/83; site uthub.UUCP Path: seismo!harpo!decvax!linus!utzoo!utcsrgv!utai!uthub!thomson From: thomson@uthub.UUCP (Brian Thomson) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: 4.2 BSD file/inode counts less than zero. Message-ID: <125@uthub.UUCP> Date: Mon, 13 Feb 84 12:44:03 EST Date-Received: Thu, 23-Feb-84 16:09:45 EST References: <14552@sri-arpa.UUCP> Organization: CSRG, University of Toronto Lines: 107 Status: O Index: sys/kern_descrip.c 4.2BSD Fix Description: It is possible to close a file descriptor more than once, or otherwise use it after it has been closed, and possibly after another process has reallocated it or reallocated the in-core inode it points to. Repeat-By: If you have installed Jeff Mogul's firewall panic in closef() [ref. unix-wizards <14552@sri-arpa.UUCP> Dec 12 83] you may have already seen this. If not, then PUT IT IN FIRST!!! like so: kern_descrip.c, closef(), before (*fp->f_ops->fo_close)(fp); insert if(fp->f_count < 1) panic("closef: f_count < 1"); Then run the following program with the shell 'exec' command, such that it is the only process that has your terminal open: #include #include #include #include jmp_buf jb; int zero; gorp() { longjmp(jb, 0); } main() { int i; for(i = 0; i < 20; i++) if(i != 1) close(i); setjmp(jb); ioctl(1, TIOCSTART, 0); ioctl(1, TIOCFLUSH, &zero); ioctl(1, TIOCSTOP, 0); write(1, "a", 1); signal(SIGALRM, gorp); alarm(1); close(1); } If all went well (so to speak) a single 'a' will print on your terminal, and your 4.2 system will have paniced. Fix: What is happening here is that the process is sleeping at interruptible priority in sys/tty.c routine ttywait() for the output queue to drain. Routine close() in sys/kern_descrip.c doesn't clear u.u_ofile[1] until the close is complete, even though the reference counts in the file table entry and in the inode are decremented BEFORE the close completes, so after the signal wakes us up we have a pointer to a freed file table entry which may also point to a freed in-core inode. Note that the same scenario holds if the process takes a fatal signal during the close, since normal exit() handling involves closing all open file descriptors, and f.d. #1 still looks open. 4.1 used to clear the u.u_ofile[] entry in close() before calling closef(), and doing so would indeed correct the above instance of the problem. But closef() is called from several other places in the code, none of which expect to be interrupted: copen() in sys/ufs_syscalls.c setregs() in sys/kern_exec.c unp_discard() in sys/uipc_usrreq.c The fix I have adopted is suggested by the comment 'XXX Should catch' in sys/sys_inode.c's ino_close(). In that routine, add the declaration label_t oqsave; and replace the last line (*cfunc)(dev, flag, fp); by the lines oqsave = u.u_qsave; if(setjmp(&u.u_qsave) == 0) (*cfunc)(dev, flag, fp); /* last arg is invalid!! */ u.u_qsave = oqsave; There is still the minor problem that the tty doesn't quite get properly closed if a signal is taken, but that is preferable to the mashed file systems people have been reporting. A better, but harder, fix would be to rework ttyclose() so that, instead of waiting, the tty structure gets marked TS_CLOSING and the close completes asynchronously at interrupt time when the outq has drained. I think the lesson to be learned here is that UNIX has become too big to let this setjmp/longjmp-on-signal nonsense remain much longer. -- Brian Thomson, CSRG Univ. of Toronto {linus,ihnp4,uw-beaver,floyd,utzoo}!utcsrgv!thomson From harpo!ulysses!burl!clyde!floyd!vax135!cornell!uw-beaver!ssc-vax!fluke!corey Mon Feb 27 16:19:56 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 Fluke 1/4/84; site fluke.UUCP Path: seismo!harpo!ulysses!burl!clyde!floyd!vax135!cornell!uw-beaver!ssc-vax!fluke!corey From: corey@fluke.UUCP (Corey Satten) Newsgroups: net.bugs.4bsd Subject: vi speedup Message-ID: <1414@vax4.fluke.UUCP> Date: Mon, 27 Feb 84 16:19:56 EST Date-Received: Tue, 28-Feb-84 15:01:59 EST Organization: John Fluke Mfg. Co., Everett, WA Lines: 31 Status: O I have found a severe inefficiency in vi under 4.2BSD which causes startup time to be substantially longer than pre-4.2 versions. The problem is in the code to source the .exrc file -- it does this using one read system call per character of .exrc file. Apparently the test for whether to buffer the reads based on the results of the istty(0) call is reversed. If you read from a tty, it buffers, and if you read from a file it does single byte reads. Since we noticed no problems reading from tty's with the test reversed I opted to eliminate the test altogether. To be safer, you can simply reverse it. If you only have a binary license don't worry, use the EXINIT environment variable instead of .exrc files and you will be fine. That also prevents double sourcing of .exrc when you invoke vi from your home directory. My changes to ex_get.c follow: diff old-ex_get.c new-ex_get.c 66c66 < static char inline[128]; --- > static char inline[BUFSIZ]; 90c90 < if (intty) { --- > { ******* Corey Satten; John Fluke Mfg. Co MS 227E; PO Box C9090 Everett WA 98206 {uw-beaver,decvax!microsof,ucbvax!lbl-csam,allegra,ssc-vax}!fluke!corey (206) 356-5058 From hao!hplabs!sri-unix!rws@mit-bold Sat Feb 25 22:19:47 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Path: seismo!hao!hplabs!sri-unix!rws@mit-bold From: rws%mit-bold@sri-unix.UUCP Newsgroups: net.unix-wizards Subject: bug in 4.2 select() Message-ID: <16949@sri-arpa.UUCP> Date: Sat, 25 Feb 84 22:19:47 EST Date-Received: Wed, 29-Feb-84 17:33:04 EST Lines: 56 Status: O From: Robert W. Scheifler Description: If a SIGTSTP is generated on the controlling tty of a process that is waiting in a select() on that tty, the process will mysteriously vanish. Repeat-By: Run in foreground the program: main() { int fds = 1; select(1, &fds, 0, 0, 0); } and then generate SIGTSTP from the keyboard. The process will correctly suspend, but as soon as a character becomes available for input to the terminal (i.e. as soon as you type CR to the shell), the process will vanish. Why: At the select(), the tty t_rsel gets set to the process, but no chars are available, so the process goes into state SSLEEP on &selwait. When the suspend character is typed, a psignal() on the process changes its state to SSTOP and sets p_cursig to SIGTSTP. When input chars are made available to the tty, a ttwakeup() is performed, which calls selwakeup() because t_rsel is still set. Since this is the only process that has done select() on the tty, there are no collisions, and selwakeup() simply calls setrun() on the process rather than calling wakeup(). Therein lies the bug, because this bogusly makes the process runnable, and it will run before the input chars are gobbled, and so the select() will succeed and try to return. However, p_cursig is still set to SIGTSTP, and syscall() will see it and call psig(), which will call exit() and the process will vanish. Also note another bug (which I don't propose a fix for here): select() will succeed on a tty even if the process and the tty are in different process groups. So the process will think there is data to read, and then hang trying to do the actual read. Fix: selwakeup() should make the same checks in the single process case that wakeup() makes per process in the general case. In selwakeup(), replace: setrun(p); with: { if (p->p_stat == SSLEEP) setrun(p); else unsleep(p); } [Note that the special casing of one process from multiple processes and tracking collisions doesn't seem to have helped much, since setrun() or unsleep() will do basically the same work wakeup() does in munging the hash chain.] From harpo!ulysses!burl!clyde!watmath!arwhite Thu Mar 1 03:06:57 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site watmath.UUCP Path: seismo!harpo!ulysses!burl!clyde!watmath!arwhite From: arwhite@watmath.UUCP (Alex White) Newsgroups: net.bugs.4bsd Subject: Adb and Local Symbols Message-ID: <7054@watmath.UUCP> Date: Thu, 1 Mar 84 03:06:57 EST Date-Received: Thu, 1 Mar 84 11:08:55 EST Organization: U of Waterloo, Ontario Lines: 248 Status: O Well, I've gotten tired of having to find variables on the stack myself, and even trying to find the value of register variables, without even adb printing out the current frame pointer. Since Berkley has eliminated the local symbols, and you have to use compiler specific stuff to get them, I figured this is better than nothing. So, with the following, $C will now print the registers and the values of automatic variables as you go back on the stack, and tells you where in the stack they were. Actually, only the changes to print.c are needed, but you might like the other two fixes, one so if you try to print using floating point format adb won't die if its the reserved operand floating point value; and also so it won't die if it gets a format repeat count of zero under some obscure condition that I forget right now. diff -c ./format.c /usr/distr/4.2/usr/src/bin/adb/format.c *** ./format.c Thu Dec 1 17:50:08 1983 --- /usr/distr/4.2/usr/src/bin/adb/format.c Thu Aug 11 23:06:52 1983 *************** *** 60,67 fcount += modifier-'0'; OD fp--; - if(fcount == 0) - fcount = 1; ELSE fcount = 1; FI --- 60,65 ----- fcount += modifier-'0'; OD fp--; ELSE fcount = 1; FI *************** *** 218,227 case 'f': fw = 0; fw.sa = wx; ! if((wx & ~0xFFFF00FF) == 0x8000) ! printf("(reserved oprnd)"); ! else ! printf("%-16.9f", fw); dotinc=4; break; case 'F': --- 216,222 ----- case 'f': fw = 0; fw.sa = wx; ! printf("%-16.9f", fw); dotinc=4; break; case 'F': *************** *** 226,235 case 'F': fw.sa = wx; ! if((wx & ~0xFFFF00FF) == 0x8000) ! printf("%-32s", "(reserved oprnd)"); ! else ! printf("%-32.18F", fw); dotinc=8; break; case 'n': case 'N': --- 221,227 ----- case 'F': fw.sa = wx; ! printf("%-32.18F", fw); dotinc=8; break; case 'n': case 'N': diff -c ./print.c /usr/distr/4.2/usr/src/bin/adb/print.c *** ./print.c Fri Feb 24 04:19:43 1984 --- /usr/distr/4.2/usr/src/bin/adb/print.c Sun Aug 14 23:38:34 1983 *************** *** 250,265 printregs(); return; ! case 'c': case 'C': { ! int regs[12], *q; ! REGPTR p; ! int i, j, k, l; ! int stackp; ! ! /* Get current registers */ ! for(p = ®list[12], q = ®s[11]; p < ®list[24]; p++, q--) ! *q = kcore ? *p->rkern : *(ADDR *)(((ADDR)&u)+p->roffs); ! IF adrflg THEN frame=adrval; word=get(adrval+6,DSP)&0xFFFF; --- 250,256 ----- printregs(); return; ! case 'c': case 'C': IF adrflg THEN frame=adrval; word=get(adrval+6,DSP)&0xFFFF; *************** *** 270,276 ELSE /* 'callg', can't tell where argp is */ argp=frame; FI callpc=get(frame+16,DSP); - stackp = argp; /* Don't know */ ELIF kcore THEN argp = pcb.pcb_ap; frame = pcb.pcb_fp; --- 261,266 ----- ELSE /* 'callg', can't tell where argp is */ argp=frame; FI callpc=get(frame+16,DSP); ELIF kcore THEN argp = pcb.pcb_ap; frame = pcb.pcb_fp; *************** *** 275,281 argp = pcb.pcb_ap; frame = pcb.pcb_fp; callpc = pcb.pcb_pc; - stackp = pcb.pcb_ksp; ELSE argp= *(ADDR *)(((ADDR)&u)+AP); frame= *(ADDR *)(((ADDR)&u)+FP); callpc= *(ADDR *)(((ADDR)&u)+PC); --- 265,270 ----- argp = pcb.pcb_ap; frame = pcb.pcb_fp; callpc = pcb.pcb_pc; ELSE argp= *(ADDR *)(((ADDR)&u)+AP); frame= *(ADDR *)(((ADDR)&u)+FP); callpc= *(ADDR *)(((ADDR)&u)+PC); *************** *** 279,285 ELSE argp= *(ADDR *)(((ADDR)&u)+AP); frame= *(ADDR *)(((ADDR)&u)+FP); callpc= *(ADDR *)(((ADDR)&u)+PC); - stackp= *(ADDR *)(((ADDR)&u)+USP); FI lastframe=0; ntramp = 0; --- 268,273 ----- ELSE argp= *(ADDR *)(((ADDR)&u)+AP); frame= *(ADDR *)(((ADDR)&u)+FP); callpc= *(ADDR *)(((ADDR)&u)+PC); FI lastframe=0; ntramp = 0; *************** *** 312,323 THEN WHILE localsym(frame,argp) DO word=get(localval,DSP); printf("%8t%s:%10t", cursym->n_un.n_name); ! IF errflg THEN ! prints("?\n"); ! errflg=0; ! ELSE ! printf("%R\n",word); ! FI OD printf("fp: %X%15tap: %X%30tsp: %X\n", frame, argp, stackp); /* Print current registers. */ --- 300,306 ----- THEN WHILE localsym(frame,argp) DO word=get(localval,DSP); printf("%8t%s:%10t", cursym->n_un.n_name); ! IF errflg THEN prints("?\n"); errflg=0; ELSE printf("%R\n",word); FI OD FI *************** *** 319,358 printf("%R\n",word); FI OD - printf("fp: %X%15tap: %X%30tsp: %X\n", frame, argp, stackp); - /* Print current registers. */ - printf("r0: %X%15tr1: %X%30tr2: %X%45tr3: %X\n", - regs[0], regs[1], regs[2], regs[3]); - printf("r4: %X%15tr5: %X%30tr6: %X%45tr7: %X\n", - regs[4], regs[5], regs[6], regs[7]); - printf("r8: %X%15tr9: %X%30tr10: %X%45tr11: %X\n", - regs[8], regs[9], regs[10], regs[11]); - /* Get next frame's registers. */ - i = get(frame+4, DSP); - i >>= 16; i &= 0xfff; /* Register mask */ - for(j = 0x1, k = 0, l = 0 ; (j & 0x1000) == 0 ; j <<= 1, k++) - if(i & j) - regs[k] = get(frame+20+l++*4, DSP); - /* - * Print the current frame's auto variables - i.e -4(fp) -> (sp) - */ - #define MAXPRINT 30 /* Max # of auto words to print */ - k = stackp; - if(frame - MAXPRINT*4 > stackp) - stackp = frame - MAXPRINT*4; - for(i = frame-4 ; i > stackp ; i -= 4) - printf("%X: %X(fp):%20t%X\n", i, i-frame, get(i, DSP)); - if(k != stackp) - printf("%X: %X(fp) ... %X: %X(fp) not displayed\n", - i, i-frame, k, k-frame); - /* - * Calculate the previous frame's sp - */ - stackp = frame + (5+l)*4; /* 0, PSW, AP, FP, PC, saved regs */ - i = get(frame+4, DSP); - stackp += (i >> 30) & 0x3; /* Stack alignment */ - if(i & (1<<29)) /* If CALLS, add on arg space */ - stackp += (get(frame+20+l*4, DSP) & 0xff) * 4; FI if (ntramp == 1) --- 302,307 ----- printf("%8t%s:%10t", cursym->n_un.n_name); IF errflg THEN prints("?\n"); errflg=0; ELSE printf("%R\n",word); FI OD FI if (ntramp == 1) *************** *** 367,373 FI OD break; - } /*print externals*/ case 'e': case 'E': --- 316,321 ----- FI OD break; /*print externals*/ case 'e': case 'E': From hao!hplabs!zehntel!tektronix!decvax!ucbvax!ucbtopaz!ucbopal!dlw Thu Mar 15 01:56:11 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83 v7 ucbopal-1.9 BSD 4.2; site ucbopal.CC.Berkeley.ARPA Path: seismo!hao!hplabs!zehntel!tektronix!decvax!ucbvax!ucbtopaz!ucbopal!dlw From: dlw@ucbopal.CC.Berkeley.ARPA Newsgroups: net.bugs.4bsd Subject: A serious bug in 4.2 bsd restore Message-ID: <157@ucbopal.CC.Berkeley.ARPA> Date: Thu, 15 Mar 84 01:56:11 EST Date-Received: Sun, 4 Mar 84 08:19:07 EST Organization: Univ. of Calif., Berkeley CA USA Lines: 86 Status: O Index: /usr/src/etc/restore 4.2 Fix Description: There is an extremely serious bug in the 4.2bsd restore. You may NOT be able to restore a multi-level dump, even though the tape is readable and everything is there. The problem is actually in ``dump''. However, the kludge given below will allow (most) existing incremental dumps to be read. I will post a fix to dump asap. The problem is that the number of inodes in a filesystem is not recorded directly in the dump tape. restore infers the number from the size of the bit maps at the beginning of the tape. But the bit maps are truncated to the smallest possible size by dump before they are recorded. Thus, if the last inode USED is 3216, the map will be (roughly) that size, instead of the ``real'' number in the filesystem. Unlike any previous dump/restore, this version saves the inode and symbol table between incremental restores. If you do a level 0 on a new filesystem, few inodes are actually ``used''. Thus the map will be small. Several days later you do a level 3 dump. Lots of inodes are used. The maps are much bigger. NOW, assume you have a head crash. The level 0 restore will have made a small map and symtable because of what is on the level 0 tape. When you go to put on the level 3, BINGO! restore will complain of "corrupted directories", "expected inode M, got N", etc. This is because the inodes it finds on the tape are outside the level 0 map, etc. The ``real'' fix is to have dump always record the full map. (It isn't THAT big.) Then restore would ``work''. However, we (and you) have racks of dump tapes already. The fix below causes restore to always use a large map. This ``works'' as long as MAXINO is larger than required for your biggest filesystem. See the output of newfs for the number you require (which is ipg * ncg). Repeat-By: See above. Fix: Below is a diff of tape.c. The line numbers are slightly off because we have a few other changes in there. While I was debugging this, I was frustrated by the fact that verbose & debug output comes out randomly out of sync on stdout and stderr due to buffering. I modified restore.h to cause everything to come out on stdout. It was simpler that way. ------- diff restore.h.old restore.h ------- 6a7,9 > > #undef stderr > #define stderr stdout ------- diff tape.c.old tape.c ------- 14a15,16 > #define MAXINO 65535 /* KLUDGE! */ > 148,150c150,152 < maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; < dprintf(stdout, "maxino = %d\n", maxino); < map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); --- > maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; /* WRONG! */ > dprintf(stdout, "ino map size = %d\n", maxino); > map = calloc((unsigned)1, (unsigned)howmany(maxino>MAXINO?maxino:MAXINO, NBBY)); 160c162 < map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); --- > map = calloc((unsigned)1, (unsigned)howmany(maxino>MAXINO?maxino:MAXINO, NBBY)); 165a168,169 > if (MAXINO > maxino) > maxino = MAXINO; /* Kludge, since we don't really know */ ****** context of the 2 lines above ****** dumpmap = map; curfile.action = USING; getfile(xtrmap, xtrmapskip); if (MAXINO > maxino) maxino = MAXINO; /* Kludge, since we don't really know */ } ****************************************** From hao!hplabs!zehntel!tektronix!decvax!ucbvax!ucbtopaz!ucbopal!dlw Fri Mar 2 22:00:43 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83 v7 ucbopal-1.9 BSD 4.2; site ucbopal.CC.Berkeley.ARPA Path: seismo!hao!hplabs!zehntel!tektronix!decvax!ucbvax!ucbtopaz!ucbopal!dlw From: dlw@ucbopal.CC.Berkeley.ARPA Newsgroups: net.bugs.4bsd Subject: serious bug in dump Message-ID: <158@ucbopal.CC.Berkeley.ARPA> Date: Fri, 2 Mar 84 22:00:43 EST Date-Received: Sun, 4 Mar 84 08:26:11 EST Organization: Univ. of Calif., Berkeley CA USA Lines: 43 Status: O Index: /usr/src/etc/dump 4.2 Fix Description: There is a serious bug in 4.2 bsd dump/restore. It can prevent restore from working even though the tape is "good". I posted a full description of this bug under Index: /usr/src/etc/restore even though the real bug is in ``dump''. This is because it is necessary to fix ``restore'' in order to be able to use existing dump tapes. The problem is that restore needs the full inode bitmap for the filesystem. Dump, as distributed, truncates the map to the smallest size possible (the highest inode of interest). This causes restore to FAIL in some cases. Repeat-by: newfs /dev/rra0h ra81 dump 0 /dev/rra0h ...(add stuff to the filesystem)... dump 3 /dev/rra0h Now try to restore it. Fix: Below is a diff of dumptraverse.c that will fix the bug. The line numbers may not match yours. The routine is ``bitmap()''. ------ diff dumptraverse.c.old dumptraverse.c ------ 210,218c211 < n = -1; < for (i = 0; i < msiz; i++) < if(map[i]) < n = i; < if (n < 0) < return; < n++; < < spcl.c_count = howmany(n * sizeof(map[0]), TP_BSIZE); --- > spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE); From harpo!ulysses!allegra!jpl Sat Mar 3 15:06:47 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site allegra.UUCP Path: seismo!harpo!ulysses!allegra!jpl From: jpl@allegra.UUCP (John P. Linderman) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: bug in realloc in 4.2 version of malloc Message-ID: <2327@allegra.UUCP> Date: Sat, 3 Mar 84 15:06:47 EST Date-Received: Sun, 4 Mar 84 11:43:03 EST Organization: AT&T Bell Laboratories, Murray Hill Lines: 111 Status: O To quote the manual page for malloc: `Realloc' changes the size of the block pointed to by `ptr' to `size' bytes and returns a pointer to the (possibly moved) block. The contents will be unchanged up to the lesser of the new and old sizes. In order to be compatible with older versions, `realloc' also works if `ptr' points to a block freed since the last call of `malloc', `realloc' or `calloc'; sequences of `free', `malloc' and `realloc' were previously used to attempt storage compaction. This procedure is no longer recommended. It certainly isn't recommended. It doesn't work if there have been too many calls to free() before the call to realloc(), as the following test program demonstrates. Repeat by: Run this under 4.2: #include main() { char *q, *p[20], *malloc(), *realloc(); int i; for (i = 0; i < 20; i++) p[i] = malloc(10); q = p[0]; for (i = 0; i < 10; *q++ = ++i); q = p[0]; for (i = 0; i < 10; i++) printf("%d ", *q++); printf("\n"); for (i = 0; i < 20; i++) free(p[i]); q = realloc(p[0], 20); for (i = 0; i < 10; i++) printf("%d ", *q++); printf("\n"); } The output will look like 1 2 3 4 5 6 7 8 9 10 1 2 3 4 0 0 0 0 0 0 Only the first four characters of p[0] are unchanged, not the original 10 bytes, as advertised. Fix by: The simplest fix is to change the initialization of realloc_srchlen in /usr/src/lib/lic/gen/malloc.c from int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ to int realloc_srchlen = -1; /* Let's be right, not fast: look everywhere */ The problems arise because realloc() tells findbucket() to look for the freed block only among the first realloc_srchlen items in the free chains, and when findbucket() fails to find it, realloc() assumes the freed block was of minimal size, and ends up copying only the first few bytes, regardless of the original size. The suggested fix will cause findbucket() to find the free block and use the correct size if it is found, defaulting to the minimum size only if the block doesn't appear on the free list at all. Comments (exercising great restraint to avoid undue sarcasm): The new malloc is very conservative of cycles and very profligate with space. If you allocate blocks whose sizes are exact powers of 2, you'll get approximately 50% storage efficiency. If you allocate a megabyte for temporary storage, then free it when you are done, you'll never use that space unless you allocate another area of comparable size. There is a tolerable amount of dead code in the routine, considering the preoccupation with efficiency. For example, in morecore(), one finds rnu = (bucket <= 8) ? 11 : bucket + 3; nblks = 1 << (rnu - (bucket + 3)); /* how many blocks to get */ if (rnu < bucket) rnu = bucket; Now, (bucket <= 8) => (rnu == 11) => (rnu > bucket) (bucket > 8) => (rnu == (bucket + 3)) => (rnu > bucket) so the `if' is always false. A little later in the same routine, one finds /* * Round up to minimum allocation size boundary * and deduct from block count to reflect. */ if ((int)op & 7) { op = (union overhead *)(((int)op + 8) &~ 7); nblks--; } Fortunately, the code earlier in the routine ensures that this conditional is also always false. If it were true, the size of the area at op might no longer be large enough after rounding op up, and an area of insufficient size could be returned. On the other hand, morecore should (but doesn't) end with a op->ov_next = NULL; since sbrk() doesn't promise to clear the new space to 0's, but malloc relies on the free chains being terminated by NULL pointers. John P. Linderman Space Cadet allegra!jpl From hao!kpno!arizona!utah-cs!lepreau Fri Mar 9 01:56:38 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Path: seismo!hao!kpno!arizona!utah-cs!lepreau From: lepreau@utah-cs.UUCP Newsgroups: net.unix-wizards Subject: Re: Request for enlightenment re `rwhod" Message-ID: <2552@utah-cs.UUCP> Date: Fri, 9 Mar 84 01:56:38 EST Date-Received: Sun, 4 Mar 84 01:54:24 EST References: vax4.1405 Lines: 10 Status: O The problem is probably simply that the 4.2 rhwod throws away malformed packets, which is OK except that the check is overly stringent and it throws out all hostnames with '-' in them. Change an "isalnum" in rwhod.c to "isprint", say. I am really do expect your ethernet is a broadcast medium and that IFF_BROADCAST is set; try ifconfig . (like "il0"). (Course ifconfig had its bugs too, but they shouldn't affect this.) Jay Lepreau, lepreau@utah-cs, harpo!utah-cs!lepreau From harpo!ulysses!allegra!princeton!astrovax!wls Mon Mar 5 16:41:08 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site astrovax.UUCP Path: seismo!harpo!ulysses!allegra!princeton!astrovax!wls From: wls@astrovax.UUCP (William L. Sebok) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: 4.2 BSD bug in handling "tbuf par fault" on VAX 750 Message-ID: <229@astrovax.UUCP> Date: Mon, 5 Mar 84 16:41:08 EST Date-Received: Mon, 5 Mar 84 20:18:15 EST Organization: Princeton Univ. Astrophysics Lines: 40 Status: O Index: /sys/vax/machdep.c 4.2BSD Description: The computer (a Vax 750) occasionally panics: machine check 2: cp tbuf par fault even though BSD 4.2 contains the patch to flush and return on tbuf parity errors. The problem is that the test for the condition insists that bit 0 of the mcesr (prefetch reference bit) be zero, which need not be true. Repeat-By: Eventually the computer will panic as described above. Fix: Here are the diffs to /sys/vax/machdep.c. The line numbers of the new machdep.c may vary as there have been other fixes necessary. *** machdep.c.ORIG Tue Feb 28 11:27:04 1984 --- machdep.c Mon Mar 5 15:10:41 1984 *************** *** 811,817 mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl, mfpr(MCSR)); mtpr(MCESR, 0xf); ! if ((mcf->mc5_mcesr&0xf) == MC750_TBPAR) { printf("tbuf par: flushing and returning\n"); mtpr(TBIA, 0); return; --- 822,828 ----- mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl, mfpr(MCSR)); mtpr(MCESR, 0xf); ! if ((mcf->mc5_mcesr&0xe) == MC750_TBPAR) { printf("tbuf par: flushing and returning\n"); mtpr(TBIA, 0); return; -- Bill Sebok Princeton University, Astrophysics {allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,princeton,vax135}!astrovax!wls From harpo!ulysses!allegra!princeton!astrovax!wls Mon Mar 5 16:43:42 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site astrovax.UUCP Path: seismo!harpo!ulysses!allegra!princeton!astrovax!wls From: wls@astrovax.UUCP (William L. Sebok) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: in BSD 4.2: "soft ecc" is printed for uncorrectible memory error Message-ID: <230@astrovax.UUCP> Date: Mon, 5 Mar 84 16:43:42 EST Date-Received: Mon, 5 Mar 84 20:18:49 EST Organization: Princeton Univ. Astrophysics Lines: 57 Status: O Index: /sys/vax/machdep.c 4.2BSD Description: In memerr() in /sys/vax/machdep.c no test is ever done to check whether memory errors on a VAX 750 are correctible or not. Thus strange panics and such may occur with no indication on the console that there was a hard error. The fix below fixes the problem for a VAX 750. I suspect that the same problem is also present in the VAX 780 and 730 support code, as I have not seen any tests for the uncorrectable memory error condition. This bug was also present in 4.1. Repeat-By: Get yourself a bad memory board with hard errors. The system may do all sorts of strange things because of memory errors yet only "soft ecc" messages will appear on the console. Fix: Here are the diffs to /sys/vax/machdep.c. The line numbers of the new machdep.c may vary as there have been other fixes necessary. *** machdep.c.ORIG Tue Feb 28 11:27:04 1984 --- machdep.c. Mon Mar 5 15:30:39 1984 *************** *** 481,488 if (M750_ERR(mcr)) { struct mcr amcr; amcr.mc_reg[0] = mcr->mc_reg[0]; ! printf("mcr%d: soft ecc addr %x syn %x\n", ! m, M750_ADDR(&amcr), M750_SYN(&amcr)); M750_INH(mcr); } break; --- 481,497 ----- if (M750_ERR(mcr)) { struct mcr amcr; amcr.mc_reg[0] = mcr->mc_reg[0]; ! /* ! * modified to distinguish hard and soft errors ! * (W. Sebok astrovax!wls 3/7/83) ! */ ! if (M750_ERR(mcr)&M750_UNCORR) { ! printf("mcr%d: hard error",m); ! } else { ! printf("mcr%d: soft ecc",m); ! } ! printf(" addr %x syn %x\n", ! M750_ADDR(&amcr), M750_SYN(&mcr)); M750_INH(mcr); } break; *************** -- Bill Sebok Princeton University, Astrophysics {allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,princeton,vax135}!astrovax!wls From harpo!ulysses!allegra!princeton!astrovax!wls Mon Mar 5 16:49:33 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site astrovax.UUCP Path: seismo!harpo!ulysses!allegra!princeton!astrovax!wls From: wls@astrovax.UUCP (William L. Sebok) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: DTR not enabled on dh driver when soft carrier flag set. Message-ID: <231@astrovax.UUCP> Date: Mon, 5 Mar 84 16:49:33 EST Date-Received: Mon, 5 Mar 84 20:19:23 EST Organization: Princeton Univ. Astrophysics Lines: 41 Status: O This bug may have been noted before but I am not sure when. Also please note the other bug in the handling of the soft carrier flag in the dh driver reported by Lou Salkind (i.e. the line hangs up when Carrier is dropped even though the soft carrier flag is set). Index: /sys/vaxuba/dh.c 4.2BSD Description: If the soft carrier flag for a dh line is set (dhsoftCAR), data terminal ready (DTR) will never be set on open. Thus, terminals (or modems) which require DTR will not work. Repeat-By: Connect a terminal or modem which requires DTR to a line with modem control which has dhsoftCAR set. The device will not operate. Fix: *** dh.c.ORIG Fri Jul 29 10:33:35 1983 --- dh.c Thu Jan 26 02:21:49 1984 *************** *** 633,640 dm = unit >> 4; tp = &dh11[unit]; unit &= 0xf; ! if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0 || ! (dhsoftCAR[dm]&(1<t_state |= TS_CARR_ON; return; } --- 633,639 ----- dm = unit >> 4; tp = &dh11[unit]; unit &= 0xf; ! if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0) { tp->t_state |= TS_CARR_ON; return; } *************** -- Bill Sebok Princeton University, Astrophysics {allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,princeton,vax135}!astrovax!wls From harpo!decvax!genrad!wjh12!n44a!hscfvax!don Mon Mar 5 13:00:40 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Path: seismo!harpo!decvax!genrad!wjh12!n44a!hscfvax!don From: don@hscfvax.UUCP Newsgroups: net.bugs.4bsd Subject: 'at' bugs Message-ID: <179@hscfvax.UUCP> Date: Mon, 5 Mar 84 13:00:40 EST Date-Received: Tue, 6 Mar 84 02:00:04 EST Lines: 51 Status: O Subject: two bugs in at Index: usr.bin/at 4.2BSD Description: (1) at's date algorithm is wrong .07% of the time: it thinks the julian date of March 1st in leap years is 60, not 61 (it screwed up our accounting last month) (2) if you try to queue more than 100 jobs at a single time, it loops (patiently looking for an unused 2-digit sequence) Repeat-By: (1) unless you lie to Unix about today's date you'll have to wait four years (2) just try it Fix: 19a20,21 > #define MAXJOBS 20 /* max no. of jobs queued in a particular minute */ > 282a285,286 > if (detail->tm_year%4==0 && found > 1) > uday += 1; 285,286d288 < if (detail->tm_year%4==0 && uday>59) < uday += 1; 336,341c338,357 < for (i=0; ; i += 53) { < sprintf(fname, "%s/%02d.%03d.%04d.%02d", dir, y, d, t, < (getpid()+i)%100); < if (access(fname, 0) == -1) < return; < } --- > for(;;){ > for (i = 0; i < MAXJOBS; i++) { > sprintf(fname, "%s/%02d.%03d.%04d.%02d", dir, y, d, t, i); > if (access(fname, 0) == -1) > return; > } > > /* come here if there are > MAXJOBS requests for the same time: > ** move to the next minute */ > > if(++t < 2400) > continue; > t = 0; > if(++d <= 365 + (y%4 == 0)) /* or day, if necessary */ > continue; > d = 0; > if(++y < 100) /* or year */ > continue; > y = 0; /* or century */ > } From harpo!ihnp4!astrovax!wls Tue Mar 6 12:10:36 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site astrovax.UUCP Path: seismo!harpo!ihnp4!astrovax!wls From: wls@astrovax.UUCP (William L. Sebok) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: Oops, bug in bugfix for VAX 750 4.2BSD hard vs. soft memory error Message-ID: <232@astrovax.UUCP> Date: Tue, 6 Mar 84 12:10:36 EST Date-Received: Tue, 6 Mar 84 15:22:54 EST References: <230@astrovax.UUCP> Organization: Princeton Univ. Astrophysics Lines: 64 Status: O One bug of my own slipped out. In the final line M750_SYS(&mcr) should be replaced by M750_SYS(&amcr). I am reposting the rest of the fix. This fix was based on a similar fix to BSD 4.1 in which mcr was used everywhere instead of &amcr. I guess I partially missed one of them. Bill Sebok Princeton University, Astrophysics {allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,princeton,vax135}!astrovax!wls Index: /sys/vax/machdep.c 4.2BSD Description: In memerr() in /sys/vax/machdep.c no test is ever done to check whether memory errors on a VAX 750 are correctible or not. Thus strange panics and such may occur with no indication on the console that there was a hard error. The fix below fixes the problem for a VAX 750. I suspect that the same problem is also present in the VAX 780 and 730 support code, as I have not seen any tests for the uncorrectable memory error condition. This bug was also present in BSD 4.1. Repeat-By: Get yourself a bad memory board with hard errors. The system may do all sorts of strange things because of memory errors yet only "soft ecc" messages will appear on the console. Fix: Here are the diffs to /sys/vax/machdep.c. The line numbers of the new machdep.c may vary as there have been other fixes necessary. *** machdep.c.ORIG Tue Feb 28 11:27:04 1984 --- machdep.c. Mon Mar 5 15:30:39 1984 *************** *** 481,488 if (M750_ERR(mcr)) { struct mcr amcr; amcr.mc_reg[0] = mcr->mc_reg[0]; ! printf("mcr%d: soft ecc addr %x syn %x\n", ! m, M750_ADDR(&amcr), M750_SYN(&amcr)); M750_INH(mcr); } break; --- 481,497 ----- if (M750_ERR(mcr)) { struct mcr amcr; amcr.mc_reg[0] = mcr->mc_reg[0]; ! /* ! * modified to distinguish hard and soft errors ! * (W. Sebok astrovax!wls 3/7/83) ! */ ! if (M750_ERR(mcr)&M750_UNCORR) { ! printf("mcr%d: hard error",m); ! } else { ! printf("mcr%d: soft ecc",m); ! } ! printf(" addr %x syn %x\n", ! M750_ADDR(&amcr), M750_SYN(&amcr)); M750_INH(mcr); } break; *************** -- Bill Sebok Princeton University, Astrophysics {allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,princeton,vax135}!astrovax!wls From unix-wizards-request@BRL-VGR.ARPA Tue Mar 6 16:49:26 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Tue, 6 Mar 84 16:49:26 est Received: From nyu-gw.ARPA by BRL-VGR via smtp; 6 Mar 84 16:28 EST Received: by NYU.ARPA; Tue, 6 Mar 84 16:29:24 est Date: Tue, 6 Mar 84 16:29:24 est From: Lou Salkind Message-Id: <8403062129.AA01295@NYU.ARPA> To: unix-wizards@brl-vgr Subject: rwhod fails on point to point links Status: RO Subject: rwhod fails on point to point links Index: etc/rwhod/rwhod.c 4.2BSD Description: rwhod will not send datagram packets over point to point links. Fix: The problem is that the SIOCGIFxxx calls clobber the ifr_name field. The easy solution is just to have rwhod.c to set this field again. Add the following strcpy line (around line 366) in rwhod.c: if (np->n_flags & IFF_POINTOPOINT) { strcpy(ifreq.ifr_name, ifr->ifr_name); if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { Another reasonable thing to do is to change the kernel so that ifr_name doesn't get clobbered in the first place (I have done this). To make this change, you will have to modify net/if.c:ifunit. Replace the line unit = *cp - '0', *cp = 0; with unit = *cp - '0'; From unix-wizards-request@BRL-VGR.ARPA Wed Mar 7 15:28:37 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Wed, 7 Mar 84 15:28:37 est Received: From Purdue.ARPA by BRL-VGR via smtp; 7 Mar 84 14:22 EST Date: Wed, 7 Mar 84 14:25:10 est From: Bob Brown Message-Id: <8403071925.AA25217@purdue.ARPA> Received: by purdue.ARPA; Wed, 7 Mar 84 14:25:10 est To: unix-wizards@brl-vgr.ARPA Subject: 4.2BSD ra81 driver Status: RO We have discovered a number of dismaying things about the 4.2BSD uda50 driver, including a performance curve that drops like a rock under moderate load and the occasional complete disappearence of the device. We've fixed both these problems and the new driver is showing two to five times the performance under heavy load. Context diffs are almost as long as the driver itself. Write or call if you need a copy. Bob Brown (415)965-5407 From unix-wizards-request@BRL-VGR.ARPA Thu Mar 8 11:15:16 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Thu, 8 Mar 84 11:15:09 est Message-Id: <8403081615.AA01375@seismo.ARPA> Received: From Sri-Unix.ARPA by BRL-VGR via smtp; 8 Mar 84 8:54 EST Received: from Usenet.uucp by sri-unix.uucp with rs232; 8 Mar 84 3:28-PST Date: 5 Mar 84 13:49:33-PST (Mon) To: Unix-Wizards@brl-vgr From: hplabs!hao!kpno!astrovax!wls@ucb-vax Subject: DTR not enabled on dh driver when soft carrier flag set. Article-I.D.: astrovax.231 Status: RO This bug may have been noted before but I am not sure when. Also please note the other bug in the handling of the soft carrier flag in the dh driver reported by Lou Salkind (i.e. the line hangs up when Carrier is dropped even though the soft carrier flag is set). Index: /sys/vaxuba/dh.c 4.2BSD Description: If the soft carrier flag for a dh line is set (dhsoftCAR), data terminal ready (DTR) will never be set on open. Thus, terminals (or modems) which require DTR will not work. Repeat-By: Connect a terminal or modem which requires DTR to a line with modem control which has dhsoftCAR set. The device will not operate. Fix: *** dh.c.ORIG Fri Jul 29 10:33:35 1983 --- dh.c Thu Jan 26 02:21:49 1984 *************** *** 633,640 dm = unit >> 4; tp = &dh11[unit]; unit &= 0xf; ! if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0 || ! (dhsoftCAR[dm]&(1<t_state |= TS_CARR_ON; return; } --- 633,639 ----- dm = unit >> 4; tp = &dh11[unit]; unit &= 0xf; ! if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0) { tp->t_state |= TS_CARR_ON; return; } *************** -- Bill Sebok Princeton University, Astrophysics {allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,princeton,vax135}!astrovax!wls From unix-wizards-request@BRL-VGR.ARPA Thu Mar 8 11:20:09 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Thu, 8 Mar 84 11:19:56 est Message-Id: <8403081619.AA01410@seismo.ARPA> Received: From Sri-Unix.ARPA by BRL-VGR via smtp; 8 Mar 84 8:55 EST Received: from Usenet.uucp by sri-unix.uucp with rs232; 8 Mar 84 3:39-PST Date: 5 Mar 84 13:41:08-PST (Mon) To: Unix-Wizards@brl-vgr From: hplabs!hao!kpno!astrovax!wls@ucb-vax Subject: 4.2 BSD bug in handling "tbuf par fault" on VAX 750 Article-I.D.: astrovax.229 Status: RO Index: /sys/vax/machdep.c 4.2BSD Description: The computer (a Vax 750) occasionally panics: machine check 2: cp tbuf par fault even though BSD 4.2 contains the patch to flush and return on tbuf parity errors. The problem is that the test for the condition insists that bit 0 of the mcesr (prefetch reference bit) be zero, which need not be true. Repeat-By: Eventually the computer will panic as described above. Fix: Here are the diffs to /sys/vax/machdep.c. The line numbers of the new machdep.c may vary as there have been other fixes necessary. *** machdep.c.ORIG Tue Feb 28 11:27:04 1984 --- machdep.c Mon Mar 5 15:10:41 1984 *************** *** 811,817 mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl, mfpr(MCSR)); mtpr(MCESR, 0xf); ! if ((mcf->mc5_mcesr&0xf) == MC750_TBPAR) { printf("tbuf par: flushing and returning\n"); mtpr(TBIA, 0); return; --- 822,828 ----- mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl, mfpr(MCSR)); mtpr(MCESR, 0xf); ! if ((mcf->mc5_mcesr&0xe) == MC750_TBPAR) { printf("tbuf par: flushing and returning\n"); mtpr(TBIA, 0); return; -- Bill Sebok Princeton University, Astrophysics {allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,princeton,vax135}!astrovax!wls From harpo!ulysses!burl!clyde!akgua!mcnc!decvax!linus!axiom!smk Wed Mar 7 16:11:38 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site axiom.UUCP Path: seismo!harpo!ulysses!burl!clyde!akgua!mcnc!decvax!linus!axiom!smk From: smk@axiom.UUCP (Steven M. Kramer) Newsgroups: net.bugs,net.bugs.4bsd Subject: bug in 4.2 (compatibility and actual) readdir/telldir Message-ID: <538@axiom.UUCP> Date: Wed, 7 Mar 84 16:11:38 EST Date-Received: Thu, 8 Mar 84 11:24:58 EST Organization: Axiom Technology, Newton MA Lines: 41 Status: O bility library), I fixed one bug but put another back in. Mark Plotnick found the problem and fixed if by reading the test for dd_loc!=0 in seekdir(). The problem, according to Mark, was: In your original code, if offset is 0, then the lseek is done, but readdir isn't called at all. (the test at the top of the while loop fails). Therefore, dd_size and dd_buf still contain info pertaining to the old block. As soon as a readdir is done everything will be OK, since the new block will be read in; the problem only occurs if a seekdir is done without an intervening readdir. If the seekdir is to a spot within the current block (not at the beginning), then your test succeeds (since you're only checking offset), dd_loc is set to the (non-zero) offset, and bingo we've clobbered the only signal we have that the new block needed to be read in. Admittedly this will probably never happen; I can't even think of a use for telldir() and seekdir() other than to rewind the directory to the beginning. The fix is to change: if (offset != 0 && (curloc & ~(DIRBLKSIZ-1)) == base) { --to-- if (dirp->dd_loc != 0 && offset != 0 && (curloc & ~(DIRBLKSIZ-1)) == base) { Both the offset and dd_loc check are needed. Mark also correctly states that dirp->dd_size = 0; should be added after the dirp->dd_loc = 0; line in seekdir(). -- --steve kramer {allegra,genrad,ihnp4,utzoo,philabs,uw-beaver}!linus!axiom!smk (UUCP) linus!axiom!smk@mitre-bedford (MIL) From harpo!decvax!decwrl!sun!shannon Wed Mar 7 18:36:55 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83 SMI; site sun.uucp Path: seismo!harpo!decvax!decwrl!sun!shannon From: shannon@sun.uucp (Bill Shannon) Newsgroups: net.bugs.4bsd Subject: SECURITY HOLE in tftpd Message-ID: <566@sun.uucp> Date: Wed, 7 Mar 84 18:36:55 EST Date-Received: Thu, 8 Mar 84 08:19:58 EST Organization: Sun Microsystems, Inc. Lines: 21 Status: O Subject: tftpd doesn't check file permissions properly Index: etc/tftpd.c 4.2BSD Description: The tftp daemon runs as root and is only supposed to let you access files with public read. However, it only checks the file itself, not the path to the file. Repeat-By: chmod 700 /sys tftp localhost get /sys/sys/tty.c Fix: I fixed it by doing a setgid(-2), setuid(-2) before checking access permissions. It's hard to check the entire path by hand because of symbolic links; you really have to run as someone who will only have public permission to the file. -2/-2 is not guaranteed to be restrictive enough, but it was a quick fix. Perhaps a uid/gid should be reserved for this purpose. Sorry, no diff of the fix. Our tftpd has changed far too much for other reasons for it to be useful. From harpo!decvax!decwrl!sun!gnu Wed Mar 14 02:30:51 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83 SMI; site sun.uucp Path: seismo!harpo!decvax!decwrl!sun!gnu From: gnu@sun.uucp (John Gilmore) Newsgroups: net.bugs.4bsd,net.mail.headers Subject: Fix for ".ARPA" hard-coded in sendmail source Message-ID: <568@sun.uucp> Date: Wed, 14 Mar 84 02:30:51 EST Date-Received: Thu, 8 Mar 84 11:22:58 EST References: <638@vax135.UUCP> Organization: Sun Microsystems, Inc. Lines: 87 Status: O Martin Levy described a problem which occurs when you are not on the Arpanet but are using SMTP over an Ethernet. The problem arises when an SMTP connection is started with e.g. "HELO vax135.uucp". The specified hostname is compared to the result of gethostbyaddr() [the name of the host on the other end of this TCP connection -- in this case "vax135"], but the code assumes that gethostbyaddr() returns a name in the domain ".ARPA". The comparision fails and both names show up: Received: from vax135.uucp (vax135.ARPA) by marvin.uucp (4.12/4.7) From HELO From gethostbyaddr I fixed that bug here, by insisting that the hostname in the HELO line contain the entire string from gethostbyaddr(), but allowing further subdomains and domains after the matching string. The relevant code in daemon.c for getting the verified name is: if (pid == 0) { extern struct hostent *gethostbyaddr(); register struct hostent *hp; extern char *RealHostName; /* srvrsmtp.c */ char buf[MAXNAME]; /* ** CHILD -- return to caller. ** Collect verified idea of sending host. ** Verify calling user id if possible here. */ /* determine host name */ hp = gethostbyaddr(&otherend.sin_addr, sizeof otherend.sin_addr, AF_INET); if (hp != NULL) strcpy(buf, hp->h_name); else strcpy(buf, inet_ntoa(otherend.sin_addr)); RealHostName = newstr(buf); The checking code in srvrsmtp.c is: case CMDHELO: /* hello -- introduce yourself */ ... if (RealHostName != NULL) { char buf[MAXNAME]; register char *a = RealHostName; register char *b = p; /* * Verify that hostname matches, but accept * a leading prefix on a domain boundary, * since the network code doesn't know which * domain the other guy is in. E.g. if we are * talking to "l5" then it can announce itself * as "l5.sun.uucp" and we won't complain. */ while (lower(*a) == lower(*b)) a++, b++; if (*a == '\0' && (*b == '\0' || *b == '.')) goto nameok; /* * Didn't pass validation. Use both names. */ (void) sprintf(buf, "%s (%s)", p, RealHostName); define('s', p = newstr(buf), CurEnv); } else { nameok: define('s', newstr(p), CurEnv); } message("250", "%s Hello %s, pleased to meet you", HostName, p); break; _________________ I just realized there's a small bug in this code; if the supplied hostname and the verified hostname are exactly the same, the while loop fails by running off the end of both. It should be changed to: while (lower(*a) == lower(*b)) { if ('\0' == *a) break; a++, b++; } This change has not been tested. The bug never occurred here, since gethostbyaddr() never returns a domain name and HELO always supplies one. From harpo!decvax!ittvax!dcdwest!sdcsvax!sdccsu3!rusty Wed Mar 7 17:06:27 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdccsu3.UUCP Path: seismo!harpo!decvax!ittvax!dcdwest!sdcsvax!sdccsu3!rusty From: rusty@sdccsu3.UUCP Newsgroups: net.unix-wizards,net.bugs.4bsd Subject: bug in syslog(3) Message-ID: <1637@sdccsu3.UUCP> Date: Wed, 7 Mar 84 17:06:27 EST Date-Received: Thu, 8 Mar 84 08:22:58 EST Organization: U.C. San Diego, Computer Center Lines: 24 Status: O there is a bug in syslog(3) that causes lines containing %C where C isn't 'm' to screw up. syslog(3) is null terminating the string incorrectly. diffs follow: *** /src/lib/libc/gen/syslog.c Mon Jun 27 15:06:44 1983 --- syslog.c Wed Mar 7 17:01:37 1984 *************** *** 70,76 } c = *f++; if (c != 'm') { ! *b++ = '%', *b++ = c, *b++ = '\0'; continue; } if ((unsigned)errno > sys_nerr) --- 70,76 ----- } c = *f++; if (c != 'm') { ! *b++ = '%', *b++ = c; continue; } if ((unsigned)errno > sys_nerr) From hao!hplabs!sri-unix!rlb@Purdue.ARPA Wed Mar 7 16:09:14 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Path: seismo!hao!hplabs!sri-unix!rlb@Purdue.ARPA From: rlb@Purdue.ARPA Newsgroups: net.unix-wizards Subject: 4.2bsd & nexus 0x6c on 11/780 Message-ID: <17291@sri-arpa.UUCP> Date: Wed, 7 Mar 84 16:09:14 EST Date-Received: Thu, 8 Mar 84 18:38:38 EST Lines: 245 Status: O From: Bob Brown 4.2BSD kernel memerr() does not properly clear soft ecc errors if you have an 11/780 running the 64kb chip interleaved memory controller. The reason is that the 0x6c controller has (at least) four registers, the address/syndrome register existing twice - once for each side. If you get an error on the second half (the "D" register), memerr() doesn't clear it and the system hangs at high IPL. Below are some context diffs that might give you an idea how to fix it. New copies of vax/machdep.c and vax/mem.h can be had from me if the diffs seem too much to handle. Bob Brown (415)965-5407 ------------------------------------------------------------------------------ *** /sys/vax/machdep.c Wed Mar 7 13:01:02 1984 --- /user/ftp/pub/machdep.c Wed Mar 7 12:27:28 1984 *************** *** 1,4 ! /* $Header: /usr/src/sys/vax/RCS/machdep.c,v 1.1 84/03/07 12:56:10 rlb Exp $ */ /* machdep.c 6.2 83/10/02 */ #include "../machine/reg.h" --- 1,4 ----- ! /* $Header: machdep.c,v 1.1 83/11/22 15:55:13 root Rel $ */ /* machdep.c 6.2 83/10/02 */ #include "../machine/reg.h" *************** *** 26,31 #include "../h/msgbuf.h" #include "../h/quota.h" #include "../vax/frame.h" #include "../vax/cons.h" #include "../vax/cpu.h" --- 26,32 ----- #include "../h/msgbuf.h" #include "../h/quota.h" + #include "../vax/nexus.h" #include "../vax/frame.h" #include "../vax/cons.h" #include "../vax/cpu.h" *************** *** 428,434 switch (cpu) { #if VAX780 case VAX_780: ! M780_ENA(mcr); break; #endif #if VAX750 --- 429,437 ----- switch (cpu) { #if VAX780 case VAX_780: ! M780_ENA(mcr,2); ! if ((mcr->mc_reg[0]&0xff)==NEX_MEM64I) ! M780_ENA(mcr,3); break; #endif #if VAX750 *************** *** 463,471 switch (cpu) { #if VAX780 case VAX_780: ! if (M780_ERR(mcr)) { ! printf("mcr%d: soft ecc addr %x syn %x\n", ! m, M780_ADDR(mcr), M780_SYN(mcr)); #ifdef TRENDATA memlog(m, mcr); #endif --- 466,474 ----- switch (cpu) { #if VAX780 case VAX_780: ! if (M780_ERR(mcr,2)) { ! printf("mcr%dc: soft ecc addr %x syn %x\n", ! m, M780_ADDR(mcr,2), M780_SYN(mcr,2)); #ifdef TRENDATA memlog(m, mcr); #endif *************** *** 469,475 #ifdef TRENDATA memlog(m, mcr); #endif ! M780_INH(mcr); } break; #endif --- 472,478 ----- #ifdef TRENDATA memlog(m, mcr); #endif ! M780_INH(mcr,2); } if ((mcr->mc_reg[0]&0xff)==NEX_MEM64I && M780_ERR(mcr,3)) { printf("mcr%dd: soft ecc addr %x syn %x\n", *************** *** 471,476 #endif M780_INH(mcr); } break; #endif #if VAX750 --- 474,484 ----- #endif M780_INH(mcr,2); } + if ((mcr->mc_reg[0]&0xff)==NEX_MEM64I && M780_ERR(mcr,3)) { + printf("mcr%dd: soft ecc addr %x syn %x\n", + m, M780_ADDR(mcr,3), M780_SYN(mcr,3)); + M780_INH(mcr,3); + } break; #endif #if VAX750 *************** *** 543,549 #if VAX780 case VAX_780: for (i = 0; i < (sizeof (memlogtab) / sizeof (memlogtab[0])); i++) ! if ((u_char)(M780_SYN(mcr)) == memlogtab[i].m_syndrome) { printf ( "mcr%d: replace %s chip in %s bank of memory board %d (0-15)\n", m, --- 551,557 ----- #if VAX780 case VAX_780: for (i = 0; i < (sizeof (memlogtab) / sizeof (memlogtab[0])); i++) ! if ((u_char)(M780_SYN(mcr,2)) == memlogtab[i].m_syndrome) { printf ( "mcr%d: replace %s chip in %s bank of memory board %d (0-15)\n", m, *************** *** 548,555 "mcr%d: replace %s chip in %s bank of memory board %d (0-15)\n", m, memlogtab[i].m_chip, ! (M780_ADDR(mcr) & 0x8000) ? "upper" : "lower", ! (M780_ADDR(mcr) >> 16)); return; } printf ("mcr%d: multiple errors, not traceable\n", m); --- 556,563 ----- "mcr%d: replace %s chip in %s bank of memory board %d (0-15)\n", m, memlogtab[i].m_chip, ! (M780_ADDR(mcr,2) & 0x8000) ? "upper" : "lower", ! (M780_ADDR(mcr,2) >> 16)); return; } printf ("mcr%d: multiple errors, not traceable\n", m); *** /sys/vax/mem.h Wed Mar 7 13:01:54 1984 --- /user/ftp/pub/mem.h Wed Mar 7 12:27:28 1984 *************** *** 1,4 - /* $Header: /usr/src/sys/vax/RCS/mem.h,v 1.1 84/03/07 12:56:28 rlb Exp $ */ /* mem.h 6.1 83/07/29 */ /* --- 1,3 ----- /* mem.h 6.1 83/07/29 */ /* *************** *** 8,14 * per cpu, so we define macros here to mask that. */ struct mcr { ! int mc_reg[3]; }; /* --- 7,13 ----- * per cpu, so we define macros here to mask that. */ struct mcr { ! int mc_reg[4]; }; /* *************** *** 37,48 /* register; bit 14 there is an error bit which we also clear */ /* these bits are in the back of the ``red book'' (or in the VMS code) */ ! #define M780_INH(mcr) \ ! (((mcr)->mc_reg[2] = (M780_ICRD|M780_HIER|M780_ERLOG)), mtpr(SBIER, 0)) ! #define M780_ENA(mcr) \ ! (((mcr)->mc_reg[2] = (M780_HIER|M780_ERLOG)), mtpr(SBIER, 3<<14)) ! #define M780_ERR(mcr) \ ! ((mcr)->mc_reg[2] & (M780_ERLOG)) #define M780_SYN(mcr) ((mcr)->mc_reg[2] & 0xff) #define M780_ADDR(mcr) (((mcr)->mc_reg[2] >> 8) & 0xfffff) --- 36,47 ----- /* register; bit 14 there is an error bit which we also clear */ /* these bits are in the back of the ``red book'' (or in the VMS code) */ ! #define M780_INH(mcr,i) \ ! (((mcr)->mc_reg[i] = (M780_ICRD|M780_HIER|M780_ERLOG)), mtpr(SBIER, 0)) ! #define M780_ENA(mcr,i) \ ! (((mcr)->mc_reg[i] = (M780_HIER|M780_ERLOG)), mtpr(SBIER, 3<<14)) ! #define M780_ERR(mcr,i) \ ! ((mcr)->mc_reg[i] & (M780_ERLOG)) #define M780_SYN(mcr,i) ((mcr)->mc_reg[i] & 0xff) #define M780_ADDR(mcr,i) (((mcr)->mc_reg[i] >> 8) & 0xfffff) *************** *** 44,51 #define M780_ERR(mcr) \ ((mcr)->mc_reg[2] & (M780_ERLOG)) ! #define M780_SYN(mcr) ((mcr)->mc_reg[2] & 0xff) ! #define M780_ADDR(mcr) (((mcr)->mc_reg[2] >> 8) & 0xfffff) #endif #if VAX750 --- 43,50 ----- #define M780_ERR(mcr,i) \ ((mcr)->mc_reg[i] & (M780_ERLOG)) ! #define M780_SYN(mcr,i) ((mcr)->mc_reg[i] & 0xff) ! #define M780_ADDR(mcr,i) (((mcr)->mc_reg[i] >> 8) & 0xfffff) #endif #if VAX750 From unix-wizards-request@BRL-VGR.ARPA Fri Mar 9 21:56:24 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Fri, 9 Mar 84 21:56:18 est Received: From Sri-Tsc.ARPA by BRL-VGR via smtp; 9 Mar 84 21:36 EST Received: by sri-tsc.ARPA at Fri, 9 Mar 84 18:33:15 pst Message-Id: <8403100233.AA04231@sri-tsc.ARPA> Date: 9 Mar 1984 1833-PST (Friday) From: Greg Satz To: unix-wizards@brl-vgr Subject: another sendmail problem Status: RO If util.c/sfgets times out during a read, a line gets passed to syserr: 554 sfgets: timeout on read (mailer may be hung) The problem is that errno is zero so the arpanet error number becomes 554 (a permanent failure) instead of a 451 (transient). *** util.cO Fri Mar 9 00:15:27 1984 --- util.c Fri Mar 9 18:26:07 1984 *************** *** 643,648 { if (setjmp(CtxReadTimeout) != 0) { syserr("sfgets: timeout on read (mailer may be hung)"); return (NULL); } --- 643,649 ----- { if (setjmp(CtxReadTimeout) != 0) { + errno = ETIMEDOUT; syserr("sfgets: timeout on read (mailer may be hung)"); return (NULL); } From unix-wizards-request@BRL-VGR.ARPA Sat Mar 10 21:41:22 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Sat, 10 Mar 84 21:41:14 est Received: From nyu-gw.ARPA by BRL-VGR via smtp; 10 Mar 84 19:19 EST Received: by NYU.ARPA; Sat, 10 Mar 84 19:19:56 est Date: Sat, 10 Mar 84 19:19:56 est From: Lou Salkind Message-Id: <8403110019.AA11242@NYU.ARPA> To: unix-wizards@brl-vgr Subject: Time zone is not set in settimeofday Status: RO Subject: Time zone is not set in settimeofday Index: sys/sys/kern_time.c 4.2BSD Description: The timezone field in the settimeofday system call is ignored. (I discovered this when I tried to change the PST timezone on our Pyramid system.) Repeat-By: Run the program below and you will see no difference. Fix: In kern_time.c:settimeofday(), just after the second if (u.u_error) return; add tz = atz; Also, the following program will allow you to change the timezone: ----- timezone.c ----- /* * timezone minuteswest [dsttime] */ #include #include struct timeval tv; struct timezone tz; main(argc, argv) int argc; char *argv[]; { if (argc < 2) exit(0); gettimeofday(&tv, &tz); tz.tz_minuteswest = atoi(argv[1]); if (argc > 2) tz.tz_dsttime = atoi(argv[2]); if (settimeofday(&tv, &tz) < 0) { perror("settimeofday"); exit(1); } exit(0); } From unix-wizards-request@BRL-VGR.ARPA Sun Mar 11 22:17:08 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Sun, 11 Mar 84 22:17:01 est Received: From Sri-Tsc.ARPA by BRL-VGR via smtp; 11 Mar 84 21:36 EST Received: by sri-tsc.ARPA at Sun, 11 Mar 84 18:24:47 pst Message-Id: <8403120224.AA13247@sri-tsc.ARPA> Date: 11 Mar 1984 1824-PST (Sunday) From: Greg Satz To: unix-wizards@brl-vgr Subject: bug in syslog(8) Status: RO Depending on the log message level, syslog(8) might try to wall a message to the list of users in /etc/syslog.conf or to all of the logged in users. Each forked process winds up hanging instead of sending the message. The gethostname() call has the second argument passed as an address instead of by value. Because of some large mailing lists, syslog dumped core unless MAXLINE was increased. My version of syslog has some fixes that allow it to run under 2.9 (4.1a). Drop me a note if you are interested. *** /tmp/,RCSt1013071 Sun Mar 11 17:57:59 1984 --- syslog.c Fri Feb 24 10:36:59 1984 *************** *** 30,36 # define NLOGS 10 /* max number of log files */ # define NSUSERS 10 /* max number of special users */ ! # define MAXLINE 256 /* maximum line length */ # define LOGHOSTNAME 1 /* log hostid on each line */ --- 30,36 ----- # define NLOGS 10 /* max number of log files */ # define NSUSERS 10 /* max number of special users */ ! # define MAXLINE 1024 /* maximum line length */ # define LOGHOSTNAME 1 /* log hostid on each line */ *************** *** 958,964 #ifdef LOG_IPC extern char *gethostname(); char hbuf[32]; - auto int hlen; #endif LOG_IPC /* open the user login file */ --- 969,974 ----- #ifdef LOG_IPC extern char *gethostname(); char hbuf[32]; #endif LOG_IPC /* open the user login file */ *************** *** 1021,1028 strcpy(sbuf, "\r\n\007Broadcast message from "); #ifdef LOG_IPC strcat(sbuf, "syslog@"); ! hlen = sizeof hbuf; ! gethostname(hbuf, &hlen); strcat(sbuf, hbuf); #else LOG_IPC strcat(sbuf, sysname); --- 1036,1042 ----- strcpy(sbuf, "\r\n\007Broadcast message from "); #ifdef LOG_IPC strcat(sbuf, "syslog@"); ! gethostname(hbuf, sizeof hbuf); strcat(sbuf, hbuf); #else LOG_IPC strcat(sbuf, sysname); From unix-wizards-request@BRL-VGR.ARPA Mon Mar 12 18:07:52 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Mon, 12 Mar 84 18:07:45 est Message-Id: <8403122307.AA00224@seismo.ARPA> Received: From Su-Coyote.ARPA by BRL-VGR via smtp; 12 Mar 84 16:25 EST Date: Mon, 12 Mar 84 13:24:30 pst From: Bill Nowicki Subject: sendmail returns message when TCP fails Index: usr.lib/sendmail/src/collect.c 4.2BSD Apparently-To: other-4bsd-bugs Apparently-To: 4bsd-bugs@BERKELEY Status: RO Description: Recently we have been having congestion problems in our Arpanet gateway. This causes packets to be dropped, and eventually TCP connections to time out. The sendmail SMTP daemon will return a message to the sender when the TCP connection times out during transmission. It should instead just discard the partially-received message, since the sending host will send it again the next time the queue is run. This bug causes our users to get copies of their outgoing mail returned hourly until the evening when our gateway congestion disappears and the message finally gets delivered properly. Repeat-By: Send a large message from host A to host B, (say, "nobody@B") where host B is running sendmail. After doing netstats on either host to determine that a TCP connection has been made, do a ps on host A and kill the sendmail process quickly before it completes. You will get a message back from mailer-daemon@B saying "SYSERR:unexpected close". The next time the queue is run, however, the message is successfully delivered to the user on host B. Fix: change the line: syserr("collect:unexpected close"); to the block: { syserr("unexpected close, from=%s", CurEnv->e_from.q_paddr); CurEnv->e_flags &= ~EF_FATALERRS; finis(); } From hao!hplabs!zehntel!dual!decwrl!Bill Mon Mar 12 22:27:27 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site decwrl.UUCP Path: seismo!hao!hplabs!zehntel!dual!decwrl!Bill From: Bill@decwrl.UUCP Newsgroups: net.bugs.4bsd Subject: sendmail returns message when TCP fails Message-ID: <6199@decwrl.UUCP> Date: Mon, 12 Mar 84 22:27:27 EST Date-Received: Tue, 13 Mar 84 07:43:56 EST Organization: DEC Western Research Lab, Los Altos, CA Lines: 32 Status: O Description: Recently we have been having congestion problems in our Arpanet gateway. This causes packets to be dropped, and eventually TCP connections to time out. The sendmail SMTP daemon will return a message to the sender when the TCP connection times out during transmission. It should instead just discard the partially-received message, since the sending host will send it again the next time the queue is run. This bug causes our users to get copies of their outgoing mail returned hourly until the evening when our gateway congestion disappears and the message finally gets delivered properly. Repeat-By: Send a large message from host A to host B, (say, "nobody@B") where host B is running sendmail. After doing netstats on either host to determine that a TCP connection has been made, do a ps on host A and kill the sendmail process quickly before it completes. You will get a message back from mailer-daemon@B saying "SYSERR:unexpected close". The next time the queue is run, however, the message is successfully delivered to the user on host B. Fix: change the line: syserr("collect:unexpected close"); to the block: { syserr("unexpected close, from=%s", CurEnv->e_from.q_paddr); CurEnv->e_flags &= ~EF_FATALERRS; finis(); } From unix-wizards-request@BRL-VGR.ARPA Wed Mar 14 01:30:19 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Wed, 14 Mar 84 01:30:10 est Received: From nyu-gw.ARPA by BRL-VGR via smtp; 13 Mar 84 21:56 EST Received: by NYU.ARPA; Wed, 14 Mar 84 01:03:31 est Date: Wed, 14 Mar 84 01:03:31 est From: Lou Salkind Message-Id: <8403140603.AA11864@NYU.ARPA> To: unix-wizards@brl-vgr Subject: a bug in if_uba.c (not that serious) Status: RO Subject: a bug in if_uba.c (not that serious) Index: sys/vaxif/if_uba. 4.2BSD Description: There are two problems in if_uba.c:if_wubaput: (1) there is a superfluous instruction (2) the variable x is used for two different purposes in if_wubaput. This will cause transfers of two full clicks or more to fail. (Luckily the network interfaces don't do this currently.) Repeat-By: Transfer 2K packets over your network device... Fix: The diff follows. Note all the routines assume hlen < PGSIZE (a very reasonable assumption, but it should be noted). *** /tmp/,RCSt1008503 Tue Mar 13 18:30:59 1984 --- /tmp/,RCSt2008503 Tue Mar 13 18:31:00 1984 *************** *** 1,3 /* if_uba.c 6.1 83/07/29 */ #include "../machine/pte.h" --- 1,7 ----- + #ifdef RCSIDENT + static char *rcsid = "$Header: /usr/sys/vaxif/RCS/if_uba.c,v 1.2 84/03/13 01:01:40 salkind Exp $"; + #endif + /* if_uba.c 6.1 83/07/29 */ #include "../machine/pte.h" *************** *** 31,36 * with the header, and nmr more UNIBUS map registers for i/o on the adapter, * doing this twice: once for reading and once for writing. We also * allocate page frames in the mbuffer pool for these pages. */ if_ubainit(ifu, uban, hlen, nmr) register struct ifuba *ifu; --- 35,41 ----- * with the header, and nmr more UNIBUS map registers for i/o on the adapter, * doing this twice: once for reading and once for writing. We also * allocate page frames in the mbuffer pool for these pages. + * NOTE IT IS IMPLICTLY ASSUMED THAT hlen < PGSIZE. */ if_ubainit(ifu, uban, hlen, nmr) register struct ifuba *ifu; *************** *** 198,204 register caddr_t cp, dp; register int i; int xswapd = 0; ! int x, cc; cp = ifu->ifu_w.ifrw_addr; while (m) { --- 203,209 ----- register caddr_t cp, dp; register int i; int xswapd = 0; ! int x, cc, t; cp = ifu->ifu_w.ifrw_addr; while (m) { *************** *** 234,240 cc = cp - ifu->ifu_w.ifrw_addr; x = ((cc - ifu->ifu_hlen) + CLBYTES - 1) >> CLSHIFT; ifu->ifu_xswapd &= ~xswapd; - xswapd &= ~ifu->ifu_xswapd; while (i = ffs(ifu->ifu_xswapd)) { i--; if (i >= x) --- 239,244 ----- cc = cp - ifu->ifu_w.ifrw_addr; x = ((cc - ifu->ifu_hlen) + CLBYTES - 1) >> CLSHIFT; ifu->ifu_xswapd &= ~xswapd; while (i = ffs(ifu->ifu_xswapd)) { i--; if (i >= x) *************** *** 241,247 break; ifu->ifu_xswapd &= ~(1<ifu_w.ifrw_mr[i] = ifu->ifu_wmap[i]; i++; } --- 245,251 ----- break; ifu->ifu_xswapd &= ~(1<ifu_w.ifrw_mr[i] = ifu->ifu_wmap[i]; i++; } From unix-wizards-request@BRL-VGR.ARPA Thu Mar 15 18:54:11 1984 Received: from BRL-VGR (brl-vgr.ARPA) by seismo.ARPA ; Thu, 15 Mar 84 18:54:04 est Received: From nyu-gw.ARPA by BRL-VGR via smtp; 15 Mar 84 18:35 EST Received: by NYU.ARPA; Thu, 15 Mar 84 18:33:45 est Date: Thu, 15 Mar 84 18:33:45 est From: Lou Salkind Message-Id: <8403152333.AA17442@NYU.ARPA> To: unix-wizards@brl-vgr Subject: Efl fails in 4.2 Status: RO Subject: Efl fails in 4.2 Index: usr.bin/efl 4.2BSD Description: Efl bombs out, even on the simplest files. It reports something like: f77 -F ../gas/gpertsub.e File ../gas/gpertsub.e: calloc(1024 words) Bad count word 1024 Highwater mark 2384 words. 2155 words left over ***Compiler error on line 15. Line 15: out of memory. Termination code 11 and then then goes into an infinite loop. Repeat-By: (file above not included) Fix: The problem is that efl defines its own memory allocation routines alloc, malloc, calloc, free, cfree with different calling conventions. Some routine in the C library (probably stdio) eventually calls one of the efl routines and corrupts the memory allocation arena. (Actually, it is surprising it worked in 4.1.) To fix the problem, add the following lines (after the #define ALLOC) to the defs file: #define calloc efl_calloc #define alloc efl_alloc #define malloc efl_malloc #define cfree efl_cfree #define free efl_free From harpo!ihnp4!astrovax!gam Thu Mar 15 17:04:18 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site astrovax.UUCP Path: seismo!harpo!ihnp4!astrovax!gam From: gam@astrovax.UUCP (Gary Mamon) Newsgroups: net.bugs.4bsd,net.lang.f77 Subject: Another F77 bug in 4.2BSD UNIX Message-ID: <238@astrovax.UUCP> Date: Thu, 15 Mar 84 17:04:18 EST Date-Received: Thu, 15 Mar 84 22:19:56 EST Organization: Princeton Univ. Astrophysics Lines: 31 Status: O Subject: F77 exponentiation. Index: /mnt/gam/BUGS/sumpow.f Description: 4.2 F77 mishandles the following in single precision: z = x1**alpha + x2**alpha + ... + xlast**alpha where alpha is a floating point constant, and z and x sub i are real variables. F77 returns for z the value N*xlast**alpha, where N is the number of terms in the sum. Furthermore F77 mishandles the following in both single and double precision. z = (x1-y1)**alpha + (x2-y2)**alpha where again alpha is a floating point constant, and z, the x sub i and the y sub i are real (real*8 in double precision) variables. Fix: Unknown. Comment: This is one of a few 4.2 BSD F77 bugs already discovered at our site. The majority of Fortran users here are now using the 4.1BSD F77 compiler. From shannon@sun.uucp Thu Mar 15 17:04:18 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83 SMI; site sun.uucp Path: seismo!hao!hplabs!tektronix!decvax!decwrl!sun!shannon From: shannon@sun.uucp (Bill Shannon) Newsgroups: net.sources Subject: 4.2 arp enhancements Message-ID: <640@sun.uucp> Date: Mon, 19 Mar 84 16:45:13 EST Organization: Sun Microsystems, Inc. Lines: 1231 Status: RO ----- cut here and extract with sh echo x - README sed 's/^X//' >README <<'!Funky!Stuff!' NEW ARP HANDLING FOR 4.2bsd (Release of 03/16/84) The code included here can be inserted into a VAX 4.2bsd system (with a little work) to greatly improve the flexibility and usability of the Ethernet Address Resolution Protocol. (See enclosed manual pages for more information.) There is no warranty of merchantability nor any warranty of fitness for a particular purpose nor any other warranty, either express or implied, as to the accuracy of the enclosed materials or as to their suitability for any particular purpose. Accordingly, Sun Microsystems Inc. assumes no responsibility for their use by the recipient. Further, Sun Microsystems Inc. assumes no obligation to furnish any assistance of any kind whatsoever, or to furnish any additional information or documentation. The included files are: README - this file arp.4p - improved ARP manual page arp.8c - manual page for new arp command ifconfig.8c - replacement manual page describing new options arp.c - code for new arp command if.c.diffs - changes to /sys/net/if.c if.h.diffs - changes to /sys/net/if.h if_ec.c.diffs - changes to /sys/vaxif/if_ec.c, as an example of changes necessary to ALL network drivers if_ether.c.diffs - changes to /sys/netinet/if_ether.c if_ether.h.diffs - changes to /sys/netinet/if_ether.h ifconfig.c.diffs - changes to /usr/src/etc/if_config.c ioctl.h.diffs - changes to /sys/h/ioctl.h (and /usr/include/ sys/ioctl.h if it isn't a link) ether_print - small routine to be added somewhere, it's in autoconf.c in the Sun system, but if_ether.c may be more appropriate in the VAX system Overview of changes You will have to change all of your network device drivers in order to put this code into your system. The changes should be straight-forward and are necessitated by the following changes to common code. 1. Ethernet addresses are now a structure instead of a 6 byte array. This allows them to be assigned directly instead of having to use bcopy. Hint - look for "edst" in the driver, all references to it will have to be changed. 2. The third address to the driver ioctl routines has changed. See the enclosed modifications of if_ec.c for an example. 3. Routine arpmyaddr() is gone. It always returned zero. Most drivers call it in the attach routine, just remove the line containing the call. The *.diffs files are diff -e scripts that can be applied to the standard files supplied with 4.2bsd. The diffs apply to the following versions of these files: /* if.c 6.2 83/09/27 */ /* if.h 6.2 83/08/28 */ /* if_ec.c 6.1 83/07/29 */ /* if_ether.c 6.2 83/08/28 */ /* if_ether.h 6.2 83/09/26 */ /* ioctl.h 6.1 83/07/29 */ static char sccsid[] = "@(#)ifconfig.c 4.5 (Berkeley) 11/2/83"; If you've modified any of these files locally you'll have to find the originals from your 4.2 distribution and apply the diffs to them, then merge in any local changes. Apply the diffs using a set of commands like this: chmod +w file ed - file arp.4p <<'!Funky!Stuff!' X.\" @(#)arp.4p 1.8 84/02/02 SMI; from UCB 4.1 X.TH ARP 4P "11 January 1984" X.SH NAME arp \- Address Resolution Protocol X.SH SYNOPSIS X.B "pseudo-device ether" X.SH DESCRIPTION ARP is a protocol used to dynamically map between DARPA Internet and 10Mb/s Ethernet addresses. It is used by all the 10Mb/s Ethernet interface drivers. X.PP ARP caches Internet-Ethernet address mappings. When an interface requests a mapping for an address not in the cache, ARP queues the message which requires the mapping and broadcasts a message on the associated network requesting the address mapping. If a response is provided, the new mapping is cached and any pending messages are transmitted. ARP will queue at most one packet while waiting for a mapping request to be responded to; only the most recently ``transmitted'' packet is kept. X.PP To enable communications with systems which do not use ARP, ioctls are provided to enter and delete entries in the Internet-to-Ethernet tables. Usage: X.LP X.nf X.ft B #include #include #include struct arpreq arpreq; ioctl(s, SIOCSARP, (caddr_t)&arpreq); ioctl(s, SIOCGARP, (caddr_t)&arpreq); ioctl(s, SIOCDARP, (caddr_t)&arpreq); X.fi X.ft R Each ioctl takes the same structure as an argument. SIOCSARP sets an ARP entry, SIOCGARP gets an ARP entry, and SIOCDARP deletes an ARP entry. These ioctls may be applied to any socket descriptor X.I s, but only by the super-user. The X.I arpreq structure contains: X.LP X.nf /* * ARP ioctl request */ struct arpreq { struct sockaddr arp_pa; /* protocol address */ struct sockaddr arp_ha; /* hardware address */ int arp_flags; /* flags */ }; /* arp_flags field values */ #define ATF_COM 2 /* completed entry (arp_ha valid) */ #define ATF_PERM 4 /* permanent entry */ #define ATF_PUBL 8 /* publish (respond for other host) */ X.fi X.LP The address family for the X.I arp_pa sockaddr must be AF_INET; for the X.I arp_ha sockaddr it must be AF_UNSPEC. The only flag bits which may be written are ATF_PERM and ATF_PUBL. ATF_PERM causes the entry to be permanent if the ioctl call succeeds. The peculiar nature of the ARP tables may cause the ioctl to fail if more than 4 (permanent) Internet host addresses hash to the same slot. ATF_PUBL specifies that the ARP code should respond to ARP requests for the indicated host coming from other machines. This allows a Sun to act as an "ARP server" which may be useful in convincing an ARP-only machine to talk to a non-ARP machine. X.PP ARP watches passively for hosts impersonating the local host (i.e. a host which responds to an ARP mapping request for the local host's address). X.SH DIAGNOSTICS X.B "duplicate IP address!! sent from ethernet address: %x:%x:%x:%x:%x:%x." ARP has discovered another host on the local network which responds to mapping requests for its own Internet address. X.SH SEE ALSO ec(4S), ie(4S), inet(4F), arp(8C), ifconfig(8C) X.br An Ethernet Address Resolution Protocol, RFC826, Dave Plummer, MIT (Sun 800-1059-01) X.SH BUGS ARP packets on the Ethernet use only 42 bytes of data, however, the smallest legal Ethernet packet is 60 bytes (not including CRC). Some systems may not enforce the minimum packet size, others will. !Funky!Stuff! echo x - arp.8c sed 's/^X//' >arp.8c <<'!Funky!Stuff!' X.\" @(#)arp.8c 1.1 84/01/12 SMI; X.TH ARP 8C "12 January 1984" X.SH NAME arp \- address resolution display and control X.SH SYNOPSIS X.B arp X.I hostname X.br X.B arp -a [ X.I vmunix ] [ X.I kmem ] X.br X.B arp -d X.I hostname X.br X.B arp -s X.I hostname ether_addr [ X.B temp ] [ X.B pub ] X.br X.B arp -f X.I filename X.SH DESCRIPTION The X.I arp program displays and modifies the Internet-to-Ethernet address translation tables used by the address resolution protocol ( X.IR arp (4p)). X.LP With no flags, the program displays the current ARP entry for X.I hostname. With the X.B -a flag, the program displays all of the current ARP entries by reading the table from the file X.I kmem (default /dev/kmem) based on the kernel file X.I vmunix (default /vmunix). X.LP With the X.B -d flag, a super-user may delete an entry for the host called X.I hostname. X.LP The X.B -s flag is given to create an ARP entry for the host called X.I hostname with the Ethernet address X.I ether_addr. The Ethernet address is given as six hex bytes separated by colons. The entry will be permanent unless the word X.B temp is given in the command. If the word X.B pub is given, the entry will be "published", e.g., this system will respond to ARP requests for X.I hostname even though the hostname is not its own. X.LP The X.B -f flag causes the file X.I filename to be read and multiple entries to be set in the ARP tables. Entries in the file should be of the form X.IP X.I hostname ether_addr [ X.B temp ] [ X.B pub ] X.LP with argument meanings as given above. X.SH "SEE ALSO" arp(4p), ifconfig(8c) !Funky!Stuff! echo x - arp.c sed 's/^X//' >arp.c <<'!Funky!Stuff!' #ifndef lint static char sccsid[] = "@(#)arp.c 1.1 83/11/29 SMI"; #endif /* * arp - display, set, and delete arp table entries */ #include #include #include #include #include #include #include #include #include #include extern int errno; main(argc, argv) char **argv; { if (argc >= 2 && strcmp(argv[1], "-a") == 0) { char *kernel = "/vmunix", *mem = "/dev/kmem"; if (argc >= 3) kernel = argv[2]; if (argc >= 4) mem = argv[3]; dump(kernel, mem); exit(0); } if (argc == 2) { get(argv[1]); exit(0); } if (argc >= 4 && strcmp(argv[1], "-s") == 0) { set(argc-2, &argv[2]); exit(0); } if (argc == 3 && strcmp(argv[1], "-d") == 0) { delete(argv[2]); exit(0); } if (argc == 3 && strcmp(argv[1], "-f") == 0) { file(argv[2]); exit(0); } usage(); exit(1); } /* * Process a file to set standard arp entries */ file(name) char *name; { FILE *fp; int i; char line[100], arg[4][50], *args[4]; if ((fp = fopen(name, "r")) == NULL) { fprintf(stderr, "arp: cannot open %s\n", name); exit(1); } args[0] = &arg[0][0]; args[1] = &arg[1][0]; args[2] = &arg[2][0]; args[3] = &arg[3][0]; while(fgets(line, 100, fp) != NULL) { i = sscanf(line, "%s %s %s %s", arg[0], arg[1], arg[2], arg[3]); if (i < 2) { fprintf(stderr, "arp: bad line: %s\n", line); continue; } set(i, args); } fclose(fp); } /* * Set an individual arp entry */ set(argc, argv) char **argv; { struct arpreq ar; struct hostent *hp; struct sockaddr_in *sin; struct ether_addr *ea; int s; char *host = argv[0], *eaddr = argv[1]; argc -= 2; argv += 2; hp = gethostbyname(host); if (hp == NULL) { fprintf(stderr, "arp: %s: unknown host\n", host); return (1); } bzero((caddr_t)&ar, sizeof ar); ar.arp_pa.sa_family = AF_INET; sin = (struct sockaddr_in *)&ar.arp_pa; sin->sin_addr = *(struct in_addr *)hp->h_addr; ea = (struct ether_addr *)ar.arp_ha.sa_data; if (ether_aton(eaddr, ea)) return; ar.arp_flags = ATF_PERM; while(argc-- > 0) { if (strncmp(argv[0], "temp", 4) == 0) ar.arp_flags &= ~ATF_PERM; if (strncmp(argv[0], "pub", 3) == 0) ar.arp_flags |= ATF_PUBL; argv++; } s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("arp: socket"); exit(1); } if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) { perror(host); exit(1); } close(s); } /* * Display an individual arp entry */ get(host) char *host; { struct arpreq ar; struct hostent *hp; struct sockaddr_in *sin; struct ether_addr *ea; int s; hp = gethostbyname(host); if (hp == NULL) { fprintf(stderr, "arp: %s: unknown host\n", host); exit(1); } bzero((caddr_t)&ar, sizeof ar); ar.arp_pa.sa_family = AF_INET; sin = (struct sockaddr_in *)&ar.arp_pa; sin->sin_addr = *(struct in_addr *)hp->h_addr; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("arp: socket"); exit(1); } if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { if (errno == ENXIO) printf("%s (%s) -- no entry\n", host, inet_ntoa(sin->sin_addr)); else perror("SIOCGARP"); exit(1); } close(s); ea = (struct ether_addr *)ar.arp_ha.sa_data; printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); if (ar.arp_flags & ATF_COM) ether_print(ea); else printf("(incomplete)"); if (!(ar.arp_flags & ATF_PERM)) printf(" temporary"); if (ar.arp_flags & ATF_PUBL) printf(" published"); printf("\n"); } /* * Delete an arp entry */ delete(host) char *host; { struct arpreq ar; struct hostent *hp; struct sockaddr_in *sin; int s; hp = gethostbyname(host); if (hp == NULL) { fprintf(stderr, "arp: %s: unknown host\n", host); exit(1); } bzero((caddr_t)&ar, sizeof ar); ar.arp_pa.sa_family = AF_INET; sin = (struct sockaddr_in *)&ar.arp_pa; sin->sin_addr = *(struct in_addr *)hp->h_addr; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("arp: socket"); exit(1); } if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) { if (errno == ENXIO) printf("%s (%s) -- no entry\n", host, inet_ntoa(sin->sin_addr)); else perror("SIOCDARP"); exit(1); } close(s); printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); } struct nlist nl[] = { #define X_ARPTAB 0 { "_arptab" }, #define X_ARPTAB_SIZE 1 { "_arptab_size" }, { "" }, }; /* * Dump the entire arp table */ dump(kernel, mem) char *kernel, *mem; { int mf, arptab_size, sz; struct arptab *at; struct hostent *hp; char *host; nlist(kernel, nl); if(nl[X_ARPTAB_SIZE].n_type == 0) { fprintf(stderr, "arp: %s: bad namelist\n", kernel); exit(1); } mf = open(mem, 0); if(mf < 0) { fprintf(fprintf, "arp: cannot open %s\n", mem); exit(1); } lseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, 0); read(mf, &arptab_size, sizeof arptab_size); if (arptab_size <=0 || arptab_size > 1000) { fprintf(stderr, "arp: %s: namelist wrong\n", kernel); exit(1); } sz = arptab_size * sizeof (struct arptab); at = (struct arptab *)malloc(sz); if (at == NULL) { fprintf(stderr, "arp: can't get memory for arptab\n"); exit(1); } lseek(mf, (long)nl[X_ARPTAB].n_value, 0); if (read(mf, (char *)at, sz) != sz) { perror("arp: error reading arptab"); exit(1); } close(mf); for (; arptab_size-- > 0; at++) { if (at->at_iaddr.s_addr == 0 || at->at_flags == 0) continue; hp = gethostbyaddr((caddr_t)&at->at_iaddr, sizeof at->at_iaddr, AF_INET); if (hp) host = hp->h_name; else host = "?"; printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr)); if (at->at_flags & ATF_COM) ether_print(&at->at_enaddr); else printf("(incomplete)"); if (!(at->at_flags & ATF_PERM)) printf(" temporary"); if (at->at_flags & ATF_PUBL) printf(" published"); printf("\n"); } } ether_print(ea) struct ether_addr *ea; { u_char *cp = &ea->ether_addr_octet[0]; printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); } ether_aton(a, n) char *a; struct ether_addr *n; { int i, o[6]; i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], &o[3], &o[4], &o[5]); if (i != 6) { fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); return (1); } for (i=0; i<6; i++) n->ether_addr_octet[i] = o[i]; return (0); } usage() { printf("Usage: arp hostname\n"); printf(" arp -a [/vmunix] [/dev/kmem]\n"); printf(" arp -d hostname\n"); printf(" arp -s hostname ether_addr [temp] [pub]\n"); printf(" arp -f filename\n"); } !Funky!Stuff! echo x - ether_print sed 's/^X//' >ether_print <<'!Funky!Stuff!' ether_print(ea) struct ether_addr *ea; { u_char *cp = &ea->ether_addr_octet[0]; printf("%x:%x:%x:%x:%x:%x\n", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); } !Funky!Stuff! echo x - if.c.diffs sed 's/^X//' >if.c.diffs <<'!Funky!Stuff!' 260a } /* * Set a new interface address. * Called by ND address assignment as well as above * XXX Most of what the drivers do is device independent! */ if_setaddr(ifp, sa) register struct ifnet *ifp; struct sockaddr *sa; { if (ifp->if_ioctl == 0) return (EOPNOTSUPP); return ((*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)sa)); X. 258c return ((*ifp->if_ioctl)(ifp, cmd, ifr->ifr_data)); X. 254a case SIOCSIFADDR: return (if_setaddr(ifp, &ifr->ifr_addr)); X. 218a case SIOCSARP: case SIOCDARP: if (!suser()) return (u.u_error); /* fall through */ case SIOCGARP: return (arpioctl(cmd, data)); X. 194c unit = *cp - '0'; X. 192c if (*cp == '\0' || cp == name + IFNAMSIZ || cp == name) X. 1c /* @(#)if.c 1.5 83/12/07 SMI; from UCB 6.2 83/09/27 */ X. w !Funky!Stuff! echo x - if.h.diffs sed 's/^X//' >if.h.diffs <<'!Funky!Stuff!' 154a /* * ARP ioctl request */ struct arpreq { struct sockaddr arp_pa; /* protocol address */ struct sockaddr arp_ha; /* hardware address */ int arp_flags; /* flags */ }; /* arp_flags and at_flags field values */ #define ATF_INUSE 1 /* entry in use */ #define ATF_COM 2 /* completed entry (enaddr valid) */ #define ATF_PERM 4 /* permanent entry */ #define ATF_PUBL 8 /* publish entry (respond for other host) */ X. 1c /* @(#)if.h 1.6 84/01/11 SMI; from UCB 6.2 83/08/28 */ X. w !Funky!Stuff! echo x - if_ec.c.diffs sed 's/^X//' >if_ec.c.diffs <<'!Funky!Stuff!' 754c ecsetaddr(ifp, sin); X. 751a sa = (struct sockaddr *)data; if (sa->sa_family == AF_UNSPEC) { if (sa->sa_data[0] & 1) /* broad or multi-cast */ return (EINVAL); es->es_addr = *(struct ether_addr *)sa->sa_data; ecinit(ifp->if_unit); break; } sin = (struct sockaddr_in *)data; if (sin->sin_family != AF_INET) return (EINVAL); X. 746c struct ec_softc *es = &ec_softc[ifp->if_unit]; struct sockaddr *sa; struct sockaddr_in *sin; X. 584d 582c ec->ether_dhost = edst; ec->ether_shost = es->es_addr; X. 539c edst = ec->ether_dhost; X. 516c if (!arpresolve(&es->es_ac, m, &idst, &edst)) X. 503c struct ether_addr edst; X. 245d 183d 171c cp = (u_char *)&es->es_addr; X. 1c /* if_ec.c 6.1.1 84/03/16 */ X. w !Funky!Stuff! echo x - if_ether.c.diffs sed 's/^X//' >if_ether.c.diffs <<'!Funky!Stuff!' 390a } arpioctl(cmd, data) int cmd; caddr_t data; { register struct arpreq *ar = (struct arpreq *)data; register struct arptab *at; register struct sockaddr_in *sin; int s; if (ar->arp_pa.sa_family != AF_INET || ar->arp_ha.sa_family != AF_UNSPEC) return (EAFNOSUPPORT); sin = (struct sockaddr_in *)&ar->arp_pa; s = splimp(); ARPTAB_LOOK(at, sin->sin_addr.s_addr); if (at == NULL) { /* not found */ if (cmd != SIOCSARP) { splx(s); return (ENXIO); } if (if_ifwithnet(&ar->arp_pa) == NULL) { splx(s); return (ENETUNREACH); } at = arptnew(&sin->sin_addr); } switch (cmd) { case SIOCSARP: /* set entry */ at->at_enaddr = *(struct ether_addr *)ar->arp_ha.sa_data; at->at_flags = ATF_COM | ATF_INUSE | (ar->arp_flags & (ATF_PERM|ATF_PUBL)); at->at_timer = 0; if (ar->arp_flags & ATF_PERM) { /* never make all entries in a bucket permanent */ register struct arptab *tat; struct in_addr addr; /* defeat has and try to re-allocate */ addr = at->at_iaddr; at->at_iaddr.s_addr = 0; tat = arptnew(&addr); if (tat == NULL) { arptfree(at); splx(s); return (EADDRNOTAVAIL); } arptfree(tat); at->at_iaddr = addr; } break; case SIOCDARP: /* delete entry */ arptfree(at); break; case SIOCGARP: /* get entry */ *(struct ether_addr *)ar->arp_ha.sa_data = at->at_enaddr; ar->arp_flags = at->at_flags; break; } splx(s); return (0); X. 384a if (ato == NULL) return (NULL); X. 380c if (at->at_flags & ATF_PERM) continue; if (ato == NULL || at->at_timer > oldest) { X. 376c if (first) { first = 0; timeout(arptimer, (caddr_t)0, hz); } at = &arptab[ARPTAB_HASH(addr->s_addr) * ARPTAB_BSIZ]; ato = NULL; X. 374a static int first = 1; X. 366a * This always succeeds for dynamic entries since arpioctl * gaurantees that no bucket can be completely filled * with permanent entries. X. 348a * Called just before buffer passed to ipintr. If ip_src.s_net is 0, * then make the ether source address available by saving the mapping. */ arpipin(ec, m) register struct ether_header *ec; register struct mbuf *m; { register struct ip *ip; int hlen; extern int ipcksum; if (m->m_len < sizeof(struct ip)) return; ip = mtod(m, struct ip *); if (ip->ip_src.s_net != 0) return; arpseten(&ip->ip_src, &ec->ether_shost); } /* * Get an ethernet address, given the IP address. */ struct ether_addr * arpgeten(addr) register struct in_addr *addr; { register struct arptab *at; ARPTAB_LOOK(at, addr->s_addr); if (at == 0 || (at->at_flags & ATF_COM) == 0) return (0); return (&at->at_enaddr); } /* * Set an ether/IP mapping. Called externally to force a mapping. */ arpseten(iaddr, eaddr) struct in_addr *iaddr; struct ether_addr *eaddr; { register struct arptab *at; int s = splimp(); ARPTAB_LOOK(at, iaddr->s_addr); if (at == 0) at = arptnew(iaddr); at->at_timer = ARPT_KILLC - 3; /* so it expires faster than normal */ at->at_flags |= ATF_COM; if (at->at_hold) m_freem(at->at_hold); at->at_hold = 0; at->at_enaddr = *eaddr; splx(s); } #endif IPENADDR /* X. 347a #ifdef IPENADDR X. 337,338c eh->ether_dhost = arp_tha(ea); X. 327,334c arp_tha(ea) = arp_sha(ea); arp_tpa(ea) = arp_spa(ea); arp_sha(ea) = at->at_enaddr; arp_spa(ea) = itaddr; X. 325a ARPTAB_LOOK(at, itaddr.s_addr); if (at == NULL) { if (itaddr.s_addr != myaddr.s_addr) goto out; /* if I am not the target */ at = arptnew(&myaddr); at->at_enaddr = ac->ac_enaddr; at->at_flags |= ATF_COM; } if (itaddr.s_addr != myaddr.s_addr && (at->at_flags & ATF_PUBL) == 0) goto out; X. 320,321c at->at_enaddr = arp_sha(ea); X. 315,318c } else if (itaddr.s_addr == myaddr.s_addr) { /* ensure we have a table entry */ X. 303,305c if (at) { /* XXX ? - can overwrite ATF_PERM */ at->at_enaddr = arp_sha(ea); X. 295,297c ether_print(&arp_sha(ea)); itaddr = myaddr; X. 288,290c isaddr = arp_spa(ea); itaddr = arp_tpa(ea); if (!bcmp((caddr_t)&arp_sha(ea), (caddr_t)&ac->ac_enaddr, X. 283a if (ac->ac_if.if_flags & IFF_NOARP) goto out; X. 266c * is received. Algorithm is that given in RFC 826. X. 243,264d 225c *desten = at->at_enaddr; X. 217,221c if (ifp->if_flags & IFF_NOARP) { *desten = ac->ac_enaddr; desten->ether_addr_octet[3] = (lna >> 16) & 0x7f; desten->ether_addr_octet[4] = (lna >> 8) & 0xff; desten->ether_addr_octet[5] = lna & 0xff; splx(s); return (1); } else { at = arptnew(destip); at->at_hold = m; arpwhohas(ac, destip); splx(s); return (0); } X. 213a #endif IPENADDR X. 207,211c #ifdef IPENADDR if (destip->s_net == 0) { /* real IP address unknown */ struct ether_addr *arpgeten(), *ap; if ((ap = arpgeten(destip)) == NULL) return (0); *desten = *ap; X. 195,196c *desten = etherbroadcastaddr; X. 189a register int i; X. 186c register struct ether_addr *desten; X. 168c return ((*ac->ac_if.if_output)(&ac->ac_if, m, &sa)); X. 162,166c arp_sha(ea) = ac->ac_enaddr; arp_spa(ea) = ((struct sockaddr_in *)&ac->ac_if.if_addr)->sin_addr; arp_tpa(ea) = *addr; X. 159,160c ea->arp_hln = sizeof arp_sha(ea); /* hardware address length */ ea->arp_pln = sizeof arp_spa(ea); /* protocol address length */ X. 154,155c eh->ether_dhost = etherbroadcastaddr; X. 148,149c return (1); m->m_len = sizeof *ea; X. 124c if (at->at_flags == 0 || (at->at_flags & ATF_PERM)) X. 105,119d 100a register struct arpcom *ac; X. 78,96d 62,75c #define IPENADDR 0 /* enable passing enaddr's thru IP layer */ X. 59c struct ether_addr etherbroadcastaddr = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}; X. 51d 37a int arptab_size = ARPTAB_SIZE; /* for arp command */ X. 19,33d 16a #include "../netinet/in_systm.h" #include "../netinet/ip.h" X. 13a #include "../h/ioctl.h" X. 1c #ifndef lint static char sccsid[] = "@(#)if_ether.c 1.7 84/02/08 SMI"; #endif X. w !Funky!Stuff! echo x - if_ether.h.diffs sed 's/^X//' >if_ether.h.diffs <<'!Funky!Stuff!' 61,62c struct ether_addr etherbroadcastaddr; X. 59a /* * Internet to ethernet address resolution table. */ struct arptab { struct in_addr at_iaddr; /* internet address */ struct ether_addr at_enaddr; /* ethernet address */ struct mbuf *at_hold; /* last packet until resolved/timeout */ u_char at_timer; /* minutes since last reference */ u_char at_flags; /* flags */ }; X. 56c struct ether_addr ac_enaddr; /* ethernet hardware address */ X. 47a #define arp_sha(ea) (*(struct ether_addr *)(ea)->arp_xsha) #define arp_spa(ea) (*(struct in_addr *)(ea)->arp_xspa) #define arp_tha(ea) (*(struct ether_addr *)(ea)->arp_xtha) #define arp_tpa(ea) (*(struct in_addr *)(ea)->arp_xtpa) X. 43,46c u_char arp_xsha[6]; /* sender hardware address */ u_char arp_xspa[4]; /* sender protocol address */ u_char arp_xtha[6]; /* target hardware address */ u_char arp_xtpa[4]; /* target protocol address */ X. 7,8c struct ether_addr ether_dhost; struct ether_addr ether_shost; X. 3a * Ethernet address - 6 octets */ struct ether_addr { u_char ether_addr_octet[6]; }; /* X. 1c /* @(#)if_ether.h 1.4 84/01/11 SMI; from UCB 4.5 83/05/15 */ X. w !Funky!Stuff! echo x - ifconfig.8c sed 's/^X//' >ifconfig.8c <<'!Funky!Stuff!' X.\" @(#)ifconfig.8c 1.2 84/01/11 SMI; X.TH IFCONFIG 8C "12 January 1984" X.UC 4 X.SH NAME ifconfig \- configure network interface parameters X.SH SYOPNSIS X.B /etc/ifconfig interface [ X.I Ethernet_address ] [ X.I hostname ] [ X.I parameters ] X.SH DESCRIPTION X.I Ifconfig is used to assign an address to a network interface and/or to configure network interface parameters. X.I Ifconfig must be used at boot time to define the network address of each interface present on a machine; it may also be used at a later time to redefine an interface's address. Used without options, X.I ifconfig displays the current configuration for a network interface. Only the super-user may modify the configuration of a network interface. X.LP The X.B interface parameter is a string of the form ``name unit'', for example ``ie0''. X.SH OPTIONS X.LP \fIEthernet_address\fP is the hardware Ethernet address of a given machine. The address is a 6-byte hexadecimal value; each byte of the address is separated by a colon. A typical Ethernet adddress is `8:0:20:1:1:A3'. This address is contained in the ID PROM on the Sun-2 CPU Board, and is reported at boot time as one of the PROM monitor's sign-on messages. The \fIEthernet_address\fP option is normally not used \(em the hardware supplies the default; the option is used only when trying to talk to a device which does not support ARP (like a VAX on a 4.1c network). X.LP \fIhostname\fP may be either the hostname of a given machine (present in the hostname database, \fIhosts\fP\^(5)), or the complete Internet address consisting of your system's network number and the machine's unique host number. A typical Internet address might be ``192.9.200.44'', where ``192.9.200'' is the network number and ``44'' is the machine's hostnumber. To find a machine's Internet address, consult the local \fI/etc/hosts\fP file. X.PP The following \fIparameters\fP may be set with X.IR ifconfig : X.TP 15 X.B "\ \ \ up" Mark an interface ``up''. X.TP 15 X.B "\ \ \ down" Mark an interface ``down''. When an interface is marked ``down'', the system will not attempt to transmit messages through that interface. X.TP 15 X.B "\ \ \ trailers" Enable the use of a ``trailer'' link level encapsulation when sending (default). If a network interface supports X.IR trailers , the system will, when possible, encapsulate outgoing messages in a manner which minimizes the number of memory to memory copy operations performed by the receiver. X.TP 15 X.B "\ \ \ \-trailers" Disable the use of a ``trailer'' link level encapsulation. X.TP 15 X.B "\ \ \ arp Enable the use of the Address Resolution Protocol in mapping between network level addresses and link level addresses (default). This is currently implemented for mapping between DARPA Internet addreses and 10Mb/s Ethernet addresses. X.TP 15 X.B "\ \ \ \-arp" Disable the use of the Address Resolution Protocol. X.RE X.SH DIAGNOSTICS Messages indicating the specified interface does not exit, the requested address is unknown, the user is not privileged and tried to alter an interface's configuration. X.SH "SEE ALSO" rc(8), intro(4N), netstat(1) !Funky!Stuff! echo x - ifconfig.c.diffs sed 's/^X//' >ifconfig.c.diffs <<'!Funky!Stuff!' 187c n = sscanf(s, "%x:%x:%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], &o[3], &o[4], &o[5], &o[6], &o[7]); if (n > 0) { p = sa->sa_data; ip = &o[0]; while (n--) *p++ = *ip++; sa->sa_family = AF_UNSPEC; return; } fprintf(stderr, "ifconfig: %s: bad address\n", s); X. 163a bzero((caddr_t)sa, sizeof *sa); X. 162c int val, n, o[8], *ip; char *p; X. 159a struct sockaddr_in *sin = (struct sockaddr_in *)sa; X. 158c struct sockaddr *sa; X. 156c getaddr(s, sa) X. 128c printb("flags", ifr.ifr_flags, IFFBITS); putchar('\n'); X. 125a strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { Perror("ioctl (SIOCGIFFLAGS)"); exit(1); } X. 110,111c ifr.ifr_flags |= value; X. 108c ifr.ifr_flags &= ~value; X. 105a strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { Perror("ioctl (SIOCGIFFLAGS)"); exit(1); } X. 95c getaddr(addr, &ifr.ifr_addr); X. 65,70d 36,37d 20d 2c static char sccsid[] = "@(#)ifconfig.c 1.5 83/12/02 SMI"; /* from UCB 4.3 09/16/83 */ X. w !Funky!Stuff! echo x - ioctl.h.diffs sed 's/^X//' >ioctl.h.diffs <<'!Funky!Stuff!' 207a #define SIOCSARP _IOW(i, 30, struct arpreq) /* set arp entry */ #define SIOCGARP _IOWR(i, 31, struct arpreq) /* get arp entry */ #define SIOCDARP _IOW(i, 32, struct arpreq) /* delete arp entry */ X. 1c /* @(#)ioctl.h 1.4 83/11/29 SMI; from UCB 4.34 83/06/13 */ X. w !Funky!Stuff! From harpo!ulysses!burl!clyde!floyd!cmcl2!rna!n44a!wjh12!genrad!decvax!decwrl!sun!shannon Wed Mar 21 19:59:08 1984 Relay-Version: version B 2.10.1 6/24/83; site seismo.UUCP Path: seismo!harpo!ulysses!burl!clyde!floyd!cmcl2!rna!n44a!wjh12!genrad!decvax!decwrl!sun!shannon From: shannon@sun.UUCP Newsgroups: net.bugs.4bsd Subject: alarm return value is wrong in 4.2bsd Message-ID: <667@sun.UUCP> Date: Wed, 21 Mar 84 19:59:08 EST Date-Received: Thu, 22 Mar 84 17:28:12 EST Lines: 40 Status: O Index: lib/libc/gen/alarm.c 4.2BSD Description: alarm (which is implemented using setitimer) can sometimes lie and return zero even when there is an alarm pending. This screws up people who do: left = alarm(0); /* turn alarm off */ diddle, diddle, diddle... alarm(left); /* turn it back on */ Repeat-By: See above. Fix: The problem is that the interval timer has higher resolution than alarm and alarm truncates the value. I fixed it to round up. Diffs follow. *** /tmp/d02314 Wed Mar 21 16:30:17 1984 --- alarm.c Wed Mar 21 16:29:59 1984 *************** *** 18,22 itp->it_value.tv_usec = 0; if (setitimer(ITIMER_REAL, itp, &oitv) < 0) return (-1); return (oitv.it_value.tv_sec); } --- 18,24 ----- itp->it_value.tv_usec = 0; if (setitimer(ITIMER_REAL, itp, &oitv) < 0) return (-1); + if (oitv.it_value.tv_usec) + oitv.it_value.tv_sec++; return (oitv.it_value.tv_sec); } Bill Shannon sun!shannon Sun Microsystems, Inc. From unix-wizards-request@BRL-TGR.ARPA Sun Mar 25 21:45:19 1984 Received: from BRL-TGR (brl-tgr.arpa.ARPA) by seismo.ARPA ; Sun, 25 Mar 84 21:45:11 est Received: From purdue-merlin.arpa.ARPA by BRL-TGR via smtp; 25 Mar 84 21:20 EST From: Christopher A Kent Message-Id: <8403260218.AA10025@merlin.ARPA> Received: by merlin.ARPA; Sun, 25 Mar 84 21:18:17 est Date: 25 Mar 1984 2118-EST (Sunday) To: unix-wizards@brl-tgr.ARPA Subject: ftpd doesn't work on multi-homed hosts Index: etc/ftpd/ftpd.c Status: RO Description: On multi-homed hosts, ftpd won't always work because the code to anchor the reply socket is incorrect; the getsockname() call has a bad argument, thus the filled in address is always 0. Repeat-By: ftp to a multi-homed host on the same net as yours, but specify the alternate address as the host to connect to. Fix: getsockname() wants an int *, not an int, for the namelen. I did it this way (don't trust the line numbers): *** ftpd.c.old --- ftpd.c *************** *** 168,173 continue; } if (fork() == 0) { signal (SIGCHLD, SIG_IGN); openlog("ftpd", LOG_PID); dolog(&his_addr); --- 168,175 ----- continue; } if (fork() == 0) { + int addrsize; + signal (SIGCHLD, SIG_IGN); openlog("ftpd", LOG_PID); dolog(&his_addr); *************** *** 183,189 form = FORM_N; stru = STRU_F; mode = MODE_S; ! (void) getsockname(0, &ctrl_addr, sizeof (ctrl_addr)); gethostname(hostname, sizeof (hostname)); reply(220, "%s FTP server (%s) ready.", hostname, version); --- 185,192 ----- form = FORM_N; stru = STRU_F; mode = MODE_S; ! addrsize = sizeof(ctrl_addr); ! (void) getsockname(0, &ctrl_addr, &addrsize); gethostname(hostname, sizeof (hostname)); reply(220, "%s FTP server (%s) ready.", hostname, version); ---------- From harpo!ihnp4!houxm!hogpc!houti!ariel!vax135!cornell!uw-beaver!tektronix!teklds!azure!scottha Thu Mar 22 16:26:05 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 (Tek) 9/26/83; site azure.UUCP Path: seismo!harpo!ihnp4!houxm!hogpc!houti!ariel!vax135!cornell!uw-beaver!tektronix!teklds!azure!scottha From: scottha@azure.UUCP Newsgroups: net.bugs.4bsd Subject: getgroups(2) doc bug Message-ID: <2632@azure.UUCP> Date: Thu, 22 Mar 84 16:26:05 EST Date-Received: Sat, 24 Mar 84 02:28:33 EST Organization: Tektronix, Beaverton OR Lines: 42 Status: O The man page for getgroups(2) in 4.2BSD has approached maximum inaccuracy for a short document. The documentation claims that the syntax is: getgroups(ngroups, gidset) int *ngroups, *gidset; where \ngroups/ initially points to an integer that informs the kernel how many integers it may place in \gidset/. After the call \ngroups/ will point to an integer that tells the user how many group numbers the kernel actually returned. The truth is that \ngroups/ must be declared as an integer and not a pointer! Getgroups then RETURNS the number of groups numbers the kernel placed into gidset. It doesn't return 0 on sucess (as the man page claims). Also, this man page claims that the maximum number of groups that the kernel can return will be NGRPS which is supposed to be defined in sys/param.h. It's not NGRPS but NGROUPS. The easiest way, then, to use getgroups is like this: int gidset[NGROUPS], n; n = getgroups(NGROUPS, gidset); After you change your on-line man page, you may want to change the lint library. Scott Hankerson teklds!tekmdp!scottha P.S. I noticed that this group list did not replace the old real and effective group ids but are an addition to the old group ids. Could someone tell me what relationship u_gid and u_rgid have with u_grps[] (the group set)? I noticed (or at least think I noticed) that the access(2) sys call only uses u_rgid and ignores all of the other groups that a user is in. Is there a document I missed somewhere? From harpo!decvax!ucbvax!mckusick Sat Mar 24 16:56:55 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site ucbvax.UUCP Path: seismo!harpo!decvax!ucbvax!mckusick From: mckusick@ucbvax.UUCP (Kirk Mckusick) Newsgroups: net.bugs.4bsd Subject: `/etc/restore R' dumps core Message-ID: <469@ucbvax.UUCP> Date: Sat, 24 Mar 84 16:56:55 EST Date-Received: Sat, 24 Mar 84 21:26:29 EST Organization: U.C. Berkeley Lines: 16 Status: O From: mckusick@ucbarpa (Kirk Mckusick) Subject: /etc/restore R dumps core Index: etc/restore/tape.c 4.2BSD Description: When restarting full or incremental restores using the 'R' option to restore, the program dumps core. Repeat-By: Start an incremental or full restore. (using the 'r' option) Once it begins restoring files, send it a kill signal. Restart the restore using the 'R' option and it will dump core. Fix: 15c15 < static long fssize; --- > static long fssize = MAXBSIZE; From harpo!decvax!ucbvax!mckusick Sat Mar 24 16:58:20 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site ucbvax.UUCP Path: seismo!harpo!decvax!ucbvax!mckusick From: mckusick@ucbvax.UUCP (Kirk Mckusick) Newsgroups: net.bugs.4bsd Subject: bug in dump Message-ID: <470@ucbvax.UUCP> Date: Sat, 24 Mar 84 16:58:20 EST Date-Received: Sat, 24 Mar 84 21:26:47 EST Organization: U.C. Berkeley Lines: 37 Status: O From: dlw@berkeley (David L Wasley) Subject: bug in dump Index: /usr/src/etc/dump 4.2 Fix Description: The problem is that restore needs the full inode bitmap for the filesystem. Dump, as distributed, truncates the map to the smallest size possible (the highest inode of interest). This causes restore to FAIL in some cases. Repeat-by: newfs /dev/rra0h ra81 dump 0 /dev/rra0h ...(add stuff to the filesystem)... dump 3 /dev/rra0h Now try to restore it. Fix: Below is a diff of dumptraverse.c that will fix the bug. The line numbers may not match yours. The routine is ``bitmap()''. ------ diff dumptraverse.c.old dumptraverse.c ------ 210,218c211 < n = -1; < for (i = 0; i < msiz; i++) < if(map[i]) < n = i; < if (n < 0) < return; < n++; < < spcl.c_count = howmany(n * sizeof(map[0]), TP_BSIZE); --- > spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE); From harpo!decvax!ucbvax!mckusick Sat Mar 24 16:59:32 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site ucbvax.UUCP Path: seismo!harpo!decvax!ucbvax!mckusick From: mckusick@ucbvax.UUCP (Kirk Mckusick) Newsgroups: net.bugs.4bsd Subject: Apparent loss of files when doing `restore i' Message-ID: <471@ucbvax.UUCP> Date: Sat, 24 Mar 84 16:59:32 EST Date-Received: Sat, 24 Mar 84 21:27:06 EST Organization: U.C. Berkeley Lines: 55 Status: O From: mckusick@ucbmonet (Kirk Mckusick) Subject: Apparent loss of files when doing `restore i' Index: etc/restore/restore.c 4.2BSD Description: When using `restore i' or `restore x' on a multireel dump, and using the recommended procedure of starting with the last reel and working towards the first, restore will sometimes give up after two or more reels, complaining that some list of files are missing. Repeat-By: Find a dump spanning three or more reels and request restore to extract files that reside on all three reels, plus THE file that starts at the end of the next to last reel and continues onto the last reel. Then load the reels from last to first. When the next to last reel is loaded it will proceed to its end and begin extracting the spanning file. Restore will demand that the last reel be loaded (so that it can finish reading the spanning file). After restore finishes extracting the spanning file it should request that another reel be loaded. Instead it will report that all requested files on the earlier reels are missing. Fix: *** restore.3.18 Thu Mar 22 19:24:00 1984 --- restore.3.19 Thu Mar 22 19:23:31 1984 *************** *** 657,668 if (next == curfile.ino && next <= last) { ep = lookupino(next); if (ep == NIL) panic("corrupted symbol table\n"); (void) extractfile(myname(ep)); ep->e_flags &= ~NEW; } } } /* * Add links. --- 657,670 ----- if (next == curfile.ino && next <= last) { ep = lookupino(next); if (ep == NIL) panic("corrupted symbol table\n"); (void) extractfile(myname(ep)); ep->e_flags &= ~NEW; + if (volno != curvol) + skipmaps(); } } } /* * Add links. From harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Tue Mar 27 01:10:52 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: /etc/dump makes bad tape use estimates when files have holes Message-ID: <1099@sdchema.UUCP> Date: Tue, 27 Mar 84 01:10:52 EST Date-Received: Wed, 28 Mar 84 00:23:42 GMT Organization: Used Softwear Jobbers, Inc. (Clandestine Computer Services) Lines: 137 Status: O Subject: /etc/dump makes bad tape use estimates when files have holes Index: etc/dump/dumpitime.c 4.2BSD Description: When you run dump, it typically prints out an estimate of the number of tapes it needs and the expected number of 1K blocks of data on those tapes. If a file on the filesystem being dumped has holes in it, the estimate can be way off. (A hole is a place in a file where no blocks have been allocated, typically found in database files. See lseek(2) if you're mystified.) Repeat-By: Make a file with holes in it and try to dump the file system. In our case dump came back with: DUMP: estimated 1794142 tape blocks on 50.53 tape(s). It should have said: DUMP: estimated 132608 tape blocks on 3.74 tape(s). This is unnerving to say the least. Fix: The problem is in the routine est() in dumpitime.c. According to the comment at the top: 'It assumes that there are no unallocated blocks; hence the estimate may be high[.]' It's actually reasonably simple to get a good estimate of the number of blocks needed even when the file has holes; there is a field in the inode structure, di_blocks, which contains the number of sectors used by the file, not counting indirect blocks. Here are the changes I made: ---------------------------------------------------------------- RCS file: RCS/dumpitime.c,v retrieving revision 1.1 diff -c -r1.1 dumpitime.c *** /tmp/,RCSt1002440 Tue Mar 27 00:52:19 1984 --- dumpitime.c Tue Mar 27 00:33:03 1984 *************** *** 204,211 /* * This is an estimation of the number of TP_BSIZE blocks in the file. ! * It assumes that there are no unallocated blocks; hence ! * the estimate may be high */ est(ip) struct dinode *ip; --- 204,211 ----- /* * This is an estimation of the number of TP_BSIZE blocks in the file. ! * WARNING: It uses the di_blocks field of the inode, which is not ! * maintained in 4.1c BSD. */ est(ip) struct dinode *ip; *************** *** 210,216 est(ip) struct dinode *ip; { ! long s; esize++; /* calc number of TP_BSIZE blocks */ --- 210,216 ----- est(ip) struct dinode *ip; { ! long s, t; esize++; *************** *** 213,220 long s; esize++; ! /* calc number of TP_BSIZE blocks */ ! s = howmany(ip->di_size, TP_BSIZE); if (ip->di_size > sblock->fs_bsize * NDADDR) { /* calc number of indirect blocks on the dump tape */ s += howmany(s - NDADDR * sblock->fs_bsize / TP_BSIZE, --- 213,235 ----- long s, t; esize++; ! ! /* ! * ip->di_size is the size of the file in bytes. ! * ip->di_blocks stores the number of sectors actually in the file. ! * If there are more sectors than the size would indicate, this just ! * means that there are unused sectors in the last file block; ! * we can safely ignore these (s = t below). ! * If the file is bigger than the number of sectors would indicate, ! * then the file has holes in it. In this case we must use the ! * block count for keeping track of actual blocks used, but we ! * use the actual size for estimating the number of indirect ! * blocks (t vs. s in the indirect block calculation). ! */ ! s = howmany(dbtob(ip->di_blocks), TP_BSIZE); ! t = howmany(ip->di_size, TP_BSIZE); ! if ( s > t ) ! s = t; if (ip->di_size > sblock->fs_bsize * NDADDR) { /* calculate the number of indirect blocks on the dump tape */ s += howmany(t - NDADDR * sblock->fs_bsize / TP_BSIZE, *************** *** 216,223 /* calc number of TP_BSIZE blocks */ s = howmany(ip->di_size, TP_BSIZE); if (ip->di_size > sblock->fs_bsize * NDADDR) { ! /* calc number of indirect blocks on the dump tape */ ! s += howmany(s - NDADDR * sblock->fs_bsize / TP_BSIZE, TP_NINDIR); } esize += s; --- 231,238 ----- if ( s > t ) s = t; if (ip->di_size > sblock->fs_bsize * NDADDR) { ! /* calculate the number of indirect blocks on the dump tape */ ! s += howmany(t - NDADDR * sblock->fs_bsize / TP_BSIZE, TP_NINDIR); } esize += s; ---------------------------------------------------------------- Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA From harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Tue Mar 27 02:18:12 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: Ghastly f77 bug in common subexpression elimination -- IMPORTANT Message-ID: <1100@sdchema.UUCP> Date: Tue, 27 Mar 84 02:18:12 EST Date-Received: Wed, 28 Mar 84 00:24:07 GMT Organization: Used Softwear Jobbers, Inc. (Clandestine Computer Services) Lines: 111 Status: O Subject: Ghastly f77 bug in common subexpression elimination -- IMPORTANT Index: usr.bin/f77/src/f77pass1/optcse.c 4.2BSD Description: F77 considers two variables from the same COMMON block to be the same variable for the purposes of common subexpression elimination. This is almost always wrong. Repeat-By: Copy the following program into a file com.f. Compile it with the optimizer turned on. ---------------------------------------------------------------- program com common /x/ a, b, c, d integer result, a, b, c, d a = 2 b = 3 c = 4 d = 5 result = a * b + c * d print *, result stop end ---------------------------------------------------------------- The expected result of running the program is '26'. What the program actually prints is '12'. To see why, here is the code produced (comments and other prettification added): ---------------------------------------------------------------- .globl _MAIN_ .set LF1,4 _MAIN_: .word LWM1 subl2 $LF1,sp jmp L12 L13: movl $2,_x_ movl $3,_x_+4 movl $4,_x_+8 movl $5,_x_+12 mull3 _x_+4,_x_,-4(fp) addl3 -4(fp),-4(fp),{result} # Mistake! pushal v.3 calls $1,_s_wsle pushl $4 pushab {result} pushal {1} pushal {3} calls $4,_do_lio calls $0,_e_wsle pushl $0 pushal {00,00} calls $2,_s_stop ret .align 1 _com_: .word LWM1 L12: moval v.1,r11 jmp L13 ---------------------------------------------------------------- The two multiplies were treated as common subexpressions, and the same temporary [-4(fp)] was used to store both results. Fix: I agonized over this one. Since this is a very urgent problem I have decided to can my earlier inconclusive changes and make a single, one-line change that has the effect of making COMMON variables pretty much ineligible for CSE (actually it gives them the status of arrays, which is convenient since COMMON blocks look just like arrays to the compiler). This is fast and has the advantage of introducing few new bugs. The change is to optcse.c in routine scantree(): ---------------------------------------------------------------- *************** *** 564,570 ap = (Addrp) p->exprblock.leftp; idp = findid(ap); killdepnodes(idp); ! if( ! ap->isarray ) { if(rnode->is_dead)idp->assgnval=idp->initval; else idp->assgnval = rnode; } --- 584,590 ----- ap = (Addrp) p->exprblock.leftp; idp = findid(ap); killdepnodes(idp); ! if( ! (ap->isarray || ap->vstg == STGCOMMON) ) { if(rnode->is_dead)idp->assgnval=idp->initval; else idp->assgnval = rnode; } ---------------------------------------------------------------- This bug is responsible for many seemingly unrelated errors, such as the previously reported 'exponentiation' error where 'x1 ** alpha + x2 ** alpha + x3 ** alpha' always turned out to be '3 * x1 ** alpha'. You should fix this as soon as you can... Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA From harpo!ihnp4!whuxle!mp Wed Mar 28 09:37:29 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site whuxle.UUCP Path: seismo!harpo!ihnp4!whuxle!mp From: mp@whuxle.UUCP (Mark Plotnick) Newsgroups: net.bugs.4bsd Subject: addbib vs. EOF Message-ID: <289@whuxle.UUCP> Date: Wed, 28 Mar 84 14:37:29 GMT Date-Received: Wed, 28 Mar 84 20:31:17 GMT Organization: Bell Labs, Whippany Lines: 46 Status: O addbib (part of refer) has the old 4.2bsd sticky-EOF misfeature, and will go into an infinite loop after you enter an abstract. The following fix (1) adds a clearerr() after the read-in-the-abstract loop and (2) returns if the user hits EOF again. *** addbib.c.bsd Sun May 8 17:34:26 1983 --- addbib.c Tue Mar 27 14:53:16 1984 *************** *** 158,163 } fputs(line, fp); } } fflush(fp); /* write to file at end of each cycle */ if (ferror(fp)) --- 158,164 ----- } fputs(line, fp); } + clearerr(stdin); } fflush(fp); /* write to file at end of each cycle */ if (ferror(fp)) *************** *** 167,173 } editloop: printf("\nContinue? "); ! fgets(line, BUFSIZ, stdin); if (line[0] == 'e' || line[0] == 'v') { bibedit(fp, line, argv); --- 168,175 ----- } editloop: printf("\nContinue? "); ! if(fgets(line, BUFSIZ, stdin) == NULL) ! return; if (line[0] == 'e' || line[0] == 'v') { bibedit(fp, line, argv); Mark Plotnick Home of the UNIX Molecule From unix-wizards-request@BRL-TGR.ARPA Wed Mar 28 18:49:53 1984 Received: from BRL-TGR (brl-tgr.arpa.ARPA) by seismo.ARPA ; Wed, 28 Mar 84 18:48:26 est Received: From brl-gateway2.ARPA by BRL-TGR via smtp; 28 Mar 84 18:21 EST Received: From ucb-vax.arpa.ARPA by BRL-AOS via smtp; 28 Mar 84 18:11 EST Received: from bbn-labs-b.ARPA (2010b80) by UCB-VAX.ARPA (4.24/4.25) id AA26992; Wed, 28 Mar 84 10:16:46 pst Received: by bbn-labs-b.ARPA (4.12/4.7) id AA03820; Wed, 28 Mar 84 13:16:02 est Date: Wed, 28 Mar 84 13:16:02 est From: Craig Partridge Message-Id: <8403281816.AA03820@bbn-labs-b.ARPA> To: unix-wizards@Brl-Aos.ARPA Subject: Bug in SDB on 4.2 Status: RO Typing ^D causes an infinite loop on 4.2 To replicate the bug just enter SDB and type ^D (and have another user prepared to kill the process). Problem is caused because you can no longer read through EOF on a tty using stdio without doing a clearerr(). To fix: insert a call to clearerr() in the following loop in readline() in sub.c (in /usr/src/old/sdb/). if ((i = getc(f)) == EOF) { *p++ = '\004'; *p = '\n'; clearerr(f); /* the fix */ } (This works because SDB later looks at the ^D and decides whether to treat it as an EOF or as ^D). Craig Partridge craig@bbn-unix (arpa) craig!bbn-cca (usenet) From unix-wizards-request@BRL-TGR.ARPA Wed Mar 28 20:21:22 1984 Received: from BRL-TGR (brl-tgr.arpa.ARPA) by seismo.ARPA ; Wed, 28 Mar 84 20:21:15 est Message-Id: <8403290121.AA17970@seismo.ARPA> Received: From brl-vgr.arpa.ARPA by BRL-TGR via smtp; 28 Mar 84 19:32 EST Received: From su-coyote.arpa.ARPA by BRL-VGR via smtp; 28 Mar 84 19:09 EST Date: Wed, 28 Mar 84 16:06:53 pst From: Jeff Mogul Subject: pxp (Pascal pretty-printer) does incorrect transformation Index: ucb/pascal/pxp/rval.c 4.2BSD Apparently-To: other-4bsd-bugs Apparently-To: 4bsd-bugs@BERKELEY Status: RO Also: /usr/src/cmd/pxp/rval.c (4.1BSD) Description: pxp in pretty-printer mode will remove a necessary parentheses around an expression preceeded by a unary minus. This can cause problems when you later try to compile code run through pxp. Repeat-By: run this program through pxp: program pxpbug(output); begin writeln(-(3-4)); end. The resulting program will print -7, instead of 1. Fix: *** /usr/src/ucb/pascal/pxp/rval.c Sat Feb 5 13:19:26 1983 --- rval.c.fixed Wed Mar 28 15:39:58 1984 *************** *** 65,71 case T_MINUS: ppop(r[0] == T_PLUS ? "+" : "-"); al = r[2]; ! rvalue(r[2], prec(al) > prec(r) || full); break; case T_NOT: ppkw(opname); --- 65,71 ----- case T_MINUS: ppop(r[0] == T_PLUS ? "+" : "-"); al = r[2]; ! rvalue(r[2], prec(al) >= prec(r) || full); break; case T_NOT: ppkw(opname); From hao!hplabs!sri-unix!mogul@Su-Coyote.ARPA Tue Mar 27 21:41:51 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Path: seismo!hao!hplabs!sri-unix!mogul@Su-Coyote.ARPA From: mogul@Su-Coyote.ARPA Newsgroups: net.unix-wizards Subject: 4.2 Unibus RL02 driver doesn't configure an off-line drive Message-ID: <300@sri-arpa.UUCP> Date: Tue, 27 Mar 84 21:41:51 EST Date-Received: Thu, 29 Mar 84 04:50:26 GMT Lines: 62 Status: O From: Jeff Mogul Description: If your system includes an RL02 drive (not that they are all that useful) but the drive is not loaded when the system is booted, the configuration procedure does not recogniz the drive and it cannot be used until the system is rebooted. Since the RL02 is a removable pack, and a darn small one at that, it's unpleasant to have to have a pack loaded whenever you boot the machine. The problem is that the distributed RL02 driver checks for a ready-to-use, loaded pack instead of simply checking that the drive is there. This is probably being done because (as a comment in the code notes) the "Get Status" operation may return invalid data. Presumably, the author felt that if the status is "all set to use", then it's valid. Repeat-By: (You need a system with an RL02 that is NOT the root drive). Unload the RL02, reboot your system. Once it is running, load the RL02. You won't be able to use it for anything. Fix: The fix involves (1) assuming that after 8 tries, either the returned status is valid or if it isn't, we'll find out later anyway; (2) checking not for "Drive Error" (which is not set for either an off-line or a non-existant drive) but for "Composite Error", i.e., any error at all. *** rl.c.old Fri Jul 29 07:33:38 1983 --- rl.c Mon Mar 26 18:13:05 1984 *************** *** 141,146 } while ((rladdr->rlmp.getstat&RLMP_STATUS) != RLMP_STATOK && ++ctr<8); if ((rladdr->rlcs & RL_DE) || (ctr >= 8)) return (0); if ((rladdr->rlmp.getstat & RLMP_DT) == 0 ) { printf("rl%d: rl01's not supported\n", ui->ui_slave); return(0); --- 147,165 ----- #ifdef MUST_BE_ONLINE if ((rladdr->rlcs & RL_DE) || (ctr >= 8)) return (0); + #else + /* + * This code does NOT assume that the disk must be online + * when the system boots. + * + * We ignore the rlmp.getstat value; it only tells us if the pack + * is loaded and online. rlcs will show an OPI error if the drive + * doesn't exist. If an invalid status is returned on the eighth + * try, we're erring on the side of optimism. + */ + if (rladdr->rlcs & RL_ERR) + return (0); + #endif MUST_BE_ONLINE if ((rladdr->rlmp.getstat & RLMP_DT) == 0 ) { printf("rl%d: rl01's not supported\n", ui->ui_slave); return(0); From unix-wizards-request@BRL-TGR.ARPA Wed Mar 28 19:31:58 1984 Received: from BRL-TGR (brl-tgr.arpa.ARPA) by seismo.ARPA ; Wed, 28 Mar 84 19:31:51 est Message-Id: <8403290031.AA16293@seismo.ARPA> Received: From brl-vgr.arpa.ARPA by BRL-TGR via smtp; 28 Mar 84 18:58 EST Date: Wed, 28 Mar 84 18:44:25 EST From: Mike Muuss To: Unix-Wizards@Brl-Vgr.ARPA Subject: IP Time-To-Live Status: RO In /sys/netinet/ip.h, the last line reads #define IPTTLDEC 5 /* subtracted when forwarding */ to operate well in the InterNet these days, especially if your host is behind several gateways, this needs to be "1", which is more faithful to the intent of the Time-To-Live field anyway. #define IPTTYDEC 1 /* subtracted when forwarding */ While this is not a problem with 4.2 to 4.2 communications, when talking to sites that may set their initial TTL to ~30, this only gives 6 hops, which in some cases may not be enough. BRL-AOS -- BRL-VOC -- BRL-GATEWAY -- MIL/ARPA -- BBN-GATEWAY -- CSNET-CIC is not an uncommon path, nor a bad example. Insert one more gateway, and *zot*, no more connectivity. -Mike From unix-wizards-request@BRL-TGR.ARPA Thu Mar 29 16:42:59 1984 Received: from BRL-TGR (brl-tgr.arpa.ARPA) by seismo.ARPA ; Thu, 29 Mar 84 16:42:47 est Message-Id: <8403292142.AA08381@seismo.ARPA> Received: From brl-vgr.arpa.ARPA by BRL-TGR via smtp; 29 Mar 84 15:36 EST Received: From cmu-cs-c.arpa.ARPA by BRL-VGR via smtp; 29 Mar 84 15:29 EST Received: from TARTAN by CMU-CS-C with TLnet; 29 Mar 84 15:27:04-EST Received: ID ; Thu 29 Mar 84 15:27:24-EST Date: Thu 29 Mar 84 15:27:23-EST From: FIRTH%TARTAN@CMU-CS-C.ARPA Subject: Dbx problems To: Unix-wizards@BRL-VGR.ARPA Cc: baer@RAND-UNIX.ARPA Status: RO The way one is supposed to call a routine from within Dbx is call routine ( arg1, ... ) Unfortunately, there are several problems. First, such an attempt crashes. This is due to a bug in "runtime.c", routine "callproc". The last statement reads cont(); which invokes routine "cont" in "process.c" with a junk actual parameter. It may be fixed to cont(0); and the call then works. However, the called routine behaves oddly with regard to breakpoints. Any breakpoint of the form "stop in FUNC" will be ignored; any of the form "stop at LINE" will be obeyed. We are still trying to find out why - stay tuned. Finally, the call performs a "compatibility" check on formal and actual arguments. There are a lot of things that can go wrong here, most of which concern the types attached to literals by dbx. The simplest and perhaps most dangerous solution is to bypass the type checking: In "runtime.c", routine "pushargs" change argc = evalargs(proc, arglist); to argc = unsafe_evalargs(proc, arglist); Add a new routine private Integer unsafe_evalargs(proc, arglist) Symbol proc; Node arglist; { Node p; Integer count; count = 0; for (p = arglist; p != nil; p = p->value.arg[1]) { eval(p->value.arg[0]); ++count; } return count; } This simply pushes as many args as you provide, as plain values. If you are adhering to the Vax convention that all args are exactly one longword in size, then this should work. It should also work most of the time for non-standard actions such as passing Double parameters by immediate value, provided the called routine knows exactly what to expect. Please feel free to mail enquiries direct. Robert Firth ------- From rochester!ritcv!kar Thu Mar 29 16:24:47 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site ritcv.UUCP Path: seismo!rochester!ritcv!kar From: kar@ritcv.UUCP (Ken Reek) Newsgroups: net.unix-wizards Subject: Bug in awk substring routine dumps core Message-ID: <974@ritcv.UUCP> Date: Thu, 29 Mar 84 21:24:47 GMT Date-Received: Thu, 29 Mar 84 23:51:57 GMT Organization: Rochester Institute of Technology, Rochester, NY Lines: 61 Status: O There is a bug in the substring routine in awk that can cause it to fail with a memory fault. Briefly, the problem stems from keeping a pointer to a string and using the pointer after the memory containing it has been free'd. Using the pointer later may corrupt malloc's storage arena, which eventually causes the failure. The awk program I had that failed is too long to include here; if anyone is interested, drop me a note. To fix the problem, change "run.c" as shown below. The line numbers may be off a little, as I've changed many of the declarations to use registers. ***255,262 (originally) obj substr(a, nnn) node **a; { char *s, temp; obj x; int k, m, n; x = execute(a[0]); s = getsval(x.optr); ---255,262 (corrected) obj substr(a, nnn) node **a; { char *s, temp; ! obj x, y; int k, m, n; ! y = execute(a[0]); ! s = getsval(y.optr); ***263,265 (originally) k = strlen(s) + 1; ! tempfree(x); x = execute(a[1]); ---263,264 (corrected) k = strlen(s) + 1; x = execute(a[1]); ***288,289 (originally) s[n+m-1] = temp; return(x); ---287,289 (corrected) s[n+m-1] = temp; ! tempfree(y); return(x); I've also incorporated changes for a version that uses doubles instead of floats (called dawk) and a version that uses long integers instead of floats (called lawk). The former is useful when greater precisions than offered by floats is needed; the latter was most useful on our PDP-11/45 which lacked floating point hardware -- the performance improvement averaged better than an order of magnitude. If you're interested, drop me a note. Ken Reek, Rochester Institute of Technology seismo!rochester!ritcv!kar From harpo!ulysses!mhuxl!houxm!hogpc!houti!ariel!vax135!floyd!clyde!watmath!watcgl!dmmartindale Thu Mar 29 23:54:12 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site watcgl.UUCP Path: seismo!harpo!ulysses!mhuxl!houxm!hogpc!houti!ariel!vax135!floyd!clyde!watmath!watcgl!dmmartindale From: dmmartindale@watcgl.UUCP Newsgroups: net.bugs.4bsd Subject: ttyslot() is very slow Message-ID: <2329@watcgl.UUCP> Date: Thu, 29 Mar 84 23:54:12 EST Date-Received: Fri, 30 Mar 84 04:29:30 GMT Sender: dmmartindale@watcgl.UUCP Organization: U of Waterloo, Ontario Lines: 75 Status: O Subject: ttyslot() is very slow Index: lib/libc/gen/ttyslot.c Description: The ttyslot() C library routine is called by many programs (either directly or via getlogin()) because it reads through /etc/ttys via sys reads of one byte. On a large system, this wastes an appreciable amount of time. Repeat-By: On a completely unloaded system, type "su". See how long it takes to prompt for a password. On watmath, su took 1.5 CPU seconds to reach this point, when invoked from a pseudo-tty line whose entry is near the end of /etc/ttys. 1.39 seconds of this was spent in sys read called from getttys(). (Gprof is wonderful!) Fix: Rewrite ttyslot.c to use stdio. The time spent in getttys() for the example above drops from 1.39 to 0.1 seconds. Presumably the original version of ttyslot avoided stdio to keep it small, but there seems little reason now. All of the other get* library routines (getpass, getpwent, etc) use stdio and few user programs are without it. The diffs below include a bit of code which skips over any trailing info on the line in /etc/ttys (we have merged /etc/ttytype into /etc/ttys here); you may omit it if you like, but it's harmless. 7a8 > #include 19c20,21 < register s, tf; --- > register s; > register FILE *tf; 27c29 < if ((tf=open(ttys, 0)) < 0) --- > if ((tf=fopen(ttys, "r")) == NULL) 33c35 < close(tf); --- > fclose(tf); 37c39 < close(tf); --- > fclose(tf); 42a45 > register FILE *f; 44c47 < static char line[32]; --- > static char line[33]; 45a49 > register c; 49c53 < if (read(f, lp, 1) != 1) --- > if ((c = getc(f)) == EOF) 51c55 < if (*lp =='\n') { --- > if (c == '\n') { 55c59,63 < if (lp >= &line[32]) --- > if (lp >= &line[32] || c == ' ' || c == '\t') { > do > c = getc(f); > while(c != EOF && c != '\n'); > *lp = 0; 57c65,66 < lp++; --- > } > *lp++ = c; From unix-wizards-request@BRL-TGR.ARPA Mon Apr 2 22:20:09 1984 Received: from BRL-TGR (brl-tgr.arpa.ARPA) by seismo.ARPA ; Mon, 2 Apr 84 22:19:56 est Message-Id: <8404030319.AA23853@seismo.ARPA> Received: From brl-vgr.arpa.ARPA by BRL-TGR via smtp; 2 Apr 84 19:47 EST Received: From su-coyote.arpa.ARPA by BRL-VGR via smtp; 2 Apr 84 19:47 EST Date: Mon, 2 Apr 84 16:42:26 pst From: Jeff Mogul Subject: 4.2 (and 4.1) Vax pcc generates bad code for real comparisons Index: lib/pcc/table.c 4.2BSD fix Apparently-To: other-4bsd-bugs Apparently-To: 4bsd-bugs@BERKELEY Status: RO Description: When pcc (the C compiler) generates code to compare a float and a double, it first converts the float to a double but doesn't realize that this takes two registers, not one. If more than one temporary register is in use while evaluating such a comparision, one of the register may be trashed. This bug applies to 4.1BSD and probably all earlier Vax pcc versions. Repeat-By: compile this C program: double dd[] = { 0.0, 2.0 }; float ff[] = { 0.0, 1.0 }; int i = 1; main(){ if( ff[i] >= dd[i] ) printf( "wrong\n" ); } If you run it, it will print "wrong" because the code that is generated (cf. cc -S) for the comparison is: movl _i,r0 movl _i,r1 cvtfd _ff[r0],r0 # trashes r1 cmpd r0,_dd[r1] # index is random jlss L19 Fix: The fix given here may be suboptimal, but it seems to give correct code. (I can't remember where I got the fix from; it's not mine.) It tells pcc to use 2 stack longwords as a temporary instead of one register. On 4.1BSD, the file is /usr/src/cmd/pcc/table.c; it's identical to the 4.2 file. *** table.c.bad Wed Dec 15 13:25:17 1982 --- table.c Mon Apr 2 16:05:08 1984 *************** *** 1,4 static char *sccsid ="@(#)table.c 1.1 (Berkeley) 12/15/82"; # include "mfile2" # define WPTR TPTRTO|TINT|TLONG|TFLOAT|TDOUBLE|TPOINT|TUNSIGNED|TULONG --- 1,9 ----- static char *sccsid ="@(#)table.c 1.1 (Berkeley) 12/15/82"; + /* + * 2 April 1984 Jeff Mogul Stanford + * Re-installed fix to prevent compare of indexed float and + * indexed double from clobbering the index register. + */ # include "mfile2" # define WPTR TPTRTO|TINT|TLONG|TFLOAT|TDOUBLE|TPOINT|TUNSIGNED|TULONG *************** *** 228,234 OPLOG, FORCC, SAREG|AWD, TDOUBLE, SAREG|AWD, TFLOAT, ! NAREG|NASR, RESCC, " cvtfd AR,A1\n cmpd AL,A1\nZP", OPLOG, FORCC, --- 233,239 ----- OPLOG, FORCC, SAREG|AWD, TDOUBLE, SAREG|AWD, TFLOAT, ! 2*NTEMP, RESCC, " cvtfd AR,A1\n cmpd AL,A1\nZP", OPLOG, FORCC, *************** *** 234,240 OPLOG, FORCC, SAREG|AWD, TFLOAT, SAREG|AWD, TDOUBLE, ! NAREG|NASL, RESCC, " cvtfd AL,A1\n cmpd A1,AR\nZP", OPLOG, FORCC, --- 239,245 ----- OPLOG, FORCC, SAREG|AWD, TFLOAT, SAREG|AWD, TDOUBLE, ! 2*NTEMP, RESCC, " cvtfd AL,A1\n cmpd A1,AR\nZP", OPLOG, FORCC, From harpo!decvax!decwrl!sun!rusty Mon Apr 2 19:26:11 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83 SMI; site sun.uucp Path: seismo!harpo!decvax!decwrl!sun!rusty From: rusty@sun.uucp (Russel Sandberg) Newsgroups: net.bugs.4bsd Subject: Broadcast ICMP ECHO system crash fix Message-ID: <745@sun.uucp> Date: Tue, 3 Apr 84 00:26:11 GMT Date-Received: Tue, 3 Apr 84 03:22:42 GMT Organization: Sun Microsystems, Inc. Lines: 49 Status: O Subject: broadcast ICMP ECHO system crash fix Index: sys/netinet/if_ether.c 4.2BSD Description: Sending a broadcast ICMP ECHO packet on an ether net with lots of hosts can cause the system to crash due to duplicate mbufs. Repeat-By: Send an ICMP ECHO packet on an ethernet with >50 hosts. Fix: The ethernet driver (if_ec.c) call arpresolve to get an ethernet address from an arpanet address. Arpresolve normaly returns 1 for success and 0 for failure. However, when arpresolve sees a packet addressed to itself it calls the loopback driver (if_loop.c) and returns the result of that call. Loopback returns 0 for success and errno for error. When the loopback call works everything is ok because arpresolve then returns a 0, if_ec interprets this as an error and returns immediately. But when the loopback driver fails (due to ip input queue full) it returns ENOBUFS and frees the mbuf chain. Arpresolve returns the error to if_ec which interprets it as success and sends out the packet. When it has been sent if_ec frees the same mbuf chain. The real fix would be to get the call to looutput out of arpresolve. This is a complete crock, the packet gets sent as a side effect of resolving the address? It's no wonder a bug turned up here. Here is a diff -c which gives a quick and dirty fix (ignore line numbers). *** if_ether.c Sun Aug 28 01:30:48 1983 --- /if_ether.c.new Mon Apr 2 15:18:54 1984 *************** *** 202,208 ((struct sockaddr_in *)&ifp->if_addr)-> sin_addr.s_addr) { sin.sin_family = AF_INET; sin.sin_addr = *destip; ! return (looutput(&loif, m, (struct sockaddr *)&sin)); } if ((ifp->if_flags & IFF_NOARP) || lna >= oldmap) { bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 3); --- 149,156 ----- ((struct sockaddr_in *)&ifp->if_addr)-> sin_addr.s_addr) { sin.sin_family = AF_INET; sin.sin_addr = *destip; ! (void) looutput(&loif, m, (struct sockaddr *)&sin); ! return (0); } #ifdef IPENADDR if (destip->s_net == 0) { /* real IP address unknown */ From harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Mon Apr 2 13:05:13 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: Constant exponents sometimes fail in f77 Message-ID: <1105@sdchema.UUCP> Date: Mon, 2 Apr 84 18:05:13 GMT Date-Received: Tue, 3 Apr 84 13:16:58 GMT Organization: Used Softwear Jobbers, Inc. (Clandestine Computer Services) Lines: 112 Status: O Subject: Bug in copy propagation causes constant exponents to break in f77 Index: usr.bin/f77/src/f77pass1/bb.c 4.2BSD Description: An f77 program that uses certain constant integer exponents greater than 4 will not get the proper results if the optimizer is turned on. In general the values produced are much larger than they should be. Repeat-By: Compile the following program with the optimizer turned on and run it: ---------------------------------------------------------------- program powbug integer i i = 10 i = i ** 5 print *, i stop end ---------------------------------------------------------------- If your f77 is broken it will print '1000000' instead of '100000'. Fix: F77 handles constant integer exponentiation with inline multiplies. The way that inline multiplies are implemented requires two temporaries, one to hold the original value and one to hold a copy which gets repeatedly squared; if the exponent is not a power of two, then the first temporary is multiplied into the second temporary the necessary remaining number of times. The copy propagation code notices that the first temporary is initialized from the second; unfortunately it misses the fact that the second copy is modified and reduces the two temporaries to one, eliminating the assignment from the one temporary to the other. The reason it misses the modification of the second temporary is that the squarings are done with an OPSTAREQ operator instead of an ordinary OPASSIGN. The solution is to make the copy propagation code know about the other assignment operators. The changes are in routine ckexpr() in bb.c: ---------------------------------------------------------------- rcsdiff -c -r1.1 bb.c *** /tmp/,RCSt1015453 Mon Apr 2 12:47:44 1984 --- bb.c Fri Mar 30 05:02:44 1984 *************** *** 343,348 { Tempp lp,rp; if (expr->exprblock.opcode == OPASSIGN) { --- 343,349 ----- { Tempp lp,rp; + int oc = expr->exprblock.opcode; if (oc == OPASSIGN || oc == OPPLUSEQ || oc == OPSTAREQ) { *************** *** 344,350 { Tempp lp,rp; ! if (expr->exprblock.opcode == OPASSIGN) { lp = (Tempp) expr->exprblock.leftp; rp = (Tempp) expr->exprblock.rightp; --- 345,351 ----- Tempp lp,rp; int oc = expr->exprblock.opcode; ! if (oc == OPASSIGN || oc == OPPLUSEQ || oc == OPSTAREQ) { lp = (Tempp) expr->exprblock.leftp; rp = (Tempp) expr->exprblock.rightp; *************** *** 349,355 lp = (Tempp) expr->exprblock.leftp; rp = (Tempp) expr->exprblock.rightp; if (lp->tag == TTEMP) ! if (rp->tag == TTEMP) enter (lp->memalloc, rp->memalloc); else enter (lp->memalloc, ENULL); --- 350,356 ----- lp = (Tempp) expr->exprblock.leftp; rp = (Tempp) expr->exprblock.rightp; if (lp->tag == TTEMP) ! if (rp->tag == TTEMP && oc == OPASSIGN) enter (lp->memalloc, rp->memalloc); else enter (lp->memalloc, ENULL); ---------------------------------------------------------------- Thanks should go to Peter Gross at the High Altitude Observatory for bringing this to my attention... Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA From harpo!decvax!mulga!munnari!basser!chris Fri Apr 6 14:48:25 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10 beta 3/9/83; site basser.SUN Path: seismo!harpo!decvax!mulga!munnari!basser!chris From: chris@basser.SUN (Chris Maltby) Newsgroups: net.bugs.4bsd Subject: Re: 4.[12] Vax pcc generates bad code for real comparisons Message-ID: <259@basser.SUN> Date: 6 Apr 84 19:48:25 GMT Date-Received: 6 Apr 84 20:10:20 GMT References: <6728@decwrl.UUCP> Organization: Dept of C.S., University of Sydney Lines: 38 Status: O x - marks the spot Here is a better fix to pcc for the problem described by Jeff of DEC western research labs. The real code generation problem is that the result of the cvtfd instruction can't be shared with its 'float' source. Of course, the double intermediate value needs 2 AREGS. In fact, the second table entry is unnecessary, as there is a rewrite rule which will convert the left operand to double (correctly) and then compare it. I leave it here mostly to keep the linenumbers right (and in case I overlooked something). ====== "table.c" line 228 - 238 OPLOG, FORCC, SAREG|AWD, TDOUBLE, SAREG|AWD, TFLOAT, - NAREG|NASR, RESCC, " cvtfd AR,A1\n cmpd AL,A1\nZP", OPLOG, FORCC, SAREG|AWD, TFLOAT, SAREG|AWD, TDOUBLE, - NAREG|NASL, RESCC, " cvtfd AL,A1\n cmpd A1,AR\nZP", ====== OPLOG, FORCC, SAREG|AWD, TDOUBLE, SAREG|AWD, TFLOAT, + 2*NAREG, RESCC, " cvtfd AR,A1\n cmpd AL,A1\nZP", OPLOG, FORCC, SAREG|AWD, TFLOAT, SAREG|AWD, TDOUBLE, + 2*NAREG, RESCC, " cvtfd AL,A1\n cmpd A1,AR\nZP", ====== From unix-wizards-request@BRL-TGR.ARPA Fri Apr 6 22:24:30 1984 Received: from BRL-TGR (brl-tgr.arpa.ARPA) by seismo.ARPA ; Fri, 6 Apr 84 22:24:24 est Message-Id: <8404070324.AA20585@seismo.ARPA> Received: From brl-vgr.arpa.ARPA by BRL-TGR via smtp; 6 Apr 84 22:01 EST Received: From su-coyote.arpa.ARPA by BRL-VGR via smtp; 6 Apr 84 22:01 EST Date: Fri, 6 Apr 84 18:58:25 pst From: Jeff Mogul Subject: Pascal doesn't like mixed-case keywords Index: ucb/pascal/src/hash.c 4.2BSD Fix Apparently-To: other-4bsd-bugs Apparently-To: 4bsd-bugs@BERKELEY Status: RO Description: Unless run in "standard" (-s) mode, the Berkeley Pascal language processors (pi, pc, pxp) demand lower-case-only keywords. In standard mode, case in the source files is ignored. This leads to a dilemma for people trying to compile code written originally for other compilers, since if they want to use any extensions, they cannot use standard mode. Repeat-By: Try running this program through pi, pc, or pxp (don't use -s): PROGRAM Test(output); BEGIN writeln('hello') END. Fix: Since this is, in effect, a change to the Berkeley Pascal language, you might want to think twice about installing it; someone you know might have been stupid enough to write a Pascal program with identifiers that look like keywords, except for case. Otherwise, this fix makes sense: it converts a private copy of each token to lower case when looking up keywords. Line numbers are for comparison only; your actual line numbers may vary. *** hash.c.old Mon Jan 10 10:32:53 1983 --- hash.c Fri Apr 6 16:32:11 1984 *************** *** 117,122 int *sym; struct ht *htp; int sh; /* * The hash function is a modular hash of --- 124,131 ----- int *sym; struct ht *htp; int sh; + static char lc_buf[sizeof(token)]; /* for lower-case-ifying */ + register char *lc_bp = lc_buf; /* * The hash function is a modular hash of *************** *** 128,135 if (cp == NIL) cp = token; /* default symbol to be hashed */ i = 0; ! while (*cp) ! i = i*2 + *cp++; sh = (i&077777) % HASHINC; cp = s; if (cp == NIL) --- 137,149 ----- if (cp == NIL) cp = token; /* default symbol to be hashed */ i = 0; ! while (*cp) { ! register int c_tmp = *cp++; ! if (isupper(c_tmp)) /* all keywords are lower-case */ ! c_tmp = tolower(c_tmp); ! *lc_bp++ = c_tmp; /* construct a lower-case copy */ ! i = i*2 + c_tmp; ! } sh = (i&077777) % HASHINC; *lc_bp = 0; cp = lc_buf; *************** *** 131,139 while (*cp) i = i*2 + *cp++; sh = (i&077777) % HASHINC; ! cp = s; ! if (cp == NIL) ! cp = token; /* * There are as many as MAXHASH active * hash tables at any given point in time. --- 145,152 ----- i = i*2 + c_tmp; } sh = (i&077777) % HASHINC; ! *lc_bp = 0; ! cp = lc_buf; /* * There are as many as MAXHASH active * hash tables at any given point in time. From harpo!decvax!mcvax!turing!haring!jim Fri Apr 6 22:34:04 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83 (MC840302); site haring.UUCP Path: seismo!harpo!decvax!mcvax!turing!haring!jim From: jim@haring.UUCP Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: Two fixes for pseudo-ttys Message-ID: <235@haring.UUCP> Date: 7 Apr 84 03:34:04 GMT Date-Received: 7 Apr 84 01:22:30 GMT Organization: CWI, Amsterdam Lines: 135 Apparently-To: rnews@turing.LOCAL Status: O Subject: Two fixes for pseudo-ttys Index: sys/sys/tty_pty.c 4.2BSD Description: 1) When the slave end of a pseudo-tty closes, the controlling side is not informed if it is already trying to read from the device. 2) As it says in the manual, it should be but isn't possible to send an end-of-file to the slave side by the controlling side doing a 0-length write in TIOCREMOTE mode. Repeat-By: 1) The following short program may or may not cause the parent to wait forever in the read(), depending on whether it gets there before the child exits. It is always possible to put a sleep() in the child process before the exit to ensure the parent gets to read. main() { switch(fork()){ case -1: perror("fork"); break; case 0: child(); /*NOTREACHED*/ default: parent(); /*NOTREACHED*/ } exit(1); } child() { register int fd; if((fd = open("/dev/ttyp4", 1)) == -1){ perror("/dev/ttyp4"); exit(1); } (void) write(fd, "Hello world\n", 12); exit(0); } parent() { register int fd, n; char buf[100]; if((fd = open("/dev/ptyp4", 2)) == -1){ perror("/dev/ptyp4"); exit(1); } while((n = read(fd, buf, sizeof(buf))) > 0) (void) write(1, buf, n); if(n == -1) perror("read"); else printf("EOF"); exit(0); } 2) Typing EOF to a process expecting input from a shell window in EMACS - the process is undisturbed. Fix: The following is a diff -c of the original 4.2BSD module with the current one. The EOF fix comes from David Rosenthal, David.Rosenthal@CMU-CS-A.ARPA *** sys.gen/sys/tty_pty.c Tue Mar 27 15:12:08 1984 --- sys/sys/tty_pty.c Sun Apr 1 20:42:26 1984 *************** *** 78,83 tp = &pt_tty[minor(dev)]; (*linesw[tp->t_line].l_close)(tp); ttyclose(tp); } ptsread(dev, uio) --- 78,84 ----- tp = &pt_tty[minor(dev)]; (*linesw[tp->t_line].l_close)(tp); ttyclose(tp); + ptcwakeup(tp); } ptsread(dev, uio) *************** *** 236,242 error = ureadc(0, uio); } while (tp->t_outq.c_cc == 0 || (tp->t_state&TS_TTSTOP)) { ! if (pti->pt_flags&PF_NBIO) return (EWOULDBLOCK); sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); } --- 237,243 ----- error = ureadc(0, uio); } while (tp->t_outq.c_cc == 0 || (tp->t_state&TS_TTSTOP)) { ! if (((tp->t_state&TS_CARR_ON) == 0) || (pti->pt_flags&PF_NBIO)) return (EWOULDBLOCK); sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); } *************** *** 337,342 break; iov = uio->uio_iov; if (iov->iov_len == 0) { uio->uio_iovcnt--; uio->uio_iov++; if (uio->uio_iovcnt < 0) --- 338,349 ----- break; iov = uio->uio_iov; if (iov->iov_len == 0) { + while((pti->pt_flags&PF_REMOTE) && tp->t_rawq.c_cc != 0) + sleep((caddr_t)&tp->t_rawq.c_cf, TTIPRI); + if(pti->pt_flags&PF_REMOTE){ + (void) putc(0, &tp->t_rawq); + wakeup((caddr_t)&tp->t_rawq); + } uio->uio_iovcnt--; uio->uio_iov++; if (uio->uio_iovcnt < 0) From harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Sat Apr 7 21:35:07 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: Massive f77 fixes for subroutine argument temporary bugs Message-ID: <1117@sdchema.UUCP> Date: 8 Apr 84 02:35:07 GMT Date-Received: 9 Apr 84 12:34:00 GMT Organization: Used Softwear Jobbers, Inc. (Clandestine Computer Services) Lines: 384 Status: O Here, as promised, are Bob Corbett's changes to f77 to prevent the allocation of subroutine argument temporaries from trashing DO loop limits and other things. I have included the fixes to Bob's changes which I have made, so if you are already running the changes from Berkeley and Bob hasn't sent you the latest round of fixes, you will want to use this code instead. In any case, this supersedes the bug report I sent out titled 'Bug in f77 loop optimizer generates incorrect code (serious!)'. If you have already installed my fix, you will need to remove it. As a reminder, here are the changes needed to remove my fix in exdo() in exec.c. (All source files that I'll be referring to are in /usr/src/f77/src/f77pass1. Also, in each set of diffs, '*' marks old code and '-' marks new or corrected code.) --------------------------------------------------------------------------- *** /tmp/,RCSt1020046 Sat Apr 7 20:23:42 1984 --- exec.c Fri Mar 23 14:50:26 1984 *************** *** 465,471 if( CONSTLIMIT ) ctlstack->domax = DOLIMIT; else ! ctlstack->domax = (expptr) mkaltemp(dotype, PNULL); if( CONSTINCR ) { --- 447,453 ----- if( CONSTLIMIT ) ctlstack->domax = DOLIMIT; else ! ctlstack->domax = (expptr) mktemp(dotype, PNULL); if( CONSTINCR ) { *************** *** 476,482 } else { ! ctlstack->dostep = (expptr) mkaltemp(dotype, PNULL); ctlstack->dostepsign = VARSTEP; } --- 458,464 ----- } else { ! ctlstack->dostep = (expptr) mktemp(dotype, PNULL); ctlstack->dostepsign = VARSTEP; } --------------------------------------------------------------------------- Here are the changes needed for the new set of fixes. Be careful -- they are complicated. Where there are long stretches of new code, it is probably a good idea to clip out the diffs from this article with an editor, remove the diff marks and install them directly into the file. The file 'defs.h' needs a couple new external definitions: --------------------------------------------------------------------------- *** /tmp/,RCSt1020106 Sat Apr 7 20:34:04 1984 --- defs.h Fri Mar 23 14:50:15 1984 *************** *** 117,122 extern flag anylocals; extern chainp templist; extern int maxdim; extern chainp holdtemps; extern struct Entrypoint *entries; --- 133,140 ----- extern flag anylocals; extern chainp templist; + extern chainp argtemplist; + extern chainp activearglist; extern int maxdim; extern chainp holdtemps; extern struct Entrypoint *entries; --------------------------------------------------------------------------- The declarations of these variables are in init.c, and the code needed to reset them is in procinit() in the same file: --------------------------------------------------------------------------- *** /tmp/,RCSt1020131 Sat Apr 7 20:38:06 1984 --- init.c Fri Mar 23 14:50:37 1984 *************** *** 112,117 flag toomanyinit; ftnint curdtelt; chainp templist = NULL; chainp holdtemps = NULL; int dorange = 0; struct Entrypoint *entries = NULL; --- 131,138 ----- flag toomanyinit; ftnint curdtelt; chainp templist = NULL; + chainp argtemplist = CHNULL; + chainp activearglist = CHNULL; chainp holdtemps = NULL; int dorange = 0; struct Entrypoint *entries = NULL; *************** *** 279,284 for(cp = templist ; cp ; cp = cp->nextp) free( (charptr) (cp->datap) ); frchain(&templist); holdtemps = NULL; dorange = 0; nregvar = 0; --- 300,308 ----- for(cp = templist ; cp ; cp = cp->nextp) free( (charptr) (cp->datap) ); frchain(&templist); + for (cp = argtemplist; cp; cp = cp->nextp) + free((char *) (cp->datap)); + frchain(&argtemplist); holdtemps = NULL; dorange = 0; nregvar = 0; --------------------------------------------------------------------------- Subroutine argument temporaries need to be recycled at each statement boundary (not at each call, unfortunately, since the code generator moves the definitions of temporaries to the beginning of each statement; the original Berkeley changes did this incorrectly). This requires a change in the production for 'stat' in gram.head: --------------------------------------------------------------------------- *** /tmp/,RCSt1020164 Sat Apr 7 20:43:40 1984 --- gram.head Fri Mar 23 22:46:53 1984 *************** *** 110,115 err("label already that of a format"); else $1->labtype = LABEXEC; } } | thislabel SINCLUDE filename --- 126,136 ----- err("label already that of a format"); else $1->labtype = LABEXEC; + } + if(!optimflag) + { + argtemplist = hookup(argtemplist, activearglist); + activearglist = CHNULL; } } | thislabel SINCLUDE filename --------------------------------------------------------------------------- A similar change must occur in putopt() in optim.c: --------------------------------------------------------------------------- *** /tmp/,RCSt1020183 Sat Apr 7 20:46:23 1984 --- optim.c Fri Mar 23 22:48:42 1984 *************** *** 179,184 badthing("SKtype", "putopt", sp->type); break; } } --- 195,208 ----- badthing("SKtype", "putopt", sp->type); break; } + + /* + * Recycle argument temporaries here. This must get done on a + * statement-by-statement basis because the code generator + * makes side effects happen at the start of a statement. + */ + argtemplist = hookup(argtemplist, activearglist); + activearglist = CHNULL; } --------------------------------------------------------------------------- Now comes the tough part. A new routine mkargtemp() must be added in proc.c following the code for mkaltmpn(): --------------------------------------------------------------------------- *** /tmp/,RCSt1020214 Sat Apr 7 20:52:40 1984 --- proc.c Fri Mar 23 14:50:58 1984 *************** *** 1003,1008 fprintf(diagfile,"mkaltmpn new offset %d\n", q->memoffset->constblock.const.ci); return(q); } ^L /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */ --- 1013,1080 ----- fprintf(diagfile,"mkaltmpn new offset %d\n", q->memoffset->constblock.const.ci); return(q); + } + + + + /* The following routine is a patch which is only needed because the */ + /* code for processing actual arguments for calls does not allocate */ + /* the temps it needs before optimization takes place. A better */ + /* solution is possible, but I do not have the time to implement it */ + /* now. */ + /* */ + /* Robert P. Corbett */ + + Addrp + mkargtemp(type, lengp) + int type; + expptr lengp; + { + ftnint leng; + chainp oldp, p; + Addrp q; + + if (type == TYUNKNOWN || type == TYERROR) + badtype("mkargtemp", type); + + if (type == TYCHAR) + { + if (ISICON(lengp)) + leng = lengp->constblock.const.ci; + else + { + err("adjustable length"); + return ((Addrp) errnode()); + } + } + + oldp = CHNULL; + p = argtemplist; + + while (p) + { + q = (Addrp) (p->datap); + if (q->vtype == type + && (type != TYCHAR || q->vleng->constblock.const.ci == leng)) + { + if (oldp) + oldp->nextp = p->nextp; + else + argtemplist = p->nextp; + + p->nextp = activearglist; + activearglist = p; + + return (q); + } + + oldp = p; + p = p->nextp; + } + + q = autovar(1, type, lengp); + activearglist = mkchain(q, activearglist); + return (q); } ^L /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */ --------------------------------------------------------------------------- Finally, the routine putcall() in putpcc.c must be changed to use mkargtemp() instead of mkaltemp(). This is what was causing the breakage before, since putcall() was dipping into the pool of temporaries after the point where that pool is supposed to be restricted. --------------------------------------------------------------------------- *** /tmp/,RCSt1020263 Sat Apr 7 21:03:51 1984 --- putpcc.c Fri Mar 23 22:51:59 1984 *************** *** 1267,1273 int n, first; Addrp t; register expptr q; ! Addrp fval; int type, type2, ctype, qtype, indir; type2 = types2[type = p->vtype]; --- 1300,1306 ----- int n, first; Addrp t; register expptr q; ! Addrp fval, mkargtemp(); int type, type2, ctype, qtype, indir; type2 = types2[type = p->vtype]; *************** *** 1312,1318 { if( ISICON(p->vleng) ) { ! fval = mkaltemp(TYCHAR, p->vleng); n += 2; } else { --- 1345,1351 ----- { if( ISICON(p->vleng) ) { ! fval = mkargtemp(TYCHAR, p->vleng); n += 2; } else { *************** *** 1322,1328 } else if( ISCOMPLEX(type) ) { ! fval = mkaltemp(type, PNULL); n += 1; } else --- 1355,1361 ----- } else if( ISCOMPLEX(type) ) { ! fval = mkargtemp(type, PNULL); n += 1; } else *************** *** 1356,1362 if(indir) putx(q); else { ! t = mkaltemp(qtype = q->headblock.vtype, q->headblock.vleng); putassign( cpexpr(t), q ); putaddr(t, NO); --- 1389,1395 ----- if(indir) putx(q); else { ! t = mkargtemp(qtype = q->headblock.vtype, q->headblock.vleng); putassign( cpexpr(t), q ); putaddr( cpexpr(t), NO ); *************** *** 1359,1365 t = mkaltemp(qtype = q->headblock.vtype, q->headblock.vleng); putassign( cpexpr(t), q ); ! putaddr(t, NO); putcomma(1, qtype, YES); } } --- 1392,1398 ----- t = mkargtemp(qtype = q->headblock.vtype, q->headblock.vleng); putassign( cpexpr(t), q ); ! putaddr( cpexpr(t), NO ); putcomma(1, qtype, YES); } } --------------------------------------------------------------------------- That should keep you busy for a while... Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA From ut-sally!nbires!mccallum Mon Apr 9 13:39:54 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site nbires.UUCP Path: seismo!ut-sally!nbires!mccallum From: mccallum@nbires.UUCP (Doug McCallum) Newsgroups: net.unix-wizards,net.bugs.4bsd Subject: kernel bug in flock Message-ID: <307@nbires.UUCP> Date: 9 Apr 84 18:39:54 GMT Date-Received: 9 Apr 84 20:26:16 GMT Organization: NBI, Boulder Lines: 44 Status: O Subject: flock panics kernel when given invalid parameter Index: sys/sys/kern_descrip.c 4.2BSD Description: The flock system call can cause the 4.2 kernel to panic when given an invalid second parameter. This occurs only when the file in question is already locked with LOCK_SH and a second call to flock where the second parameter does not contain any of (LOCK_UN|LOCK_EX|LOCK_SH) set. Repeat-By: The problem can be shown with: ... flock(fd, LOCK_SH); ... flock(fd, 0); ... Fix: The following context diff of kern_descrip.c prevents the panics: *** kern_descrip.c Mon Apr 9 08:16:14 1984 --- /sys/sys/kern_descrip.c Wed Mar 28 14:35:47 1984 *************** *** 405,414 u.u_error = EOPNOTSUPP; return; } - if ((uap->how & (LOCK_UN|LOCK_EX|LOCK_SH){ - u.u_error = EINVAL; /* ??? */ - return; - } if (uap->how & LOCK_UN) { ino_unlock(fp, FSHLOCK|FEXLOCK); return; --- 405,410 ----- u.u_error = EOPNOTSUPP; return; } if (uap->how & LOCK_UN) { ino_unlock(fp, FSHLOCK|FEXLOCK); return; From hao!denelcor!csu-cs!bentson Mon Apr 9 15:14:48 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site csu-cs.UUCP Path: seismo!hao!denelcor!csu-cs!bentson From: bentson@csu-cs.UUCP (Randolph Bentson) Newsgroups: net.bugs.4bsd Subject: 4.2 dmf problems (won't answer, etc) and a fix Message-ID: <2538@csu-cs.UUCP> Date: 9 Apr 84 20:14:48 GMT Date-Received: 10 Apr 84 16:42:24 GMT Organization: Colo. St Univ, C.S. Dpt. Lines: 19 Status: O We too had a problem similar to those reported for dh and dz (doesn't answer, hangs on open, etc.). This appeared on the DMF-11 with 4.2BSD. We actually found a fix! There's reference to a byte-sized portion of a register that should be addressed as a word. This has the effect of clearing another bit in the register (in the other byte). You'll find a reference addr->dmftms = 0; that should be changed to addr->dmftba = addr->dmftba & (~(DMF_ON<<8)|0xff); so as not to clear the "ON" bit. If I was more confident about the compiler's action it could use the "&=" form. Randy Bentson Colorado State University - Computer Science hao!csu-cs!bentson From harpo!ihnp4!inuxc!pur-ee!uiucdcs!parsec!hosking Tue Apr 10 01:00:00 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: Notesfiles; site parsec.UUCP Path: seismo!harpo!ihnp4!inuxc!pur-ee!uiucdcs!parsec!hosking From: hosking@parsec.UUCP Newsgroups: net.bugs.4bsd Subject: 4.2 TSET minor bug fix Message-ID: <33500002@parsec.UUCP> Date: 10 Apr 84 06:00:00 GMT Date-Received: 11 Apr 84 09:18:35 GMT Lines: 10 Nf-ID: #N:parsec:33500002:000:250 Nf-From: parsec!hosking Apr 10 00:00:00 1984 Nf-ID: #N:parsec:33500002:000:250 Nf-From: parsec!hosking Apr 10 00:00:00 1984 Status: O The following is a minor bug fix for 4.2 TSET. The original code would produce odd results if you typed something like: tset -k^u (as opposed to ^U). OLD: #define CTRL(x) (x ^ 0100) NEW: #define CTRL(x) (x & ~0140) allegra!convex!hosking From harpo!ulysses!burl!clyde!floyd!cmcl2!lanl-a!unm-cvax!nmtvax!fred Wed Apr 11 16:37:43 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10 beta 3/9/83; site nmtvax.UUCP Path: seismo!harpo!ulysses!burl!clyde!floyd!cmcl2!lanl-a!unm-cvax!nmtvax!fred From: fred@nmtvax.UUCP Newsgroups: net.unix-wizards,net.bugs.4bsd Subject: Re: kernal bug in flock Message-ID: <226@nmtvax.UUCP> Date: 11 Apr 84 21:37:43 GMT Date-Received: 12 Apr 84 08:21:33 GMT References: <307@nbires.UUCP> Organization: New Mexico Tech, Socorro, N.M. Lines: 73 Status: O > Subject: flock panics kernel when given invalid parameter > > Index: sys/sys/kern_descrip.c 4.2BSD > > Description: > The flock system call can cause the 4.2 kernel to panic when > given an invalid second parameter. This occurs only when the > file in question is already locked with LOCK_SH and a second > call to flock where the second parameter does not contain any > of (LOCK_UN|LOCK_EX|LOCK_SH) set. > > Repeat-By: > The problem can be shown with: > ... > flock(fd, LOCK_SH); > ... > flock(fd, 0); > ... > > Fix: > The following context diff of kern_descrip.c prevents the panics: > > *** kern_descrip.c Mon Apr 9 08:16:14 1984 > --- /sys/sys/kern_descrip.c Wed Mar 28 14:35:47 1984 > *************** > *** 405,414 > u.u_error = EOPNOTSUPP; > return; > } > - if ((uap->how & (LOCK_UN|LOCK_EX|LOCK_SH){ > - u.u_error = EINVAL; /* ??? */ > - return; > - } > if (uap->how & LOCK_UN) { > ino_unlock(fp, FSHLOCK|FEXLOCK); > return; > --- 405,410 ----- > u.u_error = EOPNOTSUPP; > return; > } > if (uap->how & LOCK_UN) { > ino_unlock(fp, FSHLOCK|FEXLOCK); > return; I found that the above fix was obviously not tested by the person who posted it. The fix had both a syntax error and a logic error. The fix should have been: - if (!(uap->how & (LOCK_UN|LOCK_EX|LOCK_SH))){ - u.u_error = EINVAL; /* ??? */ - return; - } Fred Romelfanger Computer Science Department New Mexico Tech ..!ucbvax!unmvax!nmtvax!fred (uucp) ..!cmcl2!lanl-a!nmtvax!fred (uucp) fred.nmt@rand-relay (arpa) fred@nmt (CSnet) From ut-sally!nbires!mccallum Thu Apr 12 16:02:57 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site nbires.UUCP Path: seismo!ut-sally!nbires!mccallum From: mccallum@nbires.UUCP (Doug McCallum) Newsgroups: net.unix-wizards,net.bugs.4bsd Subject: Re: kernel bug in flock Message-ID: <312@nbires.UUCP> Date: 12 Apr 84 21:02:57 GMT Date-Received: 12 Apr 84 22:13:49 GMT References: <307@nbires.UUCP> Organization: NBI, Boulder Lines: 49 Status: O There was a major bug in my last fix. The typo should have given a clue. The following is the correct bug report: Subject: flock panics kernel when given invalid parameter Index: sys/sys/kern_descrip.c 4.2BSD Description: The flock system call can cause the 4.2 kernel to panic when given an invalid second parameter. This occurs only when the file in question is already locked with LOCK_SH and a second call to flock where the second parameter does not contain any of (LOCK_UN|LOCK_EX|LOCK_SH) set. Repeat-By: The problem can be shown with: ... flock(fd, LOCK_SH); ... flock(fd, 0); ... Fix: The following context diff of kern_descrip.c prevents the panics: *** kern_descrip.c Mon Apr 9 08:16:14 1984 --- /sys/sys/kern_descrip.c Wed Mar 28 14:35:47 1984 *************** *** 405,414 u.u_error = EOPNOTSUPP; return; } - if ((uap->how & (LOCK_UN|LOCK_EX|LOCK_SH)) == 0){ - u.u_error = EINVAL; /* ??? */ - return; - } if (uap->how & LOCK_UN) { ino_unlock(fp, FSHLOCK|FEXLOCK); return; --- 405,410 ----- u.u_error = EOPNOTSUPP; return; } if (uap->how & LOCK_UN) { ino_unlock(fp, FSHLOCK|FEXLOCK); return; ---------- Doug McCallum {ucbvax,allegra,amd70,hao}!nbires!mccallum From unix-wizards-request@BRL-TGR.ARPA Fri Apr 13 10:08:05 1984 Received: from BRL-TGR (brl-tgr.arpa.ARPA) by seismo.ARPA ; Fri, 13 Apr 84 10:07:59 est Received: From brl-vgr.arpa.ARPA by BRL-TGR via smtp; 13 Apr 84 9:43 EST Received: From mit-bold.arpa.ARPA by BRL-VGR via smtp; 13 Apr 84 9:39 EST Received: by mit-bold.ARPA (4.12/4.7) id AA00614; Fri, 13 Apr 84 09:39:46 est Date: Fri, 13 Apr 84 09:39:46 est From: Robert W. Scheifler Message-Id: <8404131439.AA00614@mit-bold.ARPA> Subject: 4.2 ip_dooptions() is not paranoid Index: /sys/netinet/ip_input.c 4.2BSD Apparently-To: unix-wizards@brl-vgr Status: RO Description: IP options are not adequately sanity-checked. In particular, the option length is not checked to be reasonable. A zero length option will cause the machine to hang, executing a for loop in ip_dooptions() forever at netisr. Repeat-By: Send your enemies a bogus IP option specifying a zero option length. Watch with glee as their machines hang. Fix: Other checks may be necessary, but in ip_dooptions you at least need to change lines else optlen = cp[1]; to else { optlen = cp[1]; if (optlen <= 0 || optlen > cnt) goto bad; } From harpo!ihnp4!drutx!houxe!hogpc!houti!ariel!vax135!floyd!cmcl2!rna!dan Fri Apr 13 01:42:52 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Path: seismo!harpo!ihnp4!drutx!houxe!hogpc!houti!ariel!vax135!floyd!cmcl2!rna!dan From: dan@rna.UUCP Newsgroups: net.bugs.4bsd Subject: VI Botches deletes on non-24line VT100s Message-ID: <230@rna.UUCP> Date: 13 Apr 84 06:42:52 GMT Date-Received: 13 Apr 84 22:42:06 GMT Lines: 41 Status: O Subject: VI botches line delete on "VT100's" that don't have 24 lines. Index: /usr/src/ucb/ex/ex_vadj.c 4.2BSD Description: On ANSI/VT-100 like terminals which have termcap's CS, RC, SC defined, VI ignores AL and DL (insert line and delete line) (which in itself is probably not good) and emulates the AL and DL functions by changing the scrolling region and scrolling in or out a line. The code which emulates DL with CS had LI-1 coded as 23, which assumes a 24line VT100. 23line VT100's (i.e. VT100's with "status-line") and other terminals like the CIT-500 which has 64 lines failed to emulate correctly. Repeat-By: Set termcap entry of a VT100 to something other than 24 lines (e.g. 23 lines) and enter VI and delete a line. Fix: *** ex_vadj.c.org Thu Apr 12 23:56:47 1984 --- ex_vadj.c Fri Apr 13 00:42:21 1984 *************** *** 748,750 vputp(tgoto(CS, LINES-1, p), 1); ! vputp(tgoto(CM, 0, 23), 1); /* Go to lower left corner */ for (i=0; i Message-Id: <8404152001.AA26478@NYU.ARPA> To: unix-wizards@Brl-Vgr.ARPA Subject: htons should be ntohs (minor) Status: RO Subject: htons should be ntohs (minor) Index: netinet/in_pcb.c 4.2BSD Description: For form's sake, an htons() call in in_pcbbind should really be an ntohs() call. (It really doesn't matter that much, as they do the same thing on most machines.) Fix: The line (around 65) should read: u_short aport = ntohs(lport); From harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Fri Apr 13 01:56:18 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: f77 disallows floating point constants less than -2.59e+33 Message-ID: <1131@sdchema.UUCP> Date: 13 Apr 84 06:56:18 GMT Date-Received: 14 Apr 84 05:14:57 GMT Organization: Used Softwear Jobbers, Inc. (Clandestine Computer Services) Lines: 66 Status: O The distributed f77 will not accept floating point constants that are smaller than roughly -2.59e33, but going by the representation one would expect to be able to use constants as low as -1.70e38. The following program fails in the way shown: --------------------------------------------------------------------------- % cat tst.f program tst real s data s /-1.7e38/ print *, s stop end % f77 tst.f tst.f: MAIN tst: Error on line 4 of tst.f: data value too large Error. No assembly. --------------------------------------------------------------------------- Positive floating point numbers up to 1.70e38 ARE allowed, however. What's actually happened is that for some reason the minimum value is set incorrectly in conv.c. Here is the correction (notice that the floating point numbers are given as bit patterns): --------------------------------------------------------------------------- *** /tmp/,RCSt1004227 Fri Apr 13 01:34:35 1984 --- conv.c Fri Apr 13 01:08:19 1984 *************** *** 21,27 LOCAL long dminint[] = { 0x0000d000, 0xffff00ff }; LOCAL long dmaxreal[] = { 0xffff7fff, 0xffff7fff }; ! LOCAL long dminreal[] = { 0x0000f800, 0xffffffff }; ^L --- 34,40 ----- LOCAL long dminint[] = { 0x0000d000, 0xffff00ff }; LOCAL long dmaxreal[] = { 0xffff7fff, 0xffff7fff }; ! LOCAL long dminreal[] = { 0xffffffff, 0xffff7fff }; ^L --------------------------------------------------------------------------- In case you're curious, the reason why the least significant bits are not all ones is that an epsilon value was subtracted (added) in order to detect overflow in atof(), which indicates overflow by returning the maximum (minimum) floating point number. This has the side effect that you can't indicate the highest and lowest DOUBLE PRECISION numbers to the precision of the representation, but this is not likely to hurt anyone (famous last words). Bob Corbett tells me that this fix was applied at Berkeley back on Dec. 13 of last year, so if you have a distribution more recent than that you should ignore this article. Thanks to Mike Brown at the National Solar Observatory (kpno!brown) for pointing this bug out to me. Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn From harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Tue Apr 17 14:14:44 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: A fix for a bug in the previously distributed f77 fixes (sigh) Message-ID: <1135@sdchema.UUCP> Date: 17 Apr 84 19:14:44 GMT Date-Received: 18 Apr 84 06:25:27 GMT Organization: Used Softwear Jobbers, Inc. (Clandestine Computer Services) Lines: 83 Status: O I realized shortly after sending it out that the previous big set of fixes that implemented Bob Corbett's mkargtemp() function had a bug. The bug crops up when you use CHARACTER or COMPLEX valued functions -- the compiler breaks down and complains about 'bad type 0 in putaddr' or something. What has happened is that one of mkargtemp's private temporaries was accidentally given away to another routine, which freed it, causing it to get stomped on. The following set of fixes (sigh) elminates this problem (it actually fixes a set of problems, and replaces an earlier bug fix of mine in Bob Corbett's code). The first step is to make sure that mkargtemp() in proc.c never gives away an actual temporary, only a copy of one: ------------------------------------------------------------------------ *** /tmp/,RCSt1005360 Tue Apr 17 13:45:05 1984 --- proc.c Mon Apr 16 12:05:50 1984 *************** *** 1065,1071 p->nextp = activearglist; activearglist = p; ! return (q); } oldp = p; --- 1070,1076 ----- p->nextp = activearglist; activearglist = p; ! return ((Addrp) cpexpr(q)); } oldp = p; *************** *** 1074,1080 q = autovar(1, type, lengp); activearglist = mkchain(q, activearglist); ! return (q); } ^L /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */ --- 1079,1085 ----- q = autovar(1, type, lengp); activearglist = mkchain(q, activearglist); ! return ((Addrp) cpexpr(q)); } ^L /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */ ------------------------------------------------------------------------ The other change is to remove the remains of the old fix in putcall() in putpcc.c: ------------------------------------------------------------------------ *** /tmp/,RCSt1005497 Tue Apr 17 13:58:59 1984 --- putpcc.c Mon Apr 16 10:44:46 1984 *************** *** 1392,1398 t = mkargtemp(qtype = q->headblock.vtype, q->headblock.vleng); putassign( cpexpr(t), q ); ! putaddr( cpexpr(t), NO ); putcomma(1, qtype, YES); } } --- 1396,1402 ----- t = mkargtemp(qtype = q->headblock.vtype, q->headblock.vleng); putassign( cpexpr(t), q ); ! putaddr(t, NO); putcomma(1, qtype, YES); } } ------------------------------------------------------------------------ Sorry about this... Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn From rochester!ritcv!ccivax!crp Wed Apr 18 09:40:39 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site ccivax.UUCP Path: seismo!rochester!ritcv!ccivax!crp From: crp@ccivax.UUCP (Chuck Privitera) Newsgroups: net.bugs.4bsd Subject: Re: Re: i = i * f vs. i *= f Message-ID: <114@ccivax.UUCP> Date: 18 Apr 84 14:40:39 GMT Date-Received: 18 Apr 84 17:52:14 GMT Organization: CCI Telephony Systems Group, Roch, NY Lines: 80 Status: O The bug was reported (and fixed) back in January by randvax!edhall. I have installed the fix here and have not had any problems since. The fix follows: >From ritcv!rochester!seismo!hao!hplabs!sdcrdcf!randvax!edhall Wed Jan 11 03:13:26 1984 Subject: integer op= floating evaluated incorrectly by C compiler Newsgroups: net.bugs.4bsd,net.bugs.usg ------------------------------------ This bug may affect all pre-5.0USG C compilers, and perhaps earlier 5.0USG compilers as well. The below fix only works for PCC-derived compilers (such as the BSD VAX C compiler). Index: usr.lib/ccom 4.2BSD 4.1BSD 3.0USG Description: When assignement operators such as *= are used with an integer Left-Hand Side and a floating-point expression on the Right- Hand Side, results are incorrect. For example: int i = 6; i *= .5; leaves a value of 0 in i, rather than 3. The +=, -=, and /= operators are similarly affected. Caused by: Conversion of RHS of assignment to type of LHS before application of the operator. Fixed by: The fix is in two parts. First, the automatic forcing of type conversion to the LHS of an assignment op must be shut off in appropriate circumstances. This requires a change to tymatch() in mip/trees.c: 1031c1031,1035 < if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu ); --- > if( o==CAST || (t != t2 > && ( (dope[o]&(FLOFLG|ASGOPFLG)) != (FLOFLG|ASGOPFLG) > || t != INT || (t2 != DOUBLE && t2 != FLOAT) )) ) { > p->in.right = makety( p->in.right, tu, 0, (int)tu ); > } This causes certain assignment ops (+=, -=, *=, /=, i.e. the ones appropriate in floating-point) to remain in the parse tree without `balanced' operand types. When these get to code-generation the compiler would break unless the template table had the proper pieces added to it. Thus, in pcc/table.c: 712a713,729 > > /* begin new stuff */ > > ASG OPFLOAT, INAREG|FOREFF|FORCC, > SAREG|AWD, TWORD|TCHAR|TSHORT, > SAREG|AWD, TDOUBLE, > NAREG, RLEFT|RESCC, > " cvtZLd AL,A1\n OD2 AR,A1\n cvtdZL A1,AL\n", > > ASG OPFLOAT, INAREG|FOREFF|FORCC, > SAREG|AWD, TWORD|TCHAR|TSHORT, > SAREG|AWD, TFLOAT, > NAREG, RLEFT|RESCC, > " cvtZLf AL,A1\n OF2 AR,A1\n cvtfZL A1,AL\n", > > /* end new stuff */ > -Ed Hall Rand Corporation Santa Monica, CA decvax!randvax!edhall (UUCP) edhall@rand-unix (ARPA) There are plenty of parenthesis to miss there. Be careful! Chuck From harpo!ulysses!allegra!don Wed Apr 18 18:56:54 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site allegra.UUCP Path: seismo!harpo!ulysses!allegra!don From: don@allegra.UUCP (D. Mitchell) Newsgroups: net.math,net.unix-wizards Subject: Bug fix for 4.2bsd random.c Message-ID: <2425@allegra.UUCP> Date: 18 Apr 84 23:56:54 GMT Date-Received: 19 Apr 84 02:24:11 GMT Organization: AT&T Bell Laboratories, Murray Hill Lines: 74 Status: O 1,348c /* * Additive Random Number Generator (see: Knuth 3.2.2) * D. P. Mitchell 84/04/16. */ #define LENGTH 97 #define TAP 12 #define MANTISSA 56 static long y[LENGTH], *tap = &y[0], *feedback = &y[LENGTH - TAP]; static double fy[LENGTH], *ftap = &fy[0], *ffeedback = &fy[LENGTH - TAP]; static unsigned long x = 0xc0393e8d; random() { if (--tap < y) { if (x) /* effect of srandom might be delayed */ setup(); tap += LENGTH; } if (--feedback < y) feedback += LENGTH; return (*feedback += *tap) >> 1 & 0x7fffffff; } double frandom() { double sum; if (--ftap < fy) { if (x) /* fy cannot be preset portably! */ setup(); ftap += LENGTH; } if (--ffeedback < fy) ffeedback += LENGTH; sum = *ftap + *ffeedback; if (sum >= 1.0) { sum = *ftap - 0.5; /* must not overflow! */ sum += *ffeedback - 0.5; } *ffeedback = sum; return sum; } srandom(seed) long seed; { x = seed; } static setup() { long mask; double divisor; int i; for (i = 0; i < LENGTH; i++) { x = 177988*x*x + 505360173*x + 907633385; y[i] = x; } mask = 0x7fffffff >> (63 - MANTISSA); divisor = (double)mask + 1.0; for (i = 0; i < LENGTH; i++) { x = 177988*x*x + 505360173*x + 907633385; fy[i] = (double)x / 4294967296.0; x = 177988*x*x + 505360173*x + 907633385; fy[i] = ((double)(x & mask) + fy[i]) / divisor; } x = 0; } . From hao!hplabs!tektronix!teklds!azure!scottha Tue Apr 17 17:48:42 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 (Tek) 9/26/83; site azure.UUCP Path: seismo!hao!hplabs!tektronix!teklds!azure!scottha From: scottha@azure.UUCP (Scott Hankerson) Newsgroups: net.bugs.4bsd Subject: using :r in adb Message-ID: <2708@azure.UUCP> Date: 17 Apr 84 22:48:42 GMT Date-Received: 19 Apr 84 02:56:31 GMT Organization: Tektronix, Beaverton OR Lines: 70 Status: O Description: 4.2 Adb looses the first character of some of the arguments given to the :r (run) command. This also affects any attempts to redirect input/output from the program. Repeat-By: % adb /bin/echo - :r this is a test [adb responds with] this s test :r this is a test >file [adb responds with] this s test file Fix: While parsing the argument list given to the :r command, adb removes the white space between the arguments. The way it does this is to read a character and if it's a white space character, read again until it finds a character that isn't a white space. Since adb remembers the last character read this should work fine. The problem is that it skips the white space twice in a row, thereby loosing the first character of the arguments. The fix is to move the first attempt to skip white space to before the loop which parses the arguments. One thing to note is that it now does support ":r arg arg>file" without a white space before the '>'. Now after that miserable explanation of the fix is the diff which is all you really care about anyway (right?). *** runpcs.c.new Mon Apr 16 17:14:00 1984 --- runpcs.c.old Mon Apr 16 17:03:18 1984 *************** *** 169,176 extern STRING environ; ap=argl; p=args; *ap++=symfil; ! IF rdc()!=EOR THEN ! REP *ap = p; /* * First thing is to look for direction characters --- 169,175 ----- extern STRING environ; ap=argl; p=args; *ap++=symfil; ! REP IF rdc()==EOR THEN break; FI *ap = p; /* * First thing is to look for direction characters *************** *** 208,214 WHILE lastc==SP ORF lastc==TB DO readchar(); OD PER lastc!=EOR DONE - FI *ap++=0; exect(symfil, argl, environ); perror(symfil); --- 207,212 ----- WHILE lastc==SP ORF lastc==TB DO readchar(); OD PER lastc!=EOR DONE *ap++=0; exect(symfil, argl, environ); perror(symfil); From hao!hplabs!tektronix!teklds!azure!scottha Tue Apr 17 18:06:15 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 (Tek) 9/26/83; site azure.UUCP Path: seismo!hao!hplabs!tektronix!teklds!azure!scottha From: scottha@azure.UUCP (Scott Hankerson) Newsgroups: net.bugs.4bsd Subject: using :r in adb (I forgot something) Message-ID: <2709@azure.UUCP> Date: 17 Apr 84 23:06:15 GMT Date-Received: 19 Apr 84 02:56:45 GMT Organization: Tektronix, Beaverton OR Lines: 4 Status: O When I posted my article on adb I forgot to explicitly state the name of the file that I changed. Well the file is: /usr/src/bin/adb/runpcs.c. Sorry about that (please forgive me, I didn't mean to do it . . . really!) From harpo!decvax!decwrl!mogul@Coyote Thu Apr 19 09:08:41 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site decwrl.UUCP Path: seismo!harpo!decvax!decwrl!mogul@Coyote From: mogul@Coyote (Jeff Mogul) Newsgroups: net.bugs.4bsd Subject: arguments to adb :r command are damaged (4.[12]BSD) Message-ID: <7215@decwrl.UUCP> Date: 19 Apr 84 14:08:41 GMT Date-Received: 19 Apr 84 22:40:21 GMT Organization: DEC Western Research Lab, Los Altos, CA Lines: 40 Status: O Description: Arguments after the first supplied to the :r command of ADB have their first character dropped. (Original bug report by cmcl2!rna!dan, 30 Jan 84.) Repeat-By: % adb /bin/echo :r abc def ghi should print: abc def ghi actually prints: abc ef hi Fix: The bug is in doexec() in runpcs.c. The body of the major loop is: throws away spaces copy an argument throws away spaces the problem being that the two different sets of code for throwing away spaces are incompatible in such a way as to discard one extra character each time. My fix is to move some code out of the loop; by turning the do loop into a while loop one could get rid of a redundant test but I didn't bother. The same bug seems to lurk in the 4.1BSD version of adb; probably the same fix would work. *** runpcs.c.old Thu Aug 11 20:06:55 1983 --- runpcs.c Thu Apr 19 01:55:10 1984 *************** *** 171,173 *ap++=symfil; ! REP IF rdc()==EOR THEN break; FI *ap = p; --- 171,174 ----- *ap++=symfil; ! rdc(); ! REP IF lastc==EOR THEN break; FI *ap = p; From harpo!ulysses!allegra!jpl Mon Apr 23 14:03:16 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site allegra.UUCP Path: seismo!harpo!ulysses!allegra!jpl From: jpl@allegra.UUCP (John P. Linderman) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: minor flaw in 4.2 login/ac/wtmp Message-ID: <2440@allegra.UUCP> Date: 23 Apr 84 19:03:16 GMT Date-Received: 23 Apr 84 20:29:44 GMT Organization: AT&T Bell Laboratories, Murray Hill Lines: 52 Status: O Both /etc/ac and /usr/ucb/last assume that /usr/adm/wtmp is an array of utmp structures. So does /bin/login, but if the assumption becomes invalid, /bin/login preserves rather than corrects the error. Repeat by: cd /usr/adm mv wtmp oldwtmp echo "Garbage" > wtmp # You can also invalidate the assumption by running the /usr file system # out of space, although some users might take a dim view of this. # Both `last' and `ac' now report garbage, and will continue reporting # garbage until wtmp is reinitialized. Fix: If /bin/login insists on writing at offsets that are multiples of sizeof(struct utmp), improper initialization of /usr/adm/wtmp or write errors on that file will not spoil all future login accounting. There follows a diff of a simple and not outrageously inefficient fix to /usr/src/bin/login.c that will correct "alignment" errors. *** login.c --- nlogin.c *************** *** 93,96 char *ttyn; int ldisc = 0, zero = 0; signal(SIGALRM, timedout); --- 93,97 ----- char *ttyn; int ldisc = 0, zero = 0; + struct stat wtstat; signal(SIGALRM, timedout); *************** *** 251,255 } if (t > 0 && (f = open("/usr/adm/wtmp", 1)) >= 0) { ! lseek(f, 0L, 2); write(f, (char *)&utmp, sizeof(utmp)); close(f); --- 252,257 ----- } if (t > 0 && (f = open("/usr/adm/wtmp", 1)) >= 0) { ! fstat(f, &wtstat); ! lseek(f, wtstat.st_size - (wtstat.st_size % sizeof(utmp)), 0); write(f, (char *)&utmp, sizeof(utmp)); close(f); John P. Linderman Department of Brokeley 4.2 Studies allegra!jpl From hao!hplabs!sri-unix!jromine@Uci-750a.ARPA Fri Apr 20 00:51:48 1984 Relay-Version: version B 2.10.2 alpha 3/24/83; site seismo.UUCP Path: seismo!hao!hplabs!sri-unix!jromine@Uci-750a.ARPA From: jromine@Uci-750a.ARPA Newsgroups: net.unix-wizards Subject: routed sets flag bits incorrectly Message-ID: <12538@sri-arpa.UUCP> Date: 20 Apr 84 05:51:48 GMT Date-Received: 23 Apr 84 23:45:41 GMT Lines: 31 Status: O From: John Romine Description: Routed sets its internal flags wrong for interfaces. The flags 0x1 to 0x10 are the same as the kernel flags, but the other flag bits are never masked out. Repeat-By: Set the 'trailers', and '-arp' configuration flags for a hardware interface with /etc/ifconfig, then start routed. routed will get confused and delete the routing entry for that interface. Fix: Mask out the flag bits which are not the same as the kernel flags bits. (i'm not certain of the line numbers.) *** bk_startup.c Wed May 25 17:51:40 1983 --- startup.c Tue Apr 17 07:16:05 1984 *************** *** 103,107 strcpy(ifp->int_name, name); ifp->int_addr = ifs.if_addr; ! ifp->int_flags = ifs.if_flags | IFF_INTERFACE; /* this works because broadaddr overlaps dstaddr */ ifp->int_broadaddr = ifs.if_broadaddr; --- 103,107 ----- strcpy(ifp->int_name, name); ifp->int_addr = ifs.if_addr; ! ifp->int_flags = (ifs.if_flags & 0x1f)| IFF_INTERFACE; /* this works because broadaddr overlaps dstaddr */ ifp->int_broadaddr = ifs.if_broadaddr; *************** From harpo!ulysses!mhuxl!ihnp4!zehntel!hplabs!oliveb!tymix!feldman Wed Apr 25 12:49:43 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site tymix.UUCP Path: seismo!harpo!ulysses!mhuxl!ihnp4!zehntel!hplabs!oliveb!tymix!feldman From: feldman@tymix.UUCP (Steve Feldman) Newsgroups: net.bugs.4bsd Subject: Watchdog timer bug in 4.2bsd lp driver Message-ID: <225@tymix.UUCP> Date: 25 Apr 84 17:49:43 GMT Date-Received: 26 Apr 84 12:35:37 GMT Organization: Tymshare Inc., Cupertino CA Lines: 22 Status: O Index: sys/vaxuba/lp.c 4.2BSD Description: If the timer interrupt goes off and there has been no activity in the last few seconds, the timer routine will stop sending if the device has been closed, even if characters still remain in the output buffer. This can be a problem on slow devices, such as our laser printer. Repeat-By: Get yourself a slow laser printer, and print a lot of small things. Sometimes the last page of a job won't appear until the next one starts up. Fix: In /sys/vaxuba/lp.c in the routine lptout, change the line: if ((sc->sc_state&OPEN) == 0) { to read: if ((sc->sc_state&OPEN) == 0 && sc->sc_outq.c_cc == 0) { This will only allow it to shut down if the output queue is empty. Steve Feldman Tymshare ucbvax!hplabs!oliveb!tymix!feldman From unix-wizards-request@BRL-TGR.ARPA Sat Apr 28 17:57:16 1984 Received: from BRL-TGR (brl-tgr.arpa) by seismo.ARPA ; Sat, 28 Apr 84 17:57:09 EST Received: From brl-vgr.arpa.ARPA by BRL-TGR via smtp; 28 Apr 84 17:13 EST Received: from mit-bold.arpa by BRL-VGR.ARPA id a010607; 28 Apr 84 17:06 EST Received: by mit-bold.ARPA (4.12/4.7) id AA00896; Sat, 28 Apr 84 17:06:35 est Date: Sat, 28 Apr 84 17:06:35 est From: "Robert W. Scheifler" Message-Id: <8404282206.AA00896@mit-bold.ARPA> Subject: problems with BPT/TRACE traps Index: /sys/vax/trap.c 4.2BSD Index: /sys/vax/machdep.c 4.2BSD Apparently-To: unix-wizards@brl-vgr Status: RO Description: We have been developing an in-process debugger, using the VAX BPT instruction and the trace bit mechanism, with the signals handled in the same (user) process. This works fine by itself. We are also using keyboard generated SIGQUITs to interrupt the program and get the debugger's attention, so the user can poke around and then ultimately continue execution. This also works fine by itself. However, combining the two mechanisms got us into trouble. The basic problem is that SIGTRAP needs to be handled synchronously, but SIGQUIT (and others) can preempt it. Signals are not handled on a first-come-first server basis, but on a "find-first-set" basis, which means lowest signal number first. So the scenario is this. A BPT trap takes place, and a psignal(SIGTRAP) takes place in trap(). Just then the user types the quit character, and you eventually get to ttyinput(), which does a gsignal(SIGQUIT). Now we continue on inside trap(), doing "if (ISSIG(p)) psig()", and the signal chosen is SIGQUIT, surprise. So we hack the stack for SIGQUIT, and go off to the first instruction of the signal trampoline code. However, the psignal() back when did an aston(), so at this point we take the AST, and we are back in trap() doing another "if (ISSIG(p)) psig()", and so we hack the stack for SIGTRAP, only now, lo and behold, the PC is no longer at the BPT instruction, but at the start of the signal trampoline code instead, which is mighty confusing. But, you say, the solution is of course to mask out SIGTRAP inside of SIGQUIT. But, I say, there are two problems with this. The first, which I can live with, is that then the SIGQUIT handler can't be debugged. The bigger problem is that it still doesn't work. There is an "extraneous" REI in the signal trampoline code (that I have complained about before for a different reason). This REI is executed on the way out of a handler, and is a one instruction bridge back to user code that gets executed WITHOUT the signal mask defined by the handler. So even if you mask SIGTRAP inside SIGQUIT, you simply change the PC at the time of the SIGTRAP to be at the REI rather than the CALLS in the trampoline code. Our solution to this problem was to notice that, if the SIGTRAP handler does nothing, the BPT instruction will be executed again and we will get another trap. So, we don't mask SIGTRAP inside SIGQUIT, and in the SIGTRAP handler we check the PC, and if it's in the trampoline code, we just return and let the BPT execute again. Having taken a BPT, we need to reinstall the actual instruction, execute it using the T-bit, and then reinsert the BPT instruction. Once again, the PC you get in the SIGTRAP handler can be bogus. Just returning won't work, however, because the T-bit has been cleared and you won't get another trap. Fortunately, the debugger can know it is expecting a T-bit trap, and can save away the correct PC, and ignore the PC reported by the kernel. Actually, as it turns out, you CAN get multiple SIGTRAPs from setting the T-bit. I don't think this was intended. Fix is provided below. Repeat-By: See above. Fix: In trap(), in trap.c, change case T_TRCTRAP+USER: /* trace trap */ locr0[PS] &= PSL_T; to case T_TRCTRAP+USER: /* trace trap */ locr0[PS] &= ~(PSL_T|PSL_TP); In sendsig(), in machdep.c, change: regs[PS] &= ~(PSL_CM|PSL_FPD); to regs[PS] &= ~(PSL_CM|PSL_FPD|PSL_T|PSL_TP); I didn't bother to figure out if both changes are necessary, but they can't hurt. From harpo!ihnp4!we13!burl!clyde!akgua!mcnc!decvax!decwrl!sun!dg Sat Apr 28 16:55:36 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83 SMI; site sun.uucp Path: seismo!harpo!ihnp4!we13!burl!clyde!akgua!mcnc!decvax!decwrl!sun!dg From: dg@sun.uucp (David Goldberg) Newsgroups: net.bugs.4bsd Subject: talk(1)ing between suns and vaxes Message-ID: <995@sun.uucp> Date: 28 Apr 84 21:55:36 GMT Date-Received: 30 Apr 84 01:02:15 GMT Organization: Sun Microsystems, Inc. Lines: 212 Status: O This is ugly, but it works, and is upward compatible with the current talk. Subject: Talk doesn't work betwen sun's and vaxes Index: ucb/talk 4.2BSD Description: The Talk(1) command does not work between sun's and vaxes. Repeat-By: Try talk name@vax-machine from a sun, or vice-versa. Fix: There are changes to look_up.c and talkd.c Here is a diff -c: *** talkd.c Wed May 11 20:28:19 1983 --- /tmp/talkd.c Sat Apr 28 22:12:00 1984 *************** *** 30,35 int debug = 0; main(argc) int argc; { --- 30,37 ----- int debug = 0; + CTL_MSG swapmsg(); + main(argc) int argc; { *************** *** 104,109 if (debug) printf("Request received : \n"); if (debug) print_request(&request); process_request(&request, &response); if (debug) printf("Response sent : \n"); --- 106,112 ----- if (debug) printf("Request received : \n"); if (debug) print_request(&request); + request = swapmsg(request); process_request(&request, &response); if (debug) printf("Response sent : \n"); *************** *** 190,193 } } while (val != pid); } } --- 193,222 ----- } } while (val != pid); } + } + + #define swapshort(a) (((a << 8) | ((unsigned short) a >> 8)) & 0xffff) + #define swaplong(a) ((swapshort(a) << 16) | (swapshort(((unsigned)a >> 16)))) + + /* + * heuristic to detect if need to swap bytes + */ + + CTL_MSG + swapmsg(req) + CTL_MSG req; + { + CTL_MSG swapreq; + + if (req.ctl_addr.sin_family == swapshort(AF_INET)) { + swapreq = req; + swapreq.id_num = swaplong(req.id_num); + swapreq.pid = swaplong(req.pid); + swapreq.addr.sin_family = swapshort(req.addr.sin_family); + swapreq.ctl_addr.sin_family = + swapshort(req.ctl_addr.sin_family); + return swapreq; + } + else + return req; } *** look_up.c Wed May 11 20:28:27 1983 --- /tmp/look_up.c Sat Apr 28 22:12:06 1984 *************** *** 4,9 /* see if the local daemon has a invitation for us */ check_local() { CTL_RESPONSE response; --- 4,11 ----- /* see if the local daemon has a invitation for us */ + CTL_RESPONSE swapresponse(); + check_local() { CTL_RESPONSE response; *************** *** 26,31 current_state = "Waiting to connect with caller"; while (connect(sockt, &response.addr, sizeof(response.addr)) != 0) { if (errno == ECONNREFUSED) { --- 28,34 ----- current_state = "Waiting to connect with caller"; + response = swapresponse(response); while (connect(sockt, &response.addr, sizeof(response.addr)) != 0) { if (errno == ECONNREFUSED) { *************** *** 76,78 return(0); } } --- 79,152 ----- return(0); } } + + /* + * heuristic to detect if need to reshuffle CTL_RESPONSE structure + */ + + #define swapshort(a) (((a << 8) | ((unsigned short) a >> 8)) & 0xffff) + #define swaplong(a) ((swapshort(a) << 16) | (swapshort(((unsigned)a >> 16)))) + + #ifdef sun + struct ctl_response_vax { + char type; + char answer; + short junk; + int id_num; + struct sockaddr_in addr; + }; + + CTL_RESPONSE + swapresponse(rsp) + CTL_RESPONSE rsp; + { + struct ctl_response_vax swaprsp; + + if (rsp.addr.sin_family != AF_INET) { + bcopy(&rsp, &swaprsp, sizeof(CTL_RESPONSE)); + swaprsp.addr.sin_family = swapshort(swaprsp.addr.sin_family); + if (swaprsp.addr.sin_family == AF_INET) { + rsp.addr = swaprsp.addr; + rsp.type = swaprsp.type; + rsp.answer = swaprsp.answer; + rsp.id_num = swaplong(swaprsp.id_num); + } + } + return rsp; + } + #endif + + #ifdef vax + struct ctl_response_sun { + char type; + char answer; + unsigned short id_num2; + unsigned short id_num1; + short sin_family; + short sin_port; + short sin_addr2; + short sin_addr1; + }; + + CTL_RESPONSE + swapresponse(rsp) + CTL_RESPONSE rsp; + { + struct ctl_response_sun swaprsp; + + if (rsp.addr.sin_family != AF_INET) { + bcopy(&rsp, &swaprsp, sizeof(struct ctl_response_sun)); + if (swaprsp.sin_family == swapshort(AF_INET)) { + rsp.type = swaprsp.type; + rsp.answer = swaprsp.answer; + rsp.id_num = swapshort(swaprsp.id_num1) + | (swapshort(swaprsp.id_num2) << 16); + rsp.addr.sin_family = swapshort(swaprsp.sin_family); rsp.addr.sin_port = swaprsp.sin_port; + rsp.addr.sin_addr.s_addr = + swaprsp.sin_addr2 | (swaprsp.sin_addr1 << 16); + } + } + return rsp; + } + #endif From harpo!ulysses!mhuxl!houxm!hogpc!houti!ariel!vax135!floyd!cmcl2!lanl-a!unm-cvax!unmvax!lee Mon Apr 30 04:30:31 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site unmvax.UUCP Path: seismo!harpo!ulysses!mhuxl!houxm!hogpc!houti!ariel!vax135!floyd!cmcl2!lanl-a!unm-cvax!unmvax!lee From: lee@unmvax.UUCP Newsgroups: net.bugs.4bsd Subject: 4.2 BSD occasionally trashes files Message-ID: <314@unmvax.UUCP> Date: 30 Apr 84 08:30:31 GMT Date-Received: 1 May 84 00:05:17 GMT Organization: Univ. of New Mexico, Albuquerque Lines: 42 Status: O Subject: 4.2BSD occasionally trashes files Newsgroups: net.bugs.4bsd Subject: UNIX 4.2 BSD trashes files Index: 4.2BSD kernel Description: Occasionally files will get trashed. This was reported earlier but the only "fix" was a stop-gap measure which controlled the bug by issuing a panic. These mods were made to iput() and closef(). Repeat-By: Hard to, it looks to be a race condition. Fix: The routine irele() would lock an inode without first checking to see if such was already locked. Below is a diff of /sys/sys/ufs_inode.c. I suggest you leave in those panics for awhile just to make sure.... RCS file: RCS/ufs_inode.c,v retrieving revision 1.2 diff -r1.2 ufs_inode.c 2c2 < * $Header: ufs_inode.c,v 1.2 84/02/12 22:47:45 root Exp $ --- > * $Header: ufs_inode.c,v 1.3 84/04/30 02:12:19 root Exp $ 3a4,11 > * Revision 1.3 84/04/30 02:12:19 root > * Think I found the bug with trashed files that the stop gap measure > * (the panic in iput() and closef()) controlled. In irele() it locks > * the inode but does not check to see if it has already been locked. > * I am leaving in the stop-gap panics for now but we should know > * for sure in a month. > * --Lee > * 252c260 < ip->i_flag |= ILOCKED; --- > ilock(ip); -- --Lee (Ward) {ucbvax,convex,gatech,pur-ee}!unmvax!lee From ut-sally!mordor!jdb Tue May 8 14:00:29 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site mordor.UUCP Path: seismo!ut-sally!mordor!jdb From: jdb@mordor.UUCP Newsgroups: net.unix-wizards Subject: 4.2BSD VAX: data/stack segments > 6Mb Message-ID: <3077@mordor.UUCP> Date: 8 May 84 18:00:29 GMT Date-Received: 8 May 84 18:31:11 GMT Organization: S-1 Project, LLNL Lines: 60 Status: O Here at the S-1 Project, LLNL, we are currently running 4.1BSD on one of our VAXes and 4.2BSD on the other. We have a need to run programs with large data and stack segments (> 6Mb). This was no problem in 4.1BSD; I changed "h/dmap.h" and "h/vmparam.h" (as described in the manuals that came with 4.1), recompiled, and it worked. 4.2 is a different matter. I've made it work here, and thought that the experience might be of interest to others. As in 4.1BSD, the constants MAXTSIZ, MAXDSIZ, and MAXSSIZ control the maximum limits that may be set with the rlimit() system call. These constants are now located in "vax/vmparam.h". It seems to be safe to make these "too big" (i.e. larger than the kernel can actually allocate due to the size of the dmap [see below]); the kernel simply returns ENOMEM on a brk() call if it can't map any more memory. (In 4.1BSD if you tried to brk() more memory than it could map, you were rewarded with a panic.) I made MAXDSIZ and MAXSSIZ 30 megabytes. The kernel manages the secondary storage for a virtual address space by allocating pieces of increasing size in the swap area. The mapping is described by "struct dmap" records in the user structure. The first block of each piece is recorded in the array "dm_map". There are NDMAP entries in this array; thus it can keep track of NDMAP fragments. (The first fragment is "dmmin" (32) kilobytes long; each successive fragment is twice as large as the preceeding one until they are "dmmax" (512) kilobytes long. The remainder are all "dmmax" kilobytes. Thus, with NDMAP=16 [as distributed] the structure can map 16+32+64+128+256+512*11 = 6.1Mbytes.) NDMAP and "struct dmap" are defined in "h/dmap.h"; while the initial values of "dmmin" and "dmmax" are defined in "vax/autoconf.c". I increased NDMAP to 64. Unfortunately, increasing NDMAP increases the size of the user structure. Our user structure increased from 1904 to 2160 bytes. This is significant because the user structure and the kernel stack share an area which is UPAGES (512-byte) pages long. The larger user structure now occupies another page, resulting in insufficient space for the kernel stack (one intervening page is used by setredzone() to detect kernel stack overflow). The size of the user+stack area is UPAGES, defined in "vax/param.h". UPAGES must be a multiple of CLSIZE ["vax/vmparam.h"], so I increased it to 10. It is necessary to install the bug fix to "vax/locore.s" described by RWS@MIT-XX in <13280@sri-unix>. This parameterizes the code so that it does not implicitly assume that UPAGES is 8. The system can now be regenerated. Note that "make depend" doesn't catch include files which are included by other include files (e.g. "../vax/param.h" which is included by "../h/param.h"), so it won't properly regenerate "locore.c". It is necessary to delete "assym.s" so that the makefile will regenerate it (with the new definition of UPAGES). Finally (groan), programs which read "/dev/mem" and which include will have to be recompiled. This includes things like "ps", "pstat", "w", "adb", "sdb", "dbx", ... -- John Bruner (S-1 Project, Lawrence Livermore National Laboratory) MILNET: jdb@mordor.ARPA [jdb@s1-c] (415) 422-0758 UUCP: ...!ucbvax!dual!mordor!jdb ...!decvax!decwrl!mordor!jdb From unix-wizards-request@BRL-TGR.ARPA Wed May 9 13:29:23 1984 Received: from BRL-TGR (brl-tgr.arpa) by seismo.ARPA; Wed, 9 May 84 13:21:02 EDT Message-Id: <8405091721.AA07344@seismo.ARPA> Received: From brl.arpa.ARPA by BRL-TGR via smtp; 9 May 84 12:17 EDT Received: From bbn-labs-b.arpa.ARPA by BRL-AOS via smtp; 9 May 84 10:51 EDT Date: Wed, 9 May 84 10:39:48 EDT From: Bob Walsh Subject: Berkeley 4.2BSD UDP checksumming To: unix-wizards@Brl-Aos.ARPA Status: RO We've noticed that talk doesn't work between a machine that runs Berkeley 4.2 UDP and one that doesn't. The reason was that the Berkeley UDP was not properly checksumming packets on output. The fixes to netinet/udp_usrreq.c follow. By default, UDP checksumming is turned on. Packets with checksum 0 are not checksummed, per spec. The IP header length is put in net order for checksumming on output. On input, the header length had been correctly put in net order for checksumming so this last fix corrects an internal inconsistency and brings it into spec. 1 bbnlb>% *** udp_usrreq.c Fri May 4 14:36:34 1984 --- udp_usrreq.old Fri Jul 29 10:14:49 1983 *************** *** 31,37 udb.inp_next = udb.inp_prev = &udb; } ! int udpcksum = 1; struct sockaddr_in udp_in = { AF_INET }; udp_input(m0) --- 31,37 ----- udb.inp_next = udb.inp_prev = &udb; } ! int udpcksum; struct sockaddr_in udp_in = { AF_INET }; udp_input(m0) *************** *** 72,78 /* * Checksum extended UDP header and data. */ ! if (udpcksum && ui->ui_sum) { ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_len = htons((u_short)len); --- 72,78 ----- /* * Checksum extended UDP header and data. */ ! if (udpcksum) { ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_len = htons((u_short)len); *************** *** 185,190 ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_pr = IPPROTO_UDP; ui->ui_src = inp->inp_laddr; ui->ui_dst = inp->inp_faddr; ui->ui_sport = inp->inp_lport; --- 185,191 ----- ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_pr = IPPROTO_UDP; + ui->ui_len = len + sizeof (struct udphdr); ui->ui_src = inp->inp_laddr; ui->ui_dst = inp->inp_faddr; ui->ui_sport = inp->inp_lport; *************** *** 189,195 ui->ui_dst = inp->inp_faddr; ui->ui_sport = inp->inp_lport; ui->ui_dport = inp->inp_fport; ! ui->ui_ulen = ui->ui_len = htons(len + sizeof (struct udphdr)); /* * Stuff checksum and output datagram. --- 190,196 ----- ui->ui_dst = inp->inp_faddr; ui->ui_sport = inp->inp_lport; ui->ui_dport = inp->inp_fport; ! ui->ui_ulen = htons((u_short)ui->ui_len); /* * Stuff checksum and output datagram. bob walsh From unix-wizards-request@BRL-TGR.ARPA Fri May 11 10:25:24 1984 Received: from BRL-TGR (brl-tgr.arpa) by seismo.ARPA; Fri, 11 May 84 10:25:15 EDT Message-Id: <8405111425.AA14084@seismo.ARPA> Received: From brl.arpa.ARPA by BRL-TGR via smtp; 11 May 84 9:30 EDT Received: From bbn-labs-b.arpa.ARPA by BRL-AOS via smtp; 11 May 84 9:13 EDT Date: Fri, 11 May 84 9:03:24 EDT From: Bob Walsh Subject: 4.2BSD function m_adj To: unix-wizards@Brl-Aos.ARPA Status: RO This funtions does not act properly if it is passed an mbuf chain like: mbuf ------> mbufs of data +--------+ | tcp/ip | | header | | m_len=0| +--------+ and it is asked to trim some number of bytes from the end of the chain. To correct the code, *** uipc_mbuf.c Fri May 11 08:04:03 1984 --- uipc_mbuf.old Fri May 11 07:55:07 1984 *************** *** 375,383 struct mbuf *mp; register int len; { - #ifdef BUGFIXES - register struct mbuf *m; - #else register struct mbuf *m, *n; #endif --- 375,380 ----- struct mbuf *mp; register int len; { register struct mbuf *m, *n; if ((m = mp) == NULL) *************** *** 379,385 register struct mbuf *m; #else register struct mbuf *m, *n; - #endif if ((m = mp) == NULL) return; --- 376,381 ----- register int len; { register struct mbuf *m, *n; if ((m = mp) == NULL) return; *************** *** 396,432 } } } else { - #ifdef BUGFIXES - register struct mbuf *last, *next; - - /* step one, reverse mbuf chain */ - /* it is at least one long */ - last = 0; - len = (-len); - do { - next = m->m_next; - m->m_next = last; - last = m; - m = next; - } while (m); - - /* step two, reverse list and remove bytes */ - m = last; - last = 0; - do { - next = m->m_next; - m->m_next = last; - last = m; - if (len > m->m_len){ /* shave */ - len -= m->m_len; /* shave */ - m->m_len = 0; /* shave */ - } else { /* shave */ - m->m_len -= len; /* shave */ - len = 0; /* shave */ - } - m = next; - } while (m); - #else /* a 2 pass algorithm might be better */ len = -len; while (len > 0 && m->m_len != 0) { --- 392,397 ----- } } } else { /* a 2 pass algorithm might be better */ len = -len; while (len > 0 && m->m_len != 0) { *************** *** 443,449 break; } } - #endif } } --- 408,413 ----- break; } } } } bob walsh From brl-tgr!ron Tue May 15 13:40:52 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site brl-tgr.ARPA Path: seismo!brl-tgr!ron From: ron@brl-tgr.ARPA (Ron Natalie ) Newsgroups: net.bugs.4bsd Subject: 4.2BSD as Gateway bug Message-ID: <2971@brl-tgr.ARPA> Date: 15 May 84 17:40:52 GMT Date-Received: 15 May 84 17:45:35 GMT Organization: Ballistics Research Lab Lines: 72 Status: O Subject: 4.2BSD as Gateway bug Newsgroups: net.bugs.4bsd Subject: Fragmentation bug on packet forwarding Index: sys/netinet/ip_output.c 4.2BSD Description: When the packets are being forwarded through a 4.2 BSD system a problem sometimes shows up that results in lost packets and transmission of illegally formatted internet packets. The problem occurs when a 4.2 BSD system is gatewaying from nets that have unequal Maximum Transfer Units (MTU). When a fragmented packet arriving from an outside source must be fragmented again the MORE FRAGMENTS bit is never set on the last fragment even though it may be required. When other than the last fragment of the original packet is fragmented, the MORE FRAGMENTS bit must be set to indicate that the subsequent fragments of the original packet still follow (got that?). This problem does not happen when you are not playing gateway because ip_output does not get passed already fragmented packets in that situation. Example: Host X sends ip packet A to BSD-HOST in two fragments, A1 and A2. BSD-HOST must then fragment A1 into A1a and A1b. A1b should have MF set because fragment A2 still follows. Repeat-By: Set the MTU on you host to some small number, and then try to forward already fragmented packets through it. Fix: Set the bit on the last fragment to what it was on the packet before fragmenting began. Below is the fragmentation code from ip_ouptut(): /* * Discard IP header from logical mbuf for m_copy's sake. * Loop through length of segment, make a copy of each * part and output. */ m->m_len -= sizeof (struct ip); m->m_off += sizeof (struct ip); for (off = 0; off < ip->ip_len-hlen; off += len) { struct mbuf *mh = m_get(M_DONTWAIT, MT_HEADER); struct ip *mhip; if (mh == 0) { error = ENOBUFS; goto bad; } mh->m_off = MMAXOFF - hlen; mhip = mtod(mh, struct ip *); *mhip = *ip; if (hlen > sizeof (struct ip)) { int olen = ip_optcopy(ip, mhip, off); mh->m_len = sizeof (struct ip) + olen; } else mh->m_len = sizeof (struct ip); mhip->ip_off = off >> 3; /*******************************************************\ |* *| |* A D D T H I S L I N E *| |* *| |* If the packet we're fragmenting has fragments from *| |* other systems, propagate the MORE_FRAGMENTS flag. *| \*******************************************************/ if(ip->ip_off & IP_MF) mhip->ip_off |= IP_MF; if (off + len >= ip->ip_len-hlen) len = mhip->ip_len = ip->ip_len - hlen - off; else { mhip->ip_len = len; mhip->ip_off |= IP_MF; } From salkind@NYU.ARPA Mon May 21 11:23:00 1984 Received: from BRL-TGR (brl-tgr.arpa) by seismo.ARPA; Mon, 21 May 84 11:22:47 EDT Received: from brl-vgr.arpa by BRL-TGR.ARPA id a001906; 22 May 84 15:34 EDT Received: from nyu-gw by BRL-VGR.ARPA id a004129; 22 May 84 15:26 EDT Received: by NYU.ARPA; Tue, 22 May 84 14:26:00 edt Date: Tue, 22 May 84 14:26:00 edt From: Lou Salkind Message-Id: <8405221826.AA18236@NYU.ARPA> To: unix-wizards@BRL-VGR.ARPA Subject: inconsistency in ufs_tables Status: RO Index: sys/sys/ufs_tables.c 4.2BSD Description: Both ufs_subr.c and ufs_tables.c are used by fsck. In ufs_subr.c, the location of the #include files depends on #ifdef KERNEL. Not so in ufs_tables.c! Repeat-By: Compile fsck. Have different header files floating around. Fix: I have changed in ufs_tables.c the line #include "../h/param.h" to read #ifdef KERNEL #include "../h/param.h" #else #include #endif The other possible change would be to eliminate the KERNEL #ifdef's in ufs_tables.c. From hao!hplabs!zehntel!ihnp4!inuxc!pur-ee!CS-Mordred!Pucc-H:acg Fri May 25 16:30:58 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site pucc-h Path: seismo!hao!hplabs!zehntel!ihnp4!inuxc!pur-ee!CS-Mordred!Pucc-H:acg From: acg@pucc-h (Schwab) Newsgroups: net.unix-wizards,net.bugs.4bsd Subject: if_uba.c routines do not handle local net hlen of 0 Message-ID: <729@pucc-h> Date: 25 May 84 20:30:58 GMT Date-Received: 28 May 84 14:49:25 GMT Organization: Purdue University Computing Center Lines: 53 Status: O Description: If a local network interface has an hlen of 0, the routines in if_ubainit() allocate spurious pages and the if_rubaget() routine will exchange the wrong page when handling a packet greater than 1024 bytes long. Repeat-By: The pcl-11 is such a device. If you raise the mtu on the device from the default 1006 to anything greater than 1024, your network will be unusable. Fix: The following diff's fix the extraneous page allocations and the problems in if_rubaget(). - Jeff Schwab ---- if_ubainit() ------ register caddr_t cp; int i, ncl; + #ifdef PUCC + ncl = clrnd(nmr + (hlen? CLSIZE: 0)) / CLSIZE; + #else PUCC ncl = clrnd(nmr + CLSIZE) / CLSIZE; + #endif PUCC if (ifu->ifu_r.ifrw_addr) + #ifdef PUCC + cp = ifu->ifu_r.ifrw_addr - (hlen? (CLBYTES - hlen): 0); + #else PUCC cp = ifu->ifu_r.ifrw_addr - (CLBYTES - hlen); + #endif PUCC else { cp = m_clalloc(2 * ncl, MPG_SPACE); if (cp == 0) return (0); + #ifdef PUCC + ifu->ifu_r.ifrw_addr = cp + (hlen? (CLBYTES - hlen): 0); + #else PUCC ifu->ifu_r.ifrw_addr = cp + CLBYTES - hlen; + #endif PUCC ifu->ifu_w.ifrw_addr = ifu->ifu_r.ifrw_addr + ncl * CLBYTES; ------- if_rubaget() ------- ppte = &Mbmap[mtocl(p)*CLSIZE]; x = btop(cp - ifu->ifu_r.ifrw_addr); ip = (int *)&ifu->ifu_r.ifrw_mr[x]; + #ifdef PUCC + if (ifu->ifu_hlen == 0) { + ip--; + } + #endif PUCC for (i = 0; i < CLSIZE; i++) { struct pte t; t = *ppte; *ppte++ = *cpte; *cpte = t; From cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!bmcg!felix!zemon Thu May 24 16:49:49 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site felix.UUCP Path: seismo!cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!bmcg!felix!zemon From: zemon@felix.UUCP Newsgroups: net.bugs.4bsd Subject: error(1) does not work unless attached to a terminal Message-ID: <280@felix.UUCP> Date: 24 May 84 20:49:49 GMT Date-Received: 26 May 84 02:31:53 GMT Organization: FileNet Corp., Costa Mesa, Ca. Lines: 70 Full-Name: Art Zemon 714-966-2344 UUCP-address: ...!{ decvax | ucbvax }!trwrb!felix!zemon Status: O Index: ucb/error/errormain.c 4.2BSD Fix ---------- Description: Error(1) will not work if it is run when not attached to a terminal. For example, error(1) will fail when run under control of at(1) or the MDQS batch(1) command. The reason is that error(1) always attempts to open /dev/tty. Error(1) exits if the open fails. It is only necessary to open /dev/tty if the -q option is given. This applies to error(1) as distributed with 4.2bsd. It probably also applies to earlier versions. The sccsid line from out version of error(1) is: *sccsid = "@(#)errormain.c 1.4 (Berkeley) 5/4/82"; Repeat-By: Execute something like this within an MDQS batch queue using the C shell: ( cc ... |& error > error-stdout ) >& error-stderr "error-stdout" should contain standard status information from error(1) and "error-stderr" should be empty. Instead, "error-stdout" will be empty and "error-stderr" will contain the message "error: Can't open /dev/tty to query the user.". Fix: RCS file: RCS/errormain.c,v retrieving revision 1.1 diff -r1.1 errormain.c 0a1,11 > /* > * $Log: errormain.c,v $ > * Revision 1.2 84/05/24 15:55:16 zemon > * Don't open /dev/tty unless -q is specified. > * This is necessary to allow running error under MDQS batch. > * If the change is not installed, the attempted open of /dev/tty > * fails when the MDQS daemon is not attached to a terminal. > * > */ > > #ifndef lint 1a13,15 > static char rcsid[] = "$Header: errormain.c,v 1.2 84/05/24 15:55:16 zemon Exp $"; > #endif > 127,131c141,148 < im_on = "/dev/tty"; < if ( (queryfile = fopen(im_on, "r")) == NULL){ < fprintf(stderr,"%s: Can't open \"%s\" to query the user.\n", < processname, im_on); < exit(9); --- > if (query) { > im_on = "/dev/tty"; > if ( (queryfile = fopen(im_on, "r")) == NULL){ > fprintf(stderr, > "%s: Can't open \"%s\" to query the user.\n", > processname, im_on); > exit(9); > } 132a150 > Submitted-by: Art Zemon FileNet Corp. ...!{ucbvax,decvax}!trwrb!felix!zemon (714)966-2344 From cmcl2!philabs!hhb!je Thu May 24 10:34:34 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site hhb.UUCP Path: seismo!cmcl2!philabs!hhb!je From: je@hhb.UUCP (Jon Eiseman) Newsgroups: net.bugs.4bsd Subject: dbx bugs Message-ID: <160@hhb.UUCP> Date: 24 May 84 14:34:34 GMT Date-Received: 26 May 84 06:27:48 GMT Organization: HHB-Softron, Mahwah, NJ Lines: 34 Status: O I found and fixed two dbx bugs (diffs are included). 1. The CALL command doesn't work when the function being called takes parameters. The procedure 'cont' was called incorrectly (no parameter). 2. The PRINT command gives the wrong result when you try to examine C unsigned long variables. The size function incorrectly calculated the size as one byte. The diffs follow for runtime.c and symbols.c diff runtime.c /usr/src/ucb/dbx 512c512 < cont(0); --- > cont(); diff symbols.c /usr/src/ucb/dbx 508d507 < #define MAXULONG 0xffffffff 528,530c527 < if (lower == 0 and upper == MAXULONG) { /* unsigned long */ < r = sizeof(long); < } else if (upper == 0 and lower > 0) { /* real */ --- > if (upper == 0 and lower > 0) { /* real */ Jon Eiseman HHB-Softron Mahwah, NJ {decvax,allegra}!philabs!hhb!je From harpo!decvax!ittvax!dcdwest!sdcsvax!bmcg!felix!zemon Fri May 25 16:09:00 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site felix.UUCP Path: seismo!harpo!decvax!ittvax!dcdwest!sdcsvax!bmcg!felix!zemon From: zemon@felix.UUCP Newsgroups: net.bugs.4bsd Subject: error(1) does not work when not attached to a terminal -- ammended Message-ID: <282@felix.UUCP> Date: 25 May 84 20:09:00 GMT Date-Received: 26 May 84 18:14:41 GMT Organization: FileNet Corp., Costa Mesa, Ca. Lines: 57 Status: O Index: ucb/error/errormain.c 4.2BSD Fix Description: Error(1) will not work if it is run when not attached to a terminal. For example, error(1) will fail when run under control of at(1) or the MDQS batch(1) command. The reason is that error(1) always attempts to open /dev/tty. Error(1) exits if the open fails. It is only necessary to open /dev/tty if the -q option is given. This applies to error(1) as distributed with 4.2bsd. It probably also applies to earlier versions. The sccsid line from out version of error(1) is: *sccsid = "@(#)errormain.c 1.4 (Berkeley) 5/4/82"; Repeat-By: Execute something like this within an MDQS batch queue using the C shell: ( cc ... |& error > error-stdout ) >& error-stderr "error-stdout" should contain standard status information from error(1) and "error-stderr" should be empty. Instead, "error-stdout" will be empty and "error-stderr" will contain the message "error: Can't open /dev/tty to query the user.". Fix: RCS file: RCS/errormain.c,v retrieving revision 1.1 diff -r1.1 errormain.c 17c39 < char *im_on; /* my tty name */ --- > char im_on[] = "/dev/tty"; /* my tty name */ 127,131c149,155 < im_on = "/dev/tty"; < if ( (queryfile = fopen(im_on, "r")) == NULL){ < fprintf(stderr,"%s: Can't open \"%s\" to query the user.\n", < processname, im_on); < exit(9); --- > if (query) { > if ( (queryfile = fopen(im_on, "r")) == NULL){ > fprintf(stderr, > "%s: Can't open \"%s\" to query the user.\n", > processname, im_on); > exit(9); > } 132a157 > Submitted-by: Art Zemon FileNet Corp. ...!{ucbvax,decvax}!trwrb!felix!zemon (714)966-2344 From cmcl2!floyd!harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Mon May 28 00:16:32 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!cmcl2!floyd!harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: Squaring a function call calls the function twice in f77 Message-ID: <147@sdchema.UUCP> Date: 28 May 84 04:16:32 GMT Date-Received: 28 May 84 14:28:39 GMT Organization: State Home for the Maturity-Impaired, San Diego Lines: 81 Status: O Subject: f(x) ** 2 produces f(x) * f(x) in f77 Index: usr.bin/f77/src/f77pass1/optim.c 4.2BSD Description: When an f77 program is compiled with the optimizer enabled, side effects of an expression are evaluated twice if that expression is squared. This was originally pointed out to me by Jerry Berkman at UC Berkeley. Repeat-By: Put the following f77 subroutine in a file fsq.f and compile it to assembly language with the optimizer turned on: ---------------------------------------------------------------- subroutine fsq( x ) real f, x x = f( x ) ** 2 return end ---------------------------------------------------------------- If the bug is present in your compiler you should see the following (although probably not so pretty): ---------------------------------------------------------------- .globl _fsq_ .set LF1,4 _fsq_: .word LWM1 subl2 $LF1,sp jmp L12 L15: pushl 4(ap) calls $1,_f_ movl r0,-4(fp) pushl 4(ap) calls $1,_f_ mulf2 -4(fp),r0 movl r0,*4(ap) ret .align 1 L12: jmp L15 ---------------------------------------------------------------- Fix: In the code for buffpower() in optim.c, the comment mentions that the routine was ripped off from putpower() in putpcc.c; unfortunately the thieves did not also steal the bug fix when it was installed in putpower()... Sigh. Here is the fix: ---------------------------------------------------------------- *** /tmp/,RCSt1009277 Mon May 28 00:02:50 1984 --- optim.c Fri May 4 21:03:06 1984 *************** *** 632,638 fatal("buffpower: bad call"); base = p->exprblock.leftp; ! if (k == 2) { expptr prod; prod = mkexpr (OPSTAR,cpexpr(base),cpexpr(base)); --- 660,666 ----- fatal("buffpower: bad call"); base = p->exprblock.leftp; ! if (k == 2 && base->tag == TADDR && ISCONST(base->addrblock.memoffset)) { expptr prod; prod = mkexpr (OPSTAR,cpexpr(base),cpexpr(base)); ---------------------------------------------------------------- Another one bites the dust, Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA From harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Thu May 31 01:16:02 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!harpo!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: Really obscure bug with CHARACTER*1 comparisons in f77 Message-ID: <150@sdchema.UUCP> Date: 31 May 84 05:16:02 GMT Date-Received: 31 May 84 18:19:13 GMT Organization: State Home for the Maturity-Impaired, San Diego Lines: 182 Status: O Subject: Really obscure bug with CHARACTER*1 comparisons in f77 Index: usr.bin/f77/src/f77pass1/putpcc.c 4.2BSD Description: Sometimes a comparison of two CHARACTER*1 values gets the wrong result. Specifically this occurs when one operand of the comparison is a CHARACTER*1 expression (a function call or a type conversion) and the other operand is any CHARACTER*1 value. This is another bug contributed by Jerry Berkman at UC Berkeley; he apparently got it from a friend. This bug is so specific that it's sheer luck that anyone ever managed to exercise it. Repeat-By: Clip out the following program (courtesy of Jerry Berkman) and compile it. ---------------------------------------------------------------- character*1 getchr,ich ich=getchr("A") if(ich.ne.getchr("A")) write(6,100) 100 format("Error in character functions") stop end character*1 function getchr(ich) character*1 ich print 8000, ich, ichar(ich) 8000 format('in getchr with ich = ',a1,' (',16r,i6.2,')') getchr=ich return end ---------------------------------------------------------------- When run it prints 'Error in character functions' (surprise!). A little poking around reveals the following gaffe in the assembly language code: ---------------------------------------------------------------- pushl $1 # 'ich=getchr("A")' pushal {0101,00} pushl $1 pushal -1(fp) calls $4,_getchr_ movb -1(fp),{ich}(r11) pushl $1 # 'if(ich.ne.getchr("A")) ...' pushal {0101,00} pushl $1 pushal -1(fp) calls $4,_getchr_ cvtbl -1(fp),r1 cmpl r0,r1 # Oops! What's in r0? Not 'ich'! jeql L15 ---------------------------------------------------------------- Fix: Odd as it may seem, this is actually a bug in pass 1 of the compiler, not the code generation pass. If we look at the 'disassembled' intermediate code, the problem is obvious (it helps to have an intermediate code 'disassembler' first -- I wrote one while hunting down this bug): ---------------------------------------------------------------- oreg (char) v.2-v.1(r11) # 'ich=getchr("A")': get 'ich' int (char * ()) _getchr_ # Postfix Polish, remember reg (char *) fp int (long) -1 + (char *) # Get address of temporary int (long) 1 # Size of temporary list int (char *) L19 list int (long) 1 list # Argument list call (long) # Call getchr oreg (char) -1(fp) # Retrieve value from temporary , (long) # Notice there are 2 expr's here = (char) # Assign (finally) stmt (2) oreg (char) v.2-v.1(r11) # 'if(ich.ne.getchr("A")) ...' int (char * ()) _getchr_ # Almost the same... reg (char *) fp int (long) -1 + (char *) # Get address of temporary int (long) 1 # Size of temporary list int (char *) L19 list int (long) 1 list # Argument list call (long) # Call getchr oreg (char) -1(fp) # Retrieve return value != (char) # Oops! We're comparing the # 'result' of the call with # the actual return value... , (long) # And throwing away 'ich' int (long) 15 cbranch # If false jump to L15 stmt (3) ---------------------------------------------------------------- The compiler is clever -- it realizes that it can do a simple C-style character comparison if the objects it is working with are of type CHARACTER*1. Unfortunately f77 CHARACTER routines must return a value in a complicated way -- the caller must provide a temporary CHARACTER variable which the callee can put the return value into. Thus a call to a function of type CHARACTER takes two steps: making the call and retrieving the return value. These two operations are coordinated with a 'comma' operator in the intermediate code. Unfortunately the routine which emits the intermediate code for CHARACTER comparisons (putchcmp() in putpcc.c) gets the comma and the comparison inverted so that the comparison is between a function call with no return value and the actual return value! Since the code generator 'knows' that (unless instructed otherwise) it can find the return value in r0, the compiler doesn't complain and we get the bizarre assembly code presented above. The fix to putchcmp() is simple: ---------------------------------------------------------------- *** /tmp/,RCSt1015122 Thu May 31 00:52:49 1984 --- putpcc.c Thu May 31 00:52:16 1984 *************** *** 1010,1015 if(ISONE(lp->headblock.vleng) && ISONE(rp->headblock.vleng) ) { putaddr( putch1(lp, &ncomma) , YES ); putaddr( putch1(rp, &ncomma) , YES ); p2op(ops2[p->exprblock.opcode], P2CHAR); free( (charptr) p ); --- 1015,1022 ----- if(ISONE(lp->headblock.vleng) && ISONE(rp->headblock.vleng) ) { putaddr( putch1(lp, &ncomma) , YES ); + putcomma(ncomma, TYINT, NO); + ncomma = 0; putaddr( putch1(rp, &ncomma) , YES ); putcomma(ncomma, TYINT, NO); p2op(ops2[p->exprblock.opcode], P2CHAR); *************** *** 1011,1016 { putaddr( putch1(lp, &ncomma) , YES ); putaddr( putch1(rp, &ncomma) , YES ); p2op(ops2[p->exprblock.opcode], P2CHAR); free( (charptr) p ); putcomma(ncomma, TYINT, NO); --- 1018,1024 ----- putcomma(ncomma, TYINT, NO); ncomma = 0; putaddr( putch1(rp, &ncomma) , YES ); + putcomma(ncomma, TYINT, NO); p2op(ops2[p->exprblock.opcode], P2CHAR); free( (charptr) p ); } *************** *** 1013,1019 putaddr( putch1(rp, &ncomma) , YES ); p2op(ops2[p->exprblock.opcode], P2CHAR); free( (charptr) p ); - putcomma(ncomma, TYINT, NO); } else { --- 1021,1026 ----- putcomma(ncomma, TYINT, NO); p2op(ops2[p->exprblock.opcode], P2CHAR); free( (charptr) p ); } else { ---------------------------------------------------------------- Anybody who understands this deserves a medal... Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA From hao!hplabs!sri-unix!rlb@RIACS.ARPA Thu May 31 12:50:00 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Path: seismo!hao!hplabs!sri-unix!rlb@RIACS.ARPA From: rlb@RIACS.ARPA Newsgroups: net.unix-wizards Subject: /bin/as .fill does not work Message-ID: <311@sri-arpa.UUCP> Date: 31 May 84 16:50:00 GMT Date-Received: 1 Jun 84 17:19:00 GMT Lines: 36 Status: O From: Bob Brown Index: bin/as 4.2BSD Description: The .fill pseudo-op fills in the requested amount of data but does not increment the location assignment counter on pass two, causing the locations (r_address) in the relocation_info table to be wrong. Repeat-By: Assemble a program that contains a relocatable symbol after a .fill statement - the loader will relocate the wrong word: .globl foobar .data 0 here: .fill 8,4,0 addr: .long foobar This will result in the first longword at symbol "here" to be relocated by the amount that should have been added to the longword at symbol "addr" and the longword at "addr" will not be relocated at all. Fix: In as/asparse.c, make the following change in the "case IFILL:" part: 430,432c430,431 < if (passno == 1) { < dotp->e_xvalue += fill_rep * fill_size; < } else { --- > dotp->e_xvalue += fill_rep * fill_size; > if ( passno == 2 ) { ---------- From cmcl2!floyd!vax135!houxz!houxm!ihnp4!zehntel!hplabs!sri-unix!salkind@NYU.ARPA Tue Jun 5 00:07:39 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Path: seismo!cmcl2!floyd!vax135!houxz!houxm!ihnp4!zehntel!hplabs!sri-unix!salkind@NYU.ARPA From: salkind@NYU.ARPA Newsgroups: net.unix-wizards Subject: lprm can fail on local removes Message-ID: <264@sri-arpa.UUCP> Date: 5 Jun 84 04:07:39 GMT Date-Received: 1 Jun 84 22:37:08 GMT Lines: 15 Status: O From: Lou Salkind Index: usr.lib/lpr/rmjob.c 4.2BSD Description: If you try to remove a file local to a machine, lprm can dump core. Repeat-By: lpr lprm nnn Fix: In the routine process(), around line 135 change the line while (getline()) { to while (getline(cfp)) { From hao!hplabs!sdcrdcf!sdcsvax!dcdwest!ittvax!decvax!mulga!kre Thu May 31 05:46:56 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site mulga.OZ Path: seismo!hao!hplabs!sdcrdcf!sdcsvax!dcdwest!ittvax!decvax!mulga!kre From: kre@mulga.UUCP Newsgroups: net.bugs.4bsd Subject: Re: Null entries in passwd Message-ID: <297@mulga.OZ> Date: 31 May 84 09:46:56 GMT Date-Received: 3 Jun 84 14:18:59 GMT References: <172@kovacs.UUCP> Organization: Comp Sci, Melbourne Uni, Australia Lines: 56 Status: O >From kovacs!jim: > We are running 4.2bsd on a VAX 750. > Recently we've found "null" entries in our passwd file. > They looked like this: > : > :0:: > :0:0:: > : > :0: > Someone here added an entry to the passwd file > and accidently left out the "real life" name field. > The "null" entries followed the bad passwd entry. > Running "/usr/ucb/chfn" caused the null entries to > appear. With "chfn" disabled, we still got them, so > there must be another program which handles missing > fields with the same lack of grace. The problem > went away, of course, when we added the missing field. > Hope this helps someone else with the same symptom. That's caused by a bug in getpwent() that I had hoped had been fixed in 4.2. Oh well. Problem is caused whenever someone (manually, with an editor) miscounts the number of ':' chars in a line in /etc/passwd. From then on, any of the programs that copy passwd and create a new version (passwd, chsh, chfn) will create lots of those annoying colon and zero lines. Its a cancer, the only way to rid your passwd file of it is to completely delete all those lines and correct the line with the missing ':'. If you don't do both of those the problem will simply reappear, and grow continually. (Notice that each of those lines has incorrect numbers of ':' chars so each of them will cause more crap). To the best of my knowledge, this bug exists on all unix versions, its certainly been around ever since getpwent() appeared. I haven't looked at sys III or sys V though, so perhaps its fixed there. The cause of the problem is that pwskip() allows \n to become part of the field returned. None of the programs that write passwd files check for \n in the gecos, or name, or dir fields, they just write it ... Fix is to change the line while (*p && *p != ':') in pwskip() (which is in getpwent.c) to be while (*p && *p != ':' && *p != '\n') Then \n's won't ever make it into fields of passwd structs, and broken passwd file lines won't be cancerous any more. Of course, cancer is often easier to spot than a simple disease ... Robert Elz decvax!mulga!kre ps: this was originally found & fixed here in an early 32v system, by Richard Miller, now hcr!miller or something like that. From cmcl2!floyd!whuxle!mit-eddie!godot!bruce Tue Jun 5 23:34:34 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site godot.UUCP Path: seismo!cmcl2!floyd!whuxle!mit-eddie!godot!bruce From: bruce@godot.UUCP (Bruce Nemnich) Newsgroups: net.unix-wizards,net.bugs.4bsd Subject: tbuf par faults and 4.2bsd Message-ID: <125@godot.UUCP> Date: 6 Jun 84 03:34:34 GMT Date-Received: 6 Jun 84 10:34:26 GMT Organization: Thinking Machines, Waltham, MA Lines: 31 Status: O > From: rees@apollo.UUCP > Subject: tbuf par errors, once more > Date: Mon, 4-Jun-84 08:23:32 EDT > > Maybe this should go in the list of most-often asked questions about Unix? > > Thanks to Dennis Ritchie, Sam Leffler, Andy Tannenbaum, and all the > other people who helped straighten this out. > > The translation buffer helps translate virtual addresses to real. A > tbuf par err is a parity error in the translation buffer. The original > 4.1bsd code didn't handle these errors correctly. There is an ECO > from DEC that reduces the number of these errors, but Unix should still > be able to handle them correctly. > > There are some bogus versions of this fix floating around. They have > mc5_mcesr&0xf instead of mc5_mcesr&0xe. Make sure you have the right one. > > I have not looked at the 4.2 code to see if this fix made it in. This code > is for 4.1bsd. I just looked at the 4.2bsd code, because I have been having problems with these faults. Sure enough, the distributed version has the bogus fix. Here's the 4.2bsd diff on /sys/vax/machdep.c: 810c810 < if ((mcf->mc5_mcesr&0xf) == MC750_TBPAR) { --- > if ((mcf->mc5_mcesr&0xe) == MC750_TBPAR) { -- --Bruce Nemnich, Thinking Machines Corporation, Waltham, MA From cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!mulga!munnari!mark Tue Jun 5 18:28:31 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site munnari.OZ Path: seismo!cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!mulga!munnari!mark From: mark@munnari.OZ (Mark Davoren) Newsgroups: net.bugs.4bsd Subject: curses scrolling Message-ID: <316@munnari.OZ> Date: 5 Jun 84 22:28:31 GMT Date-Received: 7 Jun 84 06:28:40 GMT Organization: Comp Sci, Melbourne Uni, Australia Lines: 211 Status: O [] I didn't get the original question, only the replies. I hope this is of interest to those who are trying to beat curses into some sense of sanity. I have recently finished developing a screen based version of the CAI program "learn". It consists of two windows. A set of instructions is displayed in the top window then the user is put into the shell, editor, etc. operating in the bottom window (like a ~12 line screen) To do this properly the bottom window must scroll. The following are some fixes I had to make to get everything working. All the programs displayed characters by using waddch or derivatives like waddstr etc. This is then followed by a wrefresh. I let waddch decide when to scroll the screen. 1) The following are two fixes to refresh.c version 1.8 This will fix the bug which stopped windows of width less than the screen scrolling properly. diff refresh.c $S/refresh.c 198c198 < /* scroll(win); */ /* mark */ --- > scroll(win); 201,202c201,202 < ly = win->_begy+win->_maxy-1; /* mark */ < lx = win->_begx+win->_maxx; /* mark */ --- > ly = win->_begy+win->_cury; > lx = win->_begx+win->_curx; 2) Here is my copy of scroll.c (easier to give the source than a diff) This version fixes the scrolling of curscr and includes a quicky to see whether the delete line and insert line facilities of the terminal can be used (if they exist). Without this addition, scrolling windows is amazingly slow since the whole window is redrawn. Refresh does not have enough information to know when it can simply scroll a window. In addition things would get very confused if refresh had to scroll and make changes as well. ================================================================================ # include "curses.ext" /* * This routine scrolls the window up a line. * * 6/1/83 (Berkeley) @(#)scroll.c 1.3 * * with bug fixes 20/5/84 Mark Davoren (Uni of Melbourne, Australia) * with quicky using add line and delete line 1/6/84 " */ scroll(win) reg WINDOW *win; { reg char *sp; reg int i; reg char *temp; reg int tx; if (!win->_scroll) return ERR; temp = win->_y[0]; for (i = 1; i < win->_maxy; i++) win->_y[i - 1] = win->_y[i]; for (sp = temp; sp < &temp[win->_maxx]; ) *sp++ = ' '; win->_y[win->_maxy - 1] = temp; if (win == curscr) { /* BUG FIX so that scrolling curscr works */ mvcur(win->_cury, win->_curx, win->_maxy-1, win->_curx); /* * Doing a newline whilst in the middle of the screen * is not going to scroll the screen very much! */ putchar('\n'); /* * Should make use of scroll forwards functions * but only some terminals support it * and I need it to work on all our terminals */ tx = win->_curx; if (!NONL) tx = 0; /* * If we were at the top of the screen * don't go into hyperspace. */ if (win->_cury > 0) win->_cury--; mvcur(win->_maxy-1, tx, win->_cury, win->_curx); # ifdef DEBUG fprintf(outf, "SCROLL: win == curscr\n"); # endif } else { #ifdef DEBUG fprintf(outf, "SCROLL: win [0%o] != curscr [0%o]\n",win,curscr); #endif if (AL && DL && win->_maxx == curscr->_maxx) { # ifdef DEBUG fprintf(outf, "SCROLL: shifting %d - %d (%d)\n" , win->_begy , win->_begy + win->_maxy , curscr->_maxy ); # endif temp = curscr->_y[win->_begy]; for (i = win->_begy; i < win->_begy + win->_maxy; i++) curscr->_y[i - 1] = curscr->_y[i]; for (sp = temp; sp < &temp[curscr->_maxx]; ) *sp++ = ' '; curscr->_y[win->_begy + win->_maxy - 1] = temp; mvcur(curscr->_cury, curscr->_curx, win->_begy, 0); tputs(DL, 1, _putchar); if (curscr->_cury > win->_begy && curscr->_cury < win->_begy + win->_maxy) curscr->_cury--; if (win->_begy + win->_maxy != curscr->_maxy) { mvcur(win->_begy, 0, win->_begy+win->_maxy - 1, 0); tputs(AL, 1, _putchar); mvcur(win->_begy+win->_maxy - 1, 0, curscr->_cury, curscr->_curx); } else mvcur(win->_begy, 0, curscr->_cury, curscr->_curx); } } touchwin(win); return OK; } ================================================================================ 3) The following is a fix to addch.c (1.5) The call to refresh and scroll are swapped. This is to avoid the situation where a character has been placed in the bottom right hand corner of a window which corresponds to the bottom right hand corner of the screen. If refresh is called first then the char would be printed and the terminal will automatically scroll (all the terminals we use do) this of course upsets everything else on the screen, such as the top window. By calling scroll first, no chars are ever written into the bottom right hand corner and thus the terminal doesn't do anything dumb. diff addch.c $S/addch.c 48d47 < scroll(win); 49a49 > scroll(win); 4) Curses seems to have an identity crisis with cbreak mode crmode() exists as separate to raw(), yet it still sets _rawmode. This mucks up the innards of cr_put.c which use _rawmode to decide whether it can do a newline without the ensuing carriage return taking the cursor to column one. This is a problem since whilst in cbreak mode, one can still have newline mapping turned on, but not so in raw mode. (This will only occur if it is quicker to do a newline than do a cursor movement command) So here are fixes to allow a proper crmode. curses.c (1.2) curses.h (1.14) curses.ext (1.3) diff curses.c $S/curses.c 10d9 < _crmode = FALSE,/* set if stty indicates CRMODE mode */ diff curses.h $S/curses.h 60,66c60 < extern bool My_term, _echoit, _crmode, _rawmode, _endwin; < /* < * CRMOD is not the same as RAW, therefore needs a different variable < * to hold state info < * In particular nl mapping is off in raw mode, but not necessarily < * so in crmode mark. < */ --- > extern bool My_term, _echoit, _rawmode, _endwin; 139,140c133,134 < #define crmode() (_tty.sg_flags |= CBREAK, _crmode = TRUE, stty(_tty_ch,&_tty)) < #define nocrmode() (_tty.sg_flags &= ~CBREAK,_crmode=FALSE,stty(_tty_ch,&_tty)) --- > #define crmode() (_tty.sg_flags |= CBREAK, _rawmode = TRUE, stty(_tty_ch,&_tty)) > #define nocrmode() (_tty.sg_flags &= ~CBREAK,_rawmode=FALSE,stty(_tty_ch,&_tty)) diff curses.ext $S/curses.ext 11c11 < extern bool _echoit, _rawmode, My_term, _endwin, _crmode; --- > extern bool _echoit, _rawmode, My_term, _endwin; I hope this has been of some use to all you out there in curses land Mark Davoren decvax!mulga!mark From rochester!bukys Fri Jun 8 10:21:58 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10 5/3/83; site rochester.UUCP Path: seismo!rochester!bukys From: bukys@rochester.UUCP (Liudvikas Bukys) Newsgroups: net.bugs.4bsd Subject: 4.2 sendmail: can't define more than one macro from command line Message-ID: <7317@rochester.UUCP> Date: 8 Jun 84 14:21:58 GMT Date-Received: 8 Jun 84 14:51:18 GMT Organization: U. of Rochester, CS Dept. Lines: 91 Status: O Index: usr.lib/sendmail/src/readcf.c 4.2 Fix Description: Options specified on the command line are considered "sticky": they can't be overridden by later definitions on the command line or in the configuration file. (This is fine.) Unfortunately, defining a macro on the command line sets the sticky flag for 'M' (macros), so subsequent macro definitions on the command line have no effect. (This is not so good.) This is a pretty low-priority bug, since there's little reason for people to want to define more than one macro from the command line. But it would be nice if the bug disappeared from the "distribution". Repeat-By: Stick a "$Z" someplace innocuous in sendmail.cf, like in a comment in the "Received:" line header. Mail something to yourself with /usr/lib/sendmail -oMYTESTING -oMZ123 yourself < /etc/group See what the $Z expanded into; probably nothing; should be "123". Fix: Move the "set the sticky bit" code past the switch statement. Have the 'M' case turn off the "please make this sticky" flag. diff -c: ------------------------------------------------------------------------------- *** /tmp/,RCSt1009151 Fri Jun 8 09:56:25 1984 --- readcf.c Fri Jun 8 09:55:49 1984 *************** *** 621,628 else if (tTd(37, 1)) printf("\n"); #endif DEBUG - if (sticky) - setbitn(opt, StickyOpt); if (getruid() == 0) safe = TRUE; --- 621,626 ----- else if (tTd(37, 1)) printf("\n"); #endif DEBUG if (getruid() == 0) safe = TRUE; *************** *** 718,723 case 'M': /* define macro */ define(val[0], newstr(&val[1]), CurEnv); break; case 'm': /* send to me too */ --- 716,722 ----- case 'M': /* define macro */ define(val[0], newstr(&val[1]), CurEnv); + sticky = FALSE; break; case 'm': /* send to me too */ *************** *** 795,800 default: break; } return; } ^L/* --- 794,801 ----- default: break; } + if (sticky) + setbitn(opt, StickyOpt); return; } ^L/* ------------------------------------------------------------------------------- Brought to you by: Liudvikas Bukys rochester!bukys (uucp) via allegra, decvax, seismo bukys@rochester (arpa) From cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Fri Jun 8 15:17:08 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: f77 has problems when a DO loop variable is also a loop parameter Message-ID: <162@sdchema.UUCP> Date: 8 Jun 84 19:17:08 GMT Date-Received: 9 Jun 84 10:32:04 GMT Organization: State Home for the Maturity-Impaired, San Diego Lines: 150 Status: O Subject: f77 has problems when a DO loop variable is also a loop parameter Index: usr.bin/f77/src/f77pass1/exec.c 4.2BSD Description: This bug only strikes when the optimizer is OFF. If a DO loop variable is used for other purposes in a routine and in particular is used in the loop initialization, limit or increment at the same time it is used as the loop variable, the parameter containing the loop variable will appear to be garbage. This bug was originally sent to me by Robert Elz of the University of Melbourne. Repeat-By: Compile the following program with 'f77 -S' (examples are courtesy of Robert Elz): ---------------------------------------------------------------- k = 1 i = 1 do 10 k = k, 10 i = i + k 10 continue print i end ---------------------------------------------------------------- In the assembly language output we see that the register is initialized from itself, instead of the memory version of the loop variable: ---------------------------------------------------------------- movl $1,{k}(r11) movl $1,{i}(r11) movl r10,r10 <<<<<<<<<<< cmpl r10,$10 jgtr L16 L17: movl r10,{k}(r11) addl3 r10,{i}(r11),r0 movl r0,{i}(r11) L15: incl r10 cmpl r10,$10 jleq L17 L16: movl r10,{k}(r11) clrl -104(fp) movl $6,-100(fp) movl {i}(r11),-92(fp) addl3 $-104,fp,r0 pushl r0 calls $1,_s_wsfe calls $0,_e_wsfe L14: ret ---------------------------------------------------------------- Fix: The problem is that the compiler puts the DO loop variable in register before fixing the DO loop parameters. The bug goes away if you just swap the two chunks of code in exdo() in f77pass1/exec.c: ---------------------------------------------------------------- *** /tmp/,RCSt1019970 Thu Jun 7 22:27:42 1984 --- exec.c Thu Jun 7 22:12:00 1984 *************** *** 379,385 } dovarp = mkplace(np); ! if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) ) { err("bad type on DO variable"); return; --- 379,387 ----- } dovarp = mkplace(np); ! dotype = dovarp->vtype; ! ! if( ! ONEOF(dotype, MSKINT|MSKREAL) ) { err("bad type on DO variable"); return; *************** *** 387,404 return; } - ctlstack->donamep = np; - - np->vdovar = YES; - if( !optimflag && enregister(np) ) - { - /* stgp points to a storage version, varp to a register version */ - dostgp = dovarp; - dovarp = mkplace(np); - } - else - dostgp = NULL; - dotype = dovarp->vtype; - - for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp) { p = fixtype((expptr) cpexpr((tagptr) q = cp->datap)); --- 388,393 ----- return; } for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp) { p = fixtype((expptr) cpexpr((tagptr) q = cp->datap)); *************** *** 440,445 return; } for (i = 0; i < 4; i++) ctlstack->ctlabels[i] = newlabel(); --- 429,445 ----- return; } + ctlstack->donamep = np; + + np->vdovar = YES; + if( !optimflag && enregister(np) ) + { + /* stgp points to a storage version, varp to a register version */ + dostgp = dovarp; + dovarp = mkplace(np); + } + else + dostgp = NULL; for (i = 0; i < 4; i++) ctlstack->ctlabels[i] = newlabel(); ---------------------------------------------------------------- And I bet you thought it was safe as long as the optimizer was off, Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA (Moving soon to utah-cs) From cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Fri Jun 8 17:38:19 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: Revision to common subexpression bug fix in f77 Message-ID: <163@sdchema.UUCP> Date: 8 Jun 84 21:38:19 GMT Date-Received: 9 Jun 84 22:27:34 GMT Organization: State Home for the Maturity-Impaired, San Diego Lines: 104 Status: O Here's another fix for the common subexpression bug which causes elements in the same COMMON block to be confused with each other. This fix was sent to me by Ralph Campbell, who got it from a trusted source. The advantage of this new fix is that certain safe CSE optimizations on COMMON variables are now permitted. First remove the original fix that I supplied to scantree() in file optcse.c: ------------------------------------------------------------------------ *** /tmp/,RCSt1021557 Fri Jun 8 14:28:06 1984 --- optcse.c Fri Jun 8 11:45:29 1984 *************** *** 584,590 ap = (Addrp) p->exprblock.leftp; idp = findid(ap); killdepnodes(idp); ! if( ! (ap->isarray || ap->vstg == STGCOMMON) ) { if(rnode->is_dead)idp->assgnval=idp->initval; else idp->assgnval = rnode; } --- 603,609 ----- ap = (Addrp) p->exprblock.leftp; idp = findid(ap); killdepnodes(idp); ! if( ! ap->isarray ) { if(rnode->is_dead)idp->assgnval=idp->initval; else idp->assgnval = rnode; } ------------------------------------------------------------------------ Then replace the samebase() routine in the same file with the following revised version: ------------------------------------------------------------------------ LOCAL samebase(ep1,ep2) expptr ep1,ep2; { if ( ep1->tag == ep2->tag ) switch (ep2->tag) { case TTEMP : if (ep1->tempblock.memalloc == ep2->tempblock.memalloc) return (TRUE); break; case TADDR : if (ep1->addrblock.vstg == ep2->addrblock.vstg) { switch(ep1->addrblock.vstg) { case STGCOMMON: if (ep1->addrblock.memno == ep2->addrblock.memno && ISCONST(ep1->addrblock.memoffset) && ISCONST(ep2->addrblock.memoffset) && ep1->addrblock.memoffset->constblock.const.ci == ep2->addrblock.memoffset->constblock.const.ci ) { return(TRUE); } break; default: if (ep1->addrblock.memno == ep2->addrblock.memno ) { return(TRUE); } } } break; case TCONST : if( (ep1->constblock.vtype) == (ep2->constblock.vtype) ) { union Constant *ap,*bp; ap= &ep1->constblock.const; bp= &ep2->constblock.const; switch(ep1->constblock.vtype) { case TYSHORT: case TYLONG: if(ap->ci == bp->ci) return(TRUE); break; case TYREAL: case TYDREAL: if(ap->cd[0] == bp->cd[0]) return(TRUE); break; case TYCOMPLEX: case TYDCOMPLEX: if(ap->cd[0] == bp->cd[0] && ap->cd[1] == bp->cd[1] ) return(TRUE); break; } } break; default : badtag ("samebase",ep2->tag); } return(FALSE); } ------------------------------------------------------------------------ Enjoy, Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA From cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Fri Jun 8 18:36:33 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: Dbx can't access C functions that have blocks containing declarations Message-ID: <164@sdchema.UUCP> Date: 8 Jun 84 22:36:33 GMT Date-Received: 9 Jun 84 22:27:43 GMT Organization: State Home for the Maturity-Impaired, San Diego Lines: 192 Status: O Subject: Dbx can't access C functions that have blocks containing declarations Index: ucb/dbx/object.c 4.2BSD Description: Sometimes when debugging with dbx, mysterious functions like '$b4' or '$b23' appear in the stack trace when the 'where' command is given. These functions appear to share lines with the function that appears to call them -- for example, if you are stopped in function 'f' which appears to be called by function '$b4' which is in turn called by function 'g', then 'f' will appear to be called from the same source file and at the same line number in '$b4' as '$b4' is in 'g'. Moreover it is impossible to examine local variables in 'g'. The common feature of all functions 'g' mentioned above is that they contain blocks or compound statements that have their own declarations. If you stop in an inner block with declarations, you can print out that block's local variables (although none of the outer local variables), which is a good indication that they are connected with the bug. Repeat-By: Clip out the following program and compile it with 'cc -g': ---------------------------------------------------------------- #include int f(); main() { int x; x = 1; if (x > 0) { int y; y = 3; x = f(y); } printf( "%d\n", x ); exit( 0 ); } int f( z ) int z; { z = z + 1; return ( z ); } ---------------------------------------------------------------- Run dbx on the object. If you put a breakpoint anywhere in the program, run it and check the stack when you stop, you will find that there is a mysterious function '$b1' that is always present. The variable 'x' in main() will not be accessible but you can get at 'z' when 'f' is active, and you can get at 'y' at any time (clearly a bug). Fix: Hasn't someone fixed this before? I sure would like to have a good (official?) fix... I won't pretend that my fix is clean or even correct, but it seems to be an improvement. The changes are to enter_nl() and unnamed_block() in object.c: ---------------------------------------------------------------- *** /tmp/,RCSt1021606 Fri Jun 8 14:45:57 1984 --- object.c Fri Jun 8 14:44:26 1984 *************** *** 318,324 break; case N_RBRAC: ! if (addrstk[nesting] == NOADDR) { exitblock(); newfunc(curblock, (linep - 1)->addr); } --- 318,325 ----- break; case N_RBRAC: ! --nesting; ! if (nesting > 0) { exitblock(); newfunc(curblock, (linep - 1)->addr); addrstk[nesting] = (linep - 1)->addr; *************** *** 321,326 if (addrstk[nesting] == NOADDR) { exitblock(); newfunc(curblock, (linep - 1)->addr); } --nesting; break; --- 322,328 ----- if (nesting > 0) { exitblock(); newfunc(curblock, (linep - 1)->addr); + addrstk[nesting] = (linep - 1)->addr; } break; *************** *** 322,328 exitblock(); newfunc(curblock, (linep - 1)->addr); } - --nesting; break; case N_SLINE: --- 324,329 ----- newfunc(curblock, (linep - 1)->addr); addrstk[nesting] = (linep - 1)->addr; } break; case N_SLINE: *************** *** 546,552 ++bnum; sprintf(buf, "$b%d", bnum); s = insert(identname(buf, false)); ! s->class = PROG; s->symvalue.funcv.src = false; s->symvalue.funcv.inline = true; s->symvalue.funcv.beginaddr = addrstk[nesting]; --- 547,553 ----- ++bnum; sprintf(buf, "$b%d", bnum); s = insert(identname(buf, false)); ! s->class = PROC; s->symvalue.funcv.src = false; s->symvalue.funcv.inline = true; s->symvalue.funcv.beginaddr = (linep - 1)->addr; *************** *** 549,555 s->class = PROG; s->symvalue.funcv.src = false; s->symvalue.funcv.inline = true; ! s->symvalue.funcv.beginaddr = addrstk[nesting]; enterblock(s); newfunc(s, addrstk[nesting]); addrstk[nesting] = NOADDR; --- 550,556 ----- s->class = PROC; s->symvalue.funcv.src = false; s->symvalue.funcv.inline = true; ! s->symvalue.funcv.beginaddr = (linep - 1)->addr; enterblock(s); newfunc(s, (linep - 1)->addr); addrstk[nesting] = NOADDR; *************** *** 551,557 s->symvalue.funcv.inline = true; s->symvalue.funcv.beginaddr = addrstk[nesting]; enterblock(s); ! newfunc(s, addrstk[nesting]); addrstk[nesting] = NOADDR; } --- 552,558 ----- s->symvalue.funcv.inline = true; s->symvalue.funcv.beginaddr = (linep - 1)->addr; enterblock(s); ! newfunc(s, (linep - 1)->addr); addrstk[nesting] = NOADDR; } ---------------------------------------------------------------- What this fix does for you is that it makes it possible to look at the local variables of a function with an inner block containing declarations, with the caveat that if you are actually IN the inner block, you can see that block's variables but not the outer variables (essentially this reduces the scope of the bug without eliminating it). I am pretty sure that the old code is wrong, but I am not sure that my change is what the author intended. Anyone with a better solution is urged to post it... Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA From cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn Fri Jun 8 19:13:27 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site sdchema.UUCP Path: seismo!cmcl2!floyd!whuxle!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!sdchema!donn From: donn@sdchema.UUCP Newsgroups: net.bugs.4bsd Subject: Autoconfigure doesn't find overlapping disk/tape controllers Message-ID: <165@sdchema.UUCP> Date: 8 Jun 84 23:13:27 GMT Date-Received: 9 Jun 84 22:27:53 GMT Organization: State Home for the Maturity-Impaired, San Diego Lines: 277 Status: O Subject: Autoconfigure doesn't find overlapping disk/tape controllers Index: sys/vax/autoconf.c 4.2BSD Description: When the system is running through autoconfiguration, it can miss the fact that two mass storage devices are claimed to be at the same CSR. Moreover the system does not complain if the register set of one controller overlaps with another. Repeat-By: We had the following lines in our config file: ---------------------------------------------------------------- controller sc0 at uba0 csr 0176700 vector upintr disk up0 at sc0 drive 0 disk up1 at sc0 drive 1 controller sc1 at uba0 csr 0176600 vector upintr disk up2 at sc1 drive 0 disk up3 at sc1 drive 6 controller sc2 at uba0 csr 0176500 vector upintr disk up4 at sc2 drive 0 disk up5 at sc2 drive 1 ---------------------------------------------------------------- Only sc0 was actually in the system. The default CSR address for the 'up' driver is 0176700. The result was that the system did the following when booted: ---------------------------------------------------------------- ... sc0 at uba0 csr 176700 vec 254, ipl 15 up0 at sc0 slave 0 sc1 at uba0 csr 176700 didn't interrupt sc2 at uba0 csr 176700 didn't interrupt ... ---------------------------------------------------------------- Two things happened here: for sc1 and sc2, the stated CSR was not active, so the system tried the default CSR; and the system did not realize that the default CSR was already taken. Fix: I have two gripes with the autoconfigure code. I don't want the system to check the 'default address' if the specified CSR is not present; and the system should not attempt to locate a device in a place in the Unibus I/O page where another device has already found. (The 'default address' can still be used by specifying an address of 0 in the config file.) The following changes to unifind() in autoconfigure.c make the first behavior a compile-time option, and fix the second. Only the part that turns off checking for default addresses has been tested, but it all compiles and runs okay. ---------------------------------------------------------------- *** /tmp/,RCSt1021690 Fri Jun 8 15:46:41 1984 --- autoconf.c Tue Jun 5 17:21:46 1984 *************** *** 386,392 u_short *reg, *ap, addr; struct uba_hd *uhp; struct uba_driver *udp; ! int i, (**ivec)(), haveubasr; caddr_t ualloc, zmemall(); extern int catcher[256]; --- 386,392 ----- u_short *reg, *ap, addr; struct uba_hd *uhp; struct uba_driver *udp; ! int i, warned, (**ivec)(), haveubasr; caddr_t ualloc, zmemall(); extern int catcher[256]; *************** *** 478,484 * at that address, try all the standard addresses * in the driver til we find it */ ! for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { if (ualloc[ubaoff(addr)]) continue; --- 478,495 ----- * at that address, try all the standard addresses * in the driver til we find it. */ ! #ifdef STANDARDAUTOCONF ! ap = udp->ud_addr; ! #else STANDARDAUTOCONF ! /* ! * Only check for standard devices if addr is zero. ! */ ! if (addr) ! ap = &addr; ! else ! ap = udp->ud_addr; ! #endif STANDARDAUTOCONF ! for (; addr || (addr = *ap++); addr = 0) { if (ualloc[ubaoff(addr)]) { if (ap == &addr) *************** *** 480,486 */ for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { ! if (ualloc[ubaoff(addr)]) continue; reg = ubaddr(addr); if (badaddr((caddr_t)reg, 2)) --- 491,500 ----- #endif STANDARDAUTOCONF for (; addr || (addr = *ap++); addr = 0) { ! if (ualloc[ubaoff(addr)]) { ! if (ap == &addr) ! printf("WARNING: %s%d: csr %o already used\n", ! udp->ud_mname, um->um_ctlr, addr); continue; } reg = ubaddr(addr); *************** *** 482,487 if (ualloc[ubaoff(addr)]) continue; reg = ubaddr(addr); if (badaddr((caddr_t)reg, 2)) continue; --- 496,502 ----- printf("WARNING: %s%d: csr %o already used\n", udp->ud_mname, um->um_ctlr, addr); continue; + } reg = ubaddr(addr); if (badaddr((caddr_t)reg, 2)) continue; *************** *** 512,517 continue; } printf("vec %o, ipl %x\n", cvec, br); um->um_alive = 1; um->um_ubanum = numuba; um->um_hd = &uba_hd[numuba]; --- 527,540 ----- continue; } printf("vec %o, ipl %x\n", cvec, br); + warned = 0; + while ( --i >= 0 ) + if (! warned && ualloc[ubaoff(addr+i)]) { + printf("WARNING: %s%d: Address overlap at %o\n", + udp->ud_mname, um->um_ctlr, (addr+i)&~01); + ++warned; + } else + ualloc[ubaoff(addr+i)] = 1; um->um_alive = 1; um->um_ubanum = numuba; um->um_hd = &uba_hd[numuba]; *************** *** 558,563 ui->ui_alive || ui->ui_slave != -1) continue; addr = (u_short)ui->ui_addr; for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { --- 581,594 ----- ui->ui_alive || ui->ui_slave != -1) continue; addr = (u_short)ui->ui_addr; + #ifdef STANDARDAUTOCONF + ap = udp->ud_addr; + #else STANDARDAUTOCONF + if (addr) + ap = &addr; + else + ap = udp->ud_addr; + #endif STANDARDAUTOCONF for (; addr || (addr = *ap++); addr = 0) { *************** *** 559,565 continue; addr = (u_short)ui->ui_addr; ! for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { if (ualloc[ubaoff(addr)]) continue; --- 590,596 ----- ap = udp->ud_addr; #endif STANDARDAUTOCONF ! for (; addr || (addr = *ap++); addr = 0) { if (ualloc[ubaoff(addr)]) { if (ap == &addr) *************** *** 561,567 for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { ! if (ualloc[ubaoff(addr)]) continue; reg = ubaddr(addr); if (badaddr((caddr_t)reg, 2)) --- 592,601 ----- for (; addr || (addr = *ap++); addr = 0) { ! if (ualloc[ubaoff(addr)]) { ! if (ap == &addr) ! printf("WARNING: %s%d: csr %o already used\n", ! udp->ud_mname, um->um_ctlr, addr); continue; } reg = ubaddr(addr); *************** *** 563,568 if (ualloc[ubaoff(addr)]) continue; reg = ubaddr(addr); if (badaddr((caddr_t)reg, 2)) continue; --- 597,603 ----- printf("WARNING: %s%d: csr %o already used\n", udp->ud_mname, um->um_ctlr, addr); continue; + } reg = ubaddr(addr); if (badaddr((caddr_t)reg, 2)) continue; *************** *** 593,600 continue; } printf("vec %o, ipl %x\n", cvec, br); ! while (--i >= 0) ! ualloc[ubaoff(addr+i)] = 1; ui->ui_hd = &uba_hd[numuba]; for (ivec = ui->ui_intr; *ivec; ivec++) { ui->ui_hd->uh_vec[cvec/4] = --- 628,641 ----- continue; } printf("vec %o, ipl %x\n", cvec, br); ! warned = 0; ! while ( --i >= 0 ) ! if (! warned && ualloc[ubaoff(addr+i)]) { ! printf("WARNING: %s%d: Address overlap at %o\n", ! udp->ud_mname, um->um_ctlr, (addr+i)&~01 ); ! ++warned; ! } else ! ualloc[ubaoff(addr+i)] = 1; ui->ui_hd = &uba_hd[numuba]; for (ivec = ui->ui_intr; *ivec; ivec++) { ui->ui_hd->uh_vec[cvec/4] = ---------------------------------------------------------------- More scraps from the software closet, Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA From hao!hplabs!tektronix!uw-beaver!cornell!vax135!houxz!houxm!ihnp4!inuxc!pur-ee!uiucdcs!convex!hosking Sat Jun 16 01:25:00 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: Notesfiles; site convex.UUCP Path: seismo!hao!hplabs!tektronix!uw-beaver!cornell!vax135!houxz!houxm!ihnp4!inuxc!pur-ee!uiucdcs!convex!hosking From: hosking@convex.UUCP Newsgroups: net.bugs.4bsd Subject: 4.2BSD tty.c bug Message-ID: <33500006@convex.UUCP> Date: 16 Jun 84 05:25:00 GMT Date-Received: 18 Jun 84 18:35:19 GMT Lines: 18 Nf-ID: #N:convex:33500006:000:510 Nf-From: convex!hosking Jun 15 00:25:00 1984 Nf-ID: #N:convex:33500006:000:510 Nf-From: convex!hosking Jun 15 00:25:00 1984 Status: O In 4.2BSD tty.c, routine "ttwrite", there appears to be a bug with the way interrupt masking is done. Assuming you reach "ovhiwat:", interrupts are masked with s = spl5();. However, there are at least 2 ways to leave this code without a corresponding splx(s). Oops! ovhiwat: s = spl5(); . . . if (tp->t_state&TS_NBIO) { if (uio->uio_resid == cnt) return (EWOULDBLOCK); <---------- return (0); <---------- } Doug Hosking Convex Computer Corp. ..{allegra, ihnp4}!convex!hosking From cmcl2!floyd!vax135!ukc!edcaad!edee!glasgow!sysman Mon Jul 2 17:40:22 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83 (MC830713); site glasgow.UUCP Path: seismo!cmcl2!floyd!vax135!ukc!edcaad!edee!glasgow!sysman From: sysman@glasgow.UUCP (System Manager) Newsgroups: net.bugs.4bsd Subject: Bug in hp.c (4.2BSD) HCRC handling Message-ID: <757@glasgow.UUCP> Date: 2 Jul 84 21:40:22 GMT Date-Received: 20 Jun 84 06:32:50 GMT Organization: Comp. Sci., Univ. of Glasgow, Scotland Lines: 127 Status: O Bug Report: HCRC error handling in vaxmba/hp.c (4.2bsd 6.2) -------------------------------------------------------------------------- Problem: We have two adjacent bad blocks, with the second one causing an HCRC error. When an attempt was made to read the disk, the system hung in a tight loop. I obtained the following trace with hpdebug and hpbdebug set to 1: hperr: bp 8003cf6c cyl 764 blk 67460 as 0 dc 2fc da 829 errcnt 0 mbsr=13080 er1=0 er2=100000 hpecc, BSE: bn 67460 cn 764 tn 8 sn 40 revector to cn 839 tn 18 sn 42 hpecc, CONT: bn 67460 cn 764 tn 8 sn 41 hperr: bp 8003cf6c cyl 764 blk 67460 as 0 dc 2fc da 82a errcnt 0 mbsr=13080 er1=400 er2=100000 hperr: bp 8003cf6c cyl 764 blk 67460 as 0 dc 2fc da 829 errcnt 1 mbsr=13080 er1=0 er2=100000 hpecc, BSE: bn 67460 cn 764 tn 8 sn 40 revector to cn 839 tn 18 sn 42 hpecc, CONT: bn 67460 cn 764 tn 8 sn 41 and then the last 7 lines repeat ad infinitum. ------------------------------------------------------------------------- Suggested Fix: There is code in the driver to check whether an HCRC error has arisen when the sector is in the bad sector table. Unfortunately, in this loop the code is never reached. So although I don't claim to understand all that is going on here, I have moved the code to what seems to be a more suitable place. It seems to work. Don't worry if the line numbers below don't match your hp.c. We have a few local mods to allow eagles to be treated as RM80s, but the problem appears at first sight to be a general one. (We use Emulex SC750 with Eagles treated as 20-track, 44-sector RM80s.) ---------------------------------------------------------------------------- *** hp.cold Sat Jun 16 14:42:31 1984 --- hp.c Sat Jun 16 15:47:35 1984 *************** *** 605,610 } #endif if (er1 & HPER1_HCRC) { er1 &= ~(HPER1_HCE|HPER1_FER); er2 &= ~HPER2_BSE; } --- 605,617 ----- } #endif if (er1 & HPER1_HCRC) { + /* + * HCRC means the header is screwed up and the sector + * might well exist in the bad sector table, + * better check.... + */ + if (!ML11 && !sc->sc_hdr && hpecc(mi, BSE)) + return (MBD_RESTARTED); er1 &= ~(HPER1_HCE|HPER1_FER); er2 &= ~HPER2_BSE; } *************** *** 620,633 er1 & HPER1_HARD || sc->sc_hdr || (!ML11 && (er2 & HPER2_HARD))) { - /* - * HCRC means the header is screwed up and the sector - * might well exist in the bad sector table, - * better check.... - */ - if ((er1&HPER1_HCRC) && - !ML11 && !sc->sc_hdr && hpecc(mi, BSE)) - return (MBD_RESTARTED); hard: if (ML11) bp->b_blkno = MASKREG(hpaddr->hpda); --- 627,632 ----- er1 & HPER1_HARD || sc->sc_hdr || (!ML11 && (er2 & HPER2_HARD))) { hard: if (ML11) bp->b_blkno = MASKREG(hpaddr->hpda); --------------------------------------------------------------------------- Malcolm Crowe, Paisley College Zdravko Podolski, Comp Sci Dept, Univ. of Glasgow, Scotland {...!decvax!mcvax | ...!vax135 }!ukc!edcaad!edee!glasgow!paisley!mkc or: glasgow!paisley!mkc%edee%rco%ucl-cs@CSNet-Relay From harpo!decvax!linus!utzoo!utcsrgv!utai!uthub!thomson Tue Jun 19 10:42:42 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10 beta 3/9/83; site uthub.UUCP Path: seismo!harpo!decvax!linus!utzoo!utcsrgv!utai!uthub!thomson From: thomson@uthub.UUCP (Brian Thomson) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: ptcread() throughput sextupling Message-ID: <168@uthub.UUCP> Date: 19 Jun 84 14:42:42 GMT Date-Received: 20 Jun 84 17:31:22 GMT Organization: CSRG, University of Toronto Lines: 110 Status: O Index: /sys/sys/tty_pty.c 4.2BSD Fix Description: Oink oink! That is the sound that data makes as it travels through 4.2BSD's pseudo-tty driver. Even in the high-volume direction (slave to controller) there is a great deal of code executed per-character. On our otherwise idle 750 I measured the maximum pty throughput at 5K chars/sec.; after applying the following mods it reached 30K chars/sec. If your machine is often accessed through rlogin(1c) this can mean considerable savings in system-state CPU time. Repeat-By: Run this program and use iostat(1) to see what your character rate is. #include char buf[1024]; int wsize = 1024; main() { int csock, dsock, i; for(i=0 ; it_outq.c_cc && uio->uio_resid > 0) if (ureadc(getc(&tp->t_outq), uio) < 0) { error = EFAULT; break; } to be while(uio->uio_resid > 0 && error == 0) { int cc = q_to_b(&tp->t_outq, ptc_rdbuf, MIN(uio->uio_resid, BUFSIZ)); if(cc == 0) break; error = uiomove(ptc_rdbuf, cc, UIO_READ, uio); } We have been using this code for 4 months. You may not experience quite as great an improvement as we did, because we also improved the performance of q_to_b(). -- Brian Thomson, CSRG Univ. of Toronto {linus,ihnp4,uw-beaver,floyd,utzoo}!utcsrgv!uthub!thomson From mogul@GREGORIO.ARPA Wed Jun 20 20:40:21 1984 Received: from BRL-TGR (brl-tgr.arpa) by seismo.ARPA with SMTP; Wed, 20 Jun 84 20:40:11 EDT Message-Id: <8406210040.AA00474@seismo.ARPA> Received: from brl-vgr.arpa by BRL-TGR.ARPA id a016507; 20 Jun 84 19:59 EDT Received: from gregorio.arpa by BRL-VGR.ARPA id a011042; 20 Jun 84 19:56 EDT Date: Wed, 20 Jun 84 16:51:48 pdt From: Jeff Mogul Subject: savecore doesn't really work with alternate system image Index: etc/savecore.c 4.2BSD Fix Apparently-To: other-4bsd-bugs Apparently-To: 4bsd-bugs@BERKELEY Status: RO Description: Savecore takes an optional argument to specify a file besides /vmunix as the system that was running when a crash dump was made. This does not work properly, because savecore uses the namelist from /vmunix even if an alternate system is specified, and so unless the systems are almost identical it decides that the crash dump has a bad magic number and fails to save it. Repeat-By: Configure a system differently from the one you normally run; make sure that the address of the variable _dumpmag is different. Call the new kernel /newvmunix; do NOT replace /vmunix boot /newvmunix and make it crash (with a dump.) boot /vmunix single-user, mount the appropriate filesystems, and type # /etc/savecore /usr/crash /newvmunix No core dump will be saved. Fix: One cannot fix this simply by having savecore read the namelist from the alternate system instead of /vmunix; this is because the program wants to compare values from the dump and from /dev/kmem. So, we need to use two copies of the namelist and change the appropriate references in the code to use one or the other. Note that the alternate system must still use the same dump partition and size as /vmunix uses (you'd be a fool if you tried to do otherwise.) The "diff" listing given below also includes code for an additional "-v" command-line flag, to make savecore a little more verbose about why it rejects a crash dump. diff savecore.c.old savecore.c 7a8,16 > > /* > * HISTORY: > * 20 June 1984 Jeff Mogul Stanford > * - Works properly with optional "system" argument (original > * version assumed identical offsets into /dev/kmem and dump.) > * - -v flag for more verbose output > */ > 28c37 < struct nlist nl[] = { --- > struct nlist current_nl[] = { /* namelist for currently running system */ 45a55,65 > struct nlist dump_nl[] = { /* name list for dumped system */ > { "_dumpdev" }, /* entries MUST be the same as */ > { "_dumplo" }, /* those in current_nl[] */ > { "_time" }, > { "_dumpsize" }, > { "_version" }, > { "_panicstr" }, > { "_dumpmag" }, > { "" }, > }; > 64a85 > int Verbose; 70a92,107 > while ((argc > 1) && (argv[1][0] == '-')) { > switch (argv[1][1]) { > case 'v': > Verbose = 1; > break; > default: > fprintf(stderr, "savecore: illegal flag -%c\n", > argv[1][1]); > fprintf(stderr, > "usage: savecore [-v] dirname [ system ]\n"); > exit(1); > } > argc--; > argv++; > } > 72c109 < fprintf(stderr, "usage: savecore dirname [ system ]\n"); --- > fprintf(stderr, "usage: savecore [-v] dirname [ system ]\n"); 90c127,129 < } else --- > } else { > if (Verbose) > fprintf(stderr, "No space or time\n"); 91a131 > } 92a133,135 > else if (Verbose) { > fprintf(stderr, "No dump exists\n"); > } 103c146 < Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_DUMPMAG].n_value)), 0); --- > Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), 0); 105a149,152 > if (Verbose && (word != dumpmag)) { > printf("dumplo = %d (%d bytes)\n", dumplo/512, dumplo); > printf("magic number mismatch: %x != %x\n", word, dumpmag); > } 115c162 < Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_DUMPMAG].n_value)), 0); --- > Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), 0); 158a206,208 > char *dump_sys; > > dump_sys = system ? system : "/vmunix"; 160,161c210,221 < nlist("/vmunix", nl); < if (nl[X_DUMPDEV].n_value == 0) { --- > nlist("/vmunix", current_nl); > nlist(dump_sys, dump_nl); > > /* > * Some names we need for the currently running system, > * others for the system that was running when the dump was made. > * The values obtained from the current system are used > * to look for things in /dev/kmem that cannot be found > * in the dump_sys namelist, but are presumed to be the same > * (since the disk partitions are probably the same!) > */ > if (current_nl[X_DUMPDEV].n_value == 0) { 165c225 < if (nl[X_DUMPLO].n_value == 0) { --- > if (current_nl[X_DUMPLO].n_value == 0) { 169,170c229,231 < if (nl[X_TIME].n_value == 0) { < fprintf(stderr, "savecore: /vmunix: time not in namelist\n"); --- > if (dump_nl[X_TIME].n_value == 0) { > fprintf(stderr, "savecore: %s: time not in namelist\n", > dump_sys); 173,174c234,236 < if (nl[X_DUMPSIZE].n_value == 0) { < fprintf(stderr, "savecore: /vmunix: dumpsize not in namelist\n"); --- > if (dump_nl[X_DUMPSIZE].n_value == 0) { > fprintf(stderr, "savecore: %s: dumpsize not in namelist\n", > dump_sys); 177,178c239,242 < if (nl[X_VERSION].n_value == 0) { < fprintf(stderr, "savecore: /vmunix: version not in namelist\n"); --- > /* we need VERSION in both images */ > if (current_nl[X_VERSION].n_value == 0) { > fprintf(stderr, "savecore: /vmunix: version not in namelist\n", > dump_sys); 181,182c245,247 < if (nl[X_PANICSTR].n_value == 0) { < fprintf(stderr, "savecore: /vmunix: panicstr not in namelist\n"); --- > if (dump_nl[X_VERSION].n_value == 0) { > fprintf(stderr, "savecore: %s: version not in namelist\n", > dump_sys); 185c250,256 < if (nl[X_DUMPMAG].n_value == 0) { --- > if (dump_nl[X_PANICSTR].n_value == 0) { > fprintf(stderr, "savecore: %s: panicstr not in namelist\n", > dump_sys); > exit(1); > } > /* we need DUMPMAG in both images */ > if (current_nl[X_DUMPMAG].n_value == 0) { 188a260,264 > if (dump_nl[X_DUMPMAG].n_value == 0) { > fprintf(stderr, "savecore: %s: dumpmag not in namelist\n", > dump_sys); > exit(1); > } 190c266 < Lseek(kmem, (long)nl[X_DUMPDEV].n_value, 0); --- > Lseek(kmem, (long)current_nl[X_DUMPDEV].n_value, 0); 192c268 < Lseek(kmem, (long)nl[X_DUMPLO].n_value, 0); --- > Lseek(kmem, (long)current_nl[X_DUMPLO].n_value, 0); 194c270 < Lseek(kmem, (long)nl[X_DUMPMAG].n_value, 0); --- > Lseek(kmem, (long)current_nl[X_DUMPMAG].n_value, 0); 204c280 < fseek(fp, (long)nl[X_VERSION].n_value, 0); --- > fseek(fp, (long)current_nl[X_VERSION].n_value, 0); 218c294 < fseek(fp, (off_t)(dumplo+ok(nl[X_VERSION].n_value)), 0); --- > fseek(fp, (off_t)(dumplo+ok(dump_nl[X_VERSION].n_value)), 0); 221c297 < if (!eq(vers, core_vers)) --- > if (!eq(vers, core_vers) && (system == 0)) 226c302 < fseek(fp, (off_t)(dumplo + ok(nl[X_PANICSTR].n_value)), 0); --- > fseek(fp, (off_t)(dumplo + ok(dump_nl[X_PANICSTR].n_value)), 0); 246c322 < Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_TIME].n_value)), 0); --- > Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), 0); 249c325,327 < if (dumptime == 0) --- > if (dumptime == 0) { > if (Verbose) > printf("dump time not found\n"); 250a329 > } 333c412 < Lseek(ifd, (off_t)(dumplo + ok(nl[X_DUMPSIZE].n_value)), 0); --- > Lseek(ifd, (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), 0); From harpo!decvax!mcnc!ncsu!uvacs!edison!jso Tue Jun 19 16:09:12 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Path: seismo!harpo!decvax!mcnc!ncsu!uvacs!edison!jso From: jso@edison.UUCP Newsgroups: net.bugs.4bsd Subject: lock hangs on 4.2 Message-ID: <270@edison.UUCP> Date: 19 Jun 84 20:09:12 GMT Date-Received: 22 Jun 84 05:27:49 GMT Lines: 28 Status: O Index: ucb/lock.c 4.2BSD Description: lock hangs on EOF read with 4.2 Repeat-By: lock, and type your eof character Fix: *** src/lock.c Tue Jun 19 16:00:29 1984 --- /usr/src/ucb/lock.c Sat Jul 2 03:51:54 1983 *************** *** 42,49 } s[0] = 0; for (;;) { ! if(fgets(s, sizeof s, stdin) == NULL) ! clearerr(stdin); if (strcmp(s1, s) == 0) break; if (strcmp(s, masterp) == 0) --- 42,48 ----- } s[0] = 0; for (;;) { ! fgets(s, sizeof s, stdin); if (strcmp(s1, s) == 0) break; if (strcmp(s, masterp) == 0) From cmcl2!lanl-a!unm-cvax!unmvax!lee Thu Jun 21 19:41:16 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site unmvax.UUCP Path: seismo!cmcl2!lanl-a!unm-cvax!unmvax!lee From: lee@unmvax.UUCP Newsgroups: net.bugs.4bsd Subject: 4.2 fortran can't handle large, negative floating constants (fix) Message-ID: <348@unmvax.UUCP> Date: 21 Jun 84 23:41:16 GMT Date-Received: 22 Jun 84 12:50:11 GMT Organization: Univ. of New Mexico, Albuquerque Lines: 53 Status: O Subject: 4.2 fortran can't handle large, negative floating constants Index: /usr/lib/f77pass1 4.2BSD Fix Description: If one uses large, negative floating (not double!) constants the error message "data value too large" appears and the compilation bombs, even though the constant may be easily handled by the VAX floating instructions. Repeat-By: Cut this out and compile it with f77 (doesn't matter whether the optimizer is on or off, for once). -------------------------------------------------------- program test real x data x/-1.7e+38/ write (6,*) x stop end ---------------------------------------------------------- Fix: The constants given were REAL weird for dminreal. I could not figure out why it was this way. At first I thought about just swapping the long words and then thought, "oh well" and changed it to be the same unsigned number as dmaxreal. Can't see anything this would break but I do not profess to know this compiler inside-out. Here is a diff of /usr/src/usr.bin/f77/src/f77pass1/conv.c RCS file: RCS/conv.c,v retrieving revision 1.1 diff -c -r1.1 conv.c *** /tmp/,RCSt1022729 Thu Jun 21 17:35:16 1984 --- conv.c Thu Jun 21 17:20:17 1984 *************** *** 21,27 LOCAL long dminint[] = { 0x0000d000, 0xffff00ff }; LOCAL long dmaxreal[] = { 0xffff7fff, 0xffff7fff }; ! LOCAL long dminreal[] = { 0x0000f800, 0xffffffff }; --- 21,27 ----- LOCAL long dminint[] = { 0x0000d000, 0xffff00ff }; LOCAL long dmaxreal[] = { 0xffff7fff, 0xffff7fff }; ! LOCAL long dminreal[] = { 0xffffffff, 0xffff7fff }; -- --Lee (Ward) {ucbvax,convex,gatech,pur-ee}!unmvax!lee From harpo!decvax!linus!utzoo!watmath!srradia Mon Jun 25 08:16:59 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site watmath.UUCP Path: seismo!harpo!decvax!linus!utzoo!watmath!srradia From: srradia@watmath.UUCP (sanjay Radia) Newsgroups: net.bugs.4bsd Subject: Bug in dump Message-ID: <8132@watmath.UUCP> Date: 25 Jun 84 12:16:59 GMT Date-Received: 26 Jun 84 17:19:17 GMT Organization: U of Waterloo, Ontario Lines: 96 Status: O Index: dump 4.2 Fix Description: A serious bug exists in dump. Dump makes a pass through all the inodes and marks the inodes to be dumped in dirmap & nodmap. However, if the system is busy the inodes can be deleted and possibly reallocated for other files. In the next pass, when dumping inodes, dump does not bother to check to see if the inodes are still allocated and in the case of directories does not check to see the inode is still a directory. Now, the dump tape has a bunch of directories (directory-zone) followed by non-directories and as soon as restore sees a non-directory it thinks it has scanned the directory-zone. Thus if a directory inode is delelted (and maybe realloced to a file) between the 1st & 2nd passes of dump, the dump tape will not be correctly read by restore (you will loose some (a lot) of the directory information). Repeated-By: Create about 3 directories and start a dump on the file system. When dump asks you to mount the tape delete one of the three directories (the one with the lowest inode #). Now continue with the dump. Do a "/etc/restore ivd". You will see that restore will not know of any directories with inodes greater than the the one you deleted (ie they will be marked as regular files and not as directories). You can check this out by doing a "lc" in restore's interactive mode. Fix: The following is a fix to dump. Since our dump has changed, the line numbers might not match. Note that restore can be fixed to ignore free inodes (in function dirextract() in dirs.c) but there is no nice way to by-pass file-inodes in the directory-zone. There should have been a special record between the directory-zone and the file-zone (if you put this in, your old & new tapes will not be compatible). ****** dumpmain.c >change the line marked with ! (the context and old/new versions given OLD *** 265,271 bitmap(clrmap, TS_CLRI); msg("dumping (Pass III) [directories]\n"); ! pass(dump, dirmap); msg("dumping (Pass IV) [regular files]\n"); pass(dump, nodmap); NEW --- 288,295 ----- bitmap(clrmap, TS_CLRI); msg("dumping (Pass III) [directories]\n"); ! pass(dirdump, dirmap); msg("dumping (Pass IV) [regular files]\n"); pass(dump, nodmap); --- dumptraverse.c > add the function dirdump() (marked with +) (add an extern in dump.h) > and add the lines marked with '+' in dump() (the context is given) + dirdump(ip) + struct dinode *ip; + { + /* watchout for dir inodes deleted and maybe reallocated */ + if ((ip->di_mode & IFMT) != IFDIR) + return; + dump(ip); + } + + dump(ip) struct dinode *ip; { ........ ...... ..... i = ip->di_mode & IFMT; + + if (i == 0) /* free inode */ + return; + if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) { spclrec(); return; -- sanjay {allegra,decvax}!watmath!srradia From hao!hplabs!sri-unix!walsh@BBN-LABS-B.ARPA Mon Jun 25 08:16:32 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Path: seismo!hao!hplabs!sri-unix!walsh@BBN-LABS-B.ARPA From: walsh@BBN-LABS-B.ARPA Newsgroups: net.unix-wizards Subject: UPAGES and 4.2BSD Message-ID: <1252@sri-arpa.UUCP> Date: 25 Jun 84 12:16:32 GMT Date-Received: 26 Jun 84 23:01:19 GMT Lines: 53 Status: O From: Bob Walsh If you need to increase the size of the kernel stack, you can increase UPAGES in vax/param.h from 8 to 10. If you do so, you'll run into the following problems: 1. a make doesn't recompile anything 2. after touching all the appropriate files, the booted system crashes To fix the problem, you need to edit vax/locore.s. (If you edit mysys/locore.c, your edited locore.c is thrown away by the make rules.) In locore.s, the subroutine Fastreclaim should be more properly coded as: *** locore.s Sun Jun 24 18:52:02 1984 --- locore.old Tue Jun 19 15:26:23 1984 *************** *** 1161,1167 movl $1,r2 # type = CTEXT; jbr 3f 2: ! subl3 P_SSIZE(r5),$(0x400000-UPAGES),r0 cmpl r3,r0 jgequ 2f # } else if (isadsv(p, v)) { ashl $2,r3,r4 --- 1157,1163 ----- movl $1,r2 # type = CTEXT; jbr 3f 2: ! subl3 P_SSIZE(r5),$0x3ffff8,r0 cmpl r3,r0 jgequ 2f # } else if (isadsv(p, v)) { ashl $2,r3,r4 *************** *** 1171,1177 2: cvtwl P_SZPT(r5),r4 # } else (isassv(p, v)) { ashl $7,r4,r4 ! subl2 $0x400000,r4 addl2 r3,r4 ashl $2,r4,r4 addl2 P_P0BR(r5),r4 # sptopte(p, vtosp(p, v)); --- 1167,1173 ----- 2: cvtwl P_SZPT(r5),r4 # } else (isassv(p, v)) { ashl $7,r4,r4 ! subl2 $(0x3ffff8+UPAGES),r4 addl2 r3,r4 ashl $2,r4,r4 addl2 P_P0BR(r5),r4 # sptopte(p, vtosp(p, v)); bob walsh From harpo!decvax!dartvax!steve Tue Jun 26 21:00:34 1984 Relay-Version: version B 2.10.2 beta 4/10/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site dartvax.UUCP Path: seismo!harpo!decvax!dartvax!steve From: steve@dartvax.UUCP (Steve Campbell) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: Simultaneous mv's cause crash Message-ID: <1936@dartvax.UUCP> Date: 27 Jun 84 01:00:34 GMT Date-Received: 27 Jun 84 08:13:55 GMT Organization: Dartmouth College Lines: 19 Status: O Well, folks, here's one that's so simple that it's hard to belive it could happen. One of our users (while using learn) did the following: mv file1 file2 & ; mv file3 file1 and guess what happened. The system crashed with: panic: ifree: freeing free inode and so forth. The damage had to be repaired with a manual fsck run. Now no real harm was done (other than inconveniencing some users), and granted that the command issued might be said to tempt fate, but still, aren't there some lockout mechanisms that should at least prevent file system damage under these circumstances? We run 4.2 on a 750, BTW. Steve Campbell UUCP: {decvax|linus|cornell|astrovax}!dartvax!steve CSNET: steve@dartmouth ARPA: steve%dartmouth@csnet-relay From harpo!decvax!ittvax!dcdwest!sdcsvax!akgua!whuxle!spuxll!abnjh!u1100a!pyuxn!pyuxww!gamma!ulysses!allegra!jpl Tue Jun 26 07:05:43 1984 Relay-Version: version B 2.10.2 7/1/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site allegra.UUCP Path: seismo!harpo!decvax!ittvax!dcdwest!sdcsvax!akgua!whuxle!spuxll!abnjh!u1100a!pyuxn!pyuxww!gamma!ulysses!allegra!jpl From: jpl@allegra.UUCP Newsgroups: net.bugs.4bsd Subject: 4.2 /etc/pstat -s is broken Message-ID: <2551@allegra.UUCP> Date: 26 Jun 84 11:05:43 GMT Date-Received: 28 Jun 84 15:29:27 GMT Organization: AT&T Bell Laboratories, Murray Hill Lines: 203 Status: O Synopis: /etc/pstat -s does not report accurately on the swapping system Symptoms: When /etc/pstat is invoked with the -s option, it is inclined to spew out a number of bogus "swap: rmap ovflo" messages and then give the wrong results. Repeat by: Try it. Go ahead. Make your day. My output looked like this: 47566 used (2002 text), 152562 free, 18178 wasted, 2112 missing avail: swap: rmap ovflo, lost [200704,201024) swap: rmap ovflo, lost [59392,200000) 4*1024 3*512 10*256 17*128 Sometimes I'd get many more ovflo messages. Quick fix: Insert the line marked with + between the other two lines from /usr/src/etc/pstat.c. swapmap->m_name = "swap"; + swapmap->m_limit = (struct mapent *)(swapmap + nswapmap); nswap = getw(nl[SNSWAP].n_value); Clean fix: Pstat determines the amount of available swap space by copying the the swap map out of the kernel, and then allocating blocks from this copy. Of course, this gives reasonable results only if the allocation scheme that pstat uses on the copy parallels the scheme used by the kernel on the original. Pstat parallels the kernel allocation scheme because somebody copied most of /sys/sys/subr_rmap.c (where the kernel allocation code is defined) into pstat.c, then massaged it to work in that context. The slip in transcribing the algorithm is not my main problem with the way it was done; the slip can be fixed. What bothers me more is that the kernel allocation scheme might change, and pstat won't track those changes. [A suggested change to subr_rmap.c is included in this report, as if to prove that changes are not inevitable.] The "right" way to fix the problem is to make some simple changes to subr_rmap.c and pstat.c that allow the latter to #include the former, making it much easier to track changes. [Pstat can't just load the subr_rmap.o file, because it is compiled with KERNEL defined.] Fortunately, /sys/sys/subr_rmap.c is a nicely written piece of software, so the changes to both routines are relatively minor. First, the changes to subr_rmap.c. We bracket the #includes with #ifdef KERNEL so we won't get multiple definitions when subr_rmap.c is included by pstat.c. Then we add a comment pointing back to pstat, to warn people about the dependency. + #ifdef KERNEL #include "../h/param.h" #include "../h/systm.h" #include "../h/map.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/proc.h" #include "../h/text.h" #include "../h/kernel.h" + #endif KERNEL ... * N.B.: the current implementation uses a dense array and does * not admit the value ``0'' as a legal address, since that is used * as a delimiter. + * + * This routine is included in pstat.c to check on swap allocation. + * If changes are made here, pstat should be remade and checked + * for compatibility. */ Here comes the "optional" change to subr_rmap.c. What's going on is that blocks of size dmmax should be allocated on dmmax boundaries when dealing with swap space and multiple swap devices. Variable "first" identifies how many bytes must be skipped to get to a dmmax boundary. If we start out on a dmmax boundary, which is not unlikely, since we will often allocate dmmax-sized chunks starting at dmmax boundaries, first gets set to dmmax, not 0. The effect is to leave a chunk of size dmmax that must be inserted into the allocation list, where it will be allocated the next time a request for dmmax bytes comes in (and force the list to collapse.) The space isn't "wasted", but the effort inserting it into the list and collapsing it out is wasted, and there may be undesirable global effects because blocks get allocated 2,1,4,3,6,5... instead of 1,2,3,4,5,6. Anyway, I put in a simple check for the [not-so-]special case, and our swap disks haven't exploded, so it works. /* * Search for a piece of the resource map which has enough * free space to accomodate the request. */ for (bp = ep; bp->m_size; bp++) { if (bp->m_size >= size) { /* * If allocating from swapmap, * then have to respect interleaving * boundaries. */ if (mp == swapmap && nswdev > 1 && #ifndef NEW - (first = dmmax - bp->m_addr%dmmax) < bp->m_size) { #else NEW + (first = dmmax - bp->m_addr%dmmax) != dmmax && + first < bp->m_size) { #endif NEW if (bp->m_size - first < size) continue; addr = bp->m_addr + first; rest = bp->m_size - first - size; bp->m_size = first; if (rest) rmfree(swapmap, rest, addr+size); return (addr); } The #ifdef that follows logically removes a piece of code that everyone seems to agree doesn't belong there to begin with. done: + #ifdef KERNEL /* * THIS IS RIDICULOUS... IT DOESN'T BELONG HERE! */ if ((mp == kernelmap) && kmapwnt) { kmapwnt = 0; wakeup((caddr_t)kernelmap); } + #endif KERNEL return; badrmfree: panic("bad rmfree"); } That's it for subr_rmap.c. Since #ifdef KERNEL is true when building the kernel, the non-optional changes are harmless there, and the optional one looks reasonable, too. With these changes in place, pstat.c can be fixed "properly" as follows. The first change makes variable "swapmap" external, the way subr_rmap expects to reference it. The second change is the quick fix from above. int dmmin, dmmax, nswdev; + struct map *swapmap; doswap() { struct proc *proc; int nproc; struct text *xtext; int ntext; - /* struct map *swapmap; */ int nswapmap; register struct proc *pp; int nswap, used, tused, free, waste; ... read(fc, swapmap, nswapmap * sizeof (struct map)); swapmap->m_name = "swap"; + swapmap->m_limit = (struct mapent *)(swapmap + nswapmap); nswap = getw(nl[SNSWAP].n_value); dmmin = getw(nl[SDMMIN].n_value); You can then take the code starting with: /* * Allocate 'size' units from the given * map. Return the base of the allocated space. * In a map, the addresses are increasing and the * list is terminated by a 0 size. * * Algorithm is first-fit. * and replace it and everything that follows it (~175 lines) with: #include panic(msg) char *msg; { printf("Bailing out with panic message `%s'\n", msg); exit(1); } to import the "real kernel allocation code" and bind up the dangling reference to panic(). Postscript: This was a very long posting to change a dozen lines of code. I hate long items, but I also get nervous about making changes from the net when I don't understand what they do. So I have attempted to explain what I thought was going on and why I changed things. I'd like to see more "tutorial" items about 4.2, and there are obviously a lot of people on the net that know pieces of 4.2 inside-out. Any good ideas how we can get that knowledge onto the net? John P. Linderman Software Sanitation Engineer allegra!jpl From harpo!decvax!ucbvax!mckusick Sat Jun 30 20:44:21 1984 Relay-Version: version B 2.10.2 7/1/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site ucbvax.UUCP Path: seismo!harpo!decvax!ucbvax!mckusick From: mckusick@ucbvax.UUCP (Kirk Mckusick) Newsgroups: net.bugs.4bsd Subject: Race condition causing 'freeing free inode' panic Message-ID: <1221@ucbvax.UUCP> Date: 1 Jul 84 00:44:21 GMT Date-Received: 1 Jul 84 10:20:04 GMT Organization: U.C. Berkeley Lines: 60 Status: O Subject: Race condition causing "freeing free inode" panic Index: sys/ufs_syscalls.c 4.2BSD Description: There is a race condition between the `unlink' and `rename' system calls that can cause the system to leave a reference in a directory that points to an unallocated inode. The next time the entry is accessed, the system panics with a "freeing free inode panic". Repeat-By: When the following two programs are run, the directory entry for "AA" eventually points to an unallocated inode and the `rename' system call panics when it tries to delete the previous file associated with "AA" in preparation for renaming "A". main() { while(1) { close(creat("A",0666)); rename("A","AA"); } } main() { while(1) { unlink("A"); } } Fix: *** ufs_syscalls.c Wed Jun 27 16:54:26 1984 --- ufs_syscalls.c Sat Jun 30 16:41:34 1984 *************** *** 942,954 * Insure directory entry still exists and * has not changed since the start of all * this. If either has occured, forget about ! * about deleting the original entry and just ! * adjust the link count in the inode. */ ! if (dp == NULL || u.u_dent.d_ino != ip->i_number) { ! ip->i_nlink--; ! ip->i_flag |= ICHG; ! } else { /* * If source is a directory, must adjust * link count of parent directory also. --- 942,950 ----- * Insure directory entry still exists and * has not changed since the start of all * this. If either has occured, forget about ! * about deleting the original entry. */ ! if (dp != NULL && u.u_dent.d_ino == ip->i_number) { /* * If source is a directory, must adjust * link count of parent directory also. From cmcl2!philabs!linus!utzoo!watmath!clyde!burl!mgnetp!ihnp4!mhuxl!cbosgd!mark Tue Jun 26 14:12:12 1984 Relay-Version: version B 2.10.2 7/1/84; site seismo.UUCP Posting-Version: version B 2.10 3/23/84; site cbosgd.UUCP Path: seismo!cmcl2!philabs!linus!utzoo!watmath!clyde!burl!mgnetp!ihnp4!mhuxl!cbosgd!mark From: mark@cbosgd.UUCP (Mark Horton) Newsgroups: net.bugs.4bsd Subject: rwho on suns finds zero load average Message-ID: <61@cbosgd.UUCP> Date: 26 Jun 84 18:12:12 GMT Date-Received: 1 Jul 84 12:51:37 GMT Distribution: net Organization: AT&T Bell Laboratories, Columbus Lines: 68 Status: O The "ruptime" command, on any network with Sun workstations on it, either does not show the Suns at all, or shows them with a zero load average. The system comes configured not to run rwhod, apparently because it is a performance pig. However, on a Sun with 2MB of RAM or more, it seems not to degrade performance noticeably. You must uncomment out a line in /etc/rc to enable rwhod to run. Once it runs, the load average is always claimed to be zero, even though uptime shows it correctly. The problem is that, since not all Sun systems have floating point hardware, Sun apparently redid the kernel code that keeps track of the load average to use fixed point calculations. The w command was updated to know about this, but rwhod was not. The new method has an array of three 4 byte integers, rather than an array of three 8 byte doubles. The integers are stored scaled by 8 bits, that is, the integer value, divided by 256, is the correct load average. The following changes to a VAX 4.2BSD rwhod.c work correctly on a Sun 1.1 system and on a 1.0 system. (For reasons I haven't figured out, however, the 1.0 system does not see a 4.2BSD VAX on the same net.) By the way, if there is a preferred way to report Sun bugs and fixes, I'd be interested to hear about it. Mark Horton *** orwhod.c Tue Jun 26 13:46:53 1984 --- rwhod.c Tue Jun 26 13:52:21 1984 *************** *** 226,232 struct stat stb; register struct whoent *we = mywd.wd_we, *wlast; int cc; ! double avenrun[3]; time_t now = time(0); register struct neighbor *np; --- 226,232 ----- struct stat stb; register struct whoent *we = mywd.wd_we, *wlast; int cc; ! long avenrun[3]; time_t now = time(0); register struct neighbor *np; *************** *** 270,276 (void) lseek(kmemf, (long)nl[NL_AVENRUN].n_value, L_SET); (void) read(kmemf, (char *)avenrun, sizeof (avenrun)); for (i = 0; i < 3; i++) ! mywd.wd_loadav[i] = htonl((u_long)(avenrun[i] * 100)); cc = (char *)we - (char *)&mywd; mywd.wd_sendtime = htonl(time(0)); mywd.wd_vers = WHODVERSION; --- 270,276 ----- (void) lseek(kmemf, (long)nl[NL_AVENRUN].n_value, L_SET); (void) read(kmemf, (char *)avenrun, sizeof (avenrun)); for (i = 0; i < 3; i++) ! mywd.wd_loadav[i] = htonl((u_long)(avenrun[i]*100+128)/256); cc = (char *)we - (char *)&mywd; mywd.wd_sendtime = htonl(time(0)); mywd.wd_vers = WHODVERSION; From dpk@BRL-VGR.ARPA Wed Jul 4 01:59:17 1984 Received: from BRL-TGR (brl-tgr.arpa) by seismo.ARPA with SMTP; Wed, 4 Jul 84 01:59:12 EDT Message-Id: <8407040559.AA02377@seismo.ARPA> Received: from brl-vgr.arpa by BRL-TGR.ARPA id a003925; 4 Jul 84 1:36 EDT Date: Wed, 4 Jul 84 1:32:53 EDT From: Doug Kingston To: unix-wizards@BRL-VGR.ARPA Subject: Netstat is SLOW, 4.2BSD, Easy FIX Status: RO Index: ucb/netstat/inet.c 4.2BSD FIX Description: Depressed at how slow netstat was on the VAX after hashing the host tables, I profiled netstat and found that it was spending 90 percent of its time in inetname() and most of that in getnetent(). A look at the code revealed that it was ALWAYS trying to look up the net name for a net even when that net was INADDR_ANY (all zeros). After looking this up (and failing, since that is not a valid net), it checked for that case and copied "*" into a buffer and returned. Repeat-By: Run "time netstat -a". Sit and wait. Look at the large CPU time. Fix: The fix is to move the check for INADDR_ANY to the start of the inetname() function to catch this trivial case and prevent any expensive and fruitless lookups. A diff listing follows, although the line numbers will be offset due to a header we add to the file. The fix is simple. 312a316,319 > if (in.s_addr == INADDR_ANY) { /* A quick check for the easy case */ > strcpy(line, "*"); > return (line); > } 329,331c336 < if (in.s_addr == INADDR_ANY) < strcpy(line, "*"); < else if (cp) --- > if (cp) Yours for a better 4.2BSD, -Doug- Douglas P. Kingston III Advanced Computer Systems Team Ballistics Research Lab Attn: DRSMC-BLV-V (A) APG, Md. 21005 (301) 278-6651 From dpk@BRL-VGR.ARPA Wed Jul 4 06:26:05 1984 Received: from BRL-TGR (brl-tgr.arpa) by seismo.ARPA with SMTP; Wed, 4 Jul 84 06:26:00 EDT Message-Id: <8407041026.AA03904@seismo.ARPA> Received: from brl-vgr.arpa by BRL-TGR.ARPA id a004864; 4 Jul 84 6:00 EDT Date: Wed, 4 Jul 84 5:54:03 EDT From: dpk@BRL-VGR.ARPA Subject: Rwhod inefficency fix Sender: dpk@BRL-VGR.ARPA To: unix-wizards@BRL-VGR.ARPA Status: RO Subject: Efficiency fix: Rwhod unnecessarily nlists the kernel Index: etc/rwhod/rwhod.c 4.2BSD FIX Description: Rwhod was nlisting the kernel every 10*sleep_interval seconds whether it needed to or not. This caused it to consume far more CPU and disk I/O than it should have. Repeat-By: Run "sa" and look at the stats for "rwhod". Fix: The following diff lists shows some code (~12 lines) which should be added to the top of getkmem(). This code will check to see when kernel file has been changed by stating the file and comparing the last inode change time with the current inode change time (it also checks the inode number). This feature of looking for vmunix to change is so that rwhod can eventually get the load average information even if you boot up an alternate kernel. The assumption is that you will copy or link the kernel you booted to /vmunix. The line numbers will be offset by a few lines do to a header we add to the files. 323a335,348 > struct stat statb; > static time_t unixctime = 0L; > static ino_t unixinode; > > if (stat ("/vmunix", &statb) < 0) { > if (unixctime != 0L) > return; /* get new values later ... */ > } > else if (unixctime != statb.st_ctime || unixinode != statb.st_ino) { > unixctime = statb.st_ctime; /* we're updating */ > unixinode = statb.st_ino; > } > else > return; From cmcl2!philabs!linus!decvax!decwrl!sun!idi!qubix!msc Wed Jul 11 19:32:39 1984 Relay-Version: version B 2.10.2 7/1/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site qubix.UUCP Path: seismo!cmcl2!philabs!linus!decvax!decwrl!sun!idi!qubix!msc From: msc@qubix.UUCP (Mark Callow) Newsgroups: net.bugs.4bsd,net.bugs.uucp Subject: tip only tries the first dialer in a list Message-ID: <1243@qubix.UUCP> Date: 11 Jul 84 23:32:39 GMT Date-Received: 14 Jul 84 09:57:22 GMT Distribution: net Organization: Qubix Graphic Systems, Saratoga, CA Lines: 60 Status: O Index: usr.bin/tip/hunt.c 4.2BSD Fix Description: Even if your /etc/remote entry specifies a list of dialers to try tip gives up if the open of the first one in the list fails. Repeat-By: Get some autodialers. I have 3. Edit /etc/remote so that the the dv entry shows multiple dialers. For example my UNIX-1200 entry is UNIX-1200:\ :dv=/dev/cul0,/dev/cul1,/dev/cul2:el=^D^U^C^S^Q^O@:du:at=hayes:\ :ie=#$%:oe=^D:br#1200: Do something to make the first dialer busy. The open of the dialer will fail and tip exits saying "call failed". Fix: There is a while loop in hunt() that loops through the available dialers. It first tries to get a lock on the device. This fails if uucp is using the device. In that case hunt() continues with the loop and tries the next dialer. Once it has the lock though, it fails to check for any error return from the subsequent open(2) call on the dialer. It breaks out of the loop and returns. If the open failed, any subsequent operation on the file descriptor fails and tip exits. How can the dialer open fail when it's not locked by uucp I hear you ask? I have modified my dh and dz drivers to handle dialin and dialout on a single line. If the line is busy with dialin then an ENXIO error is returned to any process opening it for dialout. Here is the change to hunt.c 2c2,3 < static char sccsid[] = "@(#)hunt.c 4.7 (Berkeley) 6/25/83"; --- > static char rcsid[] = > "$Header: hunt.c,v 1.2 84/07/11 14:21:46 root Rel $ QGSI"; 4a6,9 > /* > * From:"@(#)hunt.c 4.7 (Berkeley) 6/25/83"; > */ > 48c53,55 < if (!deadfl) { --- > if (deadfl || FD < 0) > delock(uucplock); /* Try another dialer */ > else { 54d60 < delock(uucplock); -- >From the TARDIS of Mark Callow msc@qubix.UUCP, decwrl!qubix!msc@Berkeley.ARPA ...{decvax,ucbvax,ihnp4}!decwrl!qubix!msc, ...{ittvax,amd70}!qubix!msc "Nothing shocks me. I'm an Engineer." From cmcl2!philabs!linus!decvax!decwrl!sun!idi!qubix!msc Wed Jul 11 19:34:39 1984 Relay-Version: version B 2.10.2 7/1/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site qubix.UUCP Path: seismo!cmcl2!philabs!linus!decvax!decwrl!sun!idi!qubix!msc From: msc@qubix.UUCP (Mark Callow) Newsgroups: net.bugs.4bsd,net.bugs.uucp Subject: tip can't remove lock file from mode 755 directory Message-ID: <1244@qubix.UUCP> Date: 11 Jul 84 23:34:39 GMT Date-Received: 14 Jul 84 09:57:28 GMT Distribution: net Organization: Qubix Graphic Systems, Saratoga, CA Lines: 96 Status: O Index: usr.bin/tip/tip.c 4.2BSD Fix Description: If you set you /usr/spool/uucp directory to mode 755 then tip can't remove the lock file it creates there for the dialer. Repeat-By: chmod 755 /usr/spool/uucp. Run tip and exit from it. Look in /usr/spool/uucp and find LCK..cul0 (or whatever) is still there. Fix: The problem is that after creating the lock file tip reverts to the real uid and gid and so can't delete anything from the spool directory which is owned by uucp. I chose to have tip fork a new process before it switches to the real uid and gid that waits for tip to finihs and then removes the lock file. An identical fix is needed in the alternative cu.c frontend. This is not a very elegant fix. come up with. Here are the changes to tip.c. 2c2,3 < static char sccsid[] = "@(#)tip.c 4.16 (Berkeley) 6/28/83"; --- > static char rcsid[] = > "$Header: tip.c,v 1.2 84/07/11 14:43:23 root Rel $ QGSI"; 5a7,10 > * From: "@(#)tip.c 4.16 (Berkeley) 6/28/83"; > */ > > /* 34a40,42 > #ifdef FORK > int child_id; > #endif 95a104,121 > #ifdef FORK > /* > * Fork a process to remain around with the effective uid and gid. > * This process removes the lock file when tip finishes. > */ > if ((child_id = fork()) < 0) > perror( argv[0] ); > if (child_id != 0) > { > int ex_status; > > while (child_id != wait(&ex_status)) > ; > /* child has died now remove the lock file. */ > delock(uucplock); > exit( ex_status >> (sizeof( int ) / 2) ); > } > #endif FORK Here are the changes to cu.c. 2c2,3 < static char sccsid[] = "@(#)cu.c 4.6 (Berkeley) 6/28/83"; --- > static char rcsid[] = > "$Header: cu.c,v 1.2 84/07/11 14:45:10 root Rel $ QGSI"; 4a6,9 > /* > * From: "@(#)cu.c 4.6 (Berkeley) 6/28/83"; > */ > 17a23,25 > #ifdef FORK > int child_id; > #endif 83a92,109 > #ifdef FORK > /* > * Fork a process to remain around with the effective uid and gid. > * This process removes the lock file when tip finishes. > */ > if ((child_id = fork()) < 0) > perror( argv[0] ); > if (child_id != 0) > { > int ex_status; > > while (child_id != wait(&ex_status)) > ; > /* child has died now remove the lock file. */ > delock(uucplock); > exit( ex_status >> (sizeof( int ) / 2) ); > } > #endif FORK -- >From the TARDIS of Mark Callow msc@qubix.UUCP, decwrl!qubix!msc@Berkeley.ARPA ...{decvax,ucbvax,ihnp4}!decwrl!qubix!msc, ...{ittvax,amd70}!qubix!msc "Nothing shocks me. I'm an Engineer." From rochester!bukys Tue Jul 17 18:25:35 1984 Relay-Version: version B 2.10.2 7/1/84; site seismo.UUCP Posting-Version: version B 2.10 5/3/83; site rochester.UUCP Path: seismo!rochester!bukys From: bukys@rochester.UUCP (Liudvikas Bukys) Newsgroups: net.bugs.4bsd Subject: 4.2 telnet and XON/XOFF flow control Message-ID: <256@rochester.UUCP> Date: 17 Jul 84 22:25:35 GMT Date-Received: 17 Jul 84 23:32:15 GMT Organization: U. of Rochester, CS Dept. Lines: 152 Status: O Index: ucb/telnet.c 4.2 Fix Description: Some terminals require local XON/XOFF flow control to work right, e.g., VT125s at >2400 baud, or just about anything at 19.2Kbaud without hardware flow control. Telnet should leave this enabled, at least as an option. Repeat-By: Find such a terminal, telnet to something, and watch your terminal lose characters when the remote system doesn't respond quickly enough. Fix: The following diffs add a "flow" command for toggling the presence of flow control. It defaults to "on", but the default can be changed by changing the 1 in line 43 to a 0. It really should be an argument line flag, but at least this implementation is consistent with the rest of the telnet option setting code. Diffs (-c): ------- *** /tmp/,RCSt1026121 (old) --- telnet.c (new) *************** *** 40,45 int options; int debug = 0; int crmod = 0; char *prompt; char escape = CTRL(]); --- 40,46 ----- int options; int debug = 0; int crmod = 0; + int flow = 1; char *prompt; char escape = CTRL(]); *************** *** 54,60 int tn(), quit(), suspend(), bye(), help(); int setescape(), status(), toggle(), setoptions(); ! int setcrmod(), setdebug(); #define HELPINDENT (sizeof ("connect")) --- 55,61 ----- int tn(), quit(), suspend(), bye(), help(); int setescape(), status(), toggle(), setoptions(); ! int setcrmod(), setflow(), setdebug(); #define HELPINDENT (sizeof ("connect")) *************** *** 74,79 char helphelp[] = "print help information"; char optionshelp[] = "toggle viewing of options processing"; char crmodhelp[] = "toggle mapping of received carriage returns"; struct cmd cmdtab[] = { { "open", openhelp, tn }, --- 75,81 ----- char helphelp[] = "print help information"; char optionshelp[] = "toggle viewing of options processing"; char crmodhelp[] = "toggle mapping of received carriage returns"; + char flowhelp[] = "toggle flow control (usually XON/XOFF)"; struct cmd cmdtab[] = { { "open", openhelp, tn }, *************** *** 84,89 { "status", statushelp, status }, { "options", optionshelp, setoptions }, { "crmod", crmodhelp, setcrmod }, { "debug", debughelp, setdebug }, { "?", helphelp, help }, 0 --- 86,92 ----- { "status", statushelp, status }, { "options", optionshelp, setoptions }, { "crmod", crmodhelp, setcrmod }, + { "flow", flowhelp, setflow }, { "debug", debughelp, setdebug }, { "?", helphelp, help }, 0 *************** *** 354,359 tc = ¬c; ltc = &noltc; onoff = 1; break; default: --- 357,367 ----- tc = ¬c; ltc = &noltc; onoff = 1; + if (flow) { + notc.t_startc = otc.t_startc; + notc.t_stopc = otc.t_stopc; + } else + notc.t_startc = notc.t_stopc = -1; break; default: *************** *** 721,726 crmod = !crmod; printf("%s map carriage return on output.\n", crmod ? "Will" : "Wont"); fflush(stdout); } --- 729,747 ----- crmod = !crmod; printf("%s map carriage return on output.\n", crmod ? "Will" : "Wont"); + fflush(stdout); + } + + /*VARARGS*/ + setflow() + { + + flow = !flow; + printf("%s use local flow control.\n", flow ? "Will" : "Wont"); + if (flow) { + printf("(%s to stop,", control(otc.t_stopc)); + printf(" %s to start)\n", control(otc.t_startc)); + } fflush(stdout); } ------- Brought-to-you-by: Liudvikas Bukys bukys@rochester (arpa) rochester!bukys (uucp) via allegra, cmcl2, decvax, seismo From unix-wizards Mon Jul 30 23:57:11 1984 Relay-Version: version B 2.10.2 7/1/84; site seismo.UUCP Posting-Version: version B 2.10.2 7/1/84; site seismo.UUCP Path: seismo!unix-wizards From: unix-wizards@seismo.UUCP Newsgroups: unix-wizards Subject: 4.2 Tcp timer fixes Message-ID: <2487@seismo.UUCP> Date: 31 Jul 84 03:57:11 GMT Date-Received: 31 Jul 84 03:57:11 GMT Sender: daemon@seismo.UUCP Organization: Center for Seismic Studies, Arlington, VA Lines: 527 Status: O From: hplabs!tektronix!orca!hammer!steveh@UCB-VAX.ARPA The 4.2 Tcp code has several bugs in relation to Round Trip Time and Retransmissions. Also including older fixes for those folks who haven't got them. Speed fix: If you want to experiment with speeding up tcp, try increasing 'tcp_sendspace' and 'tcp_recvspace'. You can vary them up from the 2K defaults to 12K (bigger crashes system), but there is a speed/memory tradeoff here which has to be made. Bug #1: Retransmits increase round trip time. Description: If a segment being timed (to determine round trip time), is lost then the round trip time will keep increasing. Repeat-by: Try copying something (with ftp for example), on a lossy network which drops packets. The connection will get progressively slower as the computed round trip time gets progressively larger (thereby increasing the smooth round trip time, and therefore the retransmit timeout). Bug #2: Only the second segment in a window is retransmitted. Description: The round trip time is only computed by the second segment sent in a window. This causes the round trip time to computed only occasionally, leading to poor adaptive performance. Repeat-by: Observe how often the round trip time is computed with trpt, or other program (or either putting printf's in the kernel). Bug #3: (Old) Max seg size is always 1024. Description: Original code set max seg size to 1024, causing excessive fragmentation on devices with mtu < 1024. Repeat-by: Set mtu down on device, or try working with network devices with mtu < 1024 + sizeof(tcpiphdr). Fixes: *** tcp_output.4_2 Sun Jul 29 11:39:42 1984 --- tcp_output.fix Sun Jul 29 12:10:17 1984 *************** *** 1,4 ! /* tcp_output.c 6.1 83/07/29 */ #include "../h/param.h" #include "../h/systm.h" --- 1,4 ----- ! /* tcp_output.c 6.1 (Berkeley/w fixes) 83/07/29 */ #include "../h/param.h" #include "../h/systm.h" *************** *** 8,13 #include "../h/socketvar.h" #include "../h/errno.h" #include "../net/route.h" #include "../netinet/in.h" --- 8,14 ----- #include "../h/socketvar.h" #include "../h/errno.h" + #include "../net/if.h" #include "../net/route.h" #include "../netinet/in.h" *************** *** 37,42 { register struct socket *so = tp->t_inpcb->inp_socket; register int len; struct mbuf *m0; int off, flags, win, error; register struct mbuf *m; --- 38,44 ----- { register struct socket *so = tp->t_inpcb->inp_socket; register int len; + register struct ifnet *ifp; struct mbuf *m0; int off, flags, win, error; register struct mbuf *m; *************** *** 44,49 u_char *opt; unsigned optlen = 0; int sendalot; /* * Determine length of data that should be transmitted, --- 46,54 ----- u_char *opt; unsigned optlen = 0; int sendalot; + struct ifnet *tcp_getif(); + u_short ifmss; + extern int tcpprintfs; /* * Determine length of data that should be transmitted, *************** *** 172,178 goto noopt; opt = tcp_initopt; optlen = sizeof (tcp_initopt); ! *(u_short *)(opt + 2) = MIN(so->so_rcv.sb_hiwat / 2, 1024); *(u_short *)(opt + 2) = htons(*(u_short *)(opt + 2)); } else { if (tp->t_tcpopt == 0) --- 177,199 ----- goto noopt; opt = tcp_initopt; optlen = sizeof (tcp_initopt); ! /* ! * Tune max seg size to mtu of device this connection ! * will run on, in order to avoid IP fragmentation ! * as much as possible. Subtract off standard TCP/IP header. ! * If bigger than a page, round to pagesize ! * (so can use pagesize mbufs effectively). ! */ ! ! ifp = tcp_getif(tp); ! if (ifp == (struct ifnet *) 0) ! goto noopt; ! ifmss = ifp->if_mtu - sizeof(struct tcpiphdr); ! if(ifmss > CLBYTES) ! ifmss = ifmss &~ (CLBYTES-1); /* round to a page */ ! *(u_short *)(opt + 2) = MIN(so->so_rcv.sb_hiwat / 2, ifmss); ! if(tcpprintfs) ! printf("tcp output: maxseg = %d\n", *(u_short *)(opt+2)); *(u_short *)(opt + 2) = htons(*(u_short *)(opt + 2)); } else { if (tp->t_tcpopt == 0) *************** *** 249,255 if (flags & (TH_SYN|TH_FIN)) tp->snd_nxt++; tp->snd_nxt += len; ! if (SEQ_GT(tp->snd_nxt, tp->snd_max)) tp->snd_max = tp->snd_nxt; /* --- 270,276 ----- if (flags & (TH_SYN|TH_FIN)) tp->snd_nxt++; tp->snd_nxt += len; ! if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { tp->snd_max = tp->snd_nxt; /* *************** *** 252,264 if (SEQ_GT(tp->snd_nxt, tp->snd_max)) tp->snd_max = tp->snd_nxt; ! /* ! * Time this transmission if not a retransmission and ! * not currently timing anything. ! */ ! if (SEQ_GT(tp->snd_nxt, tp->snd_max) && tp->t_rtt == 0) { ! tp->t_rtt = 1; ! tp->t_rtseq = tp->snd_nxt - len; } /* --- 273,287 ----- if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { tp->snd_max = tp->snd_nxt; ! /* ! * Time this transmission if not a retransmission and ! * not currently timing anything. ! */ ! ! if ( tp->t_rtt == 0 && tp->t_rxtshift == 0) ! tp->t_rtt = 1; ! tp->t_rtseq = tp->snd_nxt - len; ! } } /* *************** *** 271,277 tp->snd_nxt != tp->snd_una) { TCPT_RANGESET(tp->t_timer[TCPT_REXMT], tcp_beta * tp->t_srtt, TCPTV_MIN, TCPTV_MAX); - tp->t_rtt = 0; tp->t_rxtshift = 0; } tp->t_timer[TCPT_PERSIST] = 0; --- 294,299 ----- tp->snd_nxt != tp->snd_una) { TCPT_RANGESET(tp->t_timer[TCPT_REXMT], tcp_beta * tp->t_srtt, TCPTV_MIN, TCPTV_MAX); tp->t_rxtshift = 0; } tp->t_timer[TCPT_PERSIST] = 0; *** tcp_timer.4_2 Sun Jul 29 11:39:52 1984 --- tcp_timer.fix Sun Jul 29 12:13:03 1984 *************** *** 1,4 ! /* tcp_timer.c 6.1 83/07/29 */ #include "../h/param.h" #include "../h/systm.h" --- 1,4 ----- ! /* tcp_timer.c 6.1 (Berkeley/w fix) 83/07/29 */ #include "../h/param.h" #include "../h/systm.h" *************** *** 80,87 } } tp->t_idle++; - if (tp->t_rtt) - tp->t_rtt++; tpgone: ip = ipnxt; } --- 80,85 ----- } } tp->t_idle++; tpgone: ip = ipnxt; } *************** *** 112,117 register struct tcpcb *tp; int timer; { switch (timer) { --- 110,118 ----- register struct tcpcb *tp; int timer; { + /* move before switch so we can reset if necessary */ + if (tp->t_rtt) + tp->t_rtt++; switch (timer) { *************** *** 148,153 TCPTV_MIN, TCPTV_MAX); } tp->snd_nxt = tp->snd_una; /* this only transmits one segment! */ (void) tcp_output(tp); break; --- 149,162 ----- TCPTV_MIN, TCPTV_MAX); } tp->snd_nxt = tp->snd_una; + + /* BUGFIX: + * if we were timing this segment, restart the timer + */ + if(tp->t_rtt && SEQ_GEQ(tp->snd_nxt,tp->t_rtseq)) { + tp->t_rtt = 1; + tp->t_rtseq = tp->snd_nxt; + } /* this only transmits one segment! */ (void) tcp_output(tp); break; *** tcp_input.4_2 Sun Jul 29 12:16:44 1984 --- tcp_input.fix Sun Jul 29 12:17:19 1984 *************** *** 1,4 ! /* tcp_input.c 6.1 83/07/29 */ #include "../h/param.h" #include "../h/systm.h" --- 1,4 ----- ! /* tcp_input.c 6.1 (Berkeley/w fixes) 83/07/29 */ #include "../h/param.h" #include "../h/systm.h" *************** *** 49,54 short ostate; struct in_addr laddr; int dropsocket = 0; /* * Get IP and TCP header together in first mbuf. --- 49,57 ----- short ostate; struct in_addr laddr; int dropsocket = 0; + struct ifnet *ifp; + struct ifnet *tcp_getif(); + u_short ifmss; /* * Get IP and TCP header together in first mbuf. *************** *** 186,193 * Process options. */ if (om) { ! tcp_dooptions(tp, om); ! om = 0; } /* --- 189,199 ----- * Process options. */ if (om) { ! /* if in LISTEN, template hasn't been filled in yet */ ! if (tp->t_state != TCPS_LISTEN){ ! tcp_dooptions(tp, ti, om); ! om = 0; ! } } /* *************** *** 246,251 tp = 0; goto drop; } tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; tp->irs = ti->ti_seq; tcp_sendseqinit(tp); --- 252,262 ----- tp = 0; goto drop; } + /* finally, we can do the options */ + if (om){ + tcp_dooptions(tp, ti, om); + om = 0; + } tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; tp->irs = ti->ti_seq; tcp_sendseqinit(tp); *************** *** 292,297 soisconnected(so); tp->t_state = TCPS_ESTABLISHED; (void) tcp_reass(tp, (struct tcpiphdr *)0); } else tp->t_state = TCPS_SYN_RECEIVED; goto trimthenstep6; --- 303,324 ----- soisconnected(so); tp->t_state = TCPS_ESTABLISHED; (void) tcp_reass(tp, (struct tcpiphdr *)0); + /* + * Tune maximum TCP segment size to i/f mtu + * (Rounded off to a pagesize if possible). + */ + ifp = (struct ifnet *) tcp_getif(tp); + if (ifp != (struct ifnet *)0){ + ifmss = ifp->if_mtu - sizeof(struct tcpiphdr); + if(ifmss > CLBYTES) + ifmss &= ~(CLBYTES-1); + if (tcpprintfs) + printf("tcp trim1 (mtu,ms)==(%d,%d) -> ", + ifmss, tp->t_maxseg); + tp->t_maxseg = MIN(ifmss, tp->t_maxseg); + if (tcpprintfs) + printf("%d\n", tp->t_maxseg); + } } else tp->t_state = TCPS_SYN_RECEIVED; goto trimthenstep6; *************** *** 452,457 soisconnected(so); tp->t_state = TCPS_ESTABLISHED; (void) tcp_reass(tp, (struct tcpiphdr *)0); tp->snd_wl1 = ti->ti_seq - 1; /* fall into ... */ --- 479,499 ----- soisconnected(so); tp->t_state = TCPS_ESTABLISHED; (void) tcp_reass(tp, (struct tcpiphdr *)0); + /* + * Tune maximum TCP segment size to i/f mtu + */ + ifp = (struct ifnet *) tcp_getif(tp); + if (ifp != (struct ifnet *)0){ + ifmss = ifp->if_mtu - sizeof(struct tcpiphdr); + if(ifmss > CLBYTES) + ifmss &= ~(CLBYTES-1); + if (tcpprintfs) + printf("tcp trim2 (mtu,ms)==(%d,%d) -> ", + ifmss, tp->t_maxseg); + tp->t_maxseg = MIN(ifmss, tp->t_maxseg); + if (tcpprintfs) + printf("%d\n", tp->t_maxseg); + } tp->snd_wl1 = ti->ti_seq - 1; /* fall into ... */ *************** *** 501,508 tp->t_rxtshift = 0; } if (acked > so->so_snd.sb_cc) { ! sbdrop(&so->so_snd, so->so_snd.sb_cc); ! tp->snd_wnd -= so->so_snd.sb_cc; } else { sbdrop(&so->so_snd, acked); tp->snd_wnd -= acked; --- 543,550 ----- tp->t_rxtshift = 0; } if (acked > so->so_snd.sb_cc) { ! tp->snd_wnd -= so->so_snd.sb_cc; /* update, */ ! sbdrop(&so->so_snd, so->so_snd.sb_cc); /* then drop */ } else { sbdrop(&so->so_snd, acked); tp->snd_wnd -= acked; *************** *** 530,535 if (so->so_state & SS_CANTRCVMORE) soisdisconnected(so); tp->t_state = TCPS_FIN_WAIT_2; } break; --- 572,583 ----- if (so->so_state & SS_CANTRCVMORE) soisdisconnected(so); tp->t_state = TCPS_FIN_WAIT_2; + /* this does not agree with spec. + * but unless we provide a way out of + * FIN_WAIT_2, it is possible to get stuck. + * Fix: from John Quarterman @ ut-sally.UUCP + */ + tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; } break; *************** *** 759,765 return; } ! tcp_dooptions(tp, om) struct tcpcb *tp; struct mbuf *om; { --- 807,813 ----- return; } ! tcp_dooptions(tp, ti, om) struct tcpcb *tp; struct tcpiphdr *ti; struct mbuf *om; *************** *** 761,766 tcp_dooptions(tp, om) struct tcpcb *tp; struct mbuf *om; { register u_char *cp; --- 809,815 ----- tcp_dooptions(tp, ti, om) struct tcpcb *tp; + struct tcpiphdr *ti; struct mbuf *om; { register u_char *cp; *************** *** 786,791 case TCPOPT_MAXSEG: if (optlen != 4) continue; tp->t_maxseg = *(u_short *)(cp + 2); tp->t_maxseg = ntohs((u_short)tp->t_maxseg); --- 835,842 ----- case TCPOPT_MAXSEG: if (optlen != 4) + continue; + if ((ti->ti_flags & TH_SYN) != TH_SYN) continue; tp->t_maxseg = *(u_short *)(cp + 2); tp->t_maxseg = ntohs((u_short)tp->t_maxseg); From rochester!ritcv!ccivax!crp Fri Sep 7 11:27:04 1984 Relay-Version: version B 2.10.2 9/5/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/5/84; site ccivax.UUCP Path: seismo!rochester!ritcv!ccivax!crp From: crp@ccivax.UUCP (Chuck Privitera) Newsgroups: net.bugs.4bsd Subject: Bug in rwhod Message-ID: <201@ccivax.UUCP> Date: 7 Sep 84 15:27:04 GMT Date-Received: 7 Sep 84 21:29:10 GMT Distribution: net Organization: CCI Telephony Systems Group, Rochester NY Lines: 41 Status: O Index: /usr/src/etc/rwhod/rwhod.c 4.2BSD Description: There is a minor nit in rwhod as distributed with 4.2 . In the routine onalrm(), they stat /etc/utmp to try to avoid re-reading it if it hasn't changed since the last time they read it. The only problem is that they never save the last-read time, so rwhod re-reads utmp every minute. The one line fix is given below in a context diff. Repeat-by: Just read the code. Fix: rcsdiff -c -r1.1 rwhod.c RCS file: RCS/rwhod.c,v retrieving revision 1.1 diff -c -r1.1 rwhod.c *** /tmp/,RCSt1002139 Fri Sep 7 10:29:39 1984 --- rwhod.c Fri Sep 7 10:27:41 1984 *************** *** 235,240 alarmcount++; (void) fstat(utmpf, &stb); if (stb.st_mtime != utmptime) { (void) lseek(utmpf, (long)0, L_SET); cc = read(utmpf, (char *)utmp, sizeof (utmp)); if (cc < 0) { --- 235,241 ----- alarmcount++; (void) fstat(utmpf, &stb); if (stb.st_mtime != utmptime) { + utmptime = stb.st_mtime; (void) lseek(utmpf, (long)0, L_SET); cc = read(utmpf, (char *)utmp, sizeof (utmp)); if (cc < 0) { -- Chuck Privitera, Computer Consoles Inc. {allegra,seismo}!rochester!ritcv!ccivax!crp From hao!hplabs!sri-unix!rlb@RIACS.ARPA Tue Sep 25 19:35:00 1984 Relay-Version: version B 2.10.2 9/18/84; site seismo.UUCP Path: seismo!hao!hplabs!sri-unix!rlb@RIACS.ARPA From: rlb@RIACS.ARPA Newsgroups: net.unix-wizards Subject: adventure doesn't work Message-ID: <12374@sri-arpa.UUCP> Date: 25 Sep 84 23:35:00 GMT Date-Received: 26 Sep 84 17:42:47 GMT Lines: 19 Status: O From: Bob Brown After one year of adventure not working (4.2BSD) someone complained and I formulated a patch. The following should be enough to make it work: % sum adventure 42120 138 % adb -w adventure 8c50?w 5 8c50: 1 = 5 8c64?w 82 8c64: 2 = 82 $q % Bob Brown RIACS/NASA Ames ---------- From cmcl2!lanl-a!unm-cvax!unmvax!lee Thu Sep 27 19:04:18 1984 Relay-Version: version B 2.10.2 9/27/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/5/84; site unmvax.UUCP Path: seismo!cmcl2!lanl-a!unm-cvax!unmvax!lee From: lee@unmvax.UUCP Newsgroups: net.bugs.4bsd Subject: 4.2 tftp goes into an infinite loop on EOF (fix) Message-ID: <450@unmvax.UUCP> Date: 27 Sep 84 23:04:18 GMT Date-Received: 28 Sep 84 10:11:41 GMT Distribution: net Organization: Univ. of New Mexico, Albuquerque Lines: 59 Status: O Subject: tftp will go into an infinite loop if given the EOF character Index: /usr/ucb/tftp 4.2BSD (fix) Description: See subject line Repeat-By: Get into tftp Type ^D or whatever your EOF character is. Watch the fun! Fix: Make the following changes to .../src/ucb/tftp/main.c RCS file: RCS/main.c,v retrieving revision 1.1 diff -c -r1.1 main.c *** /tmp/,RCSt1013708 Thu Sep 27 16:58:43 1984 --- main.c Thu Sep 27 16:58:08 1984 *************** *** 457,463 putchar('\n'); for (;;) { printf("%s> ", prompt); ! if (gets(line) == 0) continue; if (line[0] == 0) continue; --- 457,465 ----- putchar('\n'); for (;;) { printf("%s> ", prompt); ! if (gets(line) == 0) { ! clearerr(stdin); ! putchar('\n'); continue; } if (line[0] == 0) *************** *** 459,464 printf("%s> ", prompt); if (gets(line) == 0) continue; if (line[0] == 0) continue; makeargv(); --- 461,467 ----- clearerr(stdin); putchar('\n'); continue; + } if (line[0] == 0) continue; makeargv(); -- --Lee (Ward) {ucbvax,convex,gatech,pur-ee}!unmvax!lee From hao!hplabs!sri-unix!morgan@UCI-750A.ARPA Tue Oct 2 18:31:27 1984 Relay-Version: version B 2.10.2 9/27/84; site seismo.UUCP Path: seismo!hao!hplabs!sri-unix!morgan@UCI-750A.ARPA From: morgan@UCI-750A.ARPA Newsgroups: net.unix-wizards Subject: bug in dmf32 driver and possibly others Message-ID: <12610@sri-arpa.UUCP> Date: 2 Oct 84 22:31:27 GMT Date-Received: 3 Oct 84 18:56:58 GMT Lines: 50 Status: O From: Tim Morgan Description: The dmf driver does not contain code to wake up processes which are select'ing on output. Repeat-By: Log onto a terminal on a dmf32 or clone. Telnet to any system, including the local one. Run something on that system which will produce lots of output (such as cat'ing /etc/termcap). After a few hundred characters, the output will stop. It will not start again until you type something. Telnet is waiting until the output buffer empties to write more, but the dmf driver never does a selwakeup() call, so the select() call never returns unless something else occurs, such as a character in the input buffer. Fix: Here is a diff listing of the fix. The code inserted is from the dz driver; it also occurs in the dh driver and possibly others. You line numbers may differ. *** old_dmf.c Sat Sep 22 21:44:11 1984 --- dmf.c Sat Sep 22 21:44:45 1984 *************** *** 609,617 * If there are sleepers, and output has drained below low * water mark, wake up the sleepers. */ ! if ((tp->t_state&TS_ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) { ! tp->t_state &= ~TS_ASLEEP; ! wakeup((caddr_t)&tp->t_outq); } /* * Now restart transmission unless the output queue is --- 609,624 ----- * If there are sleepers, and output has drained below low * water mark, wake up the sleepers. */ ! if (tp->t_outq.c_cc<=TTLOWAT(tp)) { ! if (tp->t_state&TS_ASLEEP) { ! tp->t_state &= ~TS_ASLEEP; ! wakeup((caddr_t)&tp->t_outq); ! } ! if (tp->t_wsel) { ! selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); ! tp->t_wsel = 0; ! tp->t_state &= ~TS_WCOLL; ! } } /* * Now restart transmission unless the output queue is From unix-wizards Sun Oct 7 05:24:30 1984 Relay-Version: version B 2.10.2 9/27/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/27/84; site seismo.UUCP Path: seismo!unix-wizards From: unix-wizards@seismo.UUCP Newsgroups: unix-wizards Subject: sh conditionals do not work inside make files (with fix) Message-ID: <4545@seismo.UUCP> Date: 7 Oct 84 09:24:30 GMT Date-Received: 7 Oct 84 09:24:30 GMT Sender: daemon@seismo.UUCP Organization: Center for Seismic Studies, Arlington, VA Lines: 59 Status: O From: ihnp4!drutx!houxe!hogpc!houti!ariel!vax135!cornell!uw-beaver!fluke!joe@UCB-VAX.ARPA Subject: shell error handling -e flag breaks conditionals in make. Index: bin/sh/xec.c 4.2BSD Description: sh conditionals do not work inside make files. Repeat-By: Place an if statement with both branches in a make file such that the condition is false to try to force execution of the else clause. For example: all: if false ; then echo "true" ; else "false" ; fi Make will report an error and exit immediately after printing the command line. Fix: The -e flag is supposed to cause the shell to exit as soon as it encounters a command which returns non-zero exit status. Make obviously uses this flag so that it can pass complex shell commands without parsing them into individual lines. Unfortunately, the shell will exit if the command on a conditional test internal statement returns non-zero status. Shell should treat commands run for the if, while, and until commands differently than others when the -e flag is set. The solution is to turn off the -e flag while running the commands associated with these flow control statements, then turn it back on immediately after. Here are diff -e for the module xec.c (sorry -this is proprietary, so I can't post contextual diffs - I am also indenting them so that the naked '.'s don't offend anyones software): > 379,380c > THEN flags |= saveflg; > execute(t->thtre,execflg); > ELSE flags |= saveflg; > execute(t->eltre,execflg); > . > 377a > saveflg = flags&errflg; > flags &= ~errflg; > . > 371a > flags |= saveflg; > . > 369c > DO flags |= saveflg; > i=execute(t->dotre,0); > flags &= ~errflg; > . > 366a > saveflg = flags&errflg; > flags &= ~errflg; > . > 32a > INT saveflg; > . /Joe From harvard!wjh12!genrad!decvax!mulga!kre Mon Oct 1 06:38:36 1984 Relay-Version: version B 2.10.2 9/27/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site mulga.OZ Path: seismo!harvard!wjh12!genrad!decvax!mulga!kre From: kre@mulga.OZ (Robert Elz) Newsgroups: net.bugs.4bsd Subject: 4.2 disk quota bug setting quotas for logged in users (FIX) Message-ID: <463@mulga.OZ> Date: 1 Oct 84 10:38:36 GMT Date-Received: 8 Oct 84 05:14:23 GMT Organization: Comp Sci, Melbourne Uni, Australia Lines: 47 Status: O Index: sys/quota_sys.c 4.2bsd FIX Description: If you attempt to set a new disk quota on a user who has recently deleted some files, the system will quite likely soon panic with "maknode: dquot". This has been known to appear as if the problem is setting disk quotas of a user who is logged in. Repeat-By: Find some user who has no quotas, have him log in & delete some files (create them first if necessary) then set quotas on that filesystem (the one that files were deleted on). Have the user create the files again (any contents, or none). Unless you're very lucky, you will get a panic("maknode: dquot"). (Of course, the system may have panic'd because of some other user creating a file before you get a chance). Fix: The following diff is to sys/quota_sys.c, the line numbers are most probably way out, but its right near the end of function setdlim() (last 10 lines). First piece of text is the old (buggy) version, second is the fixed one. *** /tmp/quota_sys.c Mon Oct 1 05:27:25 1984 --- quota_sys.c Sun Jul 15 07:13:23 1984 *************** *** 171,177 if (dq == odq) return (error); for (ip = inode; ip < inodeNINODE; ip++) ! if (ip->i_uid == q->q_uid && ip->i_dev == dev) { if (dq == NODQUOT) dqrele(ip->i_dquot); else --- 171,177 ----- if (dq == odq) return (error); for (ip = inode; ip < inodeNINODE; ip++) ! if (ip->i_uid == q->q_uid && ip->i_dev == dev && ip->i_mode) { if (dq == NODQUOT) dqrele(ip->i_dquot); else Robert Elz decvax!mulga!kre From unix-wizards Wed Oct 10 13:01:17 1984 Relay-Version: version B 2.10.2 9/27/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/27/84; site seismo.UUCP Path: seismo!unix-wizards From: unix-wizards@seismo.UUCP Newsgroups: unix-wizards Subject: brl-vgr Bug Report Message-ID: <4642@seismo.UUCP> Date: 10 Oct 84 17:01:17 GMT Date-Received: 10 Oct 84 17:01:17 GMT Sender: daemon@seismo.UUCP Organization: Center for Seismic Studies, Arlington, VA Lines: 38 Status: O From: Mike Muuss Subject: Unable to do multiple-destination sendto() Index: sys/net/raw_usrreq.c 4.2BSD FIX Description: When using the sendto() system call, and alternating between two "foreign" (destination) addresses, the sendto() will return EHOSTUNREACH on all destinations which need a different outbound route. This happens for us with IPPROTO_ICMP, but is a more general bug with the (often used) raw IP mechanism. Repeat-By: Running "pong.c". Availible on request, but is easy to whip up. Fix: In /sys/net/raw_usrreq.c, make this simple change to zero the pointer to the route structure, after freeing the route structure. *** 275,281 if ((rp->rcb_flags & RAW_DONTROUTE) == 0) if (!equal(rp->rcb_faddr, rp->rcb_route.ro_dst) || rp->rcb_route.ro_rt == 0) { ! if (rp->rcb_route.ro_rt) ! rtfree(rp->rcb_route.ro_rt); rp->rcb_route.ro_dst = rp->rcb_faddr; rtalloc(&rp->rcb_route); --- 277,284 ----- rp->rcb_route.ro_rt == 0) { + if (rp->rcb_route.ro_rt) { rtfree(rp->rcb_route.ro_rt); + rp->rcb_route.ro_rt = 0; + } rp->rcb_route.ro_dst = rp->rcb_faddr; rtalloc(&rp->rcb_route); } From chris@umcp-cs.UUCP (Chris Torek) Mon Oct 22 14:22:29 1984 Relay-Version: version B 2.10.2 9/27/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site umcp-cs.UUCP Path: seismo!umcp-cs!chris From: chris@umcp-cs.UUCP (Chris Torek) Newsgroups: net.bugs.4bsd Subject: 4.2BSD fsck can dump core (with fix) Message-ID: <417@umcp-cs.UUCP> Date: 22 Oct 84 18:22:29 GMT Date-Received: 22 Oct 84 18:53:52 GMT Distribution: net Organization: U of Maryland, Computer Science Dept., College Park, MD Lines: 43 Index: etc/fsck 4.2BSD Fix Description: Under certain uncommon conditions, fsck will die with a segmentation fault instead of repairing a damaged file system. The reason is that in order to calculate the number of disk blocks used by any particular inode, one must round up. This is done by the ``howmany'' macro as follows: #define howmany(x, y) (((x)+((y)-1))/(y)) if x is sufficiently large, then adding y-1 may make it negative. This is precisely what happens to fsck. Repeat-By: Create a file system error such that an inode has a di_size of 0x7fffffff (or something very close to but not greater than that), and run ``fsck'' on that file system. Fix: Replace the test for negative sizes with a test for either a negative size or one that is too large: RCS file: RCS/fsck.c,v retrieving revision 1.1 retrieving revision 1.2 diff -r1.1 -r1.2 620c620,621 < if (dp->di_size < 0) { --- > if (dp->di_size < 0 || > dp->di_size + sblock.fs_bsize - 1 < 0) { (For those of you who need context, this is right above an if (debug) printf() line that prints a message about a bad size. Or you can just search for di_size ... there's only the one nearby.) -- (This mind accidently left blank.) In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland From terryl@tekchips.UUCP () Mon Oct 22 17:15:03 1984 Relay-Version: version B 2.10.2 9/27/84; site seismo.UUCP Posting-Version: version B 2.10.1 (Tek) 9/26/83; site tekchips.UUCP Path: seismo!harvard!godot!mit-eddie!genrad!decvax!tektronix!tekchips!terryl From: terryl@tekchips.UUCP () Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: Bug in ftp "get" command (4.2 ftp) Message-ID: <5@tekchips.UUCP> Date: 22 Oct 84 21:15:03 GMT Date-Received: 23 Oct 84 23:24:57 GMT Lines: 44 Xref: godot net.bugs.4bsd:535 net.unix-wizards:3320 There is a bug in the way ftp validates pathnames for the "get" command. In the file ftp.c, in the routine recvrequest(), the code looks something like this: if (strcmp(local, "-") && *local != '|') if (access(local, 2) < 0) { char *dir = rindex(local, '/'); if (dir != NULL) *dir = 0; /* WRONG!! */ if (access(dir ? dir : ".", 2) < 0) { perror(local); goto bad; } if (dir != NULL) *dir = '/'; } First ftp tries to see if the user has write access to the full pathname; if not, then ftp tries to see if the user has write access to the directory the file will go in. It is this test that is done wrong; as one can see from the above code, if the pathname has at least one '/' in it, then the last '/' is zero'd out to get the directory component of the name. But it passes a pointer to this zero'd out portion of the pathname to access() to validate the user has write access to the directory, essentially a null pathname. A null pathname refers to the current directory under 4.2. Now, if the user is in a directory that he does not have write permission to, AND he does not have write permission to the file he is trying to transfer (or more commonly, the file does not exist yet), then ftp will report "Permission denied.", even though he may have write permission to the target directory and the file really doesn't exist yet. To fix this, change the line marked /* WRONG!! */ to below: if (access(dir ? local : ".", 2) < 0) { and everything should be hunky-dory. It looks like this bug has been in there for quite a while. The 4.2 release we have is dated 7/26/83 version 4.11; we have sources going back to 2/25/83 version 4.4, and they both have the same bug. Terry Laskodi of Tektronix From unix-wizards@seismo.UUCP Tue Oct 30 15:53:16 1984 Relay-Version: version B 2.10.2 10/19/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/27/84; site seismo.UUCP Path: seismo!unix-wizards From: unix-wizards@seismo.UUCP Newsgroups: unix-wizards Subject: Scatter/gather I/O on raw disks doesn't work correctly Message-ID: <4921@seismo.UUCP> Date: 30 Oct 84 20:53:16 GMT Date-Received: 30 Oct 84 20:53:16 GMT Sender: daemon@seismo.UUCP Organization: Center for Seismic Studies, Arlington, VA Lines: 53 Status: O From: Larry Allen Description: A readv or writev call to or from a raw disk only does the operation specified by the first element of the io vector. Repeat-By: Try to perform a readv from a raw disk, specifying a two-element io vector. The number of bytes read will equal the number of bytes specified in the first element of the io vector. Fix: The routine physio(), in file vm_swp.c, uses a temporary pointer to the iovec entries in the uio structure. This pointer is never updated as the routine loops through the iovecs. Make the following changes to vm_swp.c: --- /sys/sys/vm_swp.c Tue Oct 30 10:41:15 1984 *************** *** 192,198 unsigned (*mincnt)(); struct uio *uio; { ! register struct iovec *iov = uio->uio_iov; register int c; char *a; int s, error = 0; --- 192,198 ----- unsigned (*mincnt)(); struct uio *uio; { ! register struct iovec *iov; register int c; char *a; int s, error = 0; *************** *** 198,203 int s, error = 0; nextiov: if (uio->uio_iovcnt == 0) return (0); if (useracc(iov->iov_base,(u_int)iov->iov_len,rw==B_READ?B_WRITE:B_READ) == NULL) --- 198,204 ----- int s, error = 0; nextiov: + iov = uio->uio_iov; if (uio->uio_iovcnt == 0) return (0); if (useracc(iov->iov_base,(u_int)iov->iov_len,rw==B_READ?B_WRITE:B_READ) == NULL) -Larry Allen From stanonik@nprdc.ARPA Fri Oct 26 19:55:00 1984 Relay-Version: version B 2.10.2 10/19/84; site seismo.UUCP Path: seismo!harvard!wjh12!genrad!decvax!ittvax!dcdwest!sdcsvax!sdcrdcf!hplabs!sri-unix!stanonik@nprdc.ARPA From: stanonik@nprdc.ARPA Newsgroups: net.unix-wizards Subject: Re: 4.2 RFNM count problem Message-ID: <11797@sri-arpa.UUCP> Date: 26 Oct 84 23:55:00 GMT Date-Received: 1 Nov 84 21:30:17 GMT Lines: 34 Status: O In response to our query about rfnm's, Bill Nesheim (cu-arpa.bill@Cornell) provided the following fix which we've installed. RCS file: RCS/if_imp.c,v retrieving revision 1.1 diff -c -r1.1 if_imp.c *** /tmp/,RCSt1017941 Fri Oct 26 11:26:49 1984 --- if_imp.c Fri Sep 21 14:16:42 1984 *************** *** 293,298 */ case IMPTYPE_RESET: impmsg(sc, "interface reset"); impnoops(sc); goto drop; --- 293,299 ----- */ case IMPTYPE_RESET: impmsg(sc, "interface reset"); + hostreset(sc->imp_if.if_net); impnoops(sc); goto drop; He said their rfnm problems disappeared, and now apparently so have ours. Of course, disappearance of the problems isn't quite the same as testing. Hitting the ecu reset button would probably be a good test, if I could think of a way of bumping up the rfnm counts (short of adb'ing /dev/kmem). I never did get a response about when the imp's clear their counts, and I couldn't find that information in bbn's 1822 report. Ron Stanonik stanonik@nprdc From Larry Allen Fri Nov 9 17:41:21 1984 Relay-Version: version B 2.10.2 11/2/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/18/84; site brl-tgr.ARPA Path: seismo!brl-tgr!internet!Larry Allen From: Larry Allen Newsgroups: net.unix-wizards Subject: recvfrom() on raw sockets sometimes gives bad source address Message-ID: <5702@brl-tgr.ARPA> Date: 9 Nov 84 22:41:21 GMT Date-Received: 9 Nov 84 22:48:25 GMT Sender: news@brl-tgr.ARPA Organization: Ballistic Research Lab Lines: 43 Description: Recvfrom occasionally (about once out of every 1000 packets received) returns a bad source address when used on a raw socket. The packet is received successfully, everything looks fine, but the contents of the from sockaddr are completely trashed. Repeat-By: Because it happens so rarely, this problem is a hard one to repeat. Fix: The problem is caused by a bug in the rawintr() procedure in the file /sys/net/raw_usrreq.c. An extra mbuf has been prepended to the received packet to hold the demultiplexing information; the address of the source address in this mbuf is passed to sbappendaddr. However, the header mbuf is mfree'd before the call to sbappendaddr, and under heavy network traffic it may be reused before the address can be copied from it. Make the following changes to rawintr(): *** /fs/usr/sys/net/raw_usrreq.c Fri Mar 23 03:15:38 1984 --- /u/sys/net/raw_usrreq.c Fri Nov 9 16:08:12 1984 *************** *** 125,133 last = rp->rcb_socket; } if (last) { - m = m_free(m); /* header */ if (sbappendaddr(&last->so_rcv, &rh->raw_src, ! m, (struct mbuf *)0) == 0) goto drop; sorwakeup(last); goto next; --- 126,132 ----- } if (last) { if (sbappendaddr(&last->so_rcv, &rh->raw_src, ! m->m_next, (struct mbuf *)0) == 0) goto drop; + m_free(m); /* header */ sorwakeup(last); ****************** -Larry Allen From crp@ccivax.UUCP (Chuck Privitera) Thu Nov 8 17:08:13 1984 Relay-Version: version B 2.10.2 10/19/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/18/84; site ccivax.UUCP Path: seismo!rochester!ritcv!ccivax!crp From: crp@ccivax.UUCP (Chuck Privitera) Newsgroups: net.bugs.4bsd,net.bugs.2bsd Subject: Bug in 4.2BSD (2.9BSD?) ls Message-ID: <218@ccivax.UUCP> Date: 8 Nov 84 22:08:13 GMT Date-Received: 10 Nov 84 15:31:07 GMT Distribution: net Organization: CCI Telephony Systems Group, Rochester NY Lines: 46 Index: bin/ls.c 4.2BSD/(2.9BSD?) Description: When using the -R (recurse) option to ls, it will sometimes complain about a directory being unreadable (even when run as root - hint). A closer inspection will show that the directory doesn't even exist! Repeat-By: Try 'ls -R /' you should get at least one of these. Run it as root, so you should be able to read anything. Fix: In routine formatd() there is a for loop that builds a linked list of sub-directories by starting at the end of the list. Thus when the linked list is traversed, the files will be presented to the user in order. The trouble is, they start one PAST the end of the list. Here's the fix: rcsdiff -c3 -r1.1 -r1.2 ls.c RCS file: RCS/ls.c,v retrieving revision 1.1 retrieving revision 1.2 diff -c3 -r1.1 -r1.2 *** /tmp/,RCSt1008114 Thu Nov 8 15:30:28 1984 --- /tmp/,RCSt2008114 Thu Nov 8 15:30:39 1984 *************** *** 197,203 printf("total %ld\n", nkb); formatf(dfp0, dfplast); if (Rflg) ! for (fp = dfplast; fp >= dfp0; fp--) { if (fp->ftype != 'd' || !strcmp(fp->fname, ".") || !strcmp(fp->fname, "..")) --- 197,203 ----- printf("total %ld\n", nkb); formatf(dfp0, dfplast); if (Rflg) ! for (fp = dfplast-1; fp >= dfp0; fp--) { if (fp->ftype != 'd' || !strcmp(fp->fname, ".") || !strcmp(fp->fname, "..")) From dpk@BRL-VGR.ARPA Wed Nov 14 01:42:12 1984 Relay-Version: version B 2.10.2 11/2/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/18/84; site brl-tgr.ARPA Path: seismo!brl-tgr!internet!dpk@BRL-VGR.ARPA From: dpk@BRL-VGR.ARPA Newsgroups: net.unix-wizards Subject: brl-vgr Bug Report Message-ID: <5764@brl-tgr.ARPA> Date: 14 Nov 84 06:42:12 GMT Date-Received: 14 Nov 84 07:41:24 GMT Sender: news@brl-tgr.ARPA Organization: Ballistic Research Lab Lines: 51 Status: O Subject: netstat is grossly inefficient for stupid reason Index: ucb/netstat/inet.c 4.2BSD Fix Description: In inet.c:inetname(), netstat stupidly checks for the special case of INADDR_ANY (a non-host) only after a linear search through the entire host table. What is worse, it will search the ENTIRE table for every INADDR_ANY socket, looking for the non-existent entry. Repeat-By: Run "netstat -a" and watch how slow it is. To be more graphic, start up a bunch of processes which hang an accept() on INTERNET sockets (say 50 or 100), and make sure your host table has several hundred entries (like the ARPA host table). Your netstat -a will take FOREVER to complete. Fix: This fix is trivial and will make netstat go MUCH MUCH faster, over an order of magnitude faster on our system for a netstat -a. I have included a diff listing, although the line number will be off by a constant due to a header we stuck on the file (~8 lines). Basically, move the check for INADDR_ANY before the search through the host table which you KNOW will fail. This is a reposting since it did not make it to Berkeley or onto the Bug List from MT. XINU. This fix is EASY. diff inet.c.old inet.c 4c4 < * $Revision: 1.2 $ --- > * $Revision: 1.3 $ 6a7,9 > * Revision 1.3 84/07/04 01:09:36 dpk > * Moved check for INADDR_ANY in inetname for efficiency > * 12c15 < static char RCSid[] = "@(#)$Header: inet.c,v 1.2 84/07/04 01:07:20 dpk BRL $"; --- > static char RCSid[] = "@(#)$Header: inet.c,v 1.3 84/07/04 01:09:36 dpk BRL $"; 312a316,319 > if (in.s_addr == INADDR_ANY) { /* A quick check for the easy case */ > strcpy(line, "*"); > return (line); > } 329,331c336 < if (in.s_addr == INADDR_ANY) < strcpy(line, "*"); < else if (cp) --- > if (cp) From chris@umcp-cs.UUCP (Chris Torek) Sun Nov 18 05:40:26 1984 Relay-Version: version B 2.10.2 11/2/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site umcp-cs.UUCP Path: seismo!umcp-cs!chris From: chris@umcp-cs.UUCP (Chris Torek) Newsgroups: net.bugs.4bsd Subject: __queue doesn't work at all Message-ID: <1209@umcp-cs.UUCP> Date: 18 Nov 84 10:40:26 GMT Date-Received: 18 Nov 84 11:00:58 GMT Distribution: net Organization: U of Maryland, Computer Science Dept., College Park, MD Lines: 34 Index: vax/asm.sed 4.2BSD Fix Description: The asm.sed file replaces calls to __queue with a VAX insque instruction. However, it gives bogus arguments. Repeat-By: Examination, or try *using* __queue.... Fix: Apply diffs. Line numbers surely off. RCS file: RCS/asm.sed,v retrieving revision 1.3 diff -c1 -r1.3 asm.sed *** /tmp/,RCSt1000853 Sun Nov 18 04:22:17 1984 --- asm.sed Sun Nov 18 04:21:57 1984 *************** *** 119,122 s/calls $2,__queue/movl (sp)+,r0\ ! movl (sp)+,r1\ ! insque r1,*4(r0)/ s/calls $1,__dequeue/movl (sp)+,r0\ --- 119,121 ----- s/calls $2,__queue/movl (sp)+,r0\ ! insque *(sp)+,*4(r0)/ s/calls $1,__dequeue/movl (sp)+,r0\ -- (This line accidently left nonblank.) In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland From chris@umcp-cs.UUCP (Chris Torek) Sun Nov 18 07:24:33 1984 Relay-Version: version B 2.10.2 11/2/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site umcp-cs.UUCP Path: seismo!umcp-cs!chris From: chris@umcp-cs.UUCP (Chris Torek) Newsgroups: net.bugs.4bsd Subject: missed optimizations in pcc Message-ID: <1213@umcp-cs.UUCP> Date: 18 Nov 84 12:24:33 GMT Date-Received: 18 Nov 84 12:44:47 GMT Distribution: net Organization: U of Maryland, Computer Science Dept., College Park, MD Lines: 71 Index: lib/pcc/optim.c 4.2 Fix Description: The machine independent expression optimizer doesn't handle "/=", "%", or "%=" by the constants 1 and 0. Repeat-By: Feed the following through /lib/ccom; look at the assembly: f () { register i,j; i = j / 1; /* nice, the division goes away */ i /= 1; /* but not this time! */ i = j % 1; /* result is always 0, but talk about doing things the hard way */ i %= 1; /* same */ } Fix: The following changes to optim.c make it like /= as well as /, and make it handle % 1 and %= 1 in a reasonable way. We also added checks for division and mod by zero (they used to just generate divisions by zero). RCS file: RCS/optim.c,v retrieving revision 1.1 diff -c1 -r1.1 optim.c *** /tmp/,RCSt1008671 Sun Nov 18 07:16:07 1984 --- optim.c Sun Nov 18 07:15:44 1984 *************** *** 142,143 case DIV: --- 142,157 ----- + case ASG MOD: + case MOD: + if( nncon( p->in.right ) ){ + if( p->in.right->tn.lval == 1 ){ + /* mod by one gives zero */ + p->in.op = p->in.op==MOD ? COMOP : ASSIGN; + p->in.right->tn.lval = 0; + break; + } + if( p->in.right->tn.lval == 0 ) uerror("mod by zero"); + } + break; + + case ASG DIV: case DIV: *************** *** 143,145 case DIV: ! if( nncon( p->in.right ) && p->in.right->tn.lval == 1 ) goto zapright; break; --- 157,162 ----- case DIV: ! if( nncon( p->in.right ) ){ ! if( p->in.right->tn.lval == 1 ) goto zapright; ! if( p->in.right->tn.lval == 0 ) uerror("division by zero"); ! } break; -- (This line accidently left nonblank.) In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland From chris@umcp-cs.UUCP (Chris Torek) Sun Nov 18 07:34:03 1984 Relay-Version: version B 2.10.2 11/2/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site umcp-cs.UUCP Path: seismo!umcp-cs!chris From: chris@umcp-cs.UUCP (Chris Torek) Newsgroups: net.bugs.4bsd Subject: (more) missed optimizations in pcc Message-ID: <1214@umcp-cs.UUCP> Date: 18 Nov 84 12:34:03 GMT Date-Received: 18 Nov 84 13:01:00 GMT Distribution: net Organization: U of Maryland, Computer Science Dept., College Park, MD Lines: 55 Index: lib/pcc/local.c 4.2 Fix Description: The machine dependent expression optimizer doesn't handle "%" or "%=" by the constants which are powers of two. These can be done more simply as "&" or "&=". Repeat-By: Feed the following through /lib/ccom; look at the assembly: f () { register i,j; i = j % 3; /* ok */ i = j % 4; /* kinda the long way */ j %= 3; /* as above */ j %= 4; i = j % 1; /* check that previous fix still works */ j %= 1; } Fix: The following changes to local.c make it notice powers of two that are greater than 1 and turn the % or %= to an & or &=. RCS file: RCS/local.c,v retrieving revision 1.1 diff -c1 -r1.1 local.c *** /tmp/,RCSt1008635 Sun Nov 18 07:14:20 1984 --- local.c Sun Nov 18 07:13:55 1984 *************** *** 151,152 case FLD: --- 151,162 ----- + case MOD: + case ASG MOD: + /* convert %(const power of two) to &(mask) */ + /* mod by one is done elsewhere */ + if( nncon( p->in.right ) && ispow2( p->in.right->tn.lval )>0 ){ + p->in.op = p->in.op==MOD ? AND : ASG AND; + p->in.right->tn.lval--; + } + break; + case FLD: -- (This line accidently left nonblank.) In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland From rws@mit-bold (Robert W. Scheifler) Mon Nov 19 15:48:04 1984 Relay-Version: version B 2.10.2 11/2/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/18/84; site brl-tgr.ARPA Path: seismo!brl-tgr!internet!rws@mit-bold (Robert W. Scheifler) From: rws@mit-bold (Robert W. Scheifler) Newsgroups: net.unix-wizards Subject: spurious illegal instructions under 4.2 Message-ID: <5909@brl-tgr.ARPA> Date: 19 Nov 84 20:48:04 GMT Date-Received: 19 Nov 84 21:42:27 GMT Sender: news@brl-tgr.ARPA Organization: Ballistic Research Lab Lines: 37 Index: sys/vax/machdep.c 4.2BSD Description: The checks for growing P1 space in sendsig() are inadequate. The code assumes that, if a signal stack is used, the signal stack will always be in P0 space. This is quite likely, but it is a bit bogus to make that restriction. The code also assumes that, if a signal stack is used, the signal context will always go on the signal stack. Unfortunately, the signal context goes on the current stack, not the new stack. If the current stack is in P1 space, and the current SP is close to the current end of P1 space, P1 space will not be grown and a subsequent check for write access will fail, causing your program to get a special SIGILL which cannot be caught (which made this bug a bit hard to track down). Repeat-By: Generate a signal that will use a signal stack in previously untouched P1 space. Generate a signal that will use a signal stack in P0 space when the current SP is within a sigcontext's length of the current end of P1 space. Fix: In sendsig(), change if (!oonstack && (int)fp <= USRSTACK - ctob(u.u_ssize)) grow((unsigned)fp); to be if ((int)fp <= USRSTACK - ctob(u.u_ssize)) grow((unsigned)fp); and change if (!u.u_onstack && (int)scp <= USRSTACK - ctob(u.u_ssize)) grow((unsigned)scp); to be if ((int)scp <= USRSTACK - ctob(u.u_ssize)) grow((unsigned)scp); Note that when fp (scp) is P0 space, grow will be called gratuitously. There should probably be additional checks to see if the address is in P1 space before calling grow. From steveh@hammer.UUCP (Stephen Hemminger) Wed Nov 21 12:40:16 1984 Relay-Version: version B 2.10.2 11/2/84; site seismo.UUCP Posting-Version: version B 2.10.1 (Tek) 9/26/83; site hammer.UUCP Path: seismo!hao!hplabs!tektronix!orca!hammer!steveh From: steveh@hammer.UUCP (Stephen Hemminger) Newsgroups: net.unix-wizards,net.bugs.4bsd Subject: Unix Domain Datagram Bug. Message-ID: <1013@hammer.UUCP> Date: 21 Nov 84 17:40:16 GMT Date-Received: 24 Nov 84 01:47:59 GMT Reply-To: steveh@hammer.UUCP (Stephen Hemminger) Organization: Tektronix, Wilsonville OR Lines: 54 Keywords: Unix Domain, IPC, 4.2Bsd Description: If a two programs communicate via Unix domain datagrams, and the receiver can't keep up with the sender, then mbuf's are not freed which will eventually bring system to its knees. Repeat-By: Make a program which sends datagrams to another program. Have receiver sleep between recvs. Fix: Their is a misunderstanding in uipc_usrreq.c: sbappendaddr() returns 0 if an error (no space, no mbufs etc). 1 data sent. The source mbuf chain is freed by sbappendaddr when it returns 1, BUT they are not freed if it returns 0! Change to uipc_usrreq.c fixes the problem. Editted diffs of uipc_usrreq.c (line #'s are different from distribution sorry). *************** *** 168,183 if (error) break; } ! /* ! * Put data address and rights on receiver's queue. ! * There's no record of source socket's ! * name, so send null name for the moment. ! * ! * If no space (returns 0), then m will be ! * freed later. ! */ ! if (sbappendaddr(&so2->so_rcv, &sun_noname, ! m, rights) != 0) { sbwakeup(&so2->so_rcv); m = 0; } --- 164,176 ----- if (error) break; } ! if (sbspace(&so2->so_rcv) > 0) { ! /* ! * There's no record of source socket's ! * name, so send null name for the moment. ! */ ! (void) sbappendaddr(&so2->so_rcv, ! &sun_noname, m, rights); sbwakeup(&so2->so_rcv); m = 0; } From jpl@allegra.UUCP (John P. Linderman) Sun Nov 25 11:54:06 1984 Relay-Version: version B 2.10.2 11/2/84; site seismo.UUCP Posting-Version: version B 2.10.1 6/24/83; site allegra.UUCP Path: seismo!harvard!godot!mit-eddie!allegra!jpl From: jpl@allegra.UUCP (John P. Linderman) Newsgroups: net.bugs.uucp Subject: Re: Re: hung line help needed Message-ID: <2923@allegra.UUCP> Date: 25 Nov 84 16:54:06 GMT Date-Received: 26 Nov 84 13:12:53 GMT References: <85@daemon.UUCP> <33700001@trsvax.UUCP> Organization: AT&T Bell Laboratories, Murray Hill Lines: 38 Could you pass the code (or diffs) along for the timeout fix you've added? {microsoft,ctvax}!trsvax!ron I think I can do better. Kirk Smith pointed out a bug in sleep(3) that causes alarms to be masked off and never rearmed. Since uucico does both sleeps and alarms, his fix (enclosed below) looks like it will cure the disease whereas mine merely treated the symptoms. From: pur-ee!ef:ks (Kirk Smith) Received: by ef.ECN; Mon, 27 Aug 84 10:32:00 est (4.12/5.20) Message-Id: <8408271532.AA03198@ef.ECN> Subject: sleep(3) and SIGALRM Index: /usr/src/lib/libc/gen/sleep.c 4.2BSD Apparently-To: ucbvax!4bsd-bugs Description: After a call to sleep(), the signal SIGALRM remains blocked. Repeat-By: main() { sleep(1); alarm(1); } This program will never terminate. Fix: In sleep.c add the following line to set the mask back to the old mask before returning as follows: (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0); (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0); +++ (void) sigsetmask(omask); } John P. Linderman (Not alarmed by the slip in sleep) allegra!jpl From bill@cu-arpa Mon Dec 17 13:25:33 1984 Relay-Version: version B 2.10.2 11/2/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/18/84; site cornell.UUCP Path: seismo!uwvax!harvard!talcott!wjh12!genrad!decvax!tektronix!uw-beaver!cornell!bill@cu-arpa From: bill@cu-arpa Newsgroups: net.unix-wizards Subject: bug in IP broadcast packet recognition Message-ID: <669@cornell.UUCP> Date: 17 Dec 84 18:25:33 GMT Date-Received: 18 Dec 84 20:56:23 GMT Sender: daemon@cornell.UUCP Organization: Cornell Univ. CS Dept. Lines: 173 Status: O From: bill@cu-arpa (William A. Nesheim) Subject: IP sometimes doesn't recognize broadcast packets Index: sys/netinet/ip_input.c 4.2BSD Description: ip_input does not recognize broadcast IP datagrams for addresses other than the first interface on a machine. This breaks rwho, and any other programs which depend on UDP broadcasts. Repeat-By: get a machine with 2 or more ethernet (or other broadcast) net interfaces, and run rwhod on it. You will only see information from the 1st ethernet on the system, NOT from the second. Fix: In ip_input(), a "quick test" for an address match of the incoming packet and the first interface is done, testing for both the full address, and the broadcast address, if the interface is marked as a broadcast interface. This works for packets with the address of the FIRST interface as their destination, but if the dest. is the broadcast address of any other interface, the test in if_ifwithaddr() fails, and the packet is handed to ip_forward(), which drops it. I replaced the test of the "first" interface with a quick trip through ALL the interfaces, and eliminated the call to if_ifwithaddr(), as its return value was never used anyway. A diff of sys/netinet/ip_input.c follows. The line numbers are undoubtedly not what you expect. RCS file: RCS/ip_input.c,v retrieving revision 1.4 diff -c -r1.4 ip_input.c *** /tmp/,RCSt1000175 Mon Dec 17 13:18:09 1984 --- ip_input.c Mon Dec 17 13:11:49 1984 *************** *** 1,4 ! /* $Header: ip_input.c,v 1.4 84/10/12 12:08:33 bill Exp $ */ /* ip_input.c 6.3 84/05/25 */ #include "../h/param.h" --- 1,4 ----- ! /* $Header: ip_input.c,v 1.5 84/12/17 13:10:41 bill Exp $ */ /* ip_input.c 6.3 84/05/25 */ #include "../h/param.h" *************** *** 146,153 goto next; /* ! * Fast check on the first internet ! * interface in the list. */ if (ifinet) { struct sockaddr_in *sin; --- 146,152 ----- goto next; /* ! * check for our address */ { register struct sockaddr_in *sin; *************** *** 149,156 * Fast check on the first internet * interface in the list. */ ! if (ifinet) { ! struct sockaddr_in *sin; sin = (struct sockaddr_in *)&ifinet->if_addr; if (sin->sin_addr.s_addr == ip->ip_dst.s_addr) --- 148,156 ----- /* * check for our address */ ! { ! register struct sockaddr_in *sin; ! register struct ifnet *ifp; for(ifp = ifnet; ifp; ifp = ifp->if_next) { if (ifp->if_addr.sa_family != AF_INET) *************** *** 152,158 if (ifinet) { struct sockaddr_in *sin; ! sin = (struct sockaddr_in *)&ifinet->if_addr; if (sin->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; sin = (struct sockaddr_in *)&ifinet->if_broadaddr; --- 152,161 ----- register struct sockaddr_in *sin; register struct ifnet *ifp; ! for(ifp = ifnet; ifp; ifp = ifp->if_next) { ! if (ifp->if_addr.sa_family != AF_INET) ! continue; ! sin = (struct sockaddr_in *)&ifp->if_addr; if (sin->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; sin = (struct sockaddr_in *)&ifp->if_broadaddr; *************** *** 155,162 sin = (struct sockaddr_in *)&ifinet->if_addr; if (sin->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; ! sin = (struct sockaddr_in *)&ifinet->if_broadaddr; ! if ((ifinet->if_flags & IFF_BROADCAST) && sin->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; } --- 158,165 ----- sin = (struct sockaddr_in *)&ifp->if_addr; if (sin->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; ! sin = (struct sockaddr_in *)&ifp->if_broadaddr; ! if ((ifp->if_flags & IFF_BROADCAST) && sin->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; } *************** *** 160,165 sin->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; } /* BEGIN GROT */ #include "nd.h" #if NND > 0 --- 163,170 ----- sin->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; } + /* not for us at this point */ + } /* BEGIN GROT */ #include "nd.h" #if NND > 0 *************** *** 174,184 goto ours; #endif /* END GROT */ ! ipaddr.sin_addr = ip->ip_dst; ! if (if_ifwithaddr((struct sockaddr *)&ipaddr) == 0) { ! ip_forward(ip); ! goto next; ! } ours: /* --- 179,187 ----- goto ours; #endif /* END GROT */ ! ! ip_forward(ip); ! goto next; ours: /* From muller@sdcc3.UUCP (Keith Muller) Sat Dec 29 18:43:30 1984 Relay-Version: version B 2.10.2 12/21/84; site seismo.UUCP Posting-Version: version B 2.10.2 9/18/84; site sdcc3.UUCP Path: seismo!harvard!godot!mit-eddie!genrad!decvax!mcnc!akgua!sdcsvax!sdcc3!muller From: muller@sdcc3.UUCP (Keith Muller) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: 4.2 does not properly size the virtual memory paging point Message-ID: <2598@sdcc3.UUCP> Date: 29 Dec 84 23:43:30 GMT Date-Received: 3 Jan 85 06:57:17 GMT Organization: U.C. San Diego, Academic Computer Center Lines: 131 Xref: godot net.bugs.4bsd:685 net.unix-wizards:4581Index: sys/sys/vm_sched.c sys/vax/vmparam.h 4.2BSD Description: At boot time 4.2 will size the paging point and swapping point according to the amount of free main memory is available. The algorithim used for sizing lotsfree (the paging point) does not have an upper bound, but always sets the paging point to be 1/4 of free memory. This can be quite a large value for machines with with greater than around 3 megabytes of main memory (with memory prices getting lower, machines with more than 4 megs are quite common). This is a real performance problem in these large memory machines as they will begin paging when the machine is not even close to running out of memory. This premature paging begins to use up cpu cycles causing the machines throughput to rapidly decline (and also tends to offset any gains obtained by increasing the amount of main memory a machine might have). The swapping point maximium (desfree) is set a bit too large. Repeat-By: Load up your machine with a lot of memory intensive programs and watch the virtual memory system with a vmstat 3. The sr (scan rate) should always be as small as possible to maximize throughput (scanning costs cpu cycles). The fr value (free memory) indicates the size of free memory in the system. On large memory machines the sr can be quite high (100 or more) with 1 megabyte (or more) of main memory free. Fix: The fix has two parts: 1) adding a new #define to vax/vmparam.h for the maximium limit on lotsfree and changing the swapping point. 2) changing the code in sys/vm_sched.c that sizes lotsfree. The diffs are below: RCS file: RCS/vmparam.h,v retrieving revision 1.1 diff -c -r1.1 vmparam.h *** /tmp/,RCSt1029938 Sat Dec 29 15:16:36 1984 --- vmparam.h Sat Dec 29 14:31:03 1984 *************** *** 97,105 /* * Paging thresholds (see vm_sched.c). ! * Strategy of 4/22/81: ! * lotsfree is 1/4 of memory free. ! * desfree is 200k bytes, but at most 1/8 of memory * minfree is 64k bytes, but at most 1/2 of desfree */ #define LOTSFREEFRACT 4 --- 97,105 ----- /* * Paging thresholds (see vm_sched.c). ! * Strategy of 9/28/84: ! * lotsfree is 512k bytes, but at most 1/4 of memory ! * desfree is 128k bytes, but at most 1/8 of memory * minfree is 64k bytes, but at most 1/2 of desfree */ #define LOTSFREE (512 * 1024) *************** *** 102,107 * desfree is 200k bytes, but at most 1/8 of memory * minfree is 64k bytes, but at most 1/2 of desfree */ #define LOTSFREEFRACT 4 #define DESFREE (200 * 1024) #define DESFREEFRACT 8 --- 102,108 ----- * desfree is 128k bytes, but at most 1/8 of memory * minfree is 64k bytes, but at most 1/2 of desfree */ + #define LOTSFREE (512 * 1024) #define LOTSFREEFRACT 4 #define DESFREE (128 * 1024) #define DESFREEFRACT 8 *************** *** 103,109 * minfree is 64k bytes, but at most 1/2 of desfree */ #define LOTSFREEFRACT 4 ! #define DESFREE (200 * 1024) #define DESFREEFRACT 8 #define MINFREE (64 * 1024) #define MINFREEFRACT 2 --- 104,110 ----- */ #define LOTSFREE (512 * 1024) #define LOTSFREEFRACT 4 ! #define DESFREE (128 * 1024) #define DESFREEFRACT 8 #define MINFREE (64 * 1024) #define MINFREEFRACT 2 -------------------------------------------------------------------- RCS file: RCS/vm_sched.c,v retrieving revision 1.1 diff -c -r1.1 vm_sched.c *** /tmp/,RCSt1029948 Sat Dec 29 15:17:11 1984 --- vm_sched.c Sat Dec 29 14:44:32 1984 *************** *** 55,61 * tolerable. */ if (lotsfree == 0) ! lotsfree = LOOPPAGES / LOTSFREEFRACT; if (desfree == 0) { desfree = DESFREE / NBPG; if (desfree > LOOPPAGES / DESFREEFRACT) --- 55,63 ----- * tolerable. */ if (lotsfree == 0) ! lotsfree = LOTSFREE / NBPG; ! if (lotsfree > LOOPPAGES / LOTSFREEFRACT) ! lotsfree = LOOPPAGES / LOTSFREEFRACT; if (desfree == 0) { desfree = DESFREE / NBPG; if (desfree > LOOPPAGES / DESFREEFRACT) --------------------------------------------------------------------- Keith Muller University of California, San Diego Academic Computer Center ucbvax!sdcsvax!muller muller@nprdc From gnu@sun.uucp (John Gilmore) Wed Jan 23 06:47:38 1985 Relay-Version: version B 2.10.2 1/18/85; site seismo.UUCP Posting-Version: version B 2.10.2 9/18/84 SMI; site sun.uucp Path: seismo!hao!hplabs!tektronix!decvax!decwrl!sun!gnu From: gnu@sun.uucp (John Gilmore) Newsgroups: net.bugs.4bsd Subject: Fix for: rlogin sessions don't handle ^S/^Q in raw mode Message-ID: <1965@sun.uucp> Date: 23 Jan 85 11:47:38 GMT Date-Received: 25 Jan 85 10:40:52 GMT References: <20379@arizona.UUCP> Organization: Sun Microsystems, Inc. Lines: 25 Xref: seismo net.bugs.4bsd:1303 > When I rlogin to one of our 4.2bsd Vaxs and do a "stty raw", it seems > that ^S and ^Q don't get picked up on the remote machine. ... > Also, rlogin to a 1.2 SUN from a 4.2 Vax does pass ^S/^Q to the remote (the > SUN), so it seems like a problem with reception rather than transmission > on the Vax. > Is this a bug or a feature? Does anybody have a fix for this? As you pointed out, we fixed the problem. It was in the packet pty driver. It's supposed to tell the master side of the interface when the stop/start characters are ^S/^Q or aren't. When the slave side of the pty goes into raw mode, it stops having stop/start chars, but the pty didn't tell the master this, so the rlogind never told the rlogin on the local machine to stop intercepting flow control. Here's our fix: % ssd -r1.5 -r1.6 tty_pty.c 480c480,481 < { int stop = (tp->t_stopc == ('s'&037) && tp->t_startc == ('q'&037)); --- > { int stop = ((tp->t_flags & RAW) == 0 && > tp->t_stopc == ('s'&037) && tp->t_startc == ('q'&037)); 483c484 < pti->pt_send &= TIOCPKT_NOSTOP; --- > pti->pt_send &= ~TIOCPKT_NOSTOP; From thomson@uthub.UUCP (Brian Thomson) Mon Jul 8 07:39:28 1985 Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site seismo.UUCP Posting-Version: version B 2.10 beta 3/9/83; site uthub.UUCP Path: seismo!harpo!whuxlm!whuxl!houxm!ihnp4!cbosgd!clyde!watmath!utzoo!utcsri!utai!uthub!thomson From: thomson@uthub.UUCP (Brian Thomson) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: Problems with 4.2 BSD TCP and half-open connections Message-ID: <219@uthub.UUCP> Date: 8 Jul 85 11:39:28 GMT Date-Received: 10 Jul 85 05:33:35 GMT Organization: CSRG, University of Toronto Lines: 63 Index: /sys/netinet/tcp_input.c 4.2BSD Fix Description: I have been having problems with half-open connections remaining after one of two connected hosts crashes. When that host reboots, it attempts to reopen the connection that the other end thinks is still in ESTABLISHED state. The TCP specification (RFC 793) argues convincingly that the two TCPs should be able to sort this out, but between a pair of 4.2BSD TCPs this doesn't happen. Instead, the reconnection attempt eventually times out, and the other end continues to think that the old connection exists. Repeat-By: rlogin from machine A to machine B, such that A's TCP port number is the first available privileged port (1023). Now crash machine A, reboot it, and attempt to rlogin to B again. (this is a rather disruptive demonstration ...) Description: It appears that the problem lies in the file netinet/tcp_input.c, where we find the code sequence: >dropafterack: > /* > * Generate an ACK dropping incoming segment if it occupies > * sequence space, where the ACK reflects our state. > */ > if ((tiflags&TH_RST) || > tlen == 0 && (tiflags&(TH_SYN|TH_FIN)) == 0) > goto drop; This is branched to under several conditions, the most interesting being when an established connection receives a segment (eg. a connection request) that is entirely outside its window. The effect of the tests is that an ACK packet will be returned to the originator of the funny segment, UNLESS that funny segment contained a reset (TH_RST) OR contained no data and no SYN or FIN flags (which do "occupy sequence space"). These ACKs have to be sent to recover from half-open connections, but they aren't being sent. What seems to happen here is the connection request contains no data (so tlen == 0) but does, ORIGINALLY, contain a SYN. The receiving TCP trims the segment to its receive window, discarding the SYN, realizes there's nothing left, and branches to this point to send an ACK. Which doesn't get sent, because the modified segment no longer appears to "occupy sequence space". Fix: The "occupy sequence space" requirement is not part of the TCP definition. I have no idea why it was added. I have deleted the test, leaving only the requirement that the original segment not contain an RST. And, now, we appear to be recovering nicely from half-open connections. The new code is: >dropafterack: > /* > * Generate an ACK dropping incoming segment if it does not > * contain an RST, where the ACK reflects our state. > */ > if (tiflags&TH_RST) > goto drop; -- Brian Thomson, CSRI Univ. of Toronto {linus,ihnp4,uw-beaver,floyd,utzoo}!utcsrgv!uthub!thomson From jbn@wdl1.UUCP Wed Nov 20 21:21:44 1985 Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site seismo.seismo.CSS.GOV Posting-Version: version B 2.10.2 9/18/84; site wdl1.UUCP Path: seismo!harvard!talcott!panda!genrad!decvax!ittatc!dcdwest!sdcsvax!sdcrdcf!hplabs!fortune!wdl1!jbn From: jbn@wdl1.UUCP Newsgroups: net.bugs.4bsd Subject: TCP congestion fix Message-ID: <874@wdl1.UUCP> Date: 21 Nov 85 02:21:44 GMT Date-Received: 26 Nov 85 02:00:59 GMT Sender: notes@wdl1.UUCP Organization: Ford Aerospace, Western Development Laboratories Lines: 63 Nf-ID: #N:wdl1:71800002:000:2056 Nf-From: wdl1!jbn Nov 20 12:57:00 1985 Index: ucb/netinet/tcp_output.c 4.2BSD Symptom: Very poor TELNET performance over non-local networks; broken network connections, gateway congestion, high dropped packet rates in gateways, etc. Description: TCP sends too many tiny packets over long-haul links, congesting networks, links, gateways, etc. Sites with a connection to the ARPANET or CSNET, Ethernet bridges, gateways, packet forwarders, DMC or DMR links, X.25 links, or any non-trivial network architecture need this fix. Any TELNET use of a low-speed net (<56Kb) by a 4.2 system without this fix will clog the net to the point of unusability. Sites with nothing but a local area net not connected to any other net do not need this fix, although it is harmless in such situations. There is a better solution in 4.3BSD but it is more complex. There is a related fix to the TCP retransmission timer which should also be installed in tcp_output.c but is not a mandatory prerequisite for this fix. See Mt. Xinu buglist. J. Nagle Cause: Poor TCP send policy in tcp_output.c. Fix: (Line numbers reference Mt. Xinu's 4.2BSD) *** tcp_output.c *** 76,77c76,77 < * Sender silly window avoidance. If can send all data, < * a maximum segment, at least 1/4 of window do it, --- > * Sender silly window and congestion avoidance. > * If a maximum segment, no outstanding data, 78a79,81 > * This is a simplified version of the technique described in > * ACM Computer Communications Review, October 1984, p. 11. > * J. Nagle 81c84 < if (len == tp->t_maxseg || off+len >= so->so_snd.sb_cc) --- > if (len == tp->t_maxseg) /* if max size seg */ 83c86 < if (len * 4 >= tp->snd_wnd) /* a lot */ --- > if (tp->snd_nxt == tp->snd_una) /* if no outstanding */ 99,100c102 < * next expected input.) If this is 35% or more of the < * maximum possible window, then want to send a segment to peer. --- > * next expected input.) 103,105d104 < if (win > 0 && < ((100*(win-(tp->rcv_adv-tp->rcv_nxt))/so->so_rcv.sb_hiwat) >= 35)) < goto send; From matt@oddjob.UUCP (Matt Crawford) Sun Feb 23 21:25:27 1986 Path: seismo!lll-crg!lll-lcc!qantel!ihnp4!oddjob!matt From: matt@oddjob.UUCP (Matt Crawford) Newsgroups: net.unix,net.bugs.4bsd Subject: Re: Make problem (archives) Message-ID: <1195@oddjob.UUCP> Date: 24 Feb 86 02:25:27 GMT References: <270@batcomputer.TN.CORNELL.EDU> Reply-To: matt@oddjob.UUCP (Matt Crawford) Followup-To: net.bugs.4bsd Organization: U. Chicago, Astronomy & Astrophysics Lines: 138 The make syntaxes "a(b)" and "a((b))" don't even come close to working in the 4.2 make. The following fixes the former only. In /usr/src/bin/make: RCS file: RCS/files.c,v retrieving revision 1.1 diff -c -r1.1 files.c *** /tmp/,RCSt1003671 Sun Feb 23 20:16:33 1986 --- files.c Sun Feb 23 20:16:21 1986 *************** *** 372,378 static long arflen; static long arfdate; ! static char arfname[16]; FILE *arfd; long int arpos, arlen; --- 372,378 ----- static long arflen; static long arfdate; ! static char arfname[16]; /* size S/B determined from ar.h */ FILE *arfd; long int arpos, arlen; *************** *** 414,420 { if(objarch) { ! getobj(); nsym = objhead.a_syms / sizeof(objentry); for(i = 0; i