[net.notes] Wrong line count from 'savtxt'

ricks@sri-unix (09/02/82)

#N:tekcad:7500092:000:5421
tekcad!ricks    Sep  2 10:26:00 1982


When saving notes/response(s) of over 127 lines in length, notesfiles
will output an incorrect number of lines saved.

This is because the program uses only one byte to store the above information
due to the way it saves the file.  The program forks off a child to 
save the file and returns the number of lines in the high order byte
of the status word.  The forking is necessary to bypass any protections
the user has since notes runs setuid NOTES_OWNER. 

The following is a solution to the problem:

	1) create a temporary file, /tmp/nfs<pid>.
	2) set the umask to something reasonable.
	3) output the note/response(s) to the temporary file.
		a) thus getting the number of lines before the fork.
	4) fork off a child,
		a) set the uid of the child to the users uid.
		b) set the umask to the users original umask.
		c) append the temporary file to the users specified file.
	5) wait for the child to exit.
	6) unlink the temporary file.

The following is a diff of the old savtxt.c with the new one.


*** oldsavtxt.c	Wed Sep  1 22:05:10 1982
--- savtxt.c	Wed Sep  1 22:31:09 1982
***************
*** 4,14
   *	it in a specified file in the users working directory.
   *	We have to do some forking in this case because the directory
   *	may be protected against us. 
-  *	What we do is to fork with the uid set back to the user.
-  *		open (creating if needed) the file, and then
-  *		writing the text via preptxt.
-  *	The we first attempt to open the file. IF we can open it
-  *	write mode, then we can save the fork (and thus time)
   *
   *	returns the number of lines written to the file.
   *

--- 4,9 -----
   *	it in a specified file in the users working directory.
   *	We have to do some forking in this case because the directory
   *	may be protected against us. 
   *
   *	A temporary file (/tmp/nfs<pid>) is created for the note.
   *	Then a child is forked off to append the temporary file
***************
*** 10,15
   *	The we first attempt to open the file. IF we can open it
   *	write mode, then we can save the fork (and thus time)
   *
   *	returns the number of lines written to the file.
   *
   *	Original Coding:	Ray Essick	December 1981

--- 5,18 -----
   *	We have to do some forking in this case because the directory
   *	may be protected against us. 
   *
+  *	A temporary file (/tmp/nfs<pid>) is created for the note.
+  *	Then a child is forked off to append the temporary file
+  *	to the users specified file.
+  *
+  *	This is a modification of the original coding.  It fixes the
+  *	problem of returning the wrong number of lines output
+  *	to the users' file.
+  *
   *	returns the number of lines written to the file.
   *
   *	Original Coding:	Ray Essick	December 1981
***************
*** 13,18
   *	returns the number of lines written to the file.
   *
   *	Original Coding:	Ray Essick	December 1981
   */
  
  long lseek ();						/* declare for lint */

--- 16,22 -----
   *	returns the number of lines written to the file.
   *
   *	Original Coding:	Ray Essick	December 1981
+  *	Modification to fix number of lines:   Rick Spickelmier  Sept 1, 1982
   */
  
  long lseek ();						/* declare for lint */
***************
*** 35,40
      register    pid,
                  rpid;
      FILE * txtfile;
  
      if ((pid = fork ()) == 0)				/* also makes him own file */
      {

--- 39,47 -----
      register    pid,
                  rpid;
      FILE * txtfile;
+     char tmpfile[20];
+     char command[60];
+     int umsk;
  
      sprintf(tmpfile,"/tmp/nfs%d",getpid());
      umsk = umask(027);
***************
*** 36,41
                  rpid;
      FILE * txtfile;
  
      if ((pid = fork ()) == 0)				/* also makes him own file */
      {
  	x (setuid (globuid) < 0, "savtxt: setuid/forked");

--- 43,55 -----
      char command[60];
      int umsk;
  
+     sprintf(tmpfile,"/tmp/nfs%d",getpid());
+     umsk = umask(027);
+     if ((txtfile = fopen (tmpfile, "w")) == NULL)
+ 	exit (0);					/* no file ... */
+     lines = preptxt (io, txtfile, nfname, author, unique, date, txtwhere);
+     fclose (txtfile);
+ 
      if ((pid = fork ()) == 0)				/* also makes him own file */
      {
  	x (setuid (globuid) < 0, "savtxt: setuid/forked");
***************
*** 39,49
      if ((pid = fork ()) == 0)				/* also makes him own file */
      {
  	x (setuid (globuid) < 0, "savtxt: setuid/forked");
! 	if ((txtfile = fopen (where, "a")) == NULL)
! 	    exit (0);					/* no file ... */
! 	lines = preptxt (io, txtfile, nfname, author, unique, date, txtwhere);
! 	fclose (txtfile);
! 	exit (lines);
      }							/* end of forked process code */
  
   /* wait here for the son to finish */

--- 53,62 -----
      if ((pid = fork ()) == 0)				/* also makes him own file */
      {
  	x (setuid (globuid) < 0, "savtxt: setuid/forked");
! 	sprintf(command,"cat %s >> %s",tmpfile,where);
! 	umask(umsk);
! 	system(command);
! 	exit (0);
      }							/* end of forked process code */
  
   /* wait here for the son to finish */
***************
*** 56,61
      signal (1, p);
      signal (2, q);
      signal (3, r);
!     lines = retcode >> 8;				/* returns status in high byte */
      return lines;
  }

--- 69,74 -----
      signal (1, p);
      signal (2, q);
      signal (3, r);
!     unlink(tmpfile);
      return lines;
  }


			Rick L Spickelmier
			...ucbvax!teklabs!tekcad!ricks  (USENET)
			ricks.tektronix@udel-relay  (APRANET)
			ricks@tektronix  (CSNET)