#include "parms.h" #include "structs.h" #include #include #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 */ }