title: Single linked list
body: <p>I have created a single linked list. Everything works fine. </p>
  
  <p>I just want to know if I have done anything potentially dangerous in my code. The code snippets I am concerned about is my push, pop, and clean-up. The parts of the code is just for user interaction so not really important (I posted anyway so that it was more clear in what I was doing). Just the linked list application.</p>
  
  <p>Many thanks for any suggestions, as this is my fist attempt.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  
  typedef struct product_data product_data_t;
  struct product_data
  {
      int product_code;
      char product_name[128];
      int product_cost;
      product_data_t *next;
  };
  
  static product_data_t *head = NULL;
  static product_data_t *tail = NULL;
  static product_data_t *new_product = NULL;
  
  // Push a product on to the list.
  void push(int code, char name[], int cost); 
  // Pop (delete) a product from the list.
  void pop(int code);
  // Display all product in the list.
  void display_list();
  // Delete all memory allocated on the list
  void clean_up();
  // Display menu
  void menu();
  
  int main(void)
  {
      menu();
  
      getchar();
  
      return 0;
  }
  
  void push(int code, char name[], int cost)
  {
      // Allocate memory for the new product
      new_product = calloc(1, sizeof(product_data_t));
      if(!new_product)
      {
          fprintf(stderr, "Cannot allocated memory");
          exit(1);
      }
  
      /* Populate new products elements fields */
      new_product-&gt;product_code = code;
      strncpy(new_product-&gt;product_name, name, sizeof(new_product-&gt;product_name));
      new_product-&gt;product_cost = cost;
      new_product-&gt;next = NULL;
  
      // Set the head and tail of the linked list
      if(head == NULL)
      {
          // First and only product
          head = new_product;
      }
      else
      {
          tail-&gt;next = new_product;
      }
  
      tail = new_product;
  }
  
  // Find the product by code and delete
  void pop(int code)
  {
      product_data_t *product = head;
      product_data_t *temp = NULL;
      product_data_t *previous = head;
      int found = 0; // 0 - Not Found, 1 - Found
  
      if(!head)
      {
          puts("The list is empty");
          return;
      }
  
      while(product)
      {
          if(product-&gt;product_code == code)
          {
              found = 1; // Found
              // Check if this is in the first node - deleting from head
              if(head-&gt;product_code == code)
              {
                  temp = head;
                  head = head-&gt;next;
                  free(temp);
  
                  // Finished Deleting product
                  return;
              }
  
              // Check if this is the end node - deleting from the tail
              if(tail-&gt;product_code == code)
              {
                  temp = tail;
                  tail = previous;
                  free(temp);
  
                  // Finished deleting product
                  return;
              }
  
              // delete from list if not a head or tail
              temp = product;
              previous-&gt;next = product-&gt;next;
              free(temp);
  
              // Finished deleting product
              return;
          }
          // Get the address of the previous pointer.
          previous = product;
          product = product-&gt;next;  
      }
  
      if(!found)
      {
          printf("code [ %d ] was not found\n", code);
      }
  
      // Set all to null after finished with them
      product = NULL;
      temp = NULL;
      previous = NULL;
  }
  
  // Traverse the linked list
  void display_list()
  {
      // Start at the beginning
      product_data_t *product = head;
  
      while(product)
      {
          printf("===================================\n");
          printf("Product code: \t\t%d\n", product-&gt;product_code);
          printf("Product name: \t\t%s\n", product-&gt;product_name);
          printf("product cost (USD): \t%d\n", product-&gt;product_cost);
          printf("===================================\n\n");
  
          // Point to the next product
          product = product-&gt;next;
      }
      // Finished set to null
      product = NULL;
  }
  
  // Release all resources
  void clean_up()
  {    
      product_data_t *temp = NULL;
  
      while(head)
      {
          temp = head;
          head = head-&gt;next;
          free(temp);    
      }
      head = NULL;
      temp = NULL;
  
      // End program - goodbye
      exit(0);
  }
  
  void menu()
  {
      int choice = 0, code = 0, cost = 0;
      char name[128] = {0};
  
      do
      {
          fflush(stdin); // Flush the input buffer
  
          puts("========= Welecome to linked list ===============");
          puts("[1] Add new product to the list");
          puts("[2] Delete a product from the list");
          puts("[3] Display all products");
          puts("[4] Exit and clean up");
          printf("Enter your choice: ");
          scanf("%d", &amp;choice);
  
          switch(choice)
          {
          case 1:
              printf("Enter product code: ");
              scanf("%d", &amp;code);
              printf("Enter cost: ");
              scanf("%d", &amp;cost);
              printf("Enter name: ");
              scanf("%s", name);
              push(code, name, cost);
              break;
  
          case 2:
              printf("Enter product code: ");
              scanf("%d", &amp;code);
              pop(code);
              break;
  
          case 3:
              display_list();
              break;
  
          case 4:
              clean_up();
              break;
  
          default:
              puts("Incorrect choice");
              break;
          }
      }while(choice != 4);
  }
  </code></pre>