Conman Laboratories

Better living through software …

My new SYSCTL table for Linux AppleTalk

Mark Grosberg

The original code in sysctl_net_atalk.c looked like this:

ctl_table atalk_table[] = 
{
  {0}    /* End of table */
};

I modified the code in this file to look like this:

int sysctl_ddp_reset = 0;

int proc_ddp_reset(ctl_table *ctl, int write, struct file *filp,
                   void *buffer, size_t *lenp);

ctl_table atalk_table[] = 
{
  {  /* Writable ddp_reset file (type: integer) */
    1, "ddp_reset", 
    &sysctl_ddp_reset, sizeof(int), 
    0644, NULL, &proc_ddp_reset
  },

  {0} /* End of table */
};

The sysctl_ddp_reset variable is basically the number you get from a read operation on that file. It is easiest to declare a real integer variable and let the default handler routine for integer nodes in /proc deal with the handling of operations.

The actual procedure, proc_ddp_reset was defined in ddp.c. It is structured as follows:

int proc_ddp_reset(ctl_table *ctl, int write, struct file *filp,
                   void *buffer, size_t *lenp)
{
  unsigned long flags;
  int           retv;

  retv = proc_dointvec(ctl, write, filp, buffer, lenp);
  if (write)
  {
    struct atalk_iface *iface;
    extern int sysctl_ddp_reset;
    
    sysctl_ddp_reset = 0;
    
    save_flags(flags);
    cli();

    Do what you want here

    restore_flags(flags);  
  }
  
  return (retv);
}                   

The code first calls proc_dintvec() which services read, write, seek, etc. It uses the value of sysctl_ddp_reset() as the contents of the file.

If the operation was a write, we reset the value of the sysctl_ddp_reset variable to zero (since it shouldn't be changed by the user). We then get the old machine state (save_flags) and disable interrupts (cli) so we are atomic.

After doing our business, restore_flags restores the machine state, including interrupt status for the routine as it exits.