2.11BSD/src/new/notes/src/buildnf.c
#include "parms.h"
#include "structs.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef RCSIDENT
static char rcsid[] = "$Header: buildnf.c,v 1.7.0.2 86/05/22 11:19:09 notes Rel $";
#endif RCSIDENT
/*
* buildnf
*
* A subroutine which creates notesfiles. Given the (1) name of
* the new notesfile and (2) the anonymous, open, and
* networked flags this routine will create a new notesfile,
* provided that it does not exist already.
*
* This routine will blindly create the notesfile. It does not
* check the real uid to see if it should create a notesfile or
* not.
*
* Returns: 0 Notesfile created
* -1 Error in notesfile creation
* -2 Notesfile exists
*
* Extracted from old "mknf" mainline. Modified mknf so it
* calls this routine.
* Also put conditional code into newsinput.c to create the
* new notesfile if desired.
*
* Original Coding: Ray Essick October 13, 1982
*/
#define N_UMASK 0 /* when making nf's */
buildnf (nfname, basedir, Aflag, Oflag, Nflag)
char *nfname;
char *basedir; /* nf directory */
int Aflag,
Oflag,
Nflag;
{
struct io_f io;
char *p; /* misc. pointer */
int i; /* misc counter */
int fid; /* misc file id */
struct daddr_f freetext; /* for writing */
struct descr_f descr; /* for writing, too */
struct perm_f perms[NPERMS];
struct perm_f pentry; /* single entry */
struct auth_f me; /* for access list */
char cmdline[WDLEN]; /* for mkdir */
char pathname[WDLEN]; /* for filenames */
char filename[WDLEN]; /* for filenames */
FILE * seqfile;
FILE * pfile; /* access list mods */
struct stat statval; /* testing existence */
unsigned short restoremode;
int old_umask; /* save his mask */
if (chkpath (nfname))
{
printf ("Invalid notesfile name: `%s'\n", nfname);
return (-1); /* bad return */
}
if (stat (basedir, &statval) == -1) /* can we read basedir? */
{
printf ("can't stat (assumed directory) %s\n", basedir);
return (-1); /* error in creation */
}
sprintf (pathname, "%s/%s", basedir, nfname);
if (stat (pathname, &statval) == 0) /* check existence */
{
printf ("Notesfile already exists\n");
/*
* Could talk about whether it's a file or directory...
* but probably not worth it.
*/
return (-2); /* already exists */
}
old_umask = umask (N_UMASK); /* clear mask */
#ifdef BSD42
{
/*
* take advantage of 4.2 bsd system call...
*/
mkdir (pathname, 0770); /* make the directory */
}
#else
{
/*
* do it the hard way ... by forking children
*/
#ifdef USG
/*
* make sure we can create the directory; restore it later
*/
if (stat (basedir, &statval) == 0)
restoremode = statval.st_mode;
else
restoremode = 0775;
chmod (basedir, 0777);
#else
/*
* under non-USG boxes, we can do setuid(geteuid()) and have it
* make the real uid match the effective uid
*/
globuid = Notesuid; /* must be notes to work */
#endif USG
#ifndef FASTFORK
sprintf (cmdline, "mkdir %s", pathname); /* build command */
dounix (cmdline, 1, 0); /* execute, captain */
#ifdef USG
/*
* fix owner on USG boxes where setuid(geteuid()) doesn't do
* what it does on V7 and BSd boxes (set both to the effective)
*/
sprintf (cmdline, "chgrp %s %s", NOTESGRP, pathname);/* fix group */
dounix (cmdline, 1, 0);
sprintf (cmdline, "chown %s %s", NOTES, pathname);/* fix owner */
dounix (cmdline, 1, 0);
#endif USG
#else
dounix (1, 0, "/bin/mkdir", pathname, 0, 0, 0);
#ifdef USG
/*
* atone for the USG behavior of setuid(geteuid())
*/
dounix (1, 0, "/bin/chgrp", NOTESGRP, pathname, 0, 0);
dounix (1, 0, "/bin/chown", NOTES, pathname, 0, 0);
#endif USG
#endif FASTFORK
/*
* done making things. set the right permissions on
* basedir (if we screwed with it) and pathname.
*/
#ifdef USG
chmod (basedir, restoremode);
#endif USG
chmod (pathname, 0770);
}
#endif BSD42
/*
* Now build the files within the directory
* Build a default notesfile descriptor and then override with
* his specific values.
*/
initdescr (&descr); /* make default */
glocknf (&io, SEQLOCK); /* grab sequence # */
sprintf (cmdline, "%s/%s", Mstdir, SEQ);
x ((seqfile = fopen (cmdline, "r")) == NULL, "mknf: open unique");
x (fscanf (seqfile, "%d", &i) != 1, "mknf: unique read");
descr.d_nfnum = i++;
fclose (seqfile); /* close it and */
x ((seqfile = fopen (cmdline, "w")) == NULL, "mknf: reopen unique");
fprintf (seqfile, "%d\n", i); /* update */
fclose (seqfile);
gunlocknf (&io, SEQLOCK); /* release file */
strncpy (descr.d_title, nfname, NNLEN);
descr.d_title[NNLEN - 1] = '\0'; /* null it */
if (Aflag) /* he wants anon */
descr.d_stat |= ANONOK;
if (Oflag) /* open */
descr.d_stat |= OPEN;
if (Nflag) /* networkable */
descr.d_stat |= NETWRKD;
sprintf (filename, "%s/%s", pathname, INDEXN); /* make the file */
x ((fid = creat (filename, 0660)) < 0, "build: Cant create note.indx");
x (write (fid, &descr, sizeof descr) != sizeof descr,
"build: Cant write note.indx");
x (close (fid) < 0, "build: bad note.indx close");
/*
* Now create the text file
*/
sprintf (filename, "%s/%s", pathname, TEXT);
x ((fid = creat (filename, 0660)) < 0, "build: Cant create text");
freetext.addr = sizeof freetext; /* past address slot */
if (freetext.addr & 1) /* odd (shouldn't be) */
freetext.addr++; /* make it even */
x (write (fid, &freetext, sizeof freetext) != sizeof freetext,
"build: Cant write text");
x (close (fid) < 0, "build: bad text close");
/*
* Now the response index file.
*/
sprintf (filename, "%s/%s", pathname, INDEXR);
x ((fid = creat (filename, 0660)) < 0, "build: Cant create resp.indx");
i = 0; /* resp 0 slot free */
x (write (fid, &i, sizeof i) != sizeof i, "build: Cant write resp.indx");
x (close (fid) < 0, "build: bad close of resp.indx");
/*
* Build the access list. This is a two phase operation.
* The first phase builds a default access list. This
* is set up with one director (the notes signon) and
* a group "Other" with read/write. System "Other" also
* has read/write privileges. This is basically a wide-open
* policy.
* The second phase is customization. This step uses the
* contents of the file ..../notes/.utilities/access-template
* as a batch of access specifications (like nfaccess)
* to add/modify specific permissions.
*/
sprintf (filename, "%s/%s", pathname, ACCESS); /* build simple */
x ((fid = creat (filename, 0660)) < 0, "build: couldnt create access");
getname (&me, 0); /* grab "notes" */
perms[0].ptype = PERMUSER;
strcpy (perms[0].name, me.aname);
perms[0].perms = READOK + WRITOK + RESPOK + DRCTOK;
perms[1].ptype = PERMGROUP;
strcpy (perms[1].name, "Other");
perms[1].perms = DFLTPERMS;
perms[2].ptype = PERMSYSTEM;
strcpy (perms[2].name, "Other");
perms[2].perms = DFLTPERMS;
x (write (fid, perms, 3 * sizeof pentry) != 3 * sizeof pentry,
"build: bad access write");
x (close (fid) < 0, "build: close access broke");
/*
* Now, process any extra specifications from utilities/access-template
* Don't do anything unless the file exists.
*/
sprintf (filename, "%s/%s/%s-template", Mstdir, UTILITY, ACCESS);
if ((pfile = fopen (filename, "r")) != NULL)
{
char pline[BUFSIZ];
int nmodes,
zapindex;
nmodes = 0; /* load perms[] */
while (fgets (pline, sizeof pline, pfile) != NULL)
{
if (pline[0] == '#') /* comment */
continue;
if (nmodes == NPERMS) /* full list */
break;
zapindex = strlen (pline);
if (pline[zapindex] == '\n')
pline[zapindex] = '\0'; /* zap newline */
if (parsemode (pline, &perms[nmodes], 0) == 0)/* worked? */
nmodes++; /* bump counter */
}
fclose (pfile); /* done with template */
if (init (&io, pathname) >= 0) /* open the nf */
{
addmodes (&io, nmodes, perms, 0); /* add them */
closenf (&io);
}
}
x (umask (old_umask) != N_UMASK, "buildnf: reset umask");/* restore umask */
return 0; /* all's well */
}
/*
* initdescr(&descr_f)
*
* Load a descriptor with a lot of default information
* Other people will load things like titles and specific
* values of flags.
*/
initdescr (descr)
struct descr_f *descr;
{
register int i;
register char *p;
descr -> d_format = DBVERSION; /* version */
strcpy (descr -> d_title, "** Notesfile Title **");
strcpy (descr -> d_drmes, "** director message **");
descr -> d_plcy = 0; /* no policy note */
descr -> d_id.uniqid = 0; /* unique within nf */
strcpy (descr -> d_id.sys, System); /* and system name */
gettime (&descr -> d_lstxmit); /* last network xmit */
gettime (&descr -> d_lastm); /* last modified now */
gettime (&descr -> d_created); /* creation date */
gettime (&descr -> d_lastuse); /* for days online */
descr -> d_daysused = 1; /* count making it ! */
descr -> d_stat = 0; /* no special status */
descr -> d_nnote = 0; /* no notes in file */
descr -> d_delnote = descr -> d_delresp = 0; /* no holes */
descr -> d_archtime = 0; /* default time */
descr -> d_workset = 0; /* working set */
descr -> d_archkeep = KEEPDFLT; /* keep/delete */
descr -> d_dmesgstat = DIRDFLT; /* dirmsg to expire */
descr -> d_rspwrit = descr -> d_notwrit = 0; /* initialize stats */
descr -> d_rspread = descr -> d_notread = 0;
descr -> d_notdrop = descr -> d_rspdrop = 0;
descr -> d_orphans = 0; /* orphan chains */
descr -> d_adopted = 0; /* chains adopted */
descr -> entries = 0; /* user entries */
descr -> walltime = 0;
descr -> d_rspxmit = descr -> d_notxmit = 0; /* network activity */
descr -> d_rsprcvd = descr -> d_notrcvd = 0;
descr -> netwrkouts = descr -> netwrkins = 0;
descr -> d_longnote = MAXMSG; /* longest permitted */
}